LCOV - code coverage report
Current view: top level - gcc/c-family - c-ppoutput.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 99.0 % 405 401
Test Date: 2024-04-13 14:00:49 Functions: 100.0 % 29 29
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Preprocess only, using cpplib.
       2                 :             :    Copyright (C) 1995-2024 Free Software Foundation, Inc.
       3                 :             :    Written by Per Bothner, 1994-95.
       4                 :             : 
       5                 :             :    This program is free software; you can redistribute it and/or modify it
       6                 :             :    under the terms of the GNU General Public License as published by the
       7                 :             :    Free Software Foundation; either version 3, or (at your option) any
       8                 :             :    later version.
       9                 :             : 
      10                 :             :    This program is distributed in the hope that it will be useful,
      11                 :             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13                 :             :    GNU General Public License for more details.
      14                 :             : 
      15                 :             :    You should have received a copy of the GNU General Public License
      16                 :             :    along with this program; see the file COPYING3.  If not see
      17                 :             :    <http://www.gnu.org/licenses/>.  */
      18                 :             : 
      19                 :             : #include "config.h"
      20                 :             : #include "system.h"
      21                 :             : #include "coretypes.h"
      22                 :             : #include "c-common.h"         /* For flags.  */
      23                 :             : #include "../libcpp/internal.h"
      24                 :             : #include "langhooks.h"
      25                 :             : #include "c-pragma.h"         /* For parse_in.  */
      26                 :             : #include "file-prefix-map.h"    /* remap_macro_filename()  */
      27                 :             : 
      28                 :             : class token_streamer;
      29                 :             : 
      30                 :             : /* Encapsulates state used to convert a stream of tokens into a text
      31                 :             :    file.  */
      32                 :             : static struct
      33                 :             : {
      34                 :             :   FILE *outf;                   /* Stream to write to.  */
      35                 :             :   const cpp_token *prev;        /* Previous token.  */
      36                 :             :   const cpp_token *source;      /* Source token for spacing.  */
      37                 :             :   unsigned src_line;            /* Line number currently being written.  */
      38                 :             :   bool printed;                 /* True if something output at line.  */
      39                 :             :   bool first_time;              /* pp_file_change hasn't been called yet.  */
      40                 :             :   bool prev_was_system_token;   /* True if the previous token was a
      41                 :             :                                    system token.*/
      42                 :             :   const char *src_file;         /* Current source file.  */
      43                 :             :   token_streamer *streamer;     /* Instance of class token_streamer using this
      44                 :             :                                    object.  */
      45                 :             : } print;
      46                 :             : 
      47                 :             : /* Defined and undefined macros being queued for output with -dU at
      48                 :             :    the next newline.  */
      49                 :             : struct macro_queue
      50                 :             : {
      51                 :             :   struct macro_queue *next;     /* Next macro in the list.  */
      52                 :             :   char *macro;                  /* The name of the macro if not
      53                 :             :                                    defined, the full definition if
      54                 :             :                                    defined.  */
      55                 :             : };
      56                 :             : static macro_queue *define_queue, *undef_queue;
      57                 :             : 
      58                 :             : /* General output routines.  */
      59                 :             : static void scan_translation_unit (cpp_reader *);
      60                 :             : static void scan_translation_unit_directives_only (cpp_reader *);
      61                 :             : static void scan_translation_unit_trad (cpp_reader *);
      62                 :             : static void account_for_newlines (const unsigned char *, size_t);
      63                 :             : static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
      64                 :             : static void dump_queued_macros (cpp_reader *);
      65                 :             : 
      66                 :             : static bool print_line_1 (location_t, const char*, FILE *);
      67                 :             : static bool print_line (location_t, const char *);
      68                 :             : static bool maybe_print_line_1 (location_t, FILE *);
      69                 :             : static bool maybe_print_line (location_t);
      70                 :             : static bool do_line_change (cpp_reader *, const cpp_token *,
      71                 :             :                             location_t, int);
      72                 :             : 
      73                 :             : /* Callback routines for the parser.   Most of these are active only
      74                 :             :    in specific modes.  */
      75                 :             : static void cb_line_change (cpp_reader *, const cpp_token *, int);
      76                 :             : static void cb_define (cpp_reader *, location_t, cpp_hashnode *);
      77                 :             : static void cb_undef (cpp_reader *, location_t, cpp_hashnode *);
      78                 :             : static void cb_used_define (cpp_reader *, location_t, cpp_hashnode *);
      79                 :             : static void cb_used_undef (cpp_reader *, location_t, cpp_hashnode *);
      80                 :             : static void cb_include (cpp_reader *, location_t, const unsigned char *,
      81                 :             :                         const char *, int, const cpp_token **);
      82                 :             : static void cb_ident (cpp_reader *, location_t, const cpp_string *);
      83                 :             : static void cb_def_pragma (cpp_reader *, location_t);
      84                 :             : static void cb_read_pch (cpp_reader *pfile, const char *name,
      85                 :             :                          int fd, const char *orig_name);
      86                 :             : 
      87                 :             : /* Preprocess and output.  */
      88                 :             : void
      89                 :        5670 : preprocess_file (cpp_reader *pfile)
      90                 :             : {
      91                 :             :   /* A successful cpp_read_main_file guarantees that we can call
      92                 :             :      cpp_scan_nooutput or cpp_get_token next.  */
      93                 :        5670 :   if (flag_no_output && pfile->buffer)
      94                 :             :     {
      95                 :             :       /* Scan -included buffers, then the main file.  */
      96                 :         177 :       while (pfile->buffer->prev)
      97                 :          88 :         cpp_scan_nooutput (pfile);
      98                 :          89 :       cpp_scan_nooutput (pfile);
      99                 :             :     }
     100                 :        5581 :   else if (cpp_get_options (pfile)->traditional)
     101                 :        2096 :     scan_translation_unit_trad (pfile);
     102                 :        3485 :   else if (cpp_get_options (pfile)->directives_only
     103                 :          71 :            && !cpp_get_options (pfile)->preprocessed)
     104                 :          61 :     scan_translation_unit_directives_only (pfile);
     105                 :             :   else
     106                 :        3424 :     scan_translation_unit (pfile);
     107                 :             : 
     108                 :             :   /* -dM command line option.  Should this be elsewhere?  */
     109                 :        5504 :   if (flag_dump_macros == 'M')
     110                 :          77 :     cpp_forall_identifiers (pfile, dump_macro, NULL);
     111                 :             : 
     112                 :             :   /* Flush any pending output.  */
     113                 :        5504 :   if (print.printed)
     114                 :        3876 :     putc ('\n', print.outf);
     115                 :        5504 : }
     116                 :             : 
     117                 :             : /* Don't emit #pragma or #ident directives if we are processing
     118                 :             :    assembly language; the assembler may choke on them.  */
     119                 :             : static bool
     120                 :       50357 : should_output_pragmas ()
     121                 :             : {
     122                 :       50357 :   return cpp_get_options (parse_in)->lang != CLK_ASM;
     123                 :             : }
     124                 :             : 
     125                 :             : /* Set up the callbacks as appropriate.  */
     126                 :             : void
     127                 :        5676 : init_pp_output (FILE *out_stream)
     128                 :             : {
     129                 :        5676 :   cpp_callbacks *cb = cpp_get_callbacks (parse_in);
     130                 :             : 
     131                 :        5676 :   if (!flag_no_output)
     132                 :             :     {
     133                 :        5587 :       cb->line_change = cb_line_change;
     134                 :        5587 :       if (should_output_pragmas ())
     135                 :             :         {
     136                 :        4609 :           cb->ident      = cb_ident;
     137                 :        4609 :           cb->def_pragma = cb_def_pragma;
     138                 :             :         }
     139                 :             :     }
     140                 :             : 
     141                 :        5676 :   if (flag_dump_includes)
     142                 :           1 :     cb->include  = cb_include;
     143                 :             : 
     144                 :        5676 :   if (flag_pch_preprocess)
     145                 :             :     {
     146                 :         469 :       cb->valid_pch = c_common_valid_pch;
     147                 :         469 :       cb->read_pch = cb_read_pch;
     148                 :             :     }
     149                 :             : 
     150                 :        5676 :   if (flag_dump_macros == 'N' || flag_dump_macros == 'D')
     151                 :             :     {
     152                 :         161 :       cb->define = cb_define;
     153                 :         161 :       cb->undef  = cb_undef;
     154                 :             :     }
     155                 :             : 
     156                 :        5676 :   if (flag_dump_macros == 'U')
     157                 :             :     {
     158                 :          23 :       cb->before_define = dump_queued_macros;
     159                 :          23 :       cb->used_define = cb_used_define;
     160                 :          23 :       cb->used_undef = cb_used_undef;
     161                 :             :     }
     162                 :             : 
     163                 :        5676 :   cb->has_attribute = c_common_has_attribute;
     164                 :        5676 :   cb->has_builtin = c_common_has_builtin;
     165                 :        5676 :   cb->has_feature = c_common_has_feature;
     166                 :        5676 :   cb->get_source_date_epoch = cb_get_source_date_epoch;
     167                 :        5676 :   cb->remap_filename = remap_macro_filename;
     168                 :             : 
     169                 :             :   /* Initialize the print structure.  */
     170                 :        5676 :   print.src_line = 1;
     171                 :        5676 :   print.printed = false;
     172                 :        5676 :   print.prev = 0;
     173                 :        5676 :   print.outf = out_stream;
     174                 :        5676 :   print.first_time = 1;
     175                 :        5676 :   print.src_file = "";
     176                 :        5676 :   print.prev_was_system_token = false;
     177                 :        5676 :   print.streamer = nullptr;
     178                 :        5676 : }
     179                 :             : 
     180                 :             : // FIXME: Ideally we'd just turn the entirety of the print struct into
     181                 :             : // an encapsulated streamer ...
     182                 :             : 
     183                 :             : class token_streamer
     184                 :             : {
     185                 :             :   bool avoid_paste;
     186                 :             :   bool do_line_adjustments;
     187                 :             :   bool in_pragma;
     188                 :             : 
     189                 :             :  public:
     190                 :        3485 :   token_streamer (cpp_reader *pfile)
     191                 :        3485 :     :avoid_paste (false),
     192                 :        6970 :     do_line_adjustments (cpp_get_options (pfile)->lang != CLK_ASM
     193                 :        3485 :                          && !flag_no_line_commands),
     194                 :        3485 :     in_pragma (false)
     195                 :             :     {
     196                 :        3485 :       gcc_assert (!print.streamer);
     197                 :        3485 :       print.streamer = this;
     198                 :        3485 :     }
     199                 :             : 
     200                 :         114 :   void begin_pragma () 
     201                 :             :   {
     202                 :         114 :     in_pragma = true;
     203                 :         114 :   }
     204                 :             : 
     205                 :             :   void stream (cpp_reader *pfile, const cpp_token *tok, location_t);
     206                 :             : };
     207                 :             : 
     208                 :             : void
     209                 :    27309996 : token_streamer::stream (cpp_reader *pfile, const cpp_token *token,
     210                 :             :                         location_t loc)
     211                 :             : {
     212                 :             :   /* Keep input_location up to date, since it is needed for processing early
     213                 :             :      pragmas such as #pragma GCC diagnostic.  */
     214                 :    27309996 :   input_location = loc;
     215                 :             : 
     216                 :    27309996 :   if (token->type == CPP_PADDING)
     217                 :             :     {
     218                 :     1962212 :       avoid_paste = true;
     219                 :     1962212 :       if (print.source == NULL
     220                 :      284533 :           || (!(print.source->flags & PREV_WHITE)
     221                 :       81757 :               && token->val.source == NULL))
     222                 :     1699124 :         print.source = token->val.source;
     223                 :     1962212 :       return;
     224                 :             :     }
     225                 :             : 
     226                 :    25347784 :   if (token->type == CPP_EOF)
     227                 :             :     return;
     228                 :             : 
     229                 :             :   /* Keep track when we move into and out of system locations.  */
     230                 :    25344526 :   const bool is_system_token = in_system_header_at (loc);
     231                 :    25344526 :   const bool system_state_changed
     232                 :    25344526 :     = (is_system_token != print.prev_was_system_token);
     233                 :    25344526 :   print.prev_was_system_token = is_system_token;
     234                 :             : 
     235                 :             :   /* Subtle logic to output a space if and only if necessary.  */
     236                 :    25344526 :   bool line_marker_emitted = false;
     237                 :    25344526 :   if (avoid_paste)
     238                 :             :     {
     239                 :     1230168 :       unsigned src_line = LOCATION_LINE (loc);
     240                 :             : 
     241                 :     1230168 :       if (print.source == NULL)
     242                 :      529945 :         print.source = token;
     243                 :             : 
     244                 :     1230168 :       if (src_line != print.src_line
     245                 :        4601 :           && do_line_adjustments
     246                 :        4567 :           && !in_pragma)
     247                 :             :         {
     248                 :        4550 :           line_marker_emitted = do_line_change (pfile, token, loc, false);
     249                 :        4550 :           putc (' ', print.outf);
     250                 :        4550 :           print.printed = true;
     251                 :             :         }
     252                 :     1225618 :       else if (print.source->flags & PREV_WHITE
     253                 :      437084 :                || (print.prev
     254                 :      380997 :                    && cpp_avoid_paste (pfile, print.prev, token))
     255                 :     1660777 :                || (print.prev == NULL && token->type == CPP_HASH))
     256                 :             :         {
     257                 :      790476 :           putc (' ', print.outf);
     258                 :      790476 :           print.printed = true;
     259                 :             :         }
     260                 :             :     }
     261                 :    24114358 :   else if (token->flags & PREV_WHITE && token->type != CPP_PRAGMA)
     262                 :             :     {
     263                 :    10425514 :       unsigned src_line = LOCATION_LINE (loc);
     264                 :             : 
     265                 :    10425514 :       if (src_line != print.src_line
     266                 :        6559 :           && do_line_adjustments
     267                 :         473 :           && !in_pragma)
     268                 :         347 :         line_marker_emitted = do_line_change (pfile, token, loc, false);
     269                 :    10425514 :       putc (' ', print.outf);
     270                 :    10425514 :       print.printed = true;
     271                 :             :     }
     272                 :             : 
     273                 :    25344526 :   avoid_paste = false;
     274                 :    25344526 :   print.source = NULL;
     275                 :    25344526 :   print.prev = token;
     276                 :    25344526 :   if (token->type == CPP_PRAGMA)
     277                 :             :     {
     278                 :       13744 :       in_pragma = true;
     279                 :       13744 :       if (should_output_pragmas ())
     280                 :             :         {
     281                 :       13744 :           const char *space;
     282                 :       13744 :           const char *name;
     283                 :             : 
     284                 :       13744 :           line_marker_emitted = maybe_print_line (token->src_loc);
     285                 :       13744 :           fputs ("#pragma ", print.outf);
     286                 :       13744 :           c_pp_lookup_pragma (token->val.pragma, &space, &name);
     287                 :       13744 :           if (space)
     288                 :       13722 :             fprintf (print.outf, "%s %s", space, name);
     289                 :             :           else
     290                 :          22 :             fprintf (print.outf, "%s", name);
     291                 :       13744 :           print.printed = true;
     292                 :             :         }
     293                 :       13744 :       if (token->val.pragma >= PRAGMA_FIRST_EXTERNAL)
     294                 :       13631 :         c_pp_invoke_early_pragma_handler (token->val.pragma);
     295                 :             :     }
     296                 :    25330782 :   else if (token->type == CPP_PRAGMA_EOL)
     297                 :             :     {
     298                 :       13858 :       if (should_output_pragmas ())
     299                 :       13858 :         maybe_print_line (UNKNOWN_LOCATION);
     300                 :       13858 :       in_pragma = false;
     301                 :             :     }
     302                 :             :   else
     303                 :             :     {
     304                 :    25316924 :       if (cpp_get_options (parse_in)->debug)
     305                 :           3 :         linemap_dump_location (line_table, token->src_loc, print.outf);
     306                 :             : 
     307                 :    25316924 :       if (do_line_adjustments
     308                 :    24846052 :           && !in_pragma
     309                 :    24828884 :           && !line_marker_emitted
     310                 :    24828884 :           && system_state_changed
     311                 :    25318826 :           && !is_location_from_builtin_token (loc))
     312                 :             :         /* The system-ness of this token is different from the one of
     313                 :             :            the previous token.  Let's emit a line change to mark the
     314                 :             :            new system-ness before we emit the token.  */
     315                 :             :         {
     316                 :        1901 :           line_marker_emitted = do_line_change (pfile, token, loc, false);
     317                 :             :         }
     318                 :    25316924 :       if (!in_pragma || should_output_pragmas ())
     319                 :             :         {
     320                 :    25316924 :           cpp_output_token (token, print.outf);
     321                 :    25316924 :           print.printed = true;
     322                 :             :         }
     323                 :             :     }
     324                 :             : 
     325                 :             :   /* CPP_COMMENT tokens and raw-string literal tokens can have
     326                 :             :      embedded new-line characters.  Rather than enumerating all the
     327                 :             :      possible token types just check if token uses val.str union
     328                 :             :      member.  */
     329                 :    25344526 :   if (cpp_token_val_index (token) == CPP_TOKEN_FLD_STR)
     330                 :      555085 :     account_for_newlines (token->val.str.text, token->val.str.len);
     331                 :             : }
     332                 :             : 
     333                 :             : /* Writes out the preprocessed file, handling spacing and paste
     334                 :             :    avoidance issues.  */
     335                 :             : 
     336                 :             : static void
     337                 :        3424 : scan_translation_unit (cpp_reader *pfile)
     338                 :             : {
     339                 :        3424 :   token_streamer streamer (pfile);
     340                 :        3424 :   uintptr_t filter = 0;
     341                 :             : 
     342                 :        3424 :   if (lang_hooks.preprocess_token)
     343                 :        1129 :     filter = lang_hooks.preprocess_token (pfile, NULL, filter);
     344                 :             : 
     345                 :        3424 :   print.source = NULL;
     346                 :    54557750 :   for (;;)
     347                 :             :     {
     348                 :    27280587 :       location_t spelling_loc;
     349                 :    27280587 :       const cpp_token *token
     350                 :    27280587 :         = cpp_get_token_with_location (pfile, &spelling_loc);
     351                 :             : 
     352                 :    27280421 :       streamer.stream (pfile, token, spelling_loc);
     353                 :    27280421 :       if (filter)
     354                 :             :         {
     355                 :      735265 :           unsigned flags = lang_hooks.preprocess_token (pfile, token, filter);
     356                 :      735265 :           if (flags & lang_hooks::PT_begin_pragma)
     357                 :          90 :             streamer.begin_pragma ();
     358                 :             :         }
     359                 :    27280421 :       if (token->type == CPP_EOF)
     360                 :             :         break;
     361                 :    27277163 :     }
     362                 :             : 
     363                 :        3258 :   if (filter)
     364                 :          51 :     lang_hooks.preprocess_token (pfile, NULL, filter);
     365                 :        3258 : }
     366                 :             : 
     367                 :             : class do_streamer : public token_streamer
     368                 :             : {
     369                 :             :  public:
     370                 :             :   uintptr_t filter;
     371                 :             : 
     372                 :          61 :   do_streamer (cpp_reader *pfile, uintptr_t filter)
     373                 :         122 :     :token_streamer (pfile), filter (filter)
     374                 :             :     {
     375                 :             :     }
     376                 :             : };
     377                 :             : 
     378                 :             : static void
     379                 :        1700 : directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
     380                 :             : {
     381                 :        1700 :   va_list args;
     382                 :        1700 :   va_start (args, data_);
     383                 :             : 
     384                 :        1700 :   do_streamer *streamer = reinterpret_cast <do_streamer *> (data_);
     385                 :        1700 :   switch (task)
     386                 :             :     {
     387                 :           0 :     default:
     388                 :           0 :       gcc_unreachable ();
     389                 :             : 
     390                 :         484 :     case CPP_DO_print:
     391                 :         484 :       {
     392                 :         484 :         print.src_line += va_arg (args, unsigned);
     393                 :             : 
     394                 :         484 :         const void *buf = va_arg (args, const void *);
     395                 :         484 :         size_t size = va_arg (args, size_t);
     396                 :         484 :         fwrite (buf, 1, size, print.outf);
     397                 :             :       }
     398                 :         484 :       break;
     399                 :             : 
     400                 :        1102 :     case CPP_DO_location:
     401                 :        1102 :       maybe_print_line (va_arg (args, location_t));
     402                 :        1102 :       break;
     403                 :             : 
     404                 :         114 :     case CPP_DO_token:
     405                 :         114 :       {
     406                 :         114 :         const cpp_token *token = va_arg (args, const cpp_token *);
     407                 :         114 :         location_t spelling_loc = va_arg (args, location_t);
     408                 :         114 :         streamer->stream (pfile, token, spelling_loc);
     409                 :         114 :         if (streamer->filter)
     410                 :             :           {
     411                 :         114 :             unsigned flags = lang_hooks.preprocess_token
     412                 :         114 :               (pfile, token, streamer->filter);
     413                 :         114 :             if (flags & lang_hooks::PT_begin_pragma)
     414                 :          24 :               streamer->begin_pragma ();
     415                 :             :           }
     416                 :             :       }
     417                 :             :       break;
     418                 :             :     }
     419                 :             : 
     420                 :        1700 :   va_end (args);
     421                 :        1700 : }
     422                 :             : 
     423                 :             : /* Writes out the preprocessed file, handling spacing and paste
     424                 :             :    avoidance issues.  */
     425                 :             : static void
     426                 :          61 : scan_translation_unit_directives_only (cpp_reader *pfile)
     427                 :             : {
     428                 :          61 :   uintptr_t filter = 0;
     429                 :          61 :   if (lang_hooks.preprocess_token)
     430                 :          47 :     filter = lang_hooks.preprocess_token (pfile, NULL, filter);
     431                 :          61 :   do_streamer streamer (pfile, filter);
     432                 :          61 :   cpp_directive_only_process (pfile, &streamer, directives_only_cb);
     433                 :          61 :   if (streamer.filter)
     434                 :           6 :     lang_hooks.preprocess_token (pfile, NULL, streamer.filter);
     435                 :          61 : }
     436                 :             : 
     437                 :             : /* Adjust print.src_line for newlines embedded in output.  For example, if a raw
     438                 :             :    string literal contains newlines, then we need to increment our notion of the
     439                 :             :    current line to keep in sync and avoid outputting a line marker
     440                 :             :    unnecessarily.  If a raw string literal containing newlines is the result of
     441                 :             :    macro expansion, then we have the opposite problem, where the token takes up
     442                 :             :    more lines in the output than it did in the input, and hence a line marker is
     443                 :             :    needed to restore the correct state for subsequent lines.  In this case,
     444                 :             :    incrementing print.src_line still does the job, because it will cause us to
     445                 :             :    emit the line marker the next time a token is streamed.  */
     446                 :             : static void
     447                 :      555260 : account_for_newlines (const unsigned char *str, size_t len)
     448                 :             : {
     449                 :     2549158 :   while (len--)
     450                 :     1993898 :     if (*str++ == '\n')
     451                 :         646 :       print.src_line++;
     452                 :      555260 : }
     453                 :             : 
     454                 :             : /* Writes out a traditionally preprocessed file.  */
     455                 :             : static void
     456                 :        2096 : scan_translation_unit_trad (cpp_reader *pfile)
     457                 :             : {
     458                 :      392888 :   while (_cpp_read_logical_line_trad (pfile))
     459                 :             :     {
     460                 :      388696 :       size_t len = pfile->out.cur - pfile->out.base;
     461                 :      388696 :       maybe_print_line (pfile->out.first_line);
     462                 :      388696 :       fwrite (pfile->out.base, 1, len, print.outf);
     463                 :      388696 :       print.printed = true;
     464                 :      388696 :       if (!CPP_OPTION (pfile, discard_comments))
     465                 :         175 :         account_for_newlines (pfile->out.base, len);
     466                 :             :     }
     467                 :        2096 : }
     468                 :             : 
     469                 :             : /* If the token read on logical line LINE needs to be output on a
     470                 :             :    different line to the current one, output the required newlines or
     471                 :             :    a line marker.  If a line marker was emitted, return TRUE otherwise
     472                 :             :    return FALSE.  */
     473                 :             : 
     474                 :             : static bool
     475                 :     4375480 : maybe_print_line_1 (location_t src_loc, FILE *stream)
     476                 :             : {
     477                 :     4375480 :   bool emitted_line_marker = false;
     478                 :     4375480 :   unsigned src_line = LOCATION_LINE (src_loc);
     479                 :     4375480 :   const char *src_file = LOCATION_FILE (src_loc);
     480                 :             : 
     481                 :             :   /* End the previous line of text.  */
     482                 :     4375480 :   if (print.printed)
     483                 :             :     {
     484                 :     4138191 :       putc ('\n', stream);
     485                 :     4138191 :       print.src_line++;
     486                 :     4138191 :       print.printed = false;
     487                 :             :     }
     488                 :             : 
     489                 :     4375480 :   if (!flag_no_line_commands
     490                 :     4366339 :       && src_line >= print.src_line
     491                 :     4283908 :       && src_line < print.src_line + 8
     492                 :     4155014 :       && src_loc != UNKNOWN_LOCATION
     493                 :     4155012 :       && strcmp (src_file, print.src_file) == 0)
     494                 :             :     {
     495                 :     5567728 :       while (src_line > print.src_line)
     496                 :             :         {
     497                 :     1412716 :           putc ('\n', stream);
     498                 :     1412716 :           print.src_line++;
     499                 :             :         }
     500                 :             :     }
     501                 :             :   else
     502                 :      220468 :     emitted_line_marker = print_line_1 (src_loc, "", stream);
     503                 :             : 
     504                 :     4375480 :   return emitted_line_marker;
     505                 :             : }
     506                 :             : 
     507                 :             : /* If the token read on logical line LINE needs to be output on a
     508                 :             :    different line to the current one, output the required newlines or
     509                 :             :    a line marker.  If a line marker was emitted, return TRUE otherwise
     510                 :             :    return FALSE.  */
     511                 :             : 
     512                 :             : static bool
     513                 :     4375480 : maybe_print_line (location_t src_loc)
     514                 :             : {
     515                 :     4375480 :   if (cpp_get_options (parse_in)->debug)
     516                 :           2 :     linemap_dump_location (line_table, src_loc,
     517                 :             :                            print.outf);
     518                 :     4375480 :   return maybe_print_line_1 (src_loc, print.outf);
     519                 :             : }
     520                 :             : 
     521                 :             : /* Output a line marker for logical line LINE.  Special flags are "1"
     522                 :             :    or "2" indicating entering or leaving a file.  If the line marker
     523                 :             :    was effectively emitted, return TRUE otherwise return FALSE.  */
     524                 :             : 
     525                 :             : static bool
     526                 :      347458 : print_line_1 (location_t src_loc, const char *special_flags, FILE *stream)
     527                 :             : {
     528                 :      347458 :   bool emitted_line_marker = false;
     529                 :             : 
     530                 :             :   /* End any previous line of text.  */
     531                 :      347458 :   if (print.printed)
     532                 :       25261 :     putc ('\n', stream);
     533                 :      347458 :   print.printed = false;
     534                 :             : 
     535                 :      347458 :   if (src_loc != UNKNOWN_LOCATION && !flag_no_line_commands)
     536                 :             :     {
     537                 :      324459 :       const char *file_path = LOCATION_FILE (src_loc);
     538                 :      324459 :       size_t to_file_len = strlen (file_path);
     539                 :      324459 :       unsigned char *to_file_quoted =
     540                 :      324459 :          (unsigned char *) alloca (to_file_len * 4 + 1);
     541                 :             : 
     542                 :             :       /* cpp_quote_string does not nul-terminate, so we have to do it
     543                 :             :          ourselves.  */
     544                 :      324459 :       unsigned char *p = cpp_quote_string (to_file_quoted,
     545                 :             :                                            (const unsigned char *) file_path,
     546                 :             :                                            to_file_len);
     547                 :      324459 :       *p = '\0';
     548                 :             : 
     549                 :      324459 :       print.src_line = LOCATION_LINE (src_loc);
     550                 :      324459 :       print.src_file = file_path;
     551                 :             : 
     552                 :      324459 :       fprintf (stream, "# %u \"%s\"%s",
     553                 :             :                print.src_line, to_file_quoted, special_flags);
     554                 :             : 
     555                 :      324459 :       int sysp = in_system_header_at (src_loc);
     556                 :      324459 :       if (sysp == 2)
     557                 :      128225 :         fputs (" 3 4", stream);
     558                 :      196234 :       else if (sysp == 1)
     559                 :       94497 :         fputs (" 3", stream);
     560                 :             : 
     561                 :      324459 :       putc ('\n', stream);
     562                 :      324459 :       emitted_line_marker = true;
     563                 :             :     }
     564                 :             : 
     565                 :      347458 :   return emitted_line_marker;
     566                 :             : }
     567                 :             : 
     568                 :             : /* Output a line marker for logical line LINE.  Special flags are "1"
     569                 :             :    or "2" indicating entering or leaving a file.  Return TRUE if a
     570                 :             :    line marker was effectively emitted, FALSE otherwise.  */
     571                 :             : 
     572                 :             : static bool
     573                 :      126990 : print_line (location_t src_loc, const char *special_flags)
     574                 :             : {
     575                 :      126990 :     if (cpp_get_options (parse_in)->debug)
     576                 :           6 :       linemap_dump_location (line_table, src_loc,
     577                 :             :                              print.outf);
     578                 :      126990 :     return print_line_1 (src_loc, special_flags, print.outf);
     579                 :             : }
     580                 :             : 
     581                 :             : /* Helper function for cb_line_change and scan_translation_unit.
     582                 :             :    Return TRUE if a line marker is emitted, FALSE otherwise.  */
     583                 :             : static bool
     584                 :     3796819 : do_line_change (cpp_reader *pfile, const cpp_token *token,
     585                 :             :                 location_t src_loc, int parsing_args)
     586                 :             : {
     587                 :     3796819 :   bool emitted_line_marker = false;
     588                 :     3796819 :   if (define_queue || undef_queue)
     589                 :          21 :     dump_queued_macros (pfile);
     590                 :             : 
     591                 :     3796819 :   if (token->type == CPP_EOF || parsing_args)
     592                 :             :     return false;
     593                 :             : 
     594                 :     3778264 :   emitted_line_marker = maybe_print_line (src_loc);
     595                 :     3778264 :   print.prev = 0;
     596                 :     3778264 :   print.source = 0;
     597                 :             : 
     598                 :             :   /* Supply enough spaces to put this token in its original column,
     599                 :             :      one space per column greater than 2, since scan_translation_unit
     600                 :             :      will provide a space if PREV_WHITE.  Don't bother trying to
     601                 :             :      reconstruct tabs; we can't get it right in general, and nothing
     602                 :             :      ought to care.  Some things do care; the fault lies with them.
     603                 :             : 
     604                 :             :      Also do not output the spaces if this is a CPP_PRAGMA token.  In this
     605                 :             :      case, libcpp has provided the location of the first token after #pragma,
     606                 :             :      so we would start at the wrong column.  */
     607                 :     3778264 :   if (!CPP_OPTION (pfile, traditional) && token->type != CPP_PRAGMA)
     608                 :             :     {
     609                 :     3764667 :       int spaces = LOCATION_COLUMN (src_loc) - 2;
     610                 :     3764667 :       print.printed = true;
     611                 :             : 
     612                 :    14047069 :       while (-- spaces >= 0)
     613                 :    10282402 :         putc (' ', print.outf);
     614                 :             :     }
     615                 :             : 
     616                 :             :   return emitted_line_marker;
     617                 :             : }
     618                 :             : 
     619                 :             : /* Called when a line of output is started.  TOKEN is the first token
     620                 :             :    of the line, and at end of file will be CPP_EOF.  */
     621                 :             : static void
     622                 :     3790021 : cb_line_change (cpp_reader *pfile, const cpp_token *token,
     623                 :             :                 int parsing_args)
     624                 :             : {
     625                 :     3790021 :   do_line_change (pfile, token, token->src_loc, parsing_args);
     626                 :     3790021 : }
     627                 :             : 
     628                 :             : static void
     629                 :           2 : cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
     630                 :             :           const cpp_string *str)
     631                 :             : {
     632                 :           2 :   maybe_print_line (line);
     633                 :           2 :   fprintf (print.outf, "#ident %s\n", str->text);
     634                 :           2 :   print.src_line++;
     635                 :           2 : }
     636                 :             : 
     637                 :             : static void
     638                 :      122741 : cb_define (cpp_reader *pfile, location_t line, cpp_hashnode *node)
     639                 :             : {
     640                 :      122741 :   const line_map_ordinary *map;
     641                 :             : 
     642                 :      122741 :   maybe_print_line (line);
     643                 :      122741 :   fputs ("#define ", print.outf);
     644                 :             : 
     645                 :             :   /* 'D' is whole definition; 'N' is name only.  */
     646                 :      122741 :   if (flag_dump_macros == 'D')
     647                 :       39847 :     fputs ((const char *) cpp_macro_definition (pfile, node),
     648                 :             :            print.outf);
     649                 :             :   else
     650                 :       82894 :     fputs ((const char *) NODE_NAME (node), print.outf);
     651                 :             : 
     652                 :      122741 :   putc ('\n', print.outf);
     653                 :      122741 :   print.printed = false;
     654                 :      122741 :   linemap_resolve_location (line_table, line,
     655                 :             :                             LRK_MACRO_DEFINITION_LOCATION,
     656                 :             :                             &map);
     657                 :      122741 :   print.src_line++;
     658                 :      122741 : }
     659                 :             : 
     660                 :             : static void
     661                 :        4095 : cb_undef (cpp_reader *pfile, location_t line, cpp_hashnode *node)
     662                 :             : {
     663                 :        4095 :   if (lang_hooks.preprocess_undef)
     664                 :           0 :     lang_hooks.preprocess_undef (pfile, line, node);
     665                 :        4095 :   maybe_print_line (line);
     666                 :        4095 :   fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
     667                 :        4095 :   print.src_line++;
     668                 :        4095 : }
     669                 :             : 
     670                 :             : static void
     671                 :          22 : cb_used_define (cpp_reader *pfile, location_t line ATTRIBUTE_UNUSED,
     672                 :             :                 cpp_hashnode *node)
     673                 :             : {
     674                 :          22 :   if (cpp_user_macro_p (node))
     675                 :             :     {
     676                 :          21 :       macro_queue *q;
     677                 :          21 :       q = XNEW (macro_queue);
     678                 :          21 :       q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node));
     679                 :          21 :       q->next = define_queue;
     680                 :          21 :       define_queue = q;
     681                 :             :     }
     682                 :          22 : }
     683                 :             : 
     684                 :             : static void
     685                 :          11 : cb_used_undef (cpp_reader *pfile ATTRIBUTE_UNUSED,
     686                 :             :                location_t line ATTRIBUTE_UNUSED,
     687                 :             :                cpp_hashnode *node)
     688                 :             : {
     689                 :          11 :   macro_queue *q;
     690                 :          11 :   q = XNEW (macro_queue);
     691                 :          11 :   q->macro = xstrdup ((const char *) NODE_NAME (node));
     692                 :          11 :   q->next = undef_queue;
     693                 :          11 :   undef_queue = q;
     694                 :          11 : }
     695                 :             : 
     696                 :             : static void
     697                 :        9018 : dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED)
     698                 :             : {
     699                 :        9018 :   macro_queue *q;
     700                 :             : 
     701                 :             :   /* End the previous line of text.  */
     702                 :        9018 :   if (print.printed)
     703                 :             :     {
     704                 :          12 :       putc ('\n', print.outf);
     705                 :          12 :       print.src_line++;
     706                 :          12 :       print.printed = false;
     707                 :             :     }
     708                 :             : 
     709                 :        9039 :   for (q = define_queue; q;)
     710                 :             :     {
     711                 :          21 :       macro_queue *oq;
     712                 :          21 :       fputs ("#define ", print.outf);
     713                 :          21 :       fputs (q->macro, print.outf);
     714                 :          21 :       putc ('\n', print.outf);
     715                 :          21 :       print.printed = false;
     716                 :          21 :       print.src_line++;
     717                 :          21 :       oq = q;
     718                 :          21 :       q = q->next;
     719                 :          21 :       free (oq->macro);
     720                 :          21 :       free (oq);
     721                 :             :     }
     722                 :        9018 :   define_queue = NULL;
     723                 :        9029 :   for (q = undef_queue; q;)
     724                 :             :     {
     725                 :          11 :       macro_queue *oq;
     726                 :          11 :       fprintf (print.outf, "#undef %s\n", q->macro);
     727                 :          11 :       print.src_line++;
     728                 :          11 :       oq = q;
     729                 :          11 :       q = q->next;
     730                 :          11 :       free (oq->macro);
     731                 :          11 :       free (oq);
     732                 :             :     }
     733                 :        9018 :   undef_queue = NULL;
     734                 :        9018 : }
     735                 :             : 
     736                 :             : static void
     737                 :           1 : cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
     738                 :             :             const unsigned char *dir, const char *header, int angle_brackets,
     739                 :             :             const cpp_token **comments)
     740                 :             : {
     741                 :           1 :   maybe_print_line (line);
     742                 :           1 :   if (angle_brackets)
     743                 :           0 :     fprintf (print.outf, "#%s <%s>", dir, header);
     744                 :             :   else
     745                 :           1 :     fprintf (print.outf, "#%s \"%s\"", dir, header);
     746                 :             : 
     747                 :           1 :   if (comments != NULL)
     748                 :             :     {
     749                 :           2 :       while (*comments != NULL)
     750                 :             :         {
     751                 :           1 :           if ((*comments)->flags & PREV_WHITE)
     752                 :           1 :             putc (' ', print.outf);
     753                 :           1 :           cpp_output_token (*comments, print.outf);
     754                 :           1 :           ++comments;
     755                 :             :         }
     756                 :             :     }
     757                 :             : 
     758                 :           1 :   putc ('\n', print.outf);
     759                 :           1 :   print.printed = false;
     760                 :           1 :   print.src_line++;
     761                 :           1 : }
     762                 :             : 
     763                 :             : /* Callback called when -fworking-director and -E to emit working
     764                 :             :    directory in cpp output file.  */
     765                 :             : 
     766                 :             : void
     767                 :        1895 : pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
     768                 :             : {
     769                 :        1895 :   size_t to_file_len = strlen (dir);
     770                 :        1895 :   unsigned char *to_file_quoted =
     771                 :        1895 :      (unsigned char *) alloca (to_file_len * 4 + 1);
     772                 :        1895 :   unsigned char *p;
     773                 :             : 
     774                 :             :   /* cpp_quote_string does not nul-terminate, so we have to do it ourselves.  */
     775                 :        1895 :   p = cpp_quote_string (to_file_quoted, (const unsigned char *) dir, to_file_len);
     776                 :        1895 :   *p = '\0';
     777                 :        1895 :   fprintf (print.outf, "# 1 \"%s//\"\n", to_file_quoted);
     778                 :        1895 : }
     779                 :             : 
     780                 :             : /* The file name, line number or system header flags have changed, as
     781                 :             :    described in MAP.  */
     782                 :             : 
     783                 :             : void
     784                 :      137382 : pp_file_change (const line_map_ordinary *map)
     785                 :             : {
     786                 :      137382 :   const char *flags = "";
     787                 :             : 
     788                 :      137382 :   if (flag_no_line_commands)
     789                 :             :     return;
     790                 :             : 
     791                 :      132376 :   if (map != NULL)
     792                 :             :     {
     793                 :      127002 :       input_location = map->start_location;
     794                 :      127002 :       if (print.first_time)
     795                 :             :         {
     796                 :             :           /* Avoid printing foo.i when the main file is foo.c.  */
     797                 :        5552 :           if (!cpp_get_options (parse_in)->preprocessed)
     798                 :        5540 :             print_line (map->start_location, flags);
     799                 :        5552 :           print.first_time = 0;
     800                 :             :         }
     801                 :             :       else
     802                 :             :         {
     803                 :             :           /* Bring current file to correct line when entering a new file.  */
     804                 :      121450 :           if (map->reason == LC_ENTER)
     805                 :             :             {
     806                 :       49233 :               maybe_print_line (linemap_included_from (map));
     807                 :       49233 :               flags = " 1";
     808                 :             :             }
     809                 :       72217 :           else if (map->reason == LC_LEAVE)
     810                 :       49228 :             flags = " 2";
     811                 :      121450 :           print_line (map->start_location, flags);
     812                 :             :         }
     813                 :             :     }
     814                 :             : }
     815                 :             : 
     816                 :             : /* Copy a #pragma directive to the preprocessed output.  */
     817                 :             : static void
     818                 :        3744 : cb_def_pragma (cpp_reader *pfile, location_t line)
     819                 :             : {
     820                 :        3744 :   maybe_print_line (line);
     821                 :        3744 :   fputs ("#pragma ", print.outf);
     822                 :        3744 :   cpp_output_line (pfile, print.outf);
     823                 :        3744 :   print.printed = false;
     824                 :        3744 :   print.src_line++;
     825                 :        3744 : }
     826                 :             : 
     827                 :             : /* Stream a token as if we had seen it directly ourselves; needed
     828                 :             :    in case a token was lexed externally, e.g. while processing a
     829                 :             :    pragma.  */
     830                 :             : void
     831                 :       29461 : c_pp_stream_token (cpp_reader *pfile, const cpp_token *tok, location_t loc)
     832                 :             : {
     833                 :       29461 :   gcc_assert (print.streamer);
     834                 :       29461 :   print.streamer->stream (pfile, tok, loc);
     835                 :       29461 : }
     836                 :             : 
     837                 :             : /* Dump out the hash table.  */
     838                 :             : static int
     839                 :      312010 : dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
     840                 :             : {
     841                 :      312010 :   if (cpp_user_macro_p (node))
     842                 :             :     {
     843                 :       51188 :       fputs ("#define ", print.outf);
     844                 :       51188 :       fputs ((const char *) cpp_macro_definition (pfile, node),
     845                 :             :              print.outf);
     846                 :       51188 :       putc ('\n', print.outf);
     847                 :       51188 :       print.printed = false;
     848                 :       51188 :       print.src_line++;
     849                 :             :     }
     850                 :             : 
     851                 :      312010 :   return 1;
     852                 :             : }
     853                 :             : 
     854                 :             : /* Load in the PCH file NAME, open on FD.  It was originally searched for
     855                 :             :    by ORIG_NAME.  Also, print out a #include command so that the PCH
     856                 :             :    file can be loaded when the preprocessed output is compiled.  */
     857                 :             : 
     858                 :             : static void
     859                 :          21 : cb_read_pch (cpp_reader *pfile, const char *name,
     860                 :             :              int fd, const char *orig_name ATTRIBUTE_UNUSED)
     861                 :             : {
     862                 :          21 :   c_common_read_pch (pfile, name, fd, orig_name);
     863                 :             : 
     864                 :          21 :   fprintf (print.outf, "#pragma GCC pch_preprocess \"%s\"\n", name);
     865                 :          21 :   print.src_line++;
     866                 :             : 
     867                 :             :   /* The process of reading the PCH has destroyed the frontend parser,
     868                 :             :      so ask the frontend to reinitialize it, in case we need it to
     869                 :             :      process any #pragma directives encountered while preprocessing.  */
     870                 :          21 :   c_init_preprocess ();
     871                 :          21 : }
        

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.