LCOV - code coverage report
Current view: top level - gcc/c-family - c-ppoutput.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 99.1 % 450 446
Test Date: 2025-03-08 13:07:09 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-2025 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                 :        6049 : 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                 :        6049 :   if (flag_no_output && pfile->buffer)
      94                 :             :     {
      95                 :         104 :       if (flag_modules)
      96                 :             :         {
      97                 :             :           /* For macros from imported headers we need directives_only_cb.  */
      98                 :          12 :           scan_translation_unit_directives_only (pfile);
      99                 :             :         }
     100                 :             :       else
     101                 :             :         {
     102                 :             :           /* Scan -included buffers, then the main file.  */
     103                 :         179 :           while (pfile->buffer->prev)
     104                 :          87 :             cpp_scan_nooutput (pfile);
     105                 :          92 :           cpp_scan_nooutput (pfile);
     106                 :             :         }
     107                 :             :     }
     108                 :        5945 :   else if (cpp_get_options (pfile)->traditional)
     109                 :        2349 :     scan_translation_unit_trad (pfile);
     110                 :        3596 :   else if (cpp_get_options (pfile)->directives_only
     111                 :          68 :            && !cpp_get_options (pfile)->preprocessed)
     112                 :          60 :     scan_translation_unit_directives_only (pfile);
     113                 :             :   else
     114                 :        3536 :     scan_translation_unit (pfile);
     115                 :             : 
     116                 :             :   /* -dM command line option.  Should this be elsewhere?  */
     117                 :        5875 :   if (flag_dump_macros == 'M')
     118                 :          80 :     cpp_forall_identifiers (pfile, dump_macro, NULL);
     119                 :             : 
     120                 :             :   /* Flush any pending output.  */
     121                 :        5875 :   if (print.printed)
     122                 :        4184 :     putc ('\n', print.outf);
     123                 :        5875 : }
     124                 :             : 
     125                 :             : /* Don't emit #pragma or #ident directives if we are processing
     126                 :             :    assembly language; the assembler may choke on them.  */
     127                 :             : static bool
     128                 :       99373 : should_output_pragmas ()
     129                 :             : {
     130                 :       99373 :   return cpp_get_options (parse_in)->lang != CLK_ASM;
     131                 :             : }
     132                 :             : 
     133                 :             : /* Set up the callbacks as appropriate.  */
     134                 :             : void
     135                 :        6054 : init_pp_output (FILE *out_stream)
     136                 :             : {
     137                 :        6054 :   cpp_callbacks *cb = cpp_get_callbacks (parse_in);
     138                 :             : 
     139                 :        6054 :   if (!flag_no_output)
     140                 :             :     {
     141                 :        5950 :       cb->line_change = cb_line_change;
     142                 :        5950 :       if (should_output_pragmas ())
     143                 :             :         {
     144                 :        4971 :           cb->ident      = cb_ident;
     145                 :        4971 :           cb->def_pragma = cb_def_pragma;
     146                 :             :         }
     147                 :             :     }
     148                 :             : 
     149                 :        6054 :   if (flag_dump_includes)
     150                 :           1 :     cb->include  = cb_include;
     151                 :             : 
     152                 :        6054 :   if (flag_pch_preprocess)
     153                 :             :     {
     154                 :         463 :       cb->valid_pch = c_common_valid_pch;
     155                 :         463 :       cb->read_pch = cb_read_pch;
     156                 :             :     }
     157                 :             : 
     158                 :        6054 :   if (flag_dump_macros == 'N' || flag_dump_macros == 'D')
     159                 :             :     {
     160                 :         172 :       cb->define = cb_define;
     161                 :         172 :       cb->undef  = cb_undef;
     162                 :             :     }
     163                 :             : 
     164                 :        6054 :   if (flag_dump_macros == 'U')
     165                 :             :     {
     166                 :          23 :       cb->before_define = dump_queued_macros;
     167                 :          23 :       cb->used_define = cb_used_define;
     168                 :          23 :       cb->used_undef = cb_used_undef;
     169                 :             :     }
     170                 :             : 
     171                 :        6054 :   cb->has_attribute = c_common_has_attribute;
     172                 :        6054 :   cb->has_builtin = c_common_has_builtin;
     173                 :        6054 :   cb->has_feature = c_common_has_feature;
     174                 :        6054 :   cb->get_source_date_epoch = cb_get_source_date_epoch;
     175                 :        6054 :   cb->get_suggestion = cb_get_suggestion;
     176                 :        6054 :   cb->remap_filename = remap_macro_filename;
     177                 :             : 
     178                 :             :   /* Initialize the print structure.  */
     179                 :        6054 :   print.src_line = 1;
     180                 :        6054 :   print.printed = false;
     181                 :        6054 :   print.prev = 0;
     182                 :        6054 :   print.outf = out_stream;
     183                 :        6054 :   print.first_time = 1;
     184                 :        6054 :   print.src_file = "";
     185                 :        6054 :   print.prev_was_system_token = false;
     186                 :        6054 :   print.streamer = nullptr;
     187                 :        6054 : }
     188                 :             : 
     189                 :             : // FIXME: Ideally we'd just turn the entirety of the print struct into
     190                 :             : // an encapsulated streamer ...
     191                 :             : 
     192                 :             : class token_streamer
     193                 :             : {
     194                 :             :   bool avoid_paste;
     195                 :             :   bool do_line_adjustments;
     196                 :             :   bool in_pragma;
     197                 :             : 
     198                 :             :  public:
     199                 :        3608 :   token_streamer (cpp_reader *pfile)
     200                 :        3608 :     :avoid_paste (false),
     201                 :        7216 :     do_line_adjustments (cpp_get_options (pfile)->lang != CLK_ASM
     202                 :        3608 :                          && !flag_no_line_commands),
     203                 :        3608 :     in_pragma (false)
     204                 :             :     {
     205                 :        3608 :       gcc_assert (!print.streamer);
     206                 :        3608 :       print.streamer = this;
     207                 :        3608 :     }
     208                 :             : 
     209                 :         156 :   void begin_pragma ()
     210                 :             :   {
     211                 :         156 :     in_pragma = true;
     212                 :         156 :   }
     213                 :             : 
     214                 :             :   void stream (cpp_reader *pfile, const cpp_token *tok, location_t);
     215                 :             : };
     216                 :             : 
     217                 :             : void
     218                 :    29560903 : token_streamer::stream (cpp_reader *pfile, const cpp_token *token,
     219                 :             :                         location_t loc)
     220                 :             : {
     221                 :             :   /* Keep input_location up to date, since it is needed for processing early
     222                 :             :      pragmas such as #pragma GCC diagnostic.  */
     223                 :    29560903 :   input_location = loc;
     224                 :             : 
     225                 :    29560903 :   if (token->type == CPP_PADDING)
     226                 :             :     {
     227                 :     2072278 :       avoid_paste = true;
     228                 :     2072278 :       if (print.source == NULL
     229                 :      302117 :           || (!(print.source->flags & PREV_WHITE)
     230                 :       86711 :               && token->val.source == NULL))
     231                 :     1792938 :         print.source = token->val.source;
     232                 :     2072278 :       return;
     233                 :             :     }
     234                 :             : 
     235                 :    27488625 :   if (token->type == CPP_EOF)
     236                 :             :     return;
     237                 :             : 
     238                 :             :   /* Keep track when we move into and out of system locations.  */
     239                 :    27485263 :   const bool is_system_token = in_system_header_at (loc);
     240                 :    27485263 :   const bool system_state_changed
     241                 :    27485263 :     = (is_system_token != print.prev_was_system_token);
     242                 :    27485263 :   print.prev_was_system_token = is_system_token;
     243                 :             : 
     244                 :             :   /* Subtle logic to output a space if and only if necessary.  */
     245                 :    27485263 :   bool line_marker_emitted = false;
     246                 :    27485263 :   if (avoid_paste)
     247                 :             :     {
     248                 :     1295007 :       unsigned src_line = LOCATION_LINE (loc);
     249                 :             : 
     250                 :     1295007 :       if (print.source == NULL)
     251                 :      557119 :         print.source = token;
     252                 :             : 
     253                 :     1295007 :       if (src_line != print.src_line
     254                 :        4711 :           && do_line_adjustments
     255                 :        4673 :           && !in_pragma)
     256                 :             :         {
     257                 :        4656 :           line_marker_emitted = do_line_change (pfile, token, loc, false);
     258                 :        4656 :           putc (' ', print.outf);
     259                 :        4656 :           print.printed = true;
     260                 :             :         }
     261                 :     1290351 :       else if (print.source->flags & PREV_WHITE
     262                 :      459406 :                || (print.prev
     263                 :      393445 :                    && cpp_avoid_paste (pfile, print.prev, token))
     264                 :     1747780 :                || (print.prev == NULL && token->type == CPP_HASH))
     265                 :             :         {
     266                 :      832939 :           putc (' ', print.outf);
     267                 :      832939 :           print.printed = true;
     268                 :             :         }
     269                 :             :     }
     270                 :    26190256 :   else if (token->flags & PREV_WHITE && token->type != CPP_PRAGMA)
     271                 :             :     {
     272                 :    11266534 :       unsigned src_line = LOCATION_LINE (loc);
     273                 :             : 
     274                 :    11266534 :       if (src_line != print.src_line
     275                 :        7237 :           && do_line_adjustments
     276                 :         527 :           && !in_pragma)
     277                 :         401 :         line_marker_emitted = do_line_change (pfile, token, loc, false);
     278                 :    11266534 :       putc (' ', print.outf);
     279                 :    11266534 :       print.printed = true;
     280                 :             :     }
     281                 :             : 
     282                 :    27485263 :   avoid_paste = false;
     283                 :    27485263 :   print.source = NULL;
     284                 :    27485263 :   print.prev = token;
     285                 :    27485263 :   if (token->type == CPP_PRAGMA)
     286                 :             :     {
     287                 :       28085 :       in_pragma = true;
     288                 :       28085 :       if (should_output_pragmas ())
     289                 :             :         {
     290                 :       28085 :           const char *space;
     291                 :       28085 :           const char *name;
     292                 :             : 
     293                 :       28085 :           line_marker_emitted = maybe_print_line (token->src_loc);
     294                 :       28085 :           fputs ("#pragma ", print.outf);
     295                 :       28085 :           c_pp_lookup_pragma (token->val.pragma, &space, &name);
     296                 :       28085 :           if (space)
     297                 :       28067 :             fprintf (print.outf, "%s %s", space, name);
     298                 :             :           else
     299                 :          18 :             fprintf (print.outf, "%s", name);
     300                 :       28085 :           print.printed = true;
     301                 :             :         }
     302                 :       28085 :       if (token->val.pragma >= PRAGMA_FIRST_EXTERNAL)
     303                 :       27991 :         c_pp_invoke_early_pragma_handler (token->val.pragma);
     304                 :             :     }
     305                 :    27457178 :   else if (token->type == CPP_PRAGMA_EOL)
     306                 :             :     {
     307                 :       28241 :       if (should_output_pragmas ())
     308                 :       28241 :         maybe_print_line (UNKNOWN_LOCATION);
     309                 :       28241 :       in_pragma = false;
     310                 :             :     }
     311                 :    27428937 :   else if (token->type == CPP_EMBED)
     312                 :             :     {
     313                 :         130 :       char buf[76 + 6];
     314                 :         130 :       maybe_print_line (token->src_loc);
     315                 :         130 :       gcc_checking_assert (token->val.str.len != 0);
     316                 :         130 :       fputs ("#embed \".\" __gnu__::__base64__(", print.outf);
     317                 :         130 :       if (token->val.str.len > 30)
     318                 :             :         {
     319                 :         130 :           fputs (" \\\n", print.outf);
     320                 :         130 :           print.src_line++;
     321                 :             :         }
     322                 :         130 :       buf[0] = '"';
     323                 :         130 :       memcpy (buf + 1 + 76, "\" \\\n", 5);
     324                 :         130 :       unsigned int j = 1;
     325                 :         130 :       static const char base64_enc[] =
     326                 :             :         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     327                 :         130 :       for (unsigned i = 0; ; i += 3)
     328                 :             :         {
     329                 :      196824 :           unsigned char a = token->val.str.text[i];
     330                 :      196824 :           unsigned char b = 0, c = 0;
     331                 :      196824 :           unsigned int n = token->val.str.len - i;
     332                 :      196824 :           if (n > 1)
     333                 :      196778 :             b = token->val.str.text[i + 1];
     334                 :      196778 :           if (n > 2)
     335                 :      196738 :             c = token->val.str.text[i + 2];
     336                 :      196824 :           unsigned long v = ((((unsigned long) a) << 16)
     337                 :      196824 :                              | (((unsigned long) b) << 8)
     338                 :      196824 :                              | c);
     339                 :      196824 :           buf[j++] = base64_enc[(v >> 18) & 63];
     340                 :      196824 :           buf[j++] = base64_enc[(v >> 12) & 63];
     341                 :      196824 :           buf[j++] = base64_enc[(v >> 6) & 63];
     342                 :      196824 :           buf[j++] = base64_enc[v & 63];
     343                 :      196824 :           if (j == 76 + 1 || n <= 3)
     344                 :             :             {
     345                 :       10438 :               if (n < 3)
     346                 :             :                 {
     347                 :          86 :                   buf[j - 1] = '=';
     348                 :          86 :                   if (n == 1)
     349                 :          46 :                     buf[j - 2] = '=';
     350                 :             :                 }
     351                 :       10438 :               if (n <= 3)
     352                 :         130 :                 memcpy (buf + j, "\")", 3);
     353                 :             :               else
     354                 :       10308 :                 print.src_line++;
     355                 :       10438 :               fputs (buf, print.outf);
     356                 :       10438 :               j = 1;
     357                 :       10438 :               if (n <= 3)
     358                 :             :                 break;
     359                 :             :             }
     360                 :      196694 :         }
     361                 :         130 :       print.printed = true;
     362                 :         130 :       maybe_print_line (token->src_loc);
     363                 :         130 :       return;
     364                 :             :     }
     365                 :             :   else
     366                 :             :     {
     367                 :    27428807 :       if (cpp_get_options (parse_in)->debug)
     368                 :           3 :         linemap_dump_location (line_table, token->src_loc, print.outf);
     369                 :             : 
     370                 :    27428807 :       if (do_line_adjustments
     371                 :    26956153 :           && !in_pragma
     372                 :    26919056 :           && !line_marker_emitted
     373                 :    26919056 :           && system_state_changed
     374                 :    27440388 :           && !is_location_from_builtin_token (loc))
     375                 :             :         /* The system-ness of this token is different from the one of
     376                 :             :            the previous token.  Let's emit a line change to mark the
     377                 :             :            new system-ness before we emit the token.  */
     378                 :             :         {
     379                 :       11578 :           line_marker_emitted = do_line_change (pfile, token, loc, false);
     380                 :             :         }
     381                 :    27428807 :       if (!in_pragma || should_output_pragmas ())
     382                 :             :         {
     383                 :    27428807 :           cpp_output_token (token, print.outf);
     384                 :    27428807 :           print.printed = true;
     385                 :             :         }
     386                 :             :     }
     387                 :             : 
     388                 :             :   /* CPP_COMMENT tokens and raw-string literal tokens can have
     389                 :             :      embedded new-line characters.  Rather than enumerating all the
     390                 :             :      possible token types just check if token uses val.str union
     391                 :             :      member.  */
     392                 :    27485133 :   if (cpp_token_val_index (token) == CPP_TOKEN_FLD_STR)
     393                 :      575469 :     account_for_newlines (token->val.str.text, token->val.str.len);
     394                 :             : }
     395                 :             : 
     396                 :             : /* Writes out the preprocessed file, handling spacing and paste
     397                 :             :    avoidance issues.  */
     398                 :             : 
     399                 :             : static void
     400                 :        3536 : scan_translation_unit (cpp_reader *pfile)
     401                 :             : {
     402                 :        3536 :   token_streamer streamer (pfile);
     403                 :        3536 :   uintptr_t filter = 0;
     404                 :             : 
     405                 :        3536 :   if (lang_hooks.preprocess_token)
     406                 :        1215 :     filter = lang_hooks.preprocess_token (pfile, NULL, filter);
     407                 :             : 
     408                 :        3536 :   print.source = NULL;
     409                 :    58988826 :   for (;;)
     410                 :             :     {
     411                 :    29496181 :       location_t spelling_loc;
     412                 :    29496181 :       const cpp_token *token
     413                 :    29496181 :         = cpp_get_token_with_location (pfile, &spelling_loc);
     414                 :             : 
     415                 :    29496007 :       streamer.stream (pfile, token, spelling_loc);
     416                 :    29496007 :       if (filter)
     417                 :             :         {
     418                 :      739030 :           unsigned flags = lang_hooks.preprocess_token (pfile, token, filter);
     419                 :      739030 :           if (flags & lang_hooks::PT_begin_pragma)
     420                 :         132 :             streamer.begin_pragma ();
     421                 :             :         }
     422                 :    29496007 :       if (token->type == CPP_EOF)
     423                 :             :         break;
     424                 :    29492645 :     }
     425                 :             : 
     426                 :        3362 :   if (filter)
     427                 :          93 :     lang_hooks.preprocess_token (pfile, NULL, filter);
     428                 :        3362 : }
     429                 :             : 
     430                 :             : class do_streamer : public token_streamer
     431                 :             : {
     432                 :             :  public:
     433                 :             :   uintptr_t filter;
     434                 :             : 
     435                 :          72 :   do_streamer (cpp_reader *pfile, uintptr_t filter)
     436                 :         144 :     :token_streamer (pfile), filter (filter)
     437                 :             :     {
     438                 :             :     }
     439                 :             : };
     440                 :             : 
     441                 :             : static void
     442                 :        3816 : directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
     443                 :             : {
     444                 :        3816 :   va_list args;
     445                 :        3816 :   va_start (args, data_);
     446                 :             : 
     447                 :        3816 :   do_streamer *streamer = reinterpret_cast <do_streamer *> (data_);
     448                 :        3816 :   switch (task)
     449                 :             :     {
     450                 :           0 :     default:
     451                 :           0 :       gcc_unreachable ();
     452                 :             : 
     453                 :         822 :     case CPP_DO_print:
     454                 :         822 :       if (!flag_no_output)
     455                 :             :         {
     456                 :         729 :           print.src_line += va_arg (args, unsigned);
     457                 :             : 
     458                 :         729 :           const void *buf = va_arg (args, const void *);
     459                 :         729 :           size_t size = va_arg (args, size_t);
     460                 :         729 :           fwrite (buf, 1, size, print.outf);
     461                 :             :         }
     462                 :             :       break;
     463                 :             : 
     464                 :        1604 :     case CPP_DO_location:
     465                 :        1604 :       if (!flag_no_output)
     466                 :        1406 :         maybe_print_line (va_arg (args, location_t));
     467                 :             :       break;
     468                 :             : 
     469                 :        1390 :     case CPP_DO_token:
     470                 :        1390 :       {
     471                 :        1390 :         const cpp_token *token = va_arg (args, const cpp_token *);
     472                 :        1390 :         unsigned flags = 0;
     473                 :        1390 :         if (streamer->filter)
     474                 :         165 :           flags = lang_hooks.preprocess_token (pfile, token, streamer->filter);
     475                 :        1390 :         if (!flag_no_output)
     476                 :             :           {
     477                 :        1339 :             location_t spelling_loc = va_arg (args, location_t);
     478                 :        1339 :             streamer->stream (pfile, token, spelling_loc);
     479                 :        1339 :             if (flags & lang_hooks::PT_begin_pragma)
     480                 :          24 :               streamer->begin_pragma ();
     481                 :             :           }
     482                 :             :       }
     483                 :             :       break;
     484                 :             :     }
     485                 :             : 
     486                 :        3816 :   va_end (args);
     487                 :        3816 : }
     488                 :             : 
     489                 :             : /* Writes out the preprocessed file, handling spacing and paste
     490                 :             :    avoidance issues.  */
     491                 :             : static void
     492                 :          72 : scan_translation_unit_directives_only (cpp_reader *pfile)
     493                 :             : {
     494                 :          72 :   uintptr_t filter = 0;
     495                 :          72 :   if (lang_hooks.preprocess_token)
     496                 :          56 :     filter = lang_hooks.preprocess_token (pfile, NULL, filter);
     497                 :          72 :   do_streamer streamer (pfile, filter);
     498                 :          72 :   cpp_directive_only_process (pfile, &streamer, directives_only_cb);
     499                 :          72 :   if (streamer.filter)
     500                 :          18 :     lang_hooks.preprocess_token (pfile, NULL, streamer.filter);
     501                 :          72 : }
     502                 :             : 
     503                 :             : /* Adjust print.src_line for newlines embedded in output.  For example, if a raw
     504                 :             :    string literal contains newlines, then we need to increment our notion of the
     505                 :             :    current line to keep in sync and avoid outputting a line marker
     506                 :             :    unnecessarily.  If a raw string literal containing newlines is the result of
     507                 :             :    macro expansion, then we have the opposite problem, where the token takes up
     508                 :             :    more lines in the output than it did in the input, and hence a line marker is
     509                 :             :    needed to restore the correct state for subsequent lines.  In this case,
     510                 :             :    incrementing print.src_line still does the job, because it will cause us to
     511                 :             :    emit the line marker the next time a token is streamed.  */
     512                 :             : static void
     513                 :      575644 : account_for_newlines (const unsigned char *str, size_t len)
     514                 :             : {
     515                 :     2778323 :   while (len--)
     516                 :     2202679 :     if (*str++ == '\n')
     517                 :         654 :       print.src_line++;
     518                 :      575644 : }
     519                 :             : 
     520                 :             : /* Writes out a traditionally preprocessed file.  */
     521                 :             : static void
     522                 :        2349 : scan_translation_unit_trad (cpp_reader *pfile)
     523                 :             : {
     524                 :      451204 :   while (_cpp_read_logical_line_trad (pfile))
     525                 :             :     {
     526                 :      446506 :       size_t len = pfile->out.cur - pfile->out.base;
     527                 :      446506 :       maybe_print_line (pfile->out.first_line);
     528                 :      446506 :       fwrite (pfile->out.base, 1, len, print.outf);
     529                 :      446506 :       print.printed = true;
     530                 :      446506 :       if (!CPP_OPTION (pfile, discard_comments))
     531                 :         175 :         account_for_newlines (pfile->out.base, len);
     532                 :             :     }
     533                 :        2349 : }
     534                 :             : 
     535                 :             : /* If the token read on logical line LINE needs to be output on a
     536                 :             :    different line to the current one, output the required newlines or
     537                 :             :    a line marker.  If a line marker was emitted, return TRUE otherwise
     538                 :             :    return FALSE.  */
     539                 :             : 
     540                 :             : static bool
     541                 :     4861465 : maybe_print_line_1 (location_t src_loc, FILE *stream)
     542                 :             : {
     543                 :     4861465 :   bool emitted_line_marker = false;
     544                 :     4861465 :   unsigned src_line = LOCATION_LINE (src_loc);
     545                 :     4861465 :   const char *src_file = LOCATION_FILE (src_loc);
     546                 :             : 
     547                 :             :   /* End the previous line of text.  */
     548                 :     4861465 :   if (print.printed)
     549                 :             :     {
     550                 :     4574420 :       putc ('\n', stream);
     551                 :     4574420 :       print.src_line++;
     552                 :     4574420 :       print.printed = false;
     553                 :             :     }
     554                 :             : 
     555                 :     4861465 :   if (!flag_no_line_commands
     556                 :     4849837 :       && src_line >= print.src_line
     557                 :     4736994 :       && src_line < print.src_line + 8
     558                 :     4598316 :       && src_loc != UNKNOWN_LOCATION
     559                 :     4598314 :       && strcmp (src_file, print.src_file) == 0)
     560                 :             :     {
     561                 :     6126764 :       while (src_line > print.src_line)
     562                 :             :         {
     563                 :     1528450 :           putc ('\n', stream);
     564                 :     1528450 :           print.src_line++;
     565                 :             :         }
     566                 :             :     }
     567                 :             :   else
     568                 :      263151 :     emitted_line_marker = print_line_1 (src_loc, "", stream);
     569                 :             : 
     570                 :     4861465 :   return emitted_line_marker;
     571                 :             : }
     572                 :             : 
     573                 :             : /* If the token read on logical line LINE needs to be output on a
     574                 :             :    different line to the current one, output the required newlines or
     575                 :             :    a line marker.  If a line marker was emitted, return TRUE otherwise
     576                 :             :    return FALSE.  */
     577                 :             : 
     578                 :             : static bool
     579                 :     4861465 : maybe_print_line (location_t src_loc)
     580                 :             : {
     581                 :     4861465 :   if (cpp_get_options (parse_in)->debug)
     582                 :           2 :     linemap_dump_location (line_table, src_loc,
     583                 :             :                            print.outf);
     584                 :     4861465 :   return maybe_print_line_1 (src_loc, print.outf);
     585                 :             : }
     586                 :             : 
     587                 :             : /* Output a line marker for logical line LINE.  Special flags are "1"
     588                 :             :    or "2" indicating entering or leaving a file.  If the line marker
     589                 :             :    was effectively emitted, return TRUE otherwise return FALSE.  */
     590                 :             : 
     591                 :             : static bool
     592                 :      390414 : print_line_1 (location_t src_loc, const char *special_flags, FILE *stream)
     593                 :             : {
     594                 :      390414 :   bool emitted_line_marker = false;
     595                 :             : 
     596                 :             :   /* End any previous line of text.  */
     597                 :      390414 :   if (print.printed)
     598                 :       19109 :     putc ('\n', stream);
     599                 :      390414 :   print.printed = false;
     600                 :             : 
     601                 :      390414 :   if (src_loc != UNKNOWN_LOCATION && !flag_no_line_commands)
     602                 :             :     {
     603                 :      350545 :       const char *file_path = LOCATION_FILE (src_loc);
     604                 :      350545 :       size_t to_file_len = strlen (file_path);
     605                 :      350545 :       unsigned char *to_file_quoted =
     606                 :      350545 :          (unsigned char *) alloca (to_file_len * 4 + 1);
     607                 :             : 
     608                 :             :       /* cpp_quote_string does not nul-terminate, so we have to do it
     609                 :             :          ourselves.  */
     610                 :      350545 :       unsigned char *p = cpp_quote_string (to_file_quoted,
     611                 :             :                                            (const unsigned char *) file_path,
     612                 :             :                                            to_file_len);
     613                 :      350545 :       *p = '\0';
     614                 :             : 
     615                 :      350545 :       print.src_line = LOCATION_LINE (src_loc);
     616                 :      350545 :       print.src_file = file_path;
     617                 :             : 
     618                 :      350545 :       fprintf (stream, "# %u \"%s\"%s",
     619                 :             :                print.src_line, to_file_quoted, special_flags);
     620                 :             : 
     621                 :      350545 :       int sysp = in_system_header_at (src_loc);
     622                 :      350545 :       if (sysp == 2)
     623                 :      141479 :         fputs (" 3 4", stream);
     624                 :      209066 :       else if (sysp == 1)
     625                 :         712 :         fputs (" 3", stream);
     626                 :             : 
     627                 :      350545 :       putc ('\n', stream);
     628                 :      350545 :       emitted_line_marker = true;
     629                 :             :     }
     630                 :             : 
     631                 :      390414 :   return emitted_line_marker;
     632                 :             : }
     633                 :             : 
     634                 :             : /* Output a line marker for logical line LINE.  Special flags are "1"
     635                 :             :    or "2" indicating entering or leaving a file.  Return TRUE if a
     636                 :             :    line marker was effectively emitted, FALSE otherwise.  */
     637                 :             : 
     638                 :             : static bool
     639                 :      127263 : print_line (location_t src_loc, const char *special_flags)
     640                 :             : {
     641                 :      127263 :     if (cpp_get_options (parse_in)->debug)
     642                 :           6 :       linemap_dump_location (line_table, src_loc,
     643                 :             :                              print.outf);
     644                 :      127263 :     return print_line_1 (src_loc, special_flags, print.outf);
     645                 :             : }
     646                 :             : 
     647                 :             : /* Helper function for cb_line_change and scan_translation_unit.
     648                 :             :    Return TRUE if a line marker is emitted, FALSE otherwise.  */
     649                 :             : static bool
     650                 :     4170480 : do_line_change (cpp_reader *pfile, const cpp_token *token,
     651                 :             :                 location_t src_loc, int parsing_args)
     652                 :             : {
     653                 :     4170480 :   bool emitted_line_marker = false;
     654                 :     4170480 :   if (define_queue || undef_queue)
     655                 :          21 :     dump_queued_macros (pfile);
     656                 :             : 
     657                 :     4170480 :   if (token->type == CPP_EOF || parsing_args)
     658                 :             :     return false;
     659                 :             : 
     660                 :     4150305 :   emitted_line_marker = maybe_print_line (src_loc);
     661                 :     4150305 :   print.prev = 0;
     662                 :     4150305 :   print.source = 0;
     663                 :             : 
     664                 :             :   /* Supply enough spaces to put this token in its original column,
     665                 :             :      one space per column greater than 2, since scan_translation_unit
     666                 :             :      will provide a space if PREV_WHITE.  Don't bother trying to
     667                 :             :      reconstruct tabs; we can't get it right in general, and nothing
     668                 :             :      ought to care.  Some things do care; the fault lies with them.
     669                 :             : 
     670                 :             :      Also do not output the spaces if this is a CPP_PRAGMA token.  In this
     671                 :             :      case, libcpp has provided the location of the first token after #pragma,
     672                 :             :      so we would start at the wrong column.  */
     673                 :     4150305 :   if (!CPP_OPTION (pfile, traditional) && token->type != CPP_PRAGMA)
     674                 :             :     {
     675                 :     4122338 :       int spaces = LOCATION_COLUMN (src_loc) - 2;
     676                 :     4122338 :       print.printed = true;
     677                 :             : 
     678                 :    15735664 :       while (-- spaces >= 0)
     679                 :    11613326 :         putc (' ', print.outf);
     680                 :             :     }
     681                 :             : 
     682                 :             :   return emitted_line_marker;
     683                 :             : }
     684                 :             : 
     685                 :             : /* Called when a line of output is started.  TOKEN is the first token
     686                 :             :    of the line, and at end of file will be CPP_EOF.  */
     687                 :             : static void
     688                 :     4153845 : cb_line_change (cpp_reader *pfile, const cpp_token *token,
     689                 :             :                 int parsing_args)
     690                 :             : {
     691                 :     4153845 :   do_line_change (pfile, token, token->src_loc, parsing_args);
     692                 :     4153845 : }
     693                 :             : 
     694                 :             : static void
     695                 :           2 : cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
     696                 :             :           const cpp_string *str)
     697                 :             : {
     698                 :           2 :   maybe_print_line (line);
     699                 :           2 :   fprintf (print.outf, "#ident %s\n", str->text);
     700                 :           2 :   print.src_line++;
     701                 :           2 : }
     702                 :             : 
     703                 :             : static void
     704                 :      145205 : cb_define (cpp_reader *pfile, location_t line, cpp_hashnode *node)
     705                 :             : {
     706                 :      145205 :   const line_map_ordinary *map;
     707                 :             : 
     708                 :      145205 :   maybe_print_line (line);
     709                 :      145205 :   fputs ("#define ", print.outf);
     710                 :             : 
     711                 :             :   /* 'D' is whole definition; 'N' is name only.  */
     712                 :      145205 :   if (flag_dump_macros == 'D')
     713                 :       39359 :     fputs ((const char *) cpp_macro_definition (pfile, node),
     714                 :             :            print.outf);
     715                 :             :   else
     716                 :      105846 :     fputs ((const char *) NODE_NAME (node), print.outf);
     717                 :             : 
     718                 :      145205 :   putc ('\n', print.outf);
     719                 :      145205 :   print.printed = false;
     720                 :      145205 :   linemap_resolve_location (line_table, line,
     721                 :             :                             LRK_MACRO_DEFINITION_LOCATION,
     722                 :             :                             &map);
     723                 :      145205 :   print.src_line++;
     724                 :      145205 : }
     725                 :             : 
     726                 :             : static void
     727                 :        5463 : cb_undef (cpp_reader *pfile, location_t line, cpp_hashnode *node)
     728                 :             : {
     729                 :        5463 :   if (lang_hooks.preprocess_undef)
     730                 :           0 :     lang_hooks.preprocess_undef (pfile, line, node);
     731                 :        5463 :   maybe_print_line (line);
     732                 :        5463 :   fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
     733                 :        5463 :   print.src_line++;
     734                 :        5463 : }
     735                 :             : 
     736                 :             : static void
     737                 :          22 : cb_used_define (cpp_reader *pfile, location_t line ATTRIBUTE_UNUSED,
     738                 :             :                 cpp_hashnode *node)
     739                 :             : {
     740                 :          22 :   if (cpp_user_macro_p (node))
     741                 :             :     {
     742                 :          21 :       macro_queue *q;
     743                 :          21 :       q = XNEW (macro_queue);
     744                 :          21 :       q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node));
     745                 :          21 :       q->next = define_queue;
     746                 :          21 :       define_queue = q;
     747                 :             :     }
     748                 :          22 : }
     749                 :             : 
     750                 :             : static void
     751                 :          11 : cb_used_undef (cpp_reader *pfile ATTRIBUTE_UNUSED,
     752                 :             :                location_t line ATTRIBUTE_UNUSED,
     753                 :             :                cpp_hashnode *node)
     754                 :             : {
     755                 :          11 :   macro_queue *q;
     756                 :          11 :   q = XNEW (macro_queue);
     757                 :          11 :   q->macro = xstrdup ((const char *) NODE_NAME (node));
     758                 :          11 :   q->next = undef_queue;
     759                 :          11 :   undef_queue = q;
     760                 :          11 : }
     761                 :             : 
     762                 :             : static void
     763                 :        9294 : dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED)
     764                 :             : {
     765                 :        9294 :   macro_queue *q;
     766                 :             : 
     767                 :             :   /* End the previous line of text.  */
     768                 :        9294 :   if (print.printed)
     769                 :             :     {
     770                 :          12 :       putc ('\n', print.outf);
     771                 :          12 :       print.src_line++;
     772                 :          12 :       print.printed = false;
     773                 :             :     }
     774                 :             : 
     775                 :        9315 :   for (q = define_queue; q;)
     776                 :             :     {
     777                 :          21 :       macro_queue *oq;
     778                 :          21 :       fputs ("#define ", print.outf);
     779                 :          21 :       fputs (q->macro, print.outf);
     780                 :          21 :       putc ('\n', print.outf);
     781                 :          21 :       print.printed = false;
     782                 :          21 :       print.src_line++;
     783                 :          21 :       oq = q;
     784                 :          21 :       q = q->next;
     785                 :          21 :       free (oq->macro);
     786                 :          21 :       free (oq);
     787                 :             :     }
     788                 :        9294 :   define_queue = NULL;
     789                 :        9305 :   for (q = undef_queue; q;)
     790                 :             :     {
     791                 :          11 :       macro_queue *oq;
     792                 :          11 :       fprintf (print.outf, "#undef %s\n", q->macro);
     793                 :          11 :       print.src_line++;
     794                 :          11 :       oq = q;
     795                 :          11 :       q = q->next;
     796                 :          11 :       free (oq->macro);
     797                 :          11 :       free (oq);
     798                 :             :     }
     799                 :        9294 :   undef_queue = NULL;
     800                 :        9294 : }
     801                 :             : 
     802                 :             : static void
     803                 :           1 : cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
     804                 :             :             const unsigned char *dir, const char *header, int angle_brackets,
     805                 :             :             const cpp_token **comments)
     806                 :             : {
     807                 :           1 :   maybe_print_line (line);
     808                 :           1 :   if (angle_brackets)
     809                 :           0 :     fprintf (print.outf, "#%s <%s>", dir, header);
     810                 :             :   else
     811                 :           1 :     fprintf (print.outf, "#%s \"%s\"", dir, header);
     812                 :             : 
     813                 :           1 :   if (comments != NULL)
     814                 :             :     {
     815                 :           2 :       while (*comments != NULL)
     816                 :             :         {
     817                 :           1 :           if ((*comments)->flags & PREV_WHITE)
     818                 :           1 :             putc (' ', print.outf);
     819                 :           1 :           cpp_output_token (*comments, print.outf);
     820                 :           1 :           ++comments;
     821                 :             :         }
     822                 :             :     }
     823                 :             : 
     824                 :           1 :   putc ('\n', print.outf);
     825                 :           1 :   print.printed = false;
     826                 :           1 :   print.src_line++;
     827                 :           1 : }
     828                 :             : 
     829                 :             : /* Callback called when -fworking-director and -E to emit working
     830                 :             :    directory in cpp output file.  */
     831                 :             : 
     832                 :             : void
     833                 :        2046 : pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
     834                 :             : {
     835                 :        2046 :   size_t to_file_len = strlen (dir);
     836                 :        2046 :   unsigned char *to_file_quoted =
     837                 :        2046 :      (unsigned char *) alloca (to_file_len * 4 + 1);
     838                 :        2046 :   unsigned char *p;
     839                 :             : 
     840                 :             :   /* cpp_quote_string does not nul-terminate, so we have to do it ourselves.  */
     841                 :        2046 :   p = cpp_quote_string (to_file_quoted, (const unsigned char *) dir, to_file_len);
     842                 :        2046 :   *p = '\0';
     843                 :        2046 :   fprintf (print.outf, "# 1 \"%s//\"\n", to_file_quoted);
     844                 :        2046 : }
     845                 :             : 
     846                 :             : /* The file name, line number or system header flags have changed, as
     847                 :             :    described in MAP.  */
     848                 :             : 
     849                 :             : void
     850                 :      138179 : pp_file_change (const line_map_ordinary *map)
     851                 :             : {
     852                 :      138179 :   const char *flags = "";
     853                 :             : 
     854                 :      138179 :   if (flag_no_line_commands)
     855                 :             :     return;
     856                 :             : 
     857                 :      132996 :   if (map != NULL)
     858                 :             :     {
     859                 :      127273 :       input_location = map->start_location;
     860                 :      127273 :       if (print.first_time)
     861                 :             :         {
     862                 :             :           /* Avoid printing foo.i when the main file is foo.c.  */
     863                 :        5907 :           if (!cpp_get_options (parse_in)->preprocessed)
     864                 :        5897 :             print_line (map->start_location, flags);
     865                 :        5907 :           print.first_time = 0;
     866                 :             :         }
     867                 :             :       else
     868                 :             :         {
     869                 :             :           /* Bring current file to correct line when entering a new file.  */
     870                 :      121366 :           if (map->reason == LC_ENTER)
     871                 :             :             {
     872                 :       51794 :               maybe_print_line (linemap_included_from (map));
     873                 :       51794 :               flags = " 1";
     874                 :             :             }
     875                 :       69572 :           else if (map->reason == LC_LEAVE)
     876                 :       51790 :             flags = " 2";
     877                 :      121366 :           print_line (map->start_location, flags);
     878                 :             :         }
     879                 :             :     }
     880                 :             : }
     881                 :             : 
     882                 :             : /* Copy a #pragma directive to the preprocessed output.  */
     883                 :             : static void
     884                 :        4197 : cb_def_pragma (cpp_reader *pfile, location_t line)
     885                 :             : {
     886                 :        4197 :   maybe_print_line (line);
     887                 :        4197 :   fputs ("#pragma ", print.outf);
     888                 :        4197 :   cpp_output_line (pfile, print.outf);
     889                 :        4197 :   print.printed = false;
     890                 :        4197 :   print.src_line++;
     891                 :        4197 : }
     892                 :             : 
     893                 :             : /* Stream a token as if we had seen it directly ourselves; needed
     894                 :             :    in case a token was lexed externally, e.g. while processing a
     895                 :             :    pragma.  */
     896                 :             : void
     897                 :       63557 : c_pp_stream_token (cpp_reader *pfile, const cpp_token *tok, location_t loc)
     898                 :             : {
     899                 :       63557 :   gcc_assert (print.streamer);
     900                 :       63557 :   print.streamer->stream (pfile, tok, loc);
     901                 :       63557 : }
     902                 :             : 
     903                 :             : /* Dump out the hash table.  */
     904                 :             : static int
     905                 :      331989 : dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
     906                 :             : {
     907                 :      331989 :   if (cpp_user_macro_p (node))
     908                 :             :     {
     909                 :       54244 :       fputs ("#define ", print.outf);
     910                 :       54244 :       fputs ((const char *) cpp_macro_definition (pfile, node),
     911                 :             :              print.outf);
     912                 :       54244 :       putc ('\n', print.outf);
     913                 :       54244 :       print.printed = false;
     914                 :       54244 :       print.src_line++;
     915                 :             :     }
     916                 :             : 
     917                 :      331989 :   return 1;
     918                 :             : }
     919                 :             : 
     920                 :             : /* Load in the PCH file NAME, open on FD.  It was originally searched for
     921                 :             :    by ORIG_NAME.  Also, print out a #include command so that the PCH
     922                 :             :    file can be loaded when the preprocessed output is compiled.  */
     923                 :             : 
     924                 :             : static void
     925                 :          24 : cb_read_pch (cpp_reader *pfile, const char *name,
     926                 :             :              int fd, const char *orig_name ATTRIBUTE_UNUSED)
     927                 :             : {
     928                 :          24 :   c_common_read_pch (pfile, name, fd, orig_name);
     929                 :             : 
     930                 :          24 :   fprintf (print.outf, "#pragma GCC pch_preprocess \"%s\"\n", name);
     931                 :          24 :   print.src_line++;
     932                 :             : 
     933                 :             :   /* The process of reading the PCH has destroyed the frontend parser,
     934                 :             :      so ask the frontend to reinitialize it, in case we need it to
     935                 :             :      process any #pragma directives encountered while preprocessing.  */
     936                 :          24 :   c_init_preprocess ();
     937                 :          24 : }
        

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.