LCOV - code coverage report
Current view: top level - gcc/c-family - c-pragma.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 88.2 % 797 703
Test Date: 2026-02-28 14:20:25 Functions: 95.7 % 47 45
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Handle #pragma, system V.4 style.  Supports #pragma weak and #pragma pack.
       2              :    Copyright (C) 1992-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : #include "config.h"
      21              : #include "system.h"
      22              : #include "coretypes.h"
      23              : #include "target.h"
      24              : #include "function.h"         /* For cfun.  */
      25              : #include "c-common.h"
      26              : #include "memmodel.h"
      27              : #include "tm_p.h"             /* For REGISTER_TARGET_PRAGMAS.  */
      28              : #include "stringpool.h"
      29              : #include "cgraph.h"
      30              : #include "diagnostic.h"
      31              : #include "attribs.h"
      32              : #include "varasm.h"
      33              : #include "c-pragma.h"
      34              : #include "opts.h"
      35              : #include "plugin.h"
      36              : #include "opt-suggestions.h"
      37              : 
      38              : #define GCC_BAD(gmsgid) \
      39              :   do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
      40              : #define GCC_BAD2(gmsgid, arg) \
      41              :   do { warning (OPT_Wpragmas, gmsgid, arg); return; } while (0)
      42              : #define GCC_BAD_AT(loc, gmsgid)                                 \
      43              :   do { warning_at (loc, OPT_Wpragmas, gmsgid); return; } while (0)
      44              : #define GCC_BAD2_AT(loc, gmsgid, arg)                   \
      45              :   do { warning_at (loc, OPT_Wpragmas, gmsgid, arg); return; } while (0)
      46              : 
      47              : struct GTY(()) align_stack {
      48              :   int                  alignment;
      49              :   tree                 id;
      50              :   struct align_stack * prev;
      51              : };
      52              : 
      53              : static GTY(()) struct align_stack * alignment_stack;
      54              : 
      55              : static void handle_pragma_pack (cpp_reader *);
      56              : 
      57              : /* If we have a "global" #pragma pack(<n>) in effect when the first
      58              :    #pragma pack(push,<n>) is encountered, this stores the value of
      59              :    maximum_field_alignment in effect.  When the final pop_alignment()
      60              :    happens, we restore the value to this, not to a value of 0 for
      61              :    maximum_field_alignment.  Value is in bits.  */
      62              : static int default_alignment;
      63              : #define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = *(alignment_stack == NULL \
      64              :         ? &default_alignment \
      65              :         : &alignment_stack->alignment) = (ALIGN))
      66              : 
      67              : static void push_alignment (int, tree);
      68              : static void pop_alignment (tree);
      69              : 
      70              : /* Push an alignment value onto the stack.  */
      71              : static void
      72           22 : push_alignment (int alignment, tree id)
      73              : {
      74           22 :   align_stack * entry = ggc_alloc<align_stack> ();
      75              : 
      76           22 :   entry->alignment  = alignment;
      77           22 :   entry->id      = id;
      78           22 :   entry->prev            = alignment_stack;
      79              : 
      80              :   /* The current value of maximum_field_alignment is not necessarily
      81              :      0 since there may be a #pragma pack(<n>) in effect; remember it
      82              :      so that we can restore it after the final #pragma pop().  */
      83           22 :   if (alignment_stack == NULL)
      84           19 :     default_alignment = maximum_field_alignment;
      85              : 
      86           22 :   alignment_stack = entry;
      87              : 
      88           22 :   maximum_field_alignment = alignment;
      89           22 : }
      90              : 
      91              : /* Undo a push of an alignment onto the stack.  */
      92              : static void
      93           24 : pop_alignment (tree id)
      94              : {
      95           24 :   align_stack * entry;
      96              : 
      97           24 :   if (alignment_stack == NULL)
      98            2 :     GCC_BAD ("%<#pragma pack (pop)%> encountered without matching "
      99              :              "%<#pragma pack (push)%>");
     100              : 
     101              :   /* If we got an identifier, strip away everything above the target
     102              :      entry so that the next step will restore the state just below it.  */
     103           22 :   if (id)
     104              :     {
     105            9 :       for (entry = alignment_stack; entry; entry = entry->prev)
     106            6 :         if (entry->id == id)
     107              :           {
     108            2 :             alignment_stack = entry;
     109            2 :             break;
     110              :           }
     111            5 :       if (entry == NULL)
     112            3 :         warning (OPT_Wpragmas,
     113              :                  "%<#pragma pack(pop, %E)%> encountered without matching "
     114              :                  "%<#pragma pack(push, %E)%>"
     115              :                  , id, id);
     116              :     }
     117              : 
     118           22 :   entry = alignment_stack->prev;
     119              : 
     120           22 :   maximum_field_alignment = entry ? entry->alignment : default_alignment;
     121              : 
     122           22 :   alignment_stack = entry;
     123              : }
     124              : 
     125              : /* #pragma pack ()
     126              :    #pragma pack (N)
     127              : 
     128              :    #pragma pack (push)
     129              :    #pragma pack (push, N)
     130              :    #pragma pack (push, ID)
     131              :    #pragma pack (push, ID, N)
     132              :    #pragma pack (pop)
     133              :    #pragma pack (pop, ID) */
     134              : static void
     135          187 : handle_pragma_pack (cpp_reader *)
     136              : {
     137          187 :   location_t loc;
     138          187 :   tree x, id = 0;
     139          187 :   int align = -1;
     140          187 :   enum cpp_ttype token;
     141          187 :   enum { set, push, pop } action;
     142              : 
     143          187 :   if (pragma_lex (&x) != CPP_OPEN_PAREN)
     144           13 :     GCC_BAD ("missing %<(%> after %<#pragma pack%> - ignored");
     145              : 
     146          186 :   token = pragma_lex (&x, &loc);
     147          186 :   if (token == CPP_CLOSE_PAREN)
     148              :     {
     149           15 :       action = set;
     150           15 :       align = initial_max_fld_align;
     151              :     }
     152          171 :   else if (token == CPP_NUMBER)
     153              :     {
     154          116 :       if (TREE_CODE (x) != INTEGER_CST)
     155            2 :         GCC_BAD_AT (loc, "invalid constant in %<#pragma pack%> - ignored");
     156          114 :       align = TREE_INT_CST_LOW (x);
     157          114 :       action = set;
     158          114 :       if (pragma_lex (&x) != CPP_CLOSE_PAREN)
     159            1 :         GCC_BAD ("malformed %<#pragma pack%> - ignored");
     160              :     }
     161           55 :   else if (token == CPP_NAME)
     162              :     {
     163              : #define GCC_BAD_ACTION do { if (action != pop) \
     164              :           GCC_BAD ("malformed %<#pragma pack(push[, id][, <n>])%> - ignored"); \
     165              :         else \
     166              :           GCC_BAD ("malformed %<#pragma pack(pop[, id])%> - ignored"); \
     167              :         } while (0)
     168              : 
     169           54 :       const char *op = IDENTIFIER_POINTER (x);
     170           54 :       if (!strcmp (op, "push"))
     171              :         action = push;
     172           28 :       else if (!strcmp (op, "pop"))
     173              :         action = pop;
     174              :       else
     175            3 :         GCC_BAD2_AT (loc, "unknown action %qE for %<#pragma pack%> - ignored",
     176              :                      x);
     177              : 
     178           75 :       while ((token = pragma_lex (&x)) == CPP_COMMA)
     179              :         {
     180           28 :           token = pragma_lex (&x, &loc);
     181           28 :           if (token == CPP_NAME && id == 0)
     182              :             {
     183           16 :               id = x;
     184              :             }
     185           12 :           else if (token == CPP_NUMBER && action == push && align == -1)
     186              :             {
     187           11 :               if (TREE_CODE (x) != INTEGER_CST)
     188            3 :                 GCC_BAD_AT (loc,
     189              :                             "invalid constant in %<#pragma pack%> - ignored");
     190            8 :               align = TREE_INT_CST_LOW (x);
     191            8 :               if (align == -1)
     192            0 :                 action = set;
     193              :             }
     194              :           else
     195           76 :             GCC_BAD_ACTION;
     196              :         }
     197              : 
     198           47 :       if (token != CPP_CLOSE_PAREN)
     199            0 :         GCC_BAD_ACTION;
     200              : #undef GCC_BAD_ACTION
     201              :     }
     202              :   else
     203            1 :     GCC_BAD ("malformed %<#pragma pack%> - ignored");
     204              : 
     205          175 :   if (pragma_lex (&x, &loc) != CPP_EOF)
     206            1 :     warning_at (loc, OPT_Wpragmas, "junk at end of %<#pragma pack%>");
     207              : 
     208          175 :   if (flag_pack_struct)
     209            0 :     GCC_BAD ("%<#pragma pack%> has no effect with %<-fpack-struct%> - ignored");
     210              : 
     211          175 :   if (action != pop)
     212          151 :     switch (align)
     213              :       {
     214          135 :       case 0:
     215          135 :       case 1:
     216          135 :       case 2:
     217          135 :       case 4:
     218          135 :       case 8:
     219          135 :       case 16:
     220          135 :         align *= BITS_PER_UNIT;
     221          135 :         break;
     222           15 :       case -1:
     223           15 :         if (action == push)
     224              :           {
     225           15 :             align = maximum_field_alignment;
     226           15 :             break;
     227              :           }
     228              :         /* FALLTHRU */
     229            1 :       default:
     230            1 :         GCC_BAD2 ("alignment must be a small power of two, not %d", align);
     231              :       }
     232              : 
     233          150 :   switch (action)
     234              :     {
     235          128 :     case set:   SET_GLOBAL_ALIGNMENT (align);  break;
     236           22 :     case push:  push_alignment (align, id);    break;
     237           24 :     case pop:   pop_alignment (id);            break;
     238              :     }
     239              : }
     240              : 
     241              : struct GTY(()) pending_weak
     242              : {
     243              :   tree name;
     244              :   tree value;
     245              : };
     246              : 
     247              : 
     248              : static GTY(()) vec<pending_weak, va_gc> *pending_weaks;
     249              : 
     250              : static void apply_pragma_weak (tree, tree);
     251              : static void handle_pragma_weak (cpp_reader *);
     252              : 
     253              : static void
     254           97 : apply_pragma_weak (tree decl, tree value)
     255              : {
     256           97 :   if (value)
     257              :     {
     258            7 :       value = build_string (IDENTIFIER_LENGTH (value),
     259            7 :                             IDENTIFIER_POINTER (value));
     260            7 :       decl_attributes (&decl, build_tree_list (get_identifier ("alias"),
     261              :                                                build_tree_list (NULL, value)),
     262              :                        0);
     263              :     }
     264              : 
     265          176 :   if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
     266           17 :       && !DECL_WEAK (decl) /* Don't complain about a redundant #pragma.  */
     267            3 :       && DECL_ASSEMBLER_NAME_SET_P (decl)
     268           97 :       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
     269            0 :     warning (OPT_Wpragmas, "applying %<#pragma weak %+D%> after first use "
     270              :              "results in unspecified behavior", decl);
     271              : 
     272           97 :   declare_weak (decl);
     273           97 : }
     274              : 
     275              : void
     276    240510984 : maybe_apply_pragma_weak (tree decl)
     277              : {
     278    240510984 :   tree id;
     279    240510984 :   int i;
     280    240510984 :   pending_weak *pe;
     281              : 
     282              :   /* Avoid asking for DECL_ASSEMBLER_NAME when it's not needed.  */
     283              : 
     284              :   /* No weak symbols pending, take the short-cut.  */
     285    240510984 :   if (vec_safe_is_empty (pending_weaks))
     286    240510984 :     return;
     287              :   /* If it's not visible outside this file, it doesn't matter whether
     288              :      it's weak.  */
     289          683 :   if (!DECL_EXTERNAL (decl) && !TREE_PUBLIC (decl))
     290              :     return;
     291              :   /* If it's not a function or a variable, it can't be weak.
     292              :      FIXME: what kinds of things are visible outside this file but
     293              :      aren't functions or variables?   Should this be an assert instead?  */
     294          114 :   if (!VAR_OR_FUNCTION_DECL_P (decl))
     295              :     return;
     296              : 
     297          114 :   if (DECL_ASSEMBLER_NAME_SET_P (decl))
     298            7 :     id = DECL_ASSEMBLER_NAME (decl);
     299              :   else
     300              :     {
     301          107 :       id = DECL_ASSEMBLER_NAME (decl);
     302          107 :       SET_DECL_ASSEMBLER_NAME (decl, NULL_TREE);
     303              :     }
     304              : 
     305          203 :   FOR_EACH_VEC_ELT (*pending_weaks, i, pe)
     306          114 :     if (id == pe->name)
     307              :       {
     308           25 :         apply_pragma_weak (decl, pe->value);
     309           25 :         pending_weaks->unordered_remove (i);
     310           25 :         break;
     311              :       }
     312              : }
     313              : 
     314              : /* Process all "#pragma weak A = B" directives where we have not seen
     315              :    a decl for A.  */
     316              : void
     317       200660 : maybe_apply_pending_pragma_weaks (void)
     318              : {
     319       200660 :   tree alias_id, id, decl;
     320       200660 :   int i;
     321       200660 :   pending_weak *pe;
     322       200660 :   symtab_node *target;
     323              : 
     324       200660 :   if (vec_safe_is_empty (pending_weaks))
     325       200660 :     return;
     326              : 
     327           42 :   FOR_EACH_VEC_ELT (*pending_weaks, i, pe)
     328              :     {
     329           21 :       alias_id = pe->name;
     330           21 :       id = pe->value;
     331              : 
     332           21 :       if (id == NULL)
     333           16 :         continue;
     334              : 
     335            5 :       target = symtab_node::get_for_asmname (id);
     336           10 :       decl = build_decl (UNKNOWN_LOCATION,
     337            5 :                          target ? TREE_CODE (target->decl) : FUNCTION_DECL,
     338              :                          alias_id, default_function_type);
     339              : 
     340            5 :       DECL_ARTIFICIAL (decl) = 1;
     341            5 :       TREE_PUBLIC (decl) = 1;
     342            5 :       DECL_WEAK (decl) = 1;
     343            5 :       if (VAR_P (decl))
     344            1 :         TREE_STATIC (decl) = 1;
     345            5 :       if (!target)
     346              :         {
     347            0 :           error ("%q+D aliased to undefined symbol %qE",
     348              :                  decl, id);
     349            0 :           continue;
     350              :         }
     351              : 
     352            5 :       assemble_alias (decl, id);
     353              :     }
     354              : }
     355              : 
     356              : /* #pragma weak name [= value] */
     357              : static void
     358          122 : handle_pragma_weak (cpp_reader *)
     359              : {
     360          122 :   tree name, value, x, decl;
     361          122 :   enum cpp_ttype t;
     362              : 
     363          122 :   value = 0;
     364              : 
     365          122 :   if (pragma_lex (&name) != CPP_NAME)
     366            4 :     GCC_BAD ("malformed %<#pragma weak%>, ignored");
     367          122 :   t = pragma_lex (&x);
     368          122 :   if (t == CPP_EQ)
     369              :     {
     370           16 :       if (pragma_lex (&value) != CPP_NAME)
     371            3 :         GCC_BAD ("malformed %<#pragma weak%>, ignored");
     372           13 :       t = pragma_lex (&x);
     373              :     }
     374          119 :   if (t != CPP_EOF)
     375            0 :     warning (OPT_Wpragmas, "junk at end of %<#pragma weak%>");
     376              : 
     377          119 :   decl = identifier_global_value (name);
     378          119 :   if (decl && DECL_P (decl))
     379              :     {
     380           73 :       if (!VAR_OR_FUNCTION_DECL_P (decl))
     381            1 :         GCC_BAD2 ("%<#pragma weak%> declaration of %q+D not allowed,"
     382              :                   " ignored", decl);
     383           72 :       apply_pragma_weak (decl, value);
     384           72 :       if (value)
     385              :         {
     386            3 :           DECL_EXTERNAL (decl) = 0;
     387            3 :           if (VAR_P (decl))
     388            2 :             TREE_STATIC (decl) = 1;
     389            3 :           assemble_alias (decl, value);
     390              :         }
     391              :     }
     392              :   else
     393              :     {
     394           46 :       pending_weak pe = {name, value};
     395           46 :       vec_safe_push (pending_weaks, pe);
     396              :     }
     397              : }
     398              : 
     399              : static enum scalar_storage_order_kind global_sso;
     400              : 
     401              : void
     402      1177591 : maybe_apply_pragma_scalar_storage_order (tree type)
     403              : {
     404      1177591 :   if (global_sso == SSO_NATIVE)
     405              :     return;
     406              : 
     407           11 :   gcc_assert (RECORD_OR_UNION_TYPE_P (type));
     408              : 
     409           11 :   if (lookup_attribute ("scalar_storage_order", TYPE_ATTRIBUTES (type)))
     410              :     return;
     411              : 
     412            9 :   if (global_sso == SSO_BIG_ENDIAN)
     413            5 :     TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
     414            4 :   else if (global_sso == SSO_LITTLE_ENDIAN)
     415            4 :     TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN;
     416              :   else
     417            0 :     gcc_unreachable ();
     418              : }
     419              : 
     420              : static void
     421           12 : handle_pragma_scalar_storage_order (cpp_reader *)
     422              : {
     423           12 :   const char *kind_string;
     424           12 :   enum cpp_ttype token;
     425           12 :   tree x;
     426              : 
     427           12 :   if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
     428              :     {
     429              :       error ("%<scalar_storage_order%> is not supported because endianness "
     430              :              "is not uniform");
     431            5 :       return;
     432              :     }
     433              : 
     434           12 :   if (c_dialect_cxx ())
     435              :     {
     436            3 :       if (warn_unknown_pragmas > in_system_header_at (input_location))
     437            3 :         warning (OPT_Wunknown_pragmas,
     438              :                  "%<#pragma scalar_storage_order%> is not supported for C++");
     439            3 :       return;
     440              :     }
     441              : 
     442            9 :   token = pragma_lex (&x);
     443            9 :   if (token != CPP_NAME)
     444            1 :     GCC_BAD ("missing %<big-endian%>, %<little-endian%>, or %<default%> after "
     445              :              "%<#pragma scalar_storage_order%>");
     446            8 :   kind_string = IDENTIFIER_POINTER (x);
     447            8 :   if (strcmp (kind_string, "default") == 0)
     448            3 :     global_sso = default_sso;
     449            5 :   else if (strcmp (kind_string, "big") == 0)
     450            2 :     global_sso = SSO_BIG_ENDIAN;
     451            3 :   else if (strcmp (kind_string, "little") == 0)
     452            2 :     global_sso = SSO_LITTLE_ENDIAN;
     453              :   else
     454            8 :     GCC_BAD ("expected %<big-endian%>, %<little-endian%>, or %<default%> after "
     455              :              "%<#pragma scalar_storage_order%>");
     456              : }
     457              : 
     458              : /* GCC supports two #pragma directives for renaming the external
     459              :    symbol associated with a declaration (DECL_ASSEMBLER_NAME), for
     460              :    compatibility with the Solaris and VMS system headers.  GCC also
     461              :    has its own notation for this, __asm__("name") annotations.
     462              : 
     463              :    Corner cases of these features and their interaction:
     464              : 
     465              :    1) Both pragmas silently apply only to declarations with external
     466              :       linkage (that is, TREE_PUBLIC || DECL_EXTERNAL).  Asm labels
     467              :       do not have this restriction.
     468              : 
     469              :    2) In C++, both #pragmas silently apply only to extern "C" declarations.
     470              :       Asm labels do not have this restriction.
     471              : 
     472              :    3) If any of the three ways of changing DECL_ASSEMBLER_NAME is
     473              :       applied to a decl whose DECL_ASSEMBLER_NAME is already set, and the
     474              :       new name is different, a warning issues and the name does not change.
     475              : 
     476              :    4) The "source name" for #pragma redefine_extname is the DECL_NAME,
     477              :       *not* the DECL_ASSEMBLER_NAME.
     478              : 
     479              :    5) If #pragma extern_prefix is in effect and a declaration occurs
     480              :       with an __asm__ name, the #pragma extern_prefix is silently
     481              :       ignored for that declaration.
     482              : 
     483              :    6) If #pragma extern_prefix and #pragma redefine_extname apply to
     484              :       the same declaration, whichever triggered first wins, and a warning
     485              :       is issued.  (We would like to have #pragma redefine_extname always
     486              :       win, but it can appear either before or after the declaration, and
     487              :       if it appears afterward, we have no way of knowing whether a modified
     488              :       DECL_ASSEMBLER_NAME is due to #pragma extern_prefix.)  */
     489              : 
     490              : struct GTY(()) pending_redefinition {
     491              :   tree oldname;
     492              :   tree newname;
     493              : };
     494              : 
     495              : 
     496              : static GTY(()) vec<pending_redefinition, va_gc> *pending_redefine_extname;
     497              : 
     498              : static void handle_pragma_redefine_extname (cpp_reader *);
     499              : 
     500              : /* #pragma redefine_extname oldname newname */
     501              : static void
     502           26 : handle_pragma_redefine_extname (cpp_reader *)
     503              : {
     504           26 :   tree oldname, newname, decls, x;
     505           26 :   enum cpp_ttype t;
     506           26 :   bool found;
     507              : 
     508           26 :   if (pragma_lex (&oldname) != CPP_NAME)
     509            3 :     GCC_BAD ("malformed %<#pragma redefine_extname%>, ignored");
     510           25 :   if (pragma_lex (&newname) != CPP_NAME)
     511            2 :     GCC_BAD ("malformed %<#pragma redefine_extname%>, ignored");
     512           23 :   t = pragma_lex (&x);
     513           23 :   if (t != CPP_EOF)
     514            1 :     warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
     515              : 
     516           23 :   found = false;
     517           23 :   for (decls = c_linkage_bindings (oldname);
     518           33 :        decls; )
     519              :     {
     520           10 :       tree decl;
     521           10 :       if (TREE_CODE (decls) == TREE_LIST)
     522              :         {
     523            3 :           decl = TREE_VALUE (decls);
     524            3 :           decls = TREE_CHAIN (decls);
     525              :         }
     526              :       else
     527              :         {
     528              :           decl = decls;
     529              :           decls = NULL_TREE;
     530              :         }
     531              : 
     532            0 :       if ((TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
     533           10 :           && VAR_OR_FUNCTION_DECL_P (decl))
     534              :         {
     535           10 :           found = true;
     536           10 :           if (DECL_ASSEMBLER_NAME_SET_P (decl))
     537              :             {
     538            0 :               const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
     539            0 :               name = targetm.strip_name_encoding (name);
     540              : 
     541            0 :               if (!id_equal (newname, name))
     542            0 :                 warning (OPT_Wpragmas, "%<#pragma redefine_extname%> "
     543              :                          "ignored due to conflict with previous rename");
     544              :             }
     545              :           else
     546           10 :             symtab->change_decl_assembler_name (decl, newname);
     547              :         }
     548              :     }
     549              : 
     550           23 :   if (!found)
     551              :     /* We have to add this to the rename list even if there's already
     552              :        a global value that doesn't meet the above criteria, because in
     553              :        C++ "struct foo {...};" puts "foo" in the current namespace but
     554              :        does *not* conflict with a subsequent declaration of a function
     555              :        or variable foo.  See g++.dg/other/pragma-re-2.C.  */
     556           16 :     add_to_renaming_pragma_list (oldname, newname);
     557              : }
     558              : 
     559              : /* This is called from here and from ia64-c.cc.  */
     560              : void
     561           16 : add_to_renaming_pragma_list (tree oldname, tree newname)
     562              : {
     563           16 :   unsigned ix;
     564           16 :   pending_redefinition *p;
     565              : 
     566           20 :   FOR_EACH_VEC_SAFE_ELT (pending_redefine_extname, ix, p)
     567            4 :     if (oldname == p->oldname)
     568              :       {
     569            0 :         if (p->newname != newname)
     570            0 :           warning (OPT_Wpragmas, "%<#pragma redefine_extname%> ignored due to "
     571              :                    "conflict with previous %<#pragma redefine_extname%>");
     572            0 :         return;
     573              :       }
     574              : 
     575           16 :   pending_redefinition e = {oldname, newname};
     576           16 :   vec_safe_push (pending_redefine_extname, e);
     577              : }
     578              : 
     579              : /* The current prefix set by #pragma extern_prefix.  */
     580              : GTY(()) tree pragma_extern_prefix;
     581              : 
     582              : /* Hook from the front ends to apply the results of one of the preceding
     583              :    pragmas that rename variables.  */
     584              : 
     585              : tree
     586     88864579 : maybe_apply_renaming_pragma (tree decl, tree asmname)
     587              : {
     588     88864579 :   unsigned ix;
     589     88864579 :   pending_redefinition *p;
     590              : 
     591              :   /* The renaming pragmas are only applied to declarations with
     592              :      external linkage.  */
     593     60614856 :   if (!VAR_OR_FUNCTION_DECL_P (decl)
     594     79492064 :       || (!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
     595    168245153 :       || !has_c_linkage (decl))
     596     45132637 :     return asmname;
     597              : 
     598              :   /* If the DECL_ASSEMBLER_NAME is already set, it does not change,
     599              :      but we may warn about a rename that conflicts.  */
     600     43731942 :   if (DECL_ASSEMBLER_NAME_SET_P (decl))
     601              :     {
     602         4572 :       const char *oldname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
     603         4572 :       oldname = targetm.strip_name_encoding (oldname);
     604              : 
     605         5151 :       if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldname))
     606            7 :           warning (OPT_Wpragmas, "%<asm%> declaration ignored due to "
     607              :                    "conflict with previous rename");
     608              : 
     609              :       /* Take any pending redefine_extname off the list.  */
     610         4575 :       FOR_EACH_VEC_SAFE_ELT (pending_redefine_extname, ix, p)
     611            3 :         if (DECL_NAME (decl) == p->oldname)
     612              :           {
     613              :             /* Only warn if there is a conflict.  */
     614            0 :             if (!id_equal (p->newname, oldname))
     615            0 :               warning (OPT_Wpragmas, "%<#pragma redefine_extname%> ignored "
     616              :                        "due to conflict with previous rename");
     617              : 
     618            0 :             pending_redefine_extname->unordered_remove (ix);
     619            0 :             break;
     620              :           }
     621         4572 :       return NULL_TREE;
     622              :     }
     623              : 
     624              :   /* Find out if we have a pending #pragma redefine_extname.  */
     625     43727383 :   FOR_EACH_VEC_SAFE_ELT (pending_redefine_extname, ix, p)
     626           25 :     if (DECL_NAME (decl) == p->oldname)
     627              :       {
     628           12 :         tree newname = p->newname;
     629           12 :         pending_redefine_extname->unordered_remove (ix);
     630              : 
     631              :         /* If we already have an asmname, #pragma redefine_extname is
     632              :            ignored (with a warning if it conflicts).  */
     633           12 :         if (asmname)
     634              :           {
     635            0 :             if (strcmp (TREE_STRING_POINTER (asmname),
     636            0 :                         IDENTIFIER_POINTER (newname)) != 0)
     637            0 :               warning (OPT_Wpragmas, "%<#pragma redefine_extname%> ignored "
     638              :                        "due to conflict with %<asm%> declaration");
     639            0 :             return asmname;
     640              :           }
     641              : 
     642              :         /* Otherwise we use what we've got; #pragma extern_prefix is
     643              :            silently ignored.  */
     644           12 :         return build_string (IDENTIFIER_LENGTH (newname),
     645           12 :                              IDENTIFIER_POINTER (newname));
     646              :       }
     647              : 
     648              :   /* If we've got an asmname, #pragma extern_prefix is silently ignored.  */
     649     43727358 :   if (asmname)
     650              :     return asmname;
     651              : 
     652              :   /* If #pragma extern_prefix is in effect, apply it.  */
     653     42313519 :   if (pragma_extern_prefix)
     654              :     {
     655            0 :       const char *prefix = TREE_STRING_POINTER (pragma_extern_prefix);
     656            0 :       size_t plen = TREE_STRING_LENGTH (pragma_extern_prefix) - 1;
     657              : 
     658            0 :       const char *id = IDENTIFIER_POINTER (DECL_NAME (decl));
     659            0 :       size_t ilen = IDENTIFIER_LENGTH (DECL_NAME (decl));
     660              : 
     661            0 :       char *newname = (char *) alloca (plen + ilen + 1);
     662              : 
     663            0 :       memcpy (newname,        prefix, plen);
     664            0 :       memcpy (newname + plen, id, ilen + 1);
     665              : 
     666            0 :       return build_string (plen + ilen, newname);
     667              :     }
     668              : 
     669              :   /* Nada.  */
     670              :   return NULL_TREE;
     671              : }
     672              : 
     673              : 
     674              : static void handle_pragma_visibility (cpp_reader *);
     675              : 
     676              : static vec<int> visstack;
     677              : 
     678              : /* Push the visibility indicated by STR onto the top of the #pragma
     679              :    visibility stack.  KIND is 0 for #pragma GCC visibility, 1 for
     680              :    C++ namespace with visibility attribute and 2 for C++ builtin
     681              :    ABI namespace.  push_visibility/pop_visibility calls must have
     682              :    matching KIND, it is not allowed to push visibility using one
     683              :    KIND and pop using a different one.  */
     684              : 
     685              : void
     686      3063774 : push_visibility (const char *str, int kind)
     687              : {
     688      3063774 :   visstack.safe_push (((int) default_visibility) | (kind << 8));
     689      3063774 :   if (!strcmp (str, "default"))
     690      3062183 :     default_visibility = VISIBILITY_DEFAULT;
     691         1591 :   else if (!strcmp (str, "internal"))
     692            0 :     default_visibility = VISIBILITY_INTERNAL;
     693         1591 :   else if (!strcmp (str, "hidden"))
     694         1591 :     default_visibility = VISIBILITY_HIDDEN;
     695            0 :   else if (!strcmp (str, "protected"))
     696            0 :     default_visibility = VISIBILITY_PROTECTED;
     697              :   else
     698            0 :     GCC_BAD ("%<#pragma GCC visibility push()%> must specify %<default%>, "
     699              :              "%<internal%>, %<hidden%> or %<protected%>");
     700      3063774 :   visibility_options.inpragma = 1;
     701              : }
     702              : 
     703              : /* Pop a level of the #pragma visibility stack.  Return true if
     704              :    successful.  */
     705              : 
     706              : bool
     707      3063758 : pop_visibility (int kind)
     708              : {
     709      3063758 :   if (!visstack.length ())
     710              :     return false;
     711      3063758 :   if ((visstack.last () >> 8) != kind)
     712              :     return false;
     713      3063755 :   default_visibility
     714      3063755 :     = (enum symbol_visibility) (visstack.pop () & 0xff);
     715      3063755 :   visibility_options.inpragma
     716      3063755 :     = visstack.length () != 0;
     717      3063755 :   return true;
     718              : }
     719              : 
     720              : /* Sets the default visibility for symbols to something other than that
     721              :    specified on the command line.  */
     722              : 
     723              : static void
     724       236230 : handle_pragma_visibility (cpp_reader *)
     725              : {
     726              :   /* Form is #pragma GCC visibility push(hidden)|pop */
     727       236230 :   tree x;
     728       236230 :   enum cpp_ttype token;
     729       236230 :   enum { bad, push, pop } action = bad;
     730              : 
     731       236230 :   token = pragma_lex (&x);
     732       236230 :   if (token == CPP_NAME)
     733              :     {
     734       236230 :       const char *op = IDENTIFIER_POINTER (x);
     735       236230 :       if (!strcmp (op, "push"))
     736              :         action = push;
     737       118107 :       else if (!strcmp (op, "pop"))
     738              :         action = pop;
     739              :     }
     740              :   if (bad == action)
     741            3 :     GCC_BAD ("%<#pragma GCC visibility%> must be followed by %<push%> "
     742              :              "or %<pop%>");
     743              :   else
     744              :     {
     745       236230 :       if (pop == action)
     746              :         {
     747       118107 :           if (! pop_visibility (0))
     748            3 :             GCC_BAD ("no matching push for %<#pragma GCC visibility pop%>");
     749              :         }
     750              :       else
     751              :         {
     752       118123 :           if (pragma_lex (&x) != CPP_OPEN_PAREN)
     753            0 :             GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
     754       118123 :           token = pragma_lex (&x);
     755       118123 :           if (token != CPP_NAME)
     756            0 :             GCC_BAD ("malformed %<#pragma GCC visibility push%>");
     757              :           else
     758       118123 :             push_visibility (IDENTIFIER_POINTER (x), 0);
     759       118123 :           if (pragma_lex (&x) != CPP_CLOSE_PAREN)
     760            0 :             GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
     761              :         }
     762              :     }
     763       236227 :   if (pragma_lex (&x) != CPP_EOF)
     764            0 :     warning (OPT_Wpragmas, "junk at end of %<#pragma GCC visibility%>");
     765              : }
     766              : 
     767              : /* Helper routines for parsing #pragma GCC diagnostic.  */
     768              : class pragma_diagnostic_data
     769              : {
     770              :   pragma_diagnostic_data (const pragma_diagnostic_data &) = delete;
     771              :   pragma_diagnostic_data& operator= (const pragma_diagnostic_data &) = delete;
     772              : 
     773              : public:
     774              :   bool valid;
     775              :   location_t loc_kind, loc_option;
     776              :   enum pd_kind_t
     777              :     {
     778              :       PK_INVALID,
     779              :       PK_PUSH,
     780              :       PK_POP,
     781              :       PK_IGNORED_ATTRIBUTES,
     782              :       PK_DIAGNOSTIC,
     783              :     } pd_kind;
     784              :   enum diagnostics::kind diagnostic_kind;
     785              :   const char *kind_str;
     786              :   const char *option_str;
     787              :   bool own_option_str;
     788              : 
     789     13320204 :   pragma_diagnostic_data () { clear (); }
     790     26640408 :   void clear ()
     791              :   {
     792     26640408 :     valid = false;
     793     26640408 :     loc_kind = loc_option = UNKNOWN_LOCATION;
     794     26640408 :     pd_kind = PK_INVALID;
     795     26640408 :     diagnostic_kind = diagnostics::kind::unspecified;
     796     26640408 :     kind_str = option_str = nullptr;
     797     26640408 :     own_option_str = false;
     798              :   }
     799              : 
     800     13320204 :   ~pragma_diagnostic_data ()
     801              :   {
     802     13320204 :     if (own_option_str && option_str)
     803            0 :       XDELETEVEC (const_cast<char *> (option_str));
     804     13320204 :   }
     805              : 
     806     13320194 :   void set_kind (const char *kind_string)
     807              :   {
     808     13320194 :     kind_str = kind_string;
     809              : 
     810     13320194 :     pd_kind = PK_INVALID;
     811     13320194 :     diagnostic_kind = diagnostics::kind::unspecified;
     812     13320194 :     if (strcmp (kind_str, "push") == 0)
     813      4271912 :       pd_kind = PK_PUSH;
     814      9048282 :     else if (strcmp (kind_str, "pop") == 0)
     815      4271269 :       pd_kind = PK_POP;
     816      4777013 :     else if (strcmp (kind_str, "ignored_attributes") == 0)
     817           77 :       pd_kind = PK_IGNORED_ATTRIBUTES;
     818      4776936 :     else if (strcmp (kind_str, "error") == 0)
     819              :       {
     820           64 :         pd_kind = PK_DIAGNOSTIC;
     821           64 :         diagnostic_kind = diagnostics::kind::error;
     822              :       }
     823      4776872 :     else if (strcmp (kind_str, "warning") == 0)
     824              :       {
     825           63 :         pd_kind = PK_DIAGNOSTIC;
     826           63 :         diagnostic_kind = diagnostics::kind::warning;
     827              :       }
     828      4776809 :     else if (strcmp (kind_str, "ignored") == 0)
     829              :       {
     830      4776801 :         pd_kind = PK_DIAGNOSTIC;
     831      4776801 :         diagnostic_kind = diagnostics::kind::ignored;
     832              :       }
     833     13320194 :   }
     834              : 
     835     13320186 :   bool needs_option () const
     836              :   {
     837     13320186 :     return pd_kind == PK_IGNORED_ATTRIBUTES
     838     13320186 :       || pd_kind == PK_DIAGNOSTIC;
     839              :   }
     840              : 
     841              : };
     842              : 
     843              : /* This will call into either the C or C++ frontends as appropriate to get
     844              :    tokens from libcpp for the pragma.  */
     845              : 
     846              : static void
     847     13320204 : pragma_diagnostic_lex (pragma_diagnostic_data *result)
     848              : {
     849     13320204 :   result->clear ();
     850     13320204 :   tree x;
     851     13320204 :   auto ttype = pragma_lex (&x, &result->loc_kind);
     852     13320204 :   if (ttype != CPP_NAME)
     853           18 :     return;
     854     13320194 :   result->set_kind (IDENTIFIER_POINTER (x));
     855     13320194 :   if (result->pd_kind == pragma_diagnostic_data::PK_INVALID)
     856              :     return;
     857              : 
     858     13320186 :   if (result->needs_option ())
     859              :     {
     860      4777005 :       ttype = pragma_lex (&x, &result->loc_option);
     861      4777005 :       if (ttype != CPP_STRING)
     862              :         return;
     863      4777005 :       result->option_str = TREE_STRING_POINTER (x);
     864              :     }
     865              : 
     866     13320186 :   result->valid = true;
     867              : }
     868              : 
     869              : /* Handle #pragma GCC diagnostic.  Early mode is used by frontends (such as C++)
     870              :    that do not process the deferred pragma while they are consuming tokens; they
     871              :    can use early mode to make sure diagnostics affecting the preprocessor itself
     872              :    are correctly modified by the #pragma.  */
     873              : template<bool early, bool is_pp> static void
     874     13320204 : handle_pragma_diagnostic_impl ()
     875              : {
     876              :   static const bool want_diagnostics = (is_pp || !early);
     877              : 
     878     13320204 :   pragma_diagnostic_data data;
     879     13320204 :   pragma_diagnostic_lex (&data);
     880              : 
     881     13320204 :   if (!data.kind_str)
     882              :     {
     883              :       if (want_diagnostics)
     884            7 :         warning_at (data.loc_kind, OPT_Wpragmas,
     885              :                     "missing %<error%>, %<warning%>, %<ignored%>, %<push%>, "
     886              :                     "%<pop%>, or %<ignored_attributes%> after "
     887              :                     "%<#pragma GCC diagnostic%>");
     888            7 :       return;
     889              :     }
     890              : 
     891     13320194 :   switch (data.pd_kind)
     892              :     {
     893              : 
     894      4271912 :     case pragma_diagnostic_data::PK_PUSH:
     895      4271912 :       diagnostic_push_diagnostics (global_dc, input_location);
     896              :       return;
     897              : 
     898      4271269 :     case pragma_diagnostic_data::PK_POP:
     899      4271269 :       diagnostic_pop_diagnostics (global_dc, input_location);
     900              :       return;
     901              : 
     902              :     case pragma_diagnostic_data::PK_IGNORED_ATTRIBUTES:
     903              :       {
     904              :         if (early)
     905              :           return;
     906           44 :         if (!data.option_str)
     907              :           {
     908            0 :             warning_at (data.loc_option, OPT_Wpragmas,
     909              :                        "missing attribute name after %<#pragma GCC diagnostic "
     910              :                         "ignored_attributes%>");
     911            0 :             return;
     912              :           }
     913           44 :         char *args = xstrdup (data.option_str);
     914           44 :         const size_t l = strlen (args);
     915           44 :         if (l == 0)
     916              :           {
     917            0 :             warning_at (data.loc_option, OPT_Wpragmas,
     918              :                         "missing argument to %<#pragma GCC "
     919              :                         "diagnostic ignored_attributes%>");
     920            0 :             free (args);
     921            0 :             return;
     922              :           }
     923           44 :         else if (args[l - 1] == ',')
     924              :           {
     925            0 :             warning_at (data.loc_option, OPT_Wpragmas,
     926              :                         "trailing %<,%> in arguments for "
     927              :                         "%<#pragma GCC diagnostic ignored_attributes%>");
     928            0 :             free (args);
     929            0 :             return;
     930              :           }
     931           44 :         auto_vec<char *> v;
     932          108 :         for (char *p = strtok (args, ","); p; p = strtok (NULL, ","))
     933           64 :           v.safe_push (p);
     934           44 :         handle_ignored_attributes_option (&v);
     935           44 :         free (args);
     936              :         return;
     937           44 :       }
     938              : 
     939      4776928 :     case pragma_diagnostic_data::PK_DIAGNOSTIC:
     940      4776928 :       if (!data.option_str)
     941              :         {
     942              :           if (want_diagnostics)
     943            0 :             warning_at (data.loc_option, OPT_Wpragmas,
     944              :                         "missing option after %<#pragma GCC diagnostic%> kind");
     945            0 :           return;
     946              :         }
     947              :       break;
     948              : 
     949            5 :     default:
     950              :       if (want_diagnostics)
     951            5 :         warning_at (data.loc_kind, OPT_Wpragmas,
     952              :                     "expected %<error%>, %<warning%>, %<ignored%>, %<push%>, "
     953              :                     "%<pop%>, %<ignored_attributes%> after "
     954              :                     "%<#pragma GCC diagnostic%>");
     955            5 :       return;
     956              : 
     957              :     }
     958              : 
     959              :   gcc_assert (data.pd_kind == pragma_diagnostic_data::PK_DIAGNOSTIC);
     960      4776928 :   gcc_assert (data.valid);
     961              : 
     962      4776928 :   unsigned int lang_mask = c_common_option_lang_mask () | CL_COMMON;
     963              :   /* option_string + 1 to skip the initial '-' */
     964      4776928 :   unsigned int option_index = find_opt (data.option_str + 1, lang_mask);
     965              : 
     966      2335857 :   if (early && !(c_option_is_from_cpp_diagnostics (option_index)
     967      2335857 :                  || option_index == OPT_Wunknown_pragmas))
     968              :     return;
     969              : 
     970      3956690 :   if (option_index == OPT_SPECIAL_unknown)
     971              :     {
     972              :       if (want_diagnostics)
     973              :         {
     974           11 :           auto_diagnostic_group d;
     975           11 :           if (warning_at (data.loc_option, OPT_Wpragmas,
     976              :                         "unknown option after %<#pragma GCC diagnostic%> kind"))
     977              :             {
     978           11 :               option_proposer op;
     979           11 :               const char *hint = op.suggest_option (data.option_str + 1);
     980           11 :               if (hint)
     981            4 :                 inform (data.loc_option, "did you mean %<-%s%>?", hint);
     982           11 :             }
     983           11 :         }
     984           11 :       return;
     985              :     }
     986      3956679 :   else if (!(cl_options[option_index].flags & CL_WARNING))
     987              :     {
     988              :       if (want_diagnostics)
     989           11 :         warning_at (data.loc_option, OPT_Wpragmas,
     990              :                     "%qs is not an option that controls warnings",
     991              :                     data.option_str);
     992           11 :       return;
     993              :     }
     994      3956668 :   else if (!(cl_options[option_index].flags & lang_mask))
     995              :     {
     996              :       if (want_diagnostics)
     997              :         {
     998            1 :           char *ok_langs = write_langs (cl_options[option_index].flags);
     999            1 :           char *bad_lang = write_langs (c_common_option_lang_mask ());
    1000            1 :           warning_at (data.loc_option, OPT_Wpragmas,
    1001              :                       "option %qs is valid for %s but not for %s",
    1002              :                       data.option_str, ok_langs, bad_lang);
    1003            1 :           free (ok_langs);
    1004            1 :           free (bad_lang);
    1005              :         }
    1006            1 :       return;
    1007              :     }
    1008              : 
    1009      3956667 :   const char *arg = NULL;
    1010      3956667 :   if (cl_options[option_index].flags & CL_JOINED)
    1011           17 :     arg = data.option_str + 1 + cl_options[option_index].opt_len;
    1012              : 
    1013              :   struct cl_option_handlers handlers;
    1014      3956667 :   set_default_handlers (&handlers, NULL);
    1015              :   /* FIXME: input_location isn't the best location here, but it is
    1016              :      what we used to do here before and changing it breaks e.g.
    1017              :      PR69543 and PR69558.  */
    1018      3956667 :   control_warning_option (option_index, (int) data.diagnostic_kind,
    1019              :                           arg,
    1020      3956667 :                           data.diagnostic_kind != diagnostics::kind::ignored,
    1021              :                           input_location, lang_mask, &handlers,
    1022              :                           &global_options, &global_options_set,
    1023              :                           global_dc);
    1024     13320204 : }
    1025              : 
    1026              : static void
    1027      6819485 : handle_pragma_diagnostic (cpp_reader *)
    1028              : {
    1029      6819485 :   handle_pragma_diagnostic_impl<false, false> ();
    1030      6819485 : }
    1031              : 
    1032              : static void
    1033      6474875 : handle_pragma_diagnostic_early (cpp_reader *)
    1034              : {
    1035      6474875 :   handle_pragma_diagnostic_impl<true, false> ();
    1036      6474875 : }
    1037              : 
    1038              : static void
    1039        25844 : handle_pragma_diagnostic_early_pp (cpp_reader *)
    1040              : {
    1041        25844 :   handle_pragma_diagnostic_impl<true, true> ();
    1042        25844 : }
    1043              : 
    1044              : /*  Parse #pragma GCC target (xxx) to set target specific options.  */
    1045              : static void
    1046       559015 : handle_pragma_target(cpp_reader *)
    1047              : {
    1048       559015 :   location_t loc;
    1049       559015 :   enum cpp_ttype token;
    1050       559015 :   tree x;
    1051       559015 :   bool close_paren_needed_p = false;
    1052              : 
    1053       559015 :   if (cfun)
    1054              :     {
    1055            0 :       error ("%<#pragma GCC option%> is not allowed inside functions");
    1056            2 :       return;
    1057              :     }
    1058              : 
    1059       559015 :   token = pragma_lex (&x, &loc);
    1060       559015 :   if (token == CPP_OPEN_PAREN)
    1061              :     {
    1062       558959 :       close_paren_needed_p = true;
    1063       558959 :       token = pragma_lex (&x, &loc);
    1064              :     }
    1065              : 
    1066       559015 :   if (token != CPP_STRING)
    1067            2 :     GCC_BAD_AT (loc, "%<#pragma GCC option%> is not a string");
    1068              : 
    1069              :   /* Strings are user options.  */
    1070              :   else
    1071              :     {
    1072              :       tree args = NULL_TREE;
    1073              : 
    1074       559031 :       do
    1075              :         {
    1076              :           /* Build up the strings now as a tree linked list.  Skip empty
    1077              :              strings.  */
    1078       559031 :           if (TREE_STRING_LENGTH (x) > 0)
    1079       559031 :             args = tree_cons (NULL_TREE, x, args);
    1080              : 
    1081       559031 :           token = pragma_lex (&x);
    1082      1118080 :           while (token == CPP_COMMA)
    1083           18 :             token = pragma_lex (&x);
    1084              :         }
    1085       559031 :       while (token == CPP_STRING);
    1086              : 
    1087       559013 :       if (close_paren_needed_p)
    1088              :         {
    1089       558958 :           if (token == CPP_CLOSE_PAREN)
    1090       558958 :             token = pragma_lex (&x);
    1091              :           else
    1092       558958 :             GCC_BAD ("%<#pragma GCC target (string [,string]...)%> does "
    1093              :                      "not have a final %<)%>");
    1094              :         }
    1095              : 
    1096       559013 :       if (token != CPP_EOF)
    1097              :         {
    1098            0 :           error ("%<#pragma GCC target%> string is badly formed");
    1099            0 :           return;
    1100              :         }
    1101              : 
    1102              :       /* put arguments in the order the user typed them.  */
    1103       559013 :       args = nreverse (args);
    1104              : 
    1105       559013 :       if (targetm.target_option.pragma_parse (args, NULL_TREE))
    1106       558744 :         current_target_pragma = chainon (current_target_pragma, args);
    1107              : 
    1108              :       /* A target pragma can also influence optimization options. */
    1109       559013 :       tree current_optimize
    1110       559013 :         = build_optimization_node (&global_options, &global_options_set);
    1111       559013 :       if (current_optimize != optimization_current_node)
    1112           78 :         optimization_current_node = current_optimize;
    1113              :     }
    1114              : }
    1115              : 
    1116              : /* Handle #pragma GCC optimize to set optimization options.  */
    1117              : static void
    1118          533 : handle_pragma_optimize (cpp_reader *)
    1119              : {
    1120          533 :   enum cpp_ttype token;
    1121          533 :   tree x;
    1122          533 :   bool close_paren_needed_p = false;
    1123          533 :   tree optimization_previous_node = optimization_current_node;
    1124              : 
    1125          533 :   if (cfun)
    1126              :     {
    1127            0 :       error ("%<#pragma GCC optimize%> is not allowed inside functions");
    1128            0 :       return;
    1129              :     }
    1130              : 
    1131          533 :   token = pragma_lex (&x);
    1132          533 :   if (token == CPP_OPEN_PAREN)
    1133              :     {
    1134          126 :       close_paren_needed_p = true;
    1135          126 :       token = pragma_lex (&x);
    1136              :     }
    1137              : 
    1138          533 :   if (token != CPP_STRING && token != CPP_NUMBER)
    1139            0 :     GCC_BAD ("%<#pragma GCC optimize%> is not a string or number");
    1140              : 
    1141              :   /* Strings/numbers are user options.  */
    1142              :   else
    1143              :     {
    1144              :       tree args = NULL_TREE;
    1145              : 
    1146          549 :       do
    1147              :         {
    1148              :           /* Build up the numbers/strings now as a list.  */
    1149          549 :           if (token != CPP_STRING || TREE_STRING_LENGTH (x) > 0)
    1150          549 :             args = tree_cons (NULL_TREE, x, args);
    1151              : 
    1152          549 :           token = pragma_lex (&x);
    1153         1114 :           while (token == CPP_COMMA)
    1154           16 :             token = pragma_lex (&x);
    1155              :         }
    1156          549 :       while (token == CPP_STRING || token == CPP_NUMBER);
    1157              : 
    1158          533 :       if (close_paren_needed_p)
    1159              :         {
    1160          126 :           if (token == CPP_CLOSE_PAREN)
    1161          126 :             token = pragma_lex (&x);
    1162              :           else
    1163          126 :             GCC_BAD ("%<#pragma GCC optimize (string [,string]...)%> does "
    1164              :                      "not have a final %<)%>");
    1165              :         }
    1166              : 
    1167          533 :       if (token != CPP_EOF)
    1168              :         {
    1169            0 :           error ("%<#pragma GCC optimize%> string is badly formed");
    1170            0 :           return;
    1171              :         }
    1172              : 
    1173              :       /* put arguments in the order the user typed them.  */
    1174          533 :       args = nreverse (args);
    1175              : 
    1176          533 :       parse_optimize_options (args, false);
    1177          533 :       current_optimize_pragma = chainon (current_optimize_pragma, args);
    1178          533 :       optimization_current_node
    1179          533 :         = build_optimization_node (&global_options, &global_options_set);
    1180          533 :       c_cpp_builtins_optimize_pragma (parse_in,
    1181              :                                       optimization_previous_node,
    1182              :                                       optimization_current_node);
    1183              :     }
    1184              : }
    1185              : 
    1186              : /* Stack of the #pragma GCC options created with #pragma GCC push_option.  Save
    1187              :    both the binary representation of the options and the TREE_LIST of
    1188              :    strings that will be added to the function's attribute list.  */
    1189              : struct GTY(()) opt_stack {
    1190              :   struct opt_stack *prev;
    1191              :   tree target_binary;
    1192              :   tree target_strings;
    1193              :   tree optimize_binary;
    1194              :   tree optimize_strings;
    1195              :   gcc_options * GTY ((skip)) saved_global_options;
    1196              : };
    1197              : 
    1198              : static GTY(()) struct opt_stack * options_stack;
    1199              : 
    1200              : /* Handle #pragma GCC push_options to save the current target and optimization
    1201              :    options.  */
    1202              : 
    1203              : static void
    1204       559225 : handle_pragma_push_options (cpp_reader *)
    1205              : {
    1206       559225 :   enum cpp_ttype token;
    1207       559225 :   tree x = 0;
    1208              : 
    1209       559225 :   token = pragma_lex (&x);
    1210       559225 :   if (token != CPP_EOF)
    1211              :     {
    1212            0 :       warning (OPT_Wpragmas, "junk at end of %<#pragma GCC push_options%>");
    1213            0 :       return;
    1214              :     }
    1215              : 
    1216       559225 :   opt_stack *p = ggc_alloc<opt_stack> ();
    1217       559225 :   p->prev = options_stack;
    1218       559225 :   options_stack = p;
    1219              : 
    1220              :   /* Save optimization and target flags in binary format.  */
    1221       559225 :   if (flag_checking)
    1222              :     {
    1223       559225 :       p->saved_global_options = XNEW (gcc_options);
    1224       559225 :       *p->saved_global_options = global_options;
    1225              :     }
    1226       559225 :   p->optimize_binary = build_optimization_node (&global_options,
    1227              :                                                 &global_options_set);
    1228       559225 :   p->target_binary = build_target_option_node (&global_options,
    1229              :                                                &global_options_set);
    1230              : 
    1231              :   /* Save optimization and target flags in string list format.  */
    1232       559225 :   p->optimize_strings = copy_list (current_optimize_pragma);
    1233       559225 :   p->target_strings = copy_list (current_target_pragma);
    1234              : }
    1235              : 
    1236              : /* Handle #pragma GCC pop_options to restore the current target and
    1237              :    optimization options from a previous push_options.  */
    1238              : 
    1239              : static void
    1240       559224 : handle_pragma_pop_options (cpp_reader *)
    1241              : {
    1242       559224 :   enum cpp_ttype token;
    1243       559224 :   tree x = 0;
    1244       559224 :   opt_stack *p;
    1245              : 
    1246       559224 :   token = pragma_lex (&x);
    1247       559224 :   if (token != CPP_EOF)
    1248              :     {
    1249            0 :       warning (OPT_Wpragmas, "junk at end of %<#pragma GCC pop_options%>");
    1250            0 :       return;
    1251              :     }
    1252              : 
    1253       559224 :   if (! options_stack)
    1254              :     {
    1255            0 :       warning (OPT_Wpragmas,
    1256              :                "%<#pragma GCC pop_options%> without a corresponding "
    1257              :                "%<#pragma GCC push_options%>");
    1258            0 :       return;
    1259              :     }
    1260              : 
    1261       559224 :   p = options_stack;
    1262       559224 :   options_stack = p->prev;
    1263              : 
    1264       559224 :   if (p->target_binary != target_option_current_node)
    1265              :     {
    1266       554043 :       (void) targetm.target_option.pragma_parse (NULL_TREE, p->target_binary);
    1267       554043 :       target_option_current_node = p->target_binary;
    1268              :     }
    1269              : 
    1270              :   /* Always restore optimization options as optimization_current_node is
    1271              :    * overwritten by invoke_set_current_function_hook.  */
    1272      1118448 :   cl_optimization_restore (&global_options, &global_options_set,
    1273       559224 :                            TREE_OPTIMIZATION (p->optimize_binary));
    1274      1118448 :   cl_target_option_restore (&global_options, &global_options_set,
    1275       559224 :                             TREE_TARGET_OPTION (p->target_binary));
    1276              : 
    1277       559224 :   if (p->optimize_binary != optimization_current_node)
    1278              :     {
    1279           53 :       c_cpp_builtins_optimize_pragma (parse_in, optimization_current_node,
    1280              :                                       p->optimize_binary);
    1281           53 :       optimization_current_node = p->optimize_binary;
    1282              :     }
    1283       559224 :   if (flag_checking && !seen_error ())
    1284              :     {
    1285       559220 :       cl_optimization_compare (p->saved_global_options, &global_options);
    1286       559220 :       free (p->saved_global_options);
    1287              :     }
    1288              : 
    1289       559224 :   current_target_pragma = p->target_strings;
    1290       559224 :   current_optimize_pragma = p->optimize_strings;
    1291              : }
    1292              : 
    1293              : /* This is mostly a helper for handle_pragma_reset_options () to do the actual
    1294              :    work, but the C++ frontend, for example, needs an external interface to
    1295              :    perform this operation, since it processes target pragmas twice.  (Once for
    1296              :    preprocessing purposes, and then again during compilation.)  */
    1297              : 
    1298              : void
    1299        95996 : c_reset_target_pragmas ()
    1300              : {
    1301        95996 :   tree new_optimize = optimization_default_node;
    1302        95996 :   tree new_target = target_option_default_node;
    1303        95996 :   if (new_target != target_option_current_node)
    1304              :     {
    1305           41 :       (void) targetm.target_option.pragma_parse (NULL_TREE, new_target);
    1306           41 :       target_option_current_node = new_target;
    1307              :     }
    1308              : 
    1309        95996 :   if (new_optimize != optimization_current_node)
    1310              :     {
    1311           49 :       tree old_optimize = optimization_current_node;
    1312           49 :       cl_optimization_restore (&global_options, &global_options_set,
    1313           49 :                                TREE_OPTIMIZATION (new_optimize));
    1314           49 :       c_cpp_builtins_optimize_pragma (parse_in, old_optimize, new_optimize);
    1315           49 :       optimization_current_node = new_optimize;
    1316              :     }
    1317              : 
    1318        95996 :   current_target_pragma = NULL_TREE;
    1319        95996 :   current_optimize_pragma = NULL_TREE;
    1320        95996 : }
    1321              : 
    1322              : /* Handle #pragma GCC reset_options to restore the current target and
    1323              :    optimization options to the original options used on the command line.  */
    1324              : 
    1325              : static void
    1326            4 : handle_pragma_reset_options (cpp_reader *)
    1327              : {
    1328            4 :   tree x;
    1329            4 :   if (pragma_lex (&x) != CPP_EOF)
    1330            0 :     warning (OPT_Wpragmas, "junk at end of %<#pragma reset_options%>");
    1331              :   else
    1332            4 :     c_reset_target_pragmas ();
    1333            4 : }
    1334              : 
    1335              : /* Print a plain user-specified message.  */
    1336              : 
    1337              : static void
    1338           56 : handle_pragma_message (cpp_reader *)
    1339              : {
    1340           56 :   location_t loc;
    1341           56 :   enum cpp_ttype token;
    1342           56 :   tree x, message = 0;
    1343              : 
    1344           56 :   token = pragma_lex (&x);
    1345           56 :   if (token == CPP_OPEN_PAREN)
    1346              :     {
    1347           21 :       token = pragma_lex (&x);
    1348           21 :       if (token == CPP_STRING)
    1349           14 :         message = x;
    1350              :       else
    1351           20 :         GCC_BAD ("expected a string after %<#pragma message%>");
    1352           14 :       if (pragma_lex (&x) != CPP_CLOSE_PAREN)
    1353            1 :         GCC_BAD ("malformed %<#pragma message%>, ignored");
    1354              :     }
    1355           35 :   else if (token == CPP_STRING)
    1356           23 :     message = x;
    1357           12 :   else if (token == CPP_STRING_USERDEF)
    1358            3 :     GCC_BAD ("string literal with user-defined suffix is invalid in this "
    1359              :              "context");
    1360              :   else
    1361            9 :     GCC_BAD ("expected a string after %<#pragma message%>");
    1362              : 
    1363           36 :   gcc_assert (message);
    1364              : 
    1365           36 :   if (pragma_lex (&x, &loc) != CPP_EOF)
    1366            3 :     warning_at (loc, OPT_Wpragmas, "junk at end of %<#pragma message%>");
    1367              : 
    1368           36 :   if (TREE_STRING_LENGTH (message) > 1)
    1369           32 :     inform (input_location, "%<#pragma message: %s%>",
    1370           32 :             TREE_STRING_POINTER (message));
    1371              : }
    1372              : 
    1373              : /* Ignore a no-op pragma that GCC recognizes, but which has no effect.  */
    1374              : static void
    1375           16 : handle_pragma_ignore (cpp_reader *)
    1376              : {
    1377           16 : }
    1378              : 
    1379              : /* Mark whether the current location is valid for a STDC pragma.  */
    1380              : 
    1381              : static bool valid_location_for_stdc_pragma;
    1382              : 
    1383              : void
    1384    127814714 : mark_valid_location_for_stdc_pragma (bool flag)
    1385              : {
    1386    127814714 :   valid_location_for_stdc_pragma = flag;
    1387    127814714 : }
    1388              : 
    1389              : /* Return true if the current location is valid for a STDC pragma.  */
    1390              : 
    1391              : bool
    1392     37190484 : valid_location_for_stdc_pragma_p (void)
    1393              : {
    1394     37190484 :   return valid_location_for_stdc_pragma;
    1395              : }
    1396              : 
    1397              : enum pragma_switch_t { PRAGMA_ON, PRAGMA_OFF, PRAGMA_DEFAULT, PRAGMA_BAD };
    1398              : 
    1399              : /* A STDC pragma must appear outside of external declarations or
    1400              :    preceding all explicit declarations and statements inside a compound
    1401              :    statement; its behavior is undefined if used in any other context.
    1402              :    It takes a switch of ON, OFF, or DEFAULT.  */
    1403              : 
    1404              : static enum pragma_switch_t
    1405           66 : handle_stdc_pragma (const char *pname)
    1406              : {
    1407           66 :   const char *arg;
    1408           66 :   tree t;
    1409           66 :   enum pragma_switch_t ret;
    1410              : 
    1411           66 :   if (!valid_location_for_stdc_pragma_p ())
    1412              :     {
    1413           12 :       warning (OPT_Wpragmas, "invalid location for %<pragma %s%>, ignored",
    1414              :                pname);
    1415           12 :       return PRAGMA_BAD;
    1416              :     }
    1417              : 
    1418           54 :   if (pragma_lex (&t) != CPP_NAME)
    1419              :     {
    1420            2 :       warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
    1421            2 :       return PRAGMA_BAD;
    1422              :     }
    1423              : 
    1424           52 :   arg = IDENTIFIER_POINTER (t);
    1425              : 
    1426           52 :   if (!strcmp (arg, "ON"))
    1427              :     ret = PRAGMA_ON;
    1428           30 :   else if (!strcmp (arg, "OFF"))
    1429              :     ret = PRAGMA_OFF;
    1430           11 :   else if (!strcmp (arg, "DEFAULT"))
    1431              :     ret = PRAGMA_DEFAULT;
    1432              :   else
    1433              :     {
    1434            2 :       warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
    1435            2 :       return PRAGMA_BAD;
    1436              :     }
    1437              : 
    1438           50 :   if (pragma_lex (&t) != CPP_EOF)
    1439              :     {
    1440            2 :       warning (OPT_Wpragmas, "junk at end of %<#pragma %s%>", pname);
    1441            2 :       return PRAGMA_BAD;
    1442              :     }
    1443              : 
    1444              :   return ret;
    1445              : }
    1446              : 
    1447              : /* #pragma STDC FLOAT_CONST_DECIMAL64 ON
    1448              :    #pragma STDC FLOAT_CONST_DECIMAL64 OFF
    1449              :    #pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT */
    1450              : 
    1451              : static void
    1452           69 : handle_pragma_float_const_decimal64 (cpp_reader *)
    1453              : {
    1454           69 :   if (c_dialect_cxx ())
    1455              :     {
    1456            3 :       if (warn_unknown_pragmas > in_system_header_at (input_location))
    1457            3 :         warning (OPT_Wunknown_pragmas,
    1458              :                  "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
    1459              :                  " for C++");
    1460            3 :       return;
    1461              :     }
    1462              : 
    1463           66 :   if (!targetm.decimal_float_supported_p ())
    1464              :     {
    1465            0 :       if (warn_unknown_pragmas > in_system_header_at (input_location))
    1466            0 :         warning (OPT_Wunknown_pragmas,
    1467              :                  "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
    1468              :                  " on this target");
    1469            0 :       return;
    1470              :     }
    1471              : 
    1472           66 :   pedwarn (input_location, OPT_Wpedantic,
    1473              :            "ISO C does not support %<#pragma STDC FLOAT_CONST_DECIMAL64%>");
    1474              : 
    1475           66 :   switch (handle_stdc_pragma ("STDC FLOAT_CONST_DECIMAL64"))
    1476              :     {
    1477           20 :     case PRAGMA_ON:
    1478           20 :       set_float_const_decimal64 ();
    1479           20 :       break;
    1480           28 :     case PRAGMA_OFF:
    1481           28 :     case PRAGMA_DEFAULT:
    1482           28 :       clear_float_const_decimal64 ();
    1483           28 :       break;
    1484              :     case PRAGMA_BAD:
    1485              :       break;
    1486              :     }
    1487              : }
    1488              : 
    1489              : /* A vector of registered pragma callbacks, which is never freed.   */
    1490              : 
    1491              : 
    1492              : struct pragma_data
    1493              : {
    1494              :   const char *space;
    1495              :   const char *name;
    1496              :   struct internal_pragma_handler ihandler;
    1497              : };
    1498              : 
    1499              : static vec<pragma_data> registered_pragmas;
    1500              : 
    1501              : struct omp_pragma_def { const char *name; unsigned int id; };
    1502              : static const struct omp_pragma_def oacc_pragmas[] = {
    1503              :   { "atomic", PRAGMA_OACC_ATOMIC },
    1504              :   { "cache", PRAGMA_OACC_CACHE },
    1505              :   { "data", PRAGMA_OACC_DATA },
    1506              :   { "declare", PRAGMA_OACC_DECLARE },
    1507              :   { "enter", PRAGMA_OACC_ENTER_DATA },
    1508              :   { "exit", PRAGMA_OACC_EXIT_DATA },
    1509              :   { "host_data", PRAGMA_OACC_HOST_DATA },
    1510              :   { "kernels", PRAGMA_OACC_KERNELS },
    1511              :   { "loop", PRAGMA_OACC_LOOP },
    1512              :   { "parallel", PRAGMA_OACC_PARALLEL },
    1513              :   { "routine", PRAGMA_OACC_ROUTINE },
    1514              :   { "serial", PRAGMA_OACC_SERIAL },
    1515              :   { "update", PRAGMA_OACC_UPDATE },
    1516              :   { "wait", PRAGMA_OACC_WAIT }
    1517              : };
    1518              : static const struct omp_pragma_def omp_pragmas[] = {
    1519              :   { "allocate", PRAGMA_OMP_ALLOCATE },
    1520              :   { "assumes", PRAGMA_OMP_ASSUMES },
    1521              :   { "atomic", PRAGMA_OMP_ATOMIC },
    1522              :   { "barrier", PRAGMA_OMP_BARRIER },
    1523              :   { "begin", PRAGMA_OMP_BEGIN },
    1524              :   { "cancel", PRAGMA_OMP_CANCEL },
    1525              :   { "cancellation", PRAGMA_OMP_CANCELLATION_POINT },
    1526              :   { "critical", PRAGMA_OMP_CRITICAL },
    1527              :   { "depobj", PRAGMA_OMP_DEPOBJ },
    1528              :   { "dispatch", PRAGMA_OMP_DISPATCH },
    1529              :   { "error", PRAGMA_OMP_ERROR },
    1530              :   { "end", PRAGMA_OMP_END },
    1531              :   { "flush", PRAGMA_OMP_FLUSH },
    1532              :   { "groupprivate", PRAGMA_OMP_GROUPPRIVATE },
    1533              :   { "interop", PRAGMA_OMP_INTEROP },
    1534              :   { "metadirective", PRAGMA_OMP_METADIRECTIVE },
    1535              :   { "nothing", PRAGMA_OMP_NOTHING },
    1536              :   { "requires", PRAGMA_OMP_REQUIRES },
    1537              :   { "scope", PRAGMA_OMP_SCOPE },
    1538              :   { "section", PRAGMA_OMP_SECTION },
    1539              :   { "sections", PRAGMA_OMP_SECTIONS },
    1540              :   { "single", PRAGMA_OMP_SINGLE },
    1541              :   { "task", PRAGMA_OMP_TASK },
    1542              :   { "taskgroup", PRAGMA_OMP_TASKGROUP },
    1543              :   { "taskwait", PRAGMA_OMP_TASKWAIT },
    1544              :   { "taskyield", PRAGMA_OMP_TASKYIELD },
    1545              :   { "threadprivate", PRAGMA_OMP_THREADPRIVATE }
    1546              : };
    1547              : static const struct omp_pragma_def omp_pragmas_simd[] = {
    1548              :   { "assume", PRAGMA_OMP_ASSUME },
    1549              :   { "declare", PRAGMA_OMP_DECLARE },
    1550              :   { "distribute", PRAGMA_OMP_DISTRIBUTE },
    1551              :   { "for", PRAGMA_OMP_FOR },
    1552              :   { "loop", PRAGMA_OMP_LOOP },
    1553              :   { "masked", PRAGMA_OMP_MASKED },
    1554              :   { "master", PRAGMA_OMP_MASTER },
    1555              :   { "ordered", PRAGMA_OMP_ORDERED },
    1556              :   { "parallel", PRAGMA_OMP_PARALLEL },
    1557              :   { "scan", PRAGMA_OMP_SCAN },
    1558              :   { "simd", PRAGMA_OMP_SIMD },
    1559              :   { "target", PRAGMA_OMP_TARGET },
    1560              :   { "taskloop", PRAGMA_OMP_TASKLOOP },
    1561              :   { "teams", PRAGMA_OMP_TEAMS },
    1562              :   { "tile", PRAGMA_OMP_TILE },
    1563              :   { "unroll", PRAGMA_OMP_UNROLL },
    1564              : };
    1565              : 
    1566              : void
    1567        33384 : c_pp_lookup_pragma (unsigned int id, const char **space, const char **name)
    1568              : {
    1569        33384 :   const int n_oacc_pragmas = ARRAY_SIZE (oacc_pragmas);
    1570        33384 :   const int n_omp_pragmas = ARRAY_SIZE (omp_pragmas);
    1571        33384 :   const int n_omp_pragmas_simd = ARRAY_SIZE (omp_pragmas_simd);
    1572        33384 :   int i;
    1573              : 
    1574       500760 :   for (i = 0; i < n_oacc_pragmas; ++i)
    1575       467376 :     if (oacc_pragmas[i].id == id)
    1576              :       {
    1577            0 :         *space = "acc";
    1578            0 :         *name = oacc_pragmas[i].name;
    1579            0 :         return;
    1580              :       }
    1581              : 
    1582       934530 :   for (i = 0; i < n_omp_pragmas; ++i)
    1583       901174 :     if (omp_pragmas[i].id == id)
    1584              :       {
    1585           28 :         *space = "omp";
    1586           28 :         *name = omp_pragmas[i].name;
    1587           28 :         return;
    1588              :       }
    1589              : 
    1590       566482 :   for (i = 0; i < n_omp_pragmas_simd; ++i)
    1591       533192 :     if (omp_pragmas_simd[i].id == id)
    1592              :       {
    1593           66 :         *space = "omp";
    1594           66 :         *name = omp_pragmas_simd[i].name;
    1595           66 :         return;
    1596              :       }
    1597              : 
    1598        33290 :   if (id >= PRAGMA_FIRST_EXTERNAL
    1599        66580 :       && (id < PRAGMA_FIRST_EXTERNAL + registered_pragmas.length ()))
    1600              :     {
    1601        33290 :       *space = registered_pragmas[id - PRAGMA_FIRST_EXTERNAL].space;
    1602        33290 :       *name = registered_pragmas[id - PRAGMA_FIRST_EXTERNAL].name;
    1603        33290 :       return;
    1604              :     }
    1605              : 
    1606            0 :   gcc_unreachable ();
    1607              : }
    1608              : 
    1609              : /* Front-end wrappers for pragma registration to avoid dragging
    1610              :    cpplib.h in almost everywhere.  */
    1611              : 
    1612              : static void
    1613      3698656 : c_register_pragma_1 (const char *space, const char *name,
    1614              :                      internal_pragma_handler ihandler, bool allow_expansion)
    1615              : {
    1616      3698656 :   unsigned id;
    1617              : 
    1618      3698656 :   pragma_data data;
    1619      3698656 :   data.space = space;
    1620      3698656 :   data.name = name;
    1621              : 
    1622      3698656 :   if (flag_preprocess_only
    1623       101505 :       && (cpp_get_options (parse_in)->directives_only
    1624       100080 :         || !(allow_expansion || ihandler.early_handler.handler_1arg)))
    1625        48129 :     return;
    1626              : 
    1627      3650527 :   data.ihandler = ihandler;
    1628      3650527 :   registered_pragmas.safe_push (data);
    1629      3650527 :   id = registered_pragmas.length ();
    1630      7301054 :   id += PRAGMA_FIRST_EXTERNAL - 1;
    1631              : 
    1632              :   /* The C front end allocates 8 bits in c_token.  The C++ front end
    1633              :      keeps the pragma kind in the form of INTEGER_CST, so no small
    1634              :      limit applies.  At present this is sufficient.  */
    1635      3650527 :   gcc_assert (id < 256);
    1636              : 
    1637      3650527 :   cpp_register_deferred_pragma (parse_in, space, name, id,
    1638              :                                 allow_expansion, false);
    1639              : }
    1640              : 
    1641              : /* Register a C pragma handler, using a space and a name.  It disallows pragma
    1642              :    expansion (if you want it, use c_register_pragma_with_expansion instead).  */
    1643              : void
    1644      2033336 : c_register_pragma (const char *space, const char *name,
    1645              :                    pragma_handler_1arg handler)
    1646              : {
    1647      2033336 :   c_register_pragma_with_early_handler (space, name, handler, nullptr);
    1648      2033336 : }
    1649      3282326 : void c_register_pragma_with_early_handler (const char *space, const char *name,
    1650              :                                            pragma_handler_1arg handler,
    1651              :                                            pragma_handler_1arg early_handler)
    1652              : {
    1653      3282326 :   internal_pragma_handler ihandler;
    1654              : 
    1655      3282326 :   ihandler.handler.handler_1arg = handler;
    1656      3282326 :   ihandler.early_handler.handler_1arg = early_handler;
    1657      3282326 :   ihandler.extra_data = false;
    1658      3282326 :   ihandler.data = NULL;
    1659      3282326 :   c_register_pragma_1 (space, name, ihandler, false);
    1660      3282326 : }
    1661              : 
    1662              : /* Register a C pragma handler, using a space and a name, it also carries an
    1663              :    extra data field which can be used by the handler.  It disallows pragma
    1664              :    expansion (if you want it, use c_register_pragma_with_expansion_and_data
    1665              :    instead).  */
    1666              : void
    1667            0 : c_register_pragma_with_data (const char *space, const char *name,
    1668              :                              pragma_handler_2arg handler, void * data)
    1669              : {
    1670            0 :   internal_pragma_handler ihandler;
    1671              : 
    1672            0 :   ihandler.handler.handler_2arg = handler;
    1673            0 :   ihandler.early_handler.handler_2arg = nullptr;
    1674            0 :   ihandler.extra_data = true;
    1675            0 :   ihandler.data = data;
    1676            0 :   c_register_pragma_1 (space, name, ihandler, false);
    1677            0 : }
    1678              : 
    1679              : /* Register a C pragma handler, using a space and a name.  It allows pragma
    1680              :    expansion as in the following example:
    1681              : 
    1682              :    #define NUMBER 10
    1683              :    #pragma count (NUMBER)
    1684              : 
    1685              :    Name expansion is still disallowed.  */
    1686              : void
    1687       416330 : c_register_pragma_with_expansion (const char *space, const char *name,
    1688              :                                   pragma_handler_1arg handler)
    1689              : {
    1690       416330 :   internal_pragma_handler ihandler;
    1691              : 
    1692       416330 :   ihandler.handler.handler_1arg = handler;
    1693       416330 :   ihandler.early_handler.handler_1arg = nullptr;
    1694       416330 :   ihandler.extra_data = false;
    1695       416330 :   ihandler.data = NULL;
    1696       416330 :   c_register_pragma_1 (space, name, ihandler, true);
    1697       416330 : }
    1698              : 
    1699              : /* Register a C pragma handler, using a space and a name, it also carries an
    1700              :    extra data field which can be used by the handler.  It allows pragma
    1701              :    expansion as in the following example:
    1702              : 
    1703              :    #define NUMBER 10
    1704              :    #pragma count (NUMBER)
    1705              : 
    1706              :    Name expansion is still disallowed.  */
    1707              : void
    1708            0 : c_register_pragma_with_expansion_and_data (const char *space, const char *name,
    1709              :                                            pragma_handler_2arg handler,
    1710              :                                            void *data)
    1711              : {
    1712            0 :   internal_pragma_handler ihandler;
    1713              : 
    1714            0 :   ihandler.handler.handler_2arg = handler;
    1715            0 :   ihandler.early_handler.handler_2arg = nullptr;
    1716            0 :   ihandler.extra_data = true;
    1717            0 :   ihandler.data = data;
    1718            0 :   c_register_pragma_1 (space, name, ihandler, true);
    1719            0 : }
    1720              : 
    1721              : void
    1722      8665385 : c_invoke_pragma_handler (unsigned int id)
    1723              : {
    1724      8665385 :   internal_pragma_handler *ihandler;
    1725      8665385 :   pragma_handler_1arg handler_1arg;
    1726      8665385 :   pragma_handler_2arg handler_2arg;
    1727              : 
    1728      8665385 :   id -= PRAGMA_FIRST_EXTERNAL;
    1729      8665385 :   ihandler = &registered_pragmas[id].ihandler;
    1730      8665385 :   if (ihandler->extra_data)
    1731              :     {
    1732            0 :       handler_2arg = ihandler->handler.handler_2arg;
    1733            0 :       handler_2arg (parse_in, ihandler->data);
    1734              :     }
    1735              :   else
    1736              :     {
    1737      8665385 :       handler_1arg = ihandler->handler.handler_1arg;
    1738      8665385 :       handler_1arg (parse_in);
    1739              :     }
    1740      8665385 : }
    1741              : 
    1742              : /* In contrast to the normal handler, the early handler is optional.  */
    1743              : void
    1744      6771094 : c_invoke_early_pragma_handler (unsigned int id)
    1745              : {
    1746      6771094 :   internal_pragma_handler *ihandler;
    1747      6771094 :   pragma_handler_1arg handler_1arg;
    1748      6771094 :   pragma_handler_2arg handler_2arg;
    1749              : 
    1750      6771094 :   id -= PRAGMA_FIRST_EXTERNAL;
    1751      6771094 :   ihandler = &registered_pragmas[id].ihandler;
    1752      6771094 :   if (ihandler->extra_data)
    1753              :     {
    1754            0 :       handler_2arg = ihandler->early_handler.handler_2arg;
    1755            0 :       if (handler_2arg)
    1756            0 :         handler_2arg (parse_in, ihandler->data);
    1757              :     }
    1758              :   else
    1759              :     {
    1760      6771094 :       handler_1arg = ihandler->early_handler.handler_1arg;
    1761      6771094 :       if (handler_1arg)
    1762      6536390 :         handler_1arg (parse_in);
    1763              :     }
    1764      6771094 : }
    1765              : 
    1766              : void
    1767        33290 : c_pp_invoke_early_pragma_handler (unsigned int id)
    1768              : {
    1769        33290 :   const auto data = &registered_pragmas[id - PRAGMA_FIRST_EXTERNAL];
    1770        33290 :   pragma_handler_1arg handler = data->ihandler.early_handler.handler_1arg;
    1771        33290 :   if (handler)
    1772              :     {
    1773        33272 :       handler (parse_in);
    1774        33272 :       pragma_lex_discard_to_eol ();
    1775              :     }
    1776        33290 : }
    1777              : 
    1778              : /* Set up front-end pragmas.  */
    1779              : void
    1780       208165 : init_pragma (void)
    1781              : {
    1782              : 
    1783       208165 :   if (!cpp_get_options (parse_in)->directives_only)
    1784              :     {
    1785       208037 :       if (flag_openacc)
    1786              :         {
    1787              :           const int n_oacc_pragmas = ARRAY_SIZE (oacc_pragmas);
    1788              :           int i;
    1789              : 
    1790        25110 :           for (i = 0; i < n_oacc_pragmas; ++i)
    1791        23436 :             cpp_register_deferred_pragma (parse_in, "acc", oacc_pragmas[i].name,
    1792        23436 :                                           oacc_pragmas[i].id, true, true);
    1793              :         }
    1794              : 
    1795       208037 :       if (flag_openmp)
    1796              :         {
    1797              :           const int n_omp_pragmas = ARRAY_SIZE (omp_pragmas);
    1798              :           int i;
    1799              : 
    1800       177268 :           for (i = 0; i < n_omp_pragmas; ++i)
    1801       170937 :             cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas[i].name,
    1802       170937 :                                           omp_pragmas[i].id, true, true);
    1803              :         }
    1804       208037 :       if (flag_openmp || flag_openmp_simd)
    1805              :         {
    1806              :           const int n_omp_pragmas_simd = ARRAY_SIZE (omp_pragmas_simd);
    1807              :           int i;
    1808              : 
    1809       114818 :           for (i = 0; i < n_omp_pragmas_simd; ++i)
    1810       108064 :             cpp_register_deferred_pragma (parse_in, "omp",
    1811       108064 :                                           omp_pragmas_simd[i].name,
    1812       108064 :                                           omp_pragmas_simd[i].id, true, true);
    1813              :         }
    1814              :     }
    1815              : 
    1816       208165 :   if (!flag_preprocess_only)
    1817       201398 :     cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
    1818              :                                   PRAGMA_GCC_PCH_PREPROCESS, false, false);
    1819              : 
    1820       208165 :   if (!flag_preprocess_only)
    1821       201398 :     cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false,
    1822              :                                   false);
    1823              : 
    1824       208165 :   if (!flag_preprocess_only)
    1825       201398 :     cpp_register_deferred_pragma (parse_in, "GCC", "unroll", PRAGMA_UNROLL,
    1826              :                                   false, false);
    1827              : 
    1828       208165 :   if (!flag_preprocess_only)
    1829       201398 :     cpp_register_deferred_pragma (parse_in, "GCC", "novector", PRAGMA_NOVECTOR,
    1830              :                                   false, false);
    1831              : 
    1832              : #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
    1833              :   c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
    1834              : #else
    1835       208165 :   c_register_pragma (0, "pack", handle_pragma_pack);
    1836              : #endif
    1837       208165 :   c_register_pragma (0, "weak", handle_pragma_weak);
    1838              : 
    1839       208165 :   c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
    1840              : 
    1841       208165 :   if (flag_preprocess_only)
    1842         6767 :     c_register_pragma_with_early_handler ("GCC", "diagnostic",
    1843              :                                           nullptr,
    1844              :                                           handle_pragma_diagnostic_early_pp);
    1845              :   else
    1846       201398 :     c_register_pragma_with_early_handler ("GCC", "diagnostic",
    1847              :                                           handle_pragma_diagnostic,
    1848              :                                           handle_pragma_diagnostic_early);
    1849       208165 :   c_register_pragma_with_early_handler ("GCC", "target",
    1850              :                                         handle_pragma_target,
    1851              :                                         handle_pragma_target);
    1852       208165 :   c_register_pragma_with_early_handler ("GCC", "optimize",
    1853              :                                         handle_pragma_optimize,
    1854              :                                         handle_pragma_optimize);
    1855       208165 :   c_register_pragma_with_early_handler ("GCC", "push_options",
    1856              :                                         handle_pragma_push_options,
    1857              :                                         handle_pragma_push_options);
    1858       208165 :   c_register_pragma_with_early_handler ("GCC", "pop_options",
    1859              :                                         handle_pragma_pop_options,
    1860              :                                         handle_pragma_pop_options);
    1861       208165 :   c_register_pragma_with_early_handler ("GCC", "reset_options",
    1862              :                                         handle_pragma_reset_options,
    1863              :                                         handle_pragma_reset_options);
    1864              : 
    1865       208165 :   c_register_pragma (0, "region", handle_pragma_ignore);
    1866       208165 :   c_register_pragma (0, "endregion", handle_pragma_ignore);
    1867              : 
    1868       208165 :   c_register_pragma ("STDC", "FLOAT_CONST_DECIMAL64",
    1869              :                      handle_pragma_float_const_decimal64);
    1870              : 
    1871       208165 :   c_register_pragma_with_expansion (0, "redefine_extname",
    1872              :                                     handle_pragma_redefine_extname);
    1873              : 
    1874       208165 :   c_register_pragma_with_expansion (0, "message", handle_pragma_message);
    1875              : 
    1876              : #ifdef REGISTER_TARGET_PRAGMAS
    1877       208165 :   REGISTER_TARGET_PRAGMAS ();
    1878              : #endif
    1879              : 
    1880       208165 :   global_sso = default_sso;
    1881       208165 :   c_register_pragma (0, "scalar_storage_order",
    1882              :                      handle_pragma_scalar_storage_order);
    1883              : 
    1884              :   /* Allow plugins to register their own pragmas. */
    1885       208165 :   invoke_plugin_callbacks (PLUGIN_PRAGMAS, NULL);
    1886       208165 : }
    1887              : 
    1888              : #include "gt-c-family-c-pragma.h"
        

Generated by: LCOV version 2.4-beta

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