]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libcpp/directives.c
* config/microblaze/microblaze.c (microblaze_expand_block_move): Treat
[thirdparty/gcc.git] / libcpp / directives.c
index b60b7bca8003bff2c131c6840bf28a2e47e76702..1ada834da17482ebd75fd9ed57312b0e41cd24a7 100644 (file)
@@ -1,13 +1,12 @@
 /* CPP Library. (Directive handling.)
 /* CPP Library. (Directive handling.)
-   Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1986-2019 Free Software Foundation, Inc.
    Contributed by Per Bothner, 1994-95.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
    Contributed by Per Bothner, 1994-95.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
 
 This program is distributed in the hope that it will be useful,
 later version.
 
 This program is distributed in the hope that it will be useful,
@@ -16,8 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+along with this program; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -31,7 +30,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 struct if_stack
 {
   struct if_stack *next;
 struct if_stack
 {
   struct if_stack *next;
-  unsigned int line;           /* Line where condition started.  */
+  location_t line;             /* Line where condition started.  */
   const cpp_hashnode *mi_cmacro;/* macro name for #ifndef around entire file */
   bool skip_elses;             /* Can future #else / #elif be skipped?  */
   bool was_skipping;           /* If were skipping on entry.  */
   const cpp_hashnode *mi_cmacro;/* macro name for #ifndef around entire file */
   bool skip_elses;             /* Can future #else / #elif be skipped?  */
   bool was_skipping;           /* If were skipping on entry.  */
@@ -46,9 +45,12 @@ struct pragma_entry
   const cpp_hashnode *pragma;  /* Name and length.  */
   bool is_nspace;
   bool is_internal;
   const cpp_hashnode *pragma;  /* Name and length.  */
   bool is_nspace;
   bool is_internal;
+  bool is_deferred;
+  bool allow_expansion;
   union {
     pragma_cb handler;
     struct pragma_entry *space;
   union {
     pragma_cb handler;
     struct pragma_entry *space;
+    unsigned int ident;
   } u;
 };
 
   } u;
 };
 
@@ -71,6 +73,7 @@ struct pragma_entry
 #define INCL           (1 << 2)
 #define IN_I           (1 << 3)
 #define EXPAND         (1 << 4)
 #define INCL           (1 << 2)
 #define IN_I           (1 << 3)
 #define EXPAND         (1 << 4)
+#define DEPRECATED     (1 << 5)
 
 /* Defines one #-directive, including how to handle it.  */
 typedef void (*directive_handler) (cpp_reader *);
 
 /* Defines one #-directive, including how to handle it.  */
 typedef void (*directive_handler) (cpp_reader *);
@@ -87,30 +90,25 @@ struct directive
 /* Forward declarations.  */
 
 static void skip_rest_of_line (cpp_reader *);
 /* Forward declarations.  */
 
 static void skip_rest_of_line (cpp_reader *);
-static void check_eol (cpp_reader *);
+static void check_eol (cpp_reader *, bool);
 static void start_directive (cpp_reader *);
 static void prepare_directive_trad (cpp_reader *);
 static void end_directive (cpp_reader *, int);
 static void directive_diagnostics (cpp_reader *, const directive *, int);
 static void run_directive (cpp_reader *, int, const char *, size_t);
 static char *glue_header_name (cpp_reader *);
 static void start_directive (cpp_reader *);
 static void prepare_directive_trad (cpp_reader *);
 static void end_directive (cpp_reader *, int);
 static void directive_diagnostics (cpp_reader *, const directive *, int);
 static void run_directive (cpp_reader *, int, const char *, size_t);
 static char *glue_header_name (cpp_reader *);
-static const char *parse_include (cpp_reader *, int *);
+static const char *parse_include (cpp_reader *, int *, const cpp_token ***,
+                                 location_t *);
 static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *);
 static unsigned int read_flag (cpp_reader *, unsigned int);
 static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *);
 static unsigned int read_flag (cpp_reader *, unsigned int);
-static int strtoul_for_line (const uchar *, unsigned int, unsigned long *);
-static void do_diagnostic (cpp_reader *, int, int);
-static cpp_hashnode *lex_macro_node (cpp_reader *);
+static bool strtolinenum (const uchar *, size_t, linenum_type *, bool *);
+static void do_diagnostic (cpp_reader *, enum cpp_diagnostic_level code,
+                          enum cpp_warning_reason reason, int);
+static cpp_hashnode *lex_macro_node (cpp_reader *, bool);
 static int undefine_macros (cpp_reader *, cpp_hashnode *, void *);
 static void do_include_common (cpp_reader *, enum include_type);
 static struct pragma_entry *lookup_pragma_entry (struct pragma_entry *,
                                                  const cpp_hashnode *);
 static int undefine_macros (cpp_reader *, cpp_hashnode *, void *);
 static void do_include_common (cpp_reader *, enum include_type);
 static struct pragma_entry *lookup_pragma_entry (struct pragma_entry *,
                                                  const cpp_hashnode *);
-static struct pragma_entry *insert_pragma_entry (cpp_reader *,
-                                                 struct pragma_entry **,
-                                                 const cpp_hashnode *,
-                                                 pragma_cb,
-                                                bool);
-static void register_pragma (cpp_reader *, const char *, const char *,
-                            pragma_cb, bool);
 static int count_registered_pragmas (struct pragma_entry *);
 static char ** save_registered_pragmas (struct pragma_entry *, char **);
 static char ** restore_registered_pragmas (cpp_reader *, struct pragma_entry *,
 static int count_registered_pragmas (struct pragma_entry *);
 static char ** save_registered_pragmas (struct pragma_entry *, char **);
 static char ** restore_registered_pragmas (cpp_reader *, struct pragma_entry *,
@@ -119,44 +117,49 @@ static void do_pragma_once (cpp_reader *);
 static void do_pragma_poison (cpp_reader *);
 static void do_pragma_system_header (cpp_reader *);
 static void do_pragma_dependency (cpp_reader *);
 static void do_pragma_poison (cpp_reader *);
 static void do_pragma_system_header (cpp_reader *);
 static void do_pragma_dependency (cpp_reader *);
+static void do_pragma_warning_or_error (cpp_reader *, bool error);
+static void do_pragma_warning (cpp_reader *);
+static void do_pragma_error (cpp_reader *);
 static void do_linemarker (cpp_reader *);
 static const cpp_token *get_token_no_padding (cpp_reader *);
 static const cpp_token *get__Pragma_string (cpp_reader *);
 static void do_linemarker (cpp_reader *);
 static const cpp_token *get_token_no_padding (cpp_reader *);
 static const cpp_token *get__Pragma_string (cpp_reader *);
-static void destringize_and_run (cpp_reader *, const cpp_string *);
-static int parse_answer (cpp_reader *, struct answer **, int);
-static cpp_hashnode *parse_assertion (cpp_reader *, struct answer **, int);
-static struct answer ** find_answer (cpp_hashnode *, const struct answer *);
+static void destringize_and_run (cpp_reader *, const cpp_string *,
+                                location_t);
+static bool parse_answer (cpp_reader *, int, location_t, cpp_macro **);
+static cpp_hashnode *parse_assertion (cpp_reader *, int, cpp_macro **);
+static cpp_macro **find_answer (cpp_hashnode *, const cpp_macro *);
 static void handle_assertion (cpp_reader *, const char *, int);
 static void handle_assertion (cpp_reader *, const char *, int);
+static void do_pragma_push_macro (cpp_reader *);
+static void do_pragma_pop_macro (cpp_reader *);
+static void cpp_pop_definition (cpp_reader *, struct def_pragma_macro *);
 
 
-/* This is the table of directive handlers.  It is ordered by
-   frequency of occurrence; the numbers at the end are directive
-   counts from all the source code I have lying around (egcs and libc
-   CVS as of 1999-05-18, plus grub-0.5.91, linux-2.2.9, and
-   pcmcia-cs-3.0.9).  This is no longer important as directive lookup
-   is now O(1).  All extensions other than #warning and #include_next
-   are deprecated.  The name is where the extension appears to have
-   come from.  */
+/* This is the table of directive handlers.  All extensions other than
+   #warning, #include_next, and #import are deprecated.  The name is
+   where the extension appears to have come from.  */
 
 #define DIRECTIVE_TABLE                                                        \
 
 #define DIRECTIVE_TABLE                                                        \
-D(define,      T_DEFINE = 0,   KANDR,     IN_I)           /* 270554 */ \
-D(include,     T_INCLUDE,      KANDR,     INCL | EXPAND)  /*  52262 */ \
-D(endif,       T_ENDIF,        KANDR,     COND)           /*  45855 */ \
-D(ifdef,       T_IFDEF,        KANDR,     COND | IF_COND) /*  22000 */ \
-D(if,          T_IF,           KANDR, COND | IF_COND | EXPAND) /*  18162 */ \
-D(else,                T_ELSE,         KANDR,     COND)           /*   9863 */ \
-D(ifndef,      T_IFNDEF,       KANDR,     COND | IF_COND) /*   9675 */ \
-D(undef,       T_UNDEF,        KANDR,     IN_I)           /*   4837 */ \
-D(line,                T_LINE,         KANDR,     EXPAND)         /*   2465 */ \
-D(elif,                T_ELIF,         STDC89,    COND | EXPAND)  /*    610 */ \
-D(error,       T_ERROR,        STDC89,    0)              /*    475 */ \
-D(pragma,      T_PRAGMA,       STDC89,    IN_I)           /*    195 */ \
-D(warning,     T_WARNING,      EXTENSION, 0)              /*     22 */ \
-D(include_next,        T_INCLUDE_NEXT, EXTENSION, INCL | EXPAND)  /*     19 */ \
-D(ident,       T_IDENT,        EXTENSION, IN_I)           /*     11 */ \
-D(import,      T_IMPORT,       EXTENSION, INCL | EXPAND)  /* 0 ObjC */ \
-D(assert,      T_ASSERT,       EXTENSION, 0)              /* 0 SVR4 */ \
-D(unassert,    T_UNASSERT,     EXTENSION, 0)              /* 0 SVR4 */ \
-D(sccs,                T_SCCS,         EXTENSION, 0)              /* 0 SVR4? */
+  D(define,    T_DEFINE = 0,   KANDR,     IN_I)                        \
+  D(include,   T_INCLUDE,      KANDR,     INCL | EXPAND)               \
+  D(endif,     T_ENDIF,        KANDR,     COND)                        \
+  D(ifdef,     T_IFDEF,        KANDR,     COND | IF_COND)              \
+  D(if,                T_IF,           KANDR,     COND | IF_COND | EXPAND)     \
+  D(else,      T_ELSE,         KANDR,     COND)                        \
+  D(ifndef,    T_IFNDEF,       KANDR,     COND | IF_COND)              \
+  D(undef,     T_UNDEF,        KANDR,     IN_I)                        \
+  D(line,      T_LINE,         KANDR,     EXPAND)                      \
+  D(elif,      T_ELIF,         STDC89,    COND | EXPAND)               \
+  D(error,     T_ERROR,        STDC89,    0)                           \
+  D(pragma,    T_PRAGMA,       STDC89,    IN_I)                        \
+  D(warning,   T_WARNING,      EXTENSION, 0)                           \
+  D(include_next, T_INCLUDE_NEXT, EXTENSION, INCL | EXPAND)            \
+  D(ident,     T_IDENT,        EXTENSION, IN_I)                        \
+  D(import,    T_IMPORT,       EXTENSION, INCL | EXPAND)  /* ObjC */   \
+  D(assert,    T_ASSERT,       EXTENSION, DEPRECATED)     /* SVR4 */   \
+  D(unassert,  T_UNASSERT,     EXTENSION, DEPRECATED)     /* SVR4 */   \
+  D(sccs,      T_SCCS,         EXTENSION, IN_I)           /*  SVR4? */
+
+/* #sccs is synonymous with #ident.  */
+#define do_sccs do_ident
 
 /* Use the table to generate a series of prototypes, an enum for the
    directive names, and an array of directive handlers.  */
 
 /* Use the table to generate a series of prototypes, an enum for the
    directive names, and an array of directive handlers.  */
@@ -181,6 +184,16 @@ static const directive dtable[] =
 DIRECTIVE_TABLE
 };
 #undef D
 DIRECTIVE_TABLE
 };
 #undef D
+
+/* A NULL-terminated array of directive names for use
+   when suggesting corrections for misspelled directives.  */
+#define D(name, t, origin, flags) #name,
+static const char * const directive_names[] = {
+DIRECTIVE_TABLE
+  NULL
+};
+#undef D
+
 #undef DIRECTIVE_TABLE
 
 /* Wrapper struct directive for linemarkers.
 #undef DIRECTIVE_TABLE
 
 /* Wrapper struct directive for linemarkers.
@@ -188,11 +201,9 @@ DIRECTIVE_TABLE
    did use this notation in its preprocessed output.  */
 static const directive linemarker_dir =
 {
    did use this notation in its preprocessed output.  */
 static const directive linemarker_dir =
 {
-  do_linemarker, U"#", 1, KANDR, IN_I
+  do_linemarker, UC"#", 1, KANDR, IN_I
 };
 
 };
 
-#define SEEN_EOL() (pfile->cur_token[-1].type == CPP_EOF)
-
 /* Skip any remaining tokens in a directive.  */
 static void
 skip_rest_of_line (cpp_reader *pfile)
 /* Skip any remaining tokens in a directive.  */
 static void
 skip_rest_of_line (cpp_reader *pfile)
@@ -207,13 +218,73 @@ skip_rest_of_line (cpp_reader *pfile)
       ;
 }
 
       ;
 }
 
-/* Ensure there are no stray tokens at the end of a directive.  */
+/* Helper function for check_oel.  */
+
 static void
 static void
-check_eol (cpp_reader *pfile)
+check_eol_1 (cpp_reader *pfile, bool expand, enum cpp_warning_reason reason)
 {
 {
-  if (! SEEN_EOL () && _cpp_lex_token (pfile)->type != CPP_EOF)
-    cpp_error (pfile, CPP_DL_PEDWARN, "extra tokens at end of #%s directive",
-              pfile->directive->name);
+  if (! SEEN_EOL () && (expand
+                       ? cpp_get_token (pfile)
+                       : _cpp_lex_token (pfile))->type != CPP_EOF)
+    cpp_pedwarning (pfile, reason, "extra tokens at end of #%s directive",
+                   pfile->directive->name);
+}
+
+/* Variant of check_eol used for Wendif-labels warnings.  */
+
+static void
+check_eol_endif_labels (cpp_reader *pfile)
+{
+  check_eol_1 (pfile, false, CPP_W_ENDIF_LABELS);
+}
+
+/* Ensure there are no stray tokens at the end of a directive.  If
+   EXPAND is true, tokens macro-expanding to nothing are allowed.  */
+
+static void
+check_eol (cpp_reader *pfile, bool expand)
+{
+  check_eol_1 (pfile, expand, CPP_W_NONE);
+}
+
+/* Ensure there are no stray tokens other than comments at the end of
+   a directive, and gather the comments.  */
+static const cpp_token **
+check_eol_return_comments (cpp_reader *pfile)
+{
+  size_t c;
+  size_t capacity = 8;
+  const cpp_token **buf;
+
+  buf = XNEWVEC (const cpp_token *, capacity);
+  c = 0;
+  if (! SEEN_EOL ())
+    {
+      while (1)
+       {
+         const cpp_token *tok;
+
+         tok = _cpp_lex_token (pfile);
+         if (tok->type == CPP_EOF)
+           break;
+         if (tok->type != CPP_COMMENT)
+           cpp_error (pfile, CPP_DL_PEDWARN,
+                      "extra tokens at end of #%s directive",
+                      pfile->directive->name);
+         else
+           {
+             if (c + 1 >= capacity)
+               {
+                 capacity *= 2;
+                 buf = XRESIZEVEC (const cpp_token *, buf, capacity);
+               }
+             buf[c] = tok;
+             ++c;
+           }
+       }
+    }
+  buf[c] = NULL;
+  return buf;
 }
 
 /* Called when entering a directive, _Pragma or command-line directive.  */
 }
 
 /* Called when entering a directive, _Pragma or command-line directive.  */
@@ -236,11 +307,14 @@ end_directive (cpp_reader *pfile, int skip_line)
   if (CPP_OPTION (pfile, traditional))
     {
       /* Revert change of prepare_directive_trad.  */
   if (CPP_OPTION (pfile, traditional))
     {
       /* Revert change of prepare_directive_trad.  */
-      pfile->state.prevent_expansion--;
+      if (!pfile->state.in_deferred_pragma)
+       pfile->state.prevent_expansion--;
 
       if (pfile->directive != &dtable[T_DEFINE])
        _cpp_remove_overlay (pfile);
     }
 
       if (pfile->directive != &dtable[T_DEFINE])
        _cpp_remove_overlay (pfile);
     }
+  else if (pfile->state.in_deferred_pragma)
+    ;
   /* We don't skip for an assembler #.  */
   else if (skip_line)
     {
   /* We don't skip for an assembler #.  */
   else if (skip_line)
     {
@@ -277,7 +351,7 @@ prepare_directive_trad (cpp_reader *pfile)
 
       if (no_expand)
        pfile->state.prevent_expansion++;
 
       if (no_expand)
        pfile->state.prevent_expansion++;
-      _cpp_scan_out_logical_line (pfile, NULL);
+      _cpp_scan_out_logical_line (pfile, NULL, false);
       if (no_expand)
        pfile->state.prevent_expansion--;
 
       if (no_expand)
        pfile->state.prevent_expansion--;
 
@@ -295,11 +369,20 @@ prepare_directive_trad (cpp_reader *pfile)
 static void
 directive_diagnostics (cpp_reader *pfile, const directive *dir, int indented)
 {
 static void
 directive_diagnostics (cpp_reader *pfile, const directive *dir, int indented)
 {
-  /* Issue -pedantic warnings for extensions.  */
-  if (CPP_PEDANTIC (pfile)
-      && ! pfile->state.skipping
-      && dir->origin == EXTENSION)
-    cpp_error (pfile, CPP_DL_PEDWARN, "#%s is a GCC extension", dir->name);
+  /* Issue -pedantic or deprecated warnings for extensions.  We let
+     -pedantic take precedence if both are applicable.  */
+  if (! pfile->state.skipping)
+    {
+      if (dir->origin == EXTENSION
+         && !(dir == &dtable[T_IMPORT] && CPP_OPTION (pfile, objc))
+         && CPP_PEDANTIC (pfile))
+       cpp_error (pfile, CPP_DL_PEDWARN, "#%s is a GCC extension", dir->name);
+      else if (((dir->flags & DEPRECATED) != 0
+               || (dir == &dtable[T_IMPORT] && !CPP_OPTION (pfile, objc)))
+              && CPP_OPTION (pfile, cpp_warn_deprecated))
+       cpp_warning (pfile, CPP_W_DEPRECATED,
+                     "#%s is a deprecated GCC extension", dir->name);
+    }
 
   /* Traditionally, a directive is ignored unless its # is in
      column 1.  Therefore in code intended to work with K+R
 
   /* Traditionally, a directive is ignored unless its # is in
      column 1.  Therefore in code intended to work with K+R
@@ -310,22 +393,22 @@ directive_diagnostics (cpp_reader *pfile, const directive *dir, int indented)
   if (CPP_WTRADITIONAL (pfile))
     {
       if (dir == &dtable[T_ELIF])
   if (CPP_WTRADITIONAL (pfile))
     {
       if (dir == &dtable[T_ELIF])
-       cpp_error (pfile, CPP_DL_WARNING,
-                  "suggest not using #elif in traditional C");
+       cpp_warning (pfile, CPP_W_TRADITIONAL,
+                    "suggest not using #elif in traditional C");
       else if (indented && dir->origin == KANDR)
       else if (indented && dir->origin == KANDR)
-       cpp_error (pfile, CPP_DL_WARNING,
-                  "traditional C ignores #%s with the # indented",
-                  dir->name);
+       cpp_warning (pfile, CPP_W_TRADITIONAL,
+                    "traditional C ignores #%s with the # indented",
+                    dir->name);
       else if (!indented && dir->origin != KANDR)
       else if (!indented && dir->origin != KANDR)
-       cpp_error (pfile, CPP_DL_WARNING,
-                  "suggest hiding #%s from traditional C with an indented #",
-                  dir->name);
+       cpp_warning (pfile, CPP_W_TRADITIONAL,
+                    "suggest hiding #%s from traditional C with an indented #",
+                    dir->name);
     }
 }
 
 /* Check if we have a known directive.  INDENTED is nonzero if the
    '#' of the directive was indented.  This function is in this file
     }
 }
 
 /* Check if we have a known directive.  INDENTED is nonzero if the
    '#' of the directive was indented.  This function is in this file
-   to save unnecessarily exporting dtable etc. to cpplex.c.  Returns
+   to save unnecessarily exporting dtable etc. to lex.c.  Returns
    nonzero if the line of tokens has been handled, zero if we should
    continue processing the line.  */
 int
    nonzero if the line of tokens has been handled, zero if we should
    continue processing the line.  */
 int
@@ -342,7 +425,7 @@ _cpp_handle_directive (cpp_reader *pfile, int indented)
 
   if (was_parsing_args)
     {
 
   if (was_parsing_args)
     {
-      if (CPP_OPTION (pfile, pedantic))
+      if (CPP_OPTION (pfile, cpp_pedantic))
        cpp_error (pfile, CPP_DL_PEDWARN,
             "embedding a directive within macro arguments is not portable");
       pfile->state.parsing_args = 0;
        cpp_error (pfile, CPP_DL_PEDWARN,
             "embedding a directive within macro arguments is not portable");
       pfile->state.parsing_args = 0;
@@ -353,8 +436,8 @@ _cpp_handle_directive (cpp_reader *pfile, int indented)
 
   if (dname->type == CPP_NAME)
     {
 
   if (dname->type == CPP_NAME)
     {
-      if (dname->val.node->is_directive)
-       dir = &dtable[dname->val.node->directive_index];
+      if (dname->val.node.node->is_directive)
+       dir = &dtable[dname->val.node.node->directive_index];
     }
   /* We do not recognize the # followed by a number extension in
      assembler code.  */
     }
   /* We do not recognize the # followed by a number extension in
      assembler code.  */
@@ -381,9 +464,14 @@ _cpp_handle_directive (cpp_reader *pfile, int indented)
 
         does not cause '#define foo bar' to get executed when
         compiled with -save-temps, we recognize directives in
 
         does not cause '#define foo bar' to get executed when
         compiled with -save-temps, we recognize directives in
-        -fpreprocessed mode only if the # is in column 1.  cppmacro.c
-        puts a space in front of any '#' at the start of a macro.  */
+        -fpreprocessed mode only if the # is in column 1.  macro.c
+        puts a space in front of any '#' at the start of a macro.
+        
+        We exclude the -fdirectives-only case because macro expansion
+        has not been performed yet, and block comments can cause spaces
+        to precede the directive.  */
       if (CPP_OPTION (pfile, preprocessed)
       if (CPP_OPTION (pfile, preprocessed)
+         && !CPP_OPTION (pfile, directives_only)
          && (indented || !(dir->flags & IN_I)))
        {
          skip = 0;
          && (indented || !(dir->flags & IN_I)))
        {
          skip = 0;
@@ -414,8 +502,35 @@ _cpp_handle_directive (cpp_reader *pfile, int indented)
       if (CPP_OPTION (pfile, lang) == CLK_ASM)
        skip = 0;
       else if (!pfile->state.skipping)
       if (CPP_OPTION (pfile, lang) == CLK_ASM)
        skip = 0;
       else if (!pfile->state.skipping)
-       cpp_error (pfile, CPP_DL_ERROR, "invalid preprocessing directive #%s",
-                  cpp_token_as_text (pfile, dname));
+       {
+         const char *unrecognized
+           = (const char *)cpp_token_as_text (pfile, dname);
+         const char *hint = NULL;
+
+         /* Call back into gcc to get a spelling suggestion.  Ideally
+            we'd just use best_match from gcc/spellcheck.h (and filter
+            out the uncommon directives), but that requires moving it
+            to a support library.  */
+         if (pfile->cb.get_suggestion)
+           hint = pfile->cb.get_suggestion (pfile, unrecognized,
+                                            directive_names);
+
+         if (hint)
+           {
+             rich_location richloc (pfile->line_table, dname->src_loc);
+             source_range misspelled_token_range
+               = get_range_from_loc (pfile->line_table, dname->src_loc);
+             richloc.add_fixit_replace (misspelled_token_range, hint);
+             cpp_error_at (pfile, CPP_DL_ERROR, &richloc,
+                           "invalid preprocessing directive #%s;"
+                           " did you mean #%s?",
+                           unrecognized, hint);
+           }
+         else
+           cpp_error (pfile, CPP_DL_ERROR,
+                      "invalid preprocessing directive #%s",
+                      unrecognized);
+       }
     }
 
   pfile->directive = dir;
     }
 
   pfile->directive = dir;
@@ -428,7 +543,7 @@ _cpp_handle_directive (cpp_reader *pfile, int indented)
     _cpp_backup_tokens (pfile, 1);
 
   end_directive (pfile, skip);
     _cpp_backup_tokens (pfile, 1);
 
   end_directive (pfile, skip);
-  if (was_parsing_args)
+  if (was_parsing_args && !pfile->state.in_deferred_pragma)
     {
       /* Restore state when within macro args.  */
       pfile->state.parsing_args = 2;
     {
       /* Restore state when within macro args.  */
       pfile->state.parsing_args = 2;
@@ -446,9 +561,6 @@ run_directive (cpp_reader *pfile, int dir_no, const char *buf, size_t count)
 {
   cpp_push_buffer (pfile, (const uchar *) buf, count,
                   /* from_stage3 */ true);
 {
   cpp_push_buffer (pfile, (const uchar *) buf, count,
                   /* from_stage3 */ true);
-  /* Disgusting hack.  */
-  if (dir_no == T_PRAGMA && pfile->buffer->prev)
-    pfile->buffer->file = pfile->buffer->prev->file;
   start_directive (pfile);
 
   /* This is a short-term fix to prevent a leading '#' being
   start_directive (pfile);
 
   /* This is a short-term fix to prevent a leading '#' being
@@ -460,15 +572,15 @@ run_directive (cpp_reader *pfile, int dir_no, const char *buf, size_t count)
     prepare_directive_trad (pfile);
   pfile->directive->handler (pfile);
   end_directive (pfile, 1);
     prepare_directive_trad (pfile);
   pfile->directive->handler (pfile);
   end_directive (pfile, 1);
-  if (dir_no == T_PRAGMA)
-    pfile->buffer->file = NULL;
   _cpp_pop_buffer (pfile);
 }
 
 /* Checks for validity the macro name in #define, #undef, #ifdef and
   _cpp_pop_buffer (pfile);
 }
 
 /* Checks for validity the macro name in #define, #undef, #ifdef and
-   #ifndef directives.  */
+   #ifndef directives.  IS_DEF_OR_UNDEF is true if this call is
+   processing a #define or #undefine directive, and false
+   otherwise.  */
 static cpp_hashnode *
 static cpp_hashnode *
-lex_macro_node (cpp_reader *pfile)
+lex_macro_node (cpp_reader *pfile, bool is_def_or_undef)
 {
   const cpp_token *token = _cpp_lex_token (pfile);
 
 {
   const cpp_token *token = _cpp_lex_token (pfile);
 
@@ -481,18 +593,23 @@ lex_macro_node (cpp_reader *pfile)
 
   if (token->type == CPP_NAME)
     {
 
   if (token->type == CPP_NAME)
     {
-      cpp_hashnode *node = token->val.node;
+      cpp_hashnode *node = token->val.node.node;
 
 
-      if (node == pfile->spec_nodes.n_defined)
+      if (is_def_or_undef && node == pfile->spec_nodes.n_defined)
        cpp_error (pfile, CPP_DL_ERROR,
                   "\"defined\" cannot be used as a macro name");
        cpp_error (pfile, CPP_DL_ERROR,
                   "\"defined\" cannot be used as a macro name");
+      else if (is_def_or_undef
+           && (node == pfile->spec_nodes.n__has_include__
+            || node == pfile->spec_nodes.n__has_include_next__))
+       cpp_error (pfile, CPP_DL_ERROR,
+                  "\"__has_include__\" cannot be used as a macro name");
       else if (! (node->flags & NODE_POISONED))
        return node;
     }
   else if (token->flags & NAMED_OP)
     cpp_error (pfile, CPP_DL_ERROR,
        "\"%s\" cannot be used as a macro name as it is an operator in C++",
       else if (! (node->flags & NODE_POISONED))
        return node;
     }
   else if (token->flags & NAMED_OP)
     cpp_error (pfile, CPP_DL_ERROR,
        "\"%s\" cannot be used as a macro name as it is an operator in C++",
-              NODE_NAME (token->val.node));
+              NODE_NAME (token->val.node.node));
   else if (token->type == CPP_EOF)
     cpp_error (pfile, CPP_DL_ERROR, "no macro name given in #%s directive",
               pfile->directive->name);
   else if (token->type == CPP_EOF)
     cpp_error (pfile, CPP_DL_ERROR, "no macro name given in #%s directive",
               pfile->directive->name);
@@ -502,11 +619,11 @@ lex_macro_node (cpp_reader *pfile)
   return NULL;
 }
 
   return NULL;
 }
 
-/* Process a #define directive.  Most work is done in cppmacro.c.  */
+/* Process a #define directive.  Most work is done in macro.c.  */
 static void
 do_define (cpp_reader *pfile)
 {
 static void
 do_define (cpp_reader *pfile)
 {
-  cpp_hashnode *node = lex_macro_node (pfile);
+  cpp_hashnode *node = lex_macro_node (pfile, true);
 
   if (node)
     {
 
   if (node)
     {
@@ -515,9 +632,14 @@ do_define (cpp_reader *pfile)
       pfile->state.save_comments =
        ! CPP_OPTION (pfile, discard_comments_in_macro_exp);
 
       pfile->state.save_comments =
        ! CPP_OPTION (pfile, discard_comments_in_macro_exp);
 
+      if (pfile->cb.before_define)
+       pfile->cb.before_define (pfile);
+
       if (_cpp_create_definition (pfile, node))
        if (pfile->cb.define)
          pfile->cb.define (pfile, pfile->directive_line, node);
       if (_cpp_create_definition (pfile, node))
        if (pfile->cb.define)
          pfile->cb.define (pfile, pfile->directive_line, node);
+
+      node->flags &= ~NODE_USED;
     }
 }
 
     }
 }
 
@@ -525,20 +647,28 @@ do_define (cpp_reader *pfile)
 static void
 do_undef (cpp_reader *pfile)
 {
 static void
 do_undef (cpp_reader *pfile)
 {
-  cpp_hashnode *node = lex_macro_node (pfile);
+  cpp_hashnode *node = lex_macro_node (pfile, true);
 
   if (node)
     {
 
   if (node)
     {
+      if (pfile->cb.before_define)
+       pfile->cb.before_define (pfile);
+
       if (pfile->cb.undef)
        pfile->cb.undef (pfile, pfile->directive_line, node);
 
       /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified
         identifier is not currently defined as a macro name.  */
       if (pfile->cb.undef)
        pfile->cb.undef (pfile, pfile->directive_line, node);
 
       /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified
         identifier is not currently defined as a macro name.  */
-      if (node->type == NT_MACRO)
+      if (cpp_macro_p (node))
        {
          if (node->flags & NODE_WARN)
            cpp_error (pfile, CPP_DL_WARNING,
                       "undefining \"%s\"", NODE_NAME (node));
        {
          if (node->flags & NODE_WARN)
            cpp_error (pfile, CPP_DL_WARNING,
                       "undefining \"%s\"", NODE_NAME (node));
+         else if (cpp_builtin_macro_p (node)
+                  && CPP_OPTION (pfile, warn_builtin_macro_redefined))
+           cpp_warning_with_line (pfile, CPP_W_BUILTIN_MACRO_REDEFINED,
+                                  pfile->directive_line, 0,
+                                  "undefining \"%s\"", NODE_NAME (node));
 
          if (CPP_OPTION (pfile, warn_unused_macros))
            _cpp_warn_if_unused_macro (pfile, node, NULL);
 
          if (CPP_OPTION (pfile, warn_unused_macros))
            _cpp_warn_if_unused_macro (pfile, node, NULL);
@@ -547,7 +677,7 @@ do_undef (cpp_reader *pfile)
        }
     }
 
        }
     }
 
-  check_eol (pfile);
+  check_eol (pfile, false);
 }
 
 /* Undefine a single macro/assertion/whatever.  */
 }
 
 /* Undefine a single macro/assertion/whatever.  */
@@ -559,7 +689,8 @@ undefine_macros (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *h,
   /* Body of _cpp_free_definition inlined here for speed.
      Macros and assertions no longer have anything to free.  */
   h->type = NT_VOID;
   /* Body of _cpp_free_definition inlined here for speed.
      Macros and assertions no longer have anything to free.  */
   h->type = NT_VOID;
-  h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED);
+  h->value.answers = NULL;
+  h->flags &= ~(NODE_POISONED|NODE_DISABLED|NODE_USED);
   return 1;
 }
 
   return 1;
 }
 
@@ -584,7 +715,7 @@ glue_header_name (cpp_reader *pfile)
 
   /* To avoid lexed tokens overwriting our glued name, we can only
      allocate from the string pool once we've lexed everything.  */
 
   /* To avoid lexed tokens overwriting our glued name, we can only
      allocate from the string pool once we've lexed everything.  */
-  buffer = xmalloc (capacity);
+  buffer = XNEWVEC (char, capacity);
   for (;;)
     {
       token = get_token_no_padding (pfile);
   for (;;)
     {
       token = get_token_no_padding (pfile);
@@ -601,13 +732,14 @@ glue_header_name (cpp_reader *pfile)
       if (total_len + len > capacity)
        {
          capacity = (capacity + len) * 2;
       if (total_len + len > capacity)
        {
          capacity = (capacity + len) * 2;
-         buffer = xrealloc (buffer, capacity);
+         buffer = XRESIZEVEC (char, buffer, capacity);
        }
 
       if (token->flags & PREV_WHITE)
        buffer[total_len++] = ' ';
 
        }
 
       if (token->flags & PREV_WHITE)
        buffer[total_len++] = ' ';
 
-      total_len = (cpp_spell_token (pfile, token, (uchar *) &buffer[total_len])
+      total_len = (cpp_spell_token (pfile, token, (uchar *) &buffer[total_len],
+                                   true)
                   - (uchar *) buffer);
     }
 
                   - (uchar *) buffer);
     }
 
@@ -617,18 +749,23 @@ glue_header_name (cpp_reader *pfile)
 
 /* Returns the file name of #include, #include_next, #import and
    #pragma dependency.  The string is malloced and the caller should
 
 /* Returns the file name of #include, #include_next, #import and
    #pragma dependency.  The string is malloced and the caller should
-   free it.  Returns NULL on error.  */
+   free it.  Returns NULL on error.  LOCATION is the source location
+   of the file name.  */
+
 static const char *
 static const char *
-parse_include (cpp_reader *pfile, int *pangle_brackets)
+parse_include (cpp_reader *pfile, int *pangle_brackets,
+              const cpp_token ***buf, location_t *location)
 {
   char *fname;
   const cpp_token *header;
 
   /* Allow macro expansion.  */
   header = get_token_no_padding (pfile);
 {
   char *fname;
   const cpp_token *header;
 
   /* Allow macro expansion.  */
   header = get_token_no_padding (pfile);
-  if (header->type == CPP_STRING || header->type == CPP_HEADER_NAME)
+  *location = header->src_loc;
+  if ((header->type == CPP_STRING && header->val.str.text[0] != 'R')
+      || header->type == CPP_HEADER_NAME)
     {
     {
-      fname = xmalloc (header->val.str.len - 1);
+      fname = XNEWVEC (char, header->val.str.len - 1);
       memcpy (fname, header->val.str.text + 1, header->val.str.len - 2);
       fname[header->val.str.len - 2] = '\0';
       *pangle_brackets = header->type == CPP_HEADER_NAME;
       memcpy (fname, header->val.str.text + 1, header->val.str.len - 2);
       fname[header->val.str.len - 2] = '\0';
       *pangle_brackets = header->type == CPP_HEADER_NAME;
@@ -643,7 +780,7 @@ parse_include (cpp_reader *pfile, int *pangle_brackets)
       const unsigned char *dir;
 
       if (pfile->directive == &dtable[T_PRAGMA])
       const unsigned char *dir;
 
       if (pfile->directive == &dtable[T_PRAGMA])
-       dir = U"pragma dependency";
+       dir = UC"pragma dependency";
       else
        dir = pfile->directive->name;
       cpp_error (pfile, CPP_DL_ERROR, "#%s expects \"FILENAME\" or <FILENAME>",
       else
        dir = pfile->directive->name;
       cpp_error (pfile, CPP_DL_ERROR, "#%s expects \"FILENAME\" or <FILENAME>",
@@ -652,7 +789,19 @@ parse_include (cpp_reader *pfile, int *pangle_brackets)
       return NULL;
     }
 
       return NULL;
     }
 
-  check_eol (pfile);
+  if (pfile->directive == &dtable[T_PRAGMA])
+    {
+      /* This pragma allows extra tokens after the file name.  */
+    }
+  else if (buf == NULL || CPP_OPTION (pfile, discard_comments))
+    check_eol (pfile, true);
+  else
+    {
+      /* If we are not discarding comments, then gather them while
+        doing the eol check.  */
+      *buf = check_eol_return_comments (pfile);
+    }
+
   return fname;
 }
 
   return fname;
 }
 
@@ -662,10 +811,24 @@ do_include_common (cpp_reader *pfile, enum include_type type)
 {
   const char *fname;
   int angle_brackets;
 {
   const char *fname;
   int angle_brackets;
+  const cpp_token **buf = NULL;
+  location_t location;
+
+  /* Re-enable saving of comments if requested, so that the include
+     callback can dump comments which follow #include.  */
+  pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
 
 
-  fname = parse_include (pfile, &angle_brackets);
+  fname = parse_include (pfile, &angle_brackets, &buf, &location);
   if (!fname)
   if (!fname)
-    return;
+    goto done;
+
+  if (!*fname)
+    {
+      cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0,
+                          "empty filename in #%s",
+                          pfile->directive->name);
+      goto done;
+    }
 
   /* Prevent #include recursion.  */
   if (pfile->line_table->depth >= CPP_STACK_MAX)
 
   /* Prevent #include recursion.  */
   if (pfile->line_table->depth >= CPP_STACK_MAX)
@@ -677,12 +840,16 @@ do_include_common (cpp_reader *pfile, enum include_type type)
 
       if (pfile->cb.include)
        pfile->cb.include (pfile, pfile->directive_line,
 
       if (pfile->cb.include)
        pfile->cb.include (pfile, pfile->directive_line,
-                          pfile->directive->name, fname, angle_brackets);
+                          pfile->directive->name, fname, angle_brackets,
+                          buf);
 
 
-      _cpp_stack_include (pfile, fname, angle_brackets, type);
+      _cpp_stack_include (pfile, fname, angle_brackets, type, location);
     }
 
     }
 
-  free ((void *) fname);
+ done:
+  XDELETEVEC (fname);
+  if (buf)
+    XDELETEVEC (buf);
 }
 
 static void
 }
 
 static void
@@ -704,7 +871,7 @@ do_include_next (cpp_reader *pfile)
 
   /* If this is the primary source file, warn and use the normal
      search logic.  */
 
   /* If this is the primary source file, warn and use the normal
      search logic.  */
-  if (! pfile->buffer->prev)
+  if (cpp_in_primary_file (pfile))
     {
       cpp_error (pfile, CPP_DL_WARNING,
                 "#include_next in primary source file");
     {
       cpp_error (pfile, CPP_DL_WARNING,
                 "#include_next in primary source file");
@@ -739,23 +906,30 @@ read_flag (cpp_reader *pfile, unsigned int last)
 }
 
 /* Subroutine of do_line and do_linemarker.  Convert a number in STR,
 }
 
 /* Subroutine of do_line and do_linemarker.  Convert a number in STR,
-   of length LEN, to binary; store it in NUMP, and return 0 if the
-   number was well-formed, 1 if not.  Temporary, hopefully.  */
-static int
-strtoul_for_line (const uchar *str, unsigned int len, long unsigned int *nump)
+   of length LEN, to binary; store it in NUMP, and return false if the
+   number was well-formed, true if not. WRAPPED is set to true if the
+   number did not fit into 'unsigned long'.  */
+static bool
+strtolinenum (const uchar *str, size_t len, linenum_type *nump, bool *wrapped)
 {
 {
-  unsigned long reg = 0;
+  linenum_type reg = 0;
+  linenum_type reg_prev = 0;
+
   uchar c;
   uchar c;
+  *wrapped = false;
   while (len--)
     {
       c = *str++;
       if (!ISDIGIT (c))
   while (len--)
     {
       c = *str++;
       if (!ISDIGIT (c))
-       return 1;
+       return true;
       reg *= 10;
       reg += c - '0';
       reg *= 10;
       reg += c - '0';
+      if (reg < reg_prev) 
+       *wrapped = true;
+      reg_prev = reg;
     }
   *nump = reg;
     }
   *nump = reg;
-  return 0;
+  return false;
 }
 
 /* Interpret #line command.
 }
 
 /* Interpret #line command.
@@ -764,38 +938,49 @@ strtoul_for_line (const uchar *str, unsigned int len, long unsigned int *nump)
 static void
 do_line (cpp_reader *pfile)
 {
 static void
 do_line (cpp_reader *pfile)
 {
-  const struct line_maps *line_table = pfile->line_table;
-  const struct line_map *map = &line_table->maps[line_table->used - 1];
+  struct line_maps *line_table = pfile->line_table;
+  const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+
+  /* skip_rest_of_line() may cause line table to be realloc()ed so note down
+     sysp right now.  */
+
+  unsigned char map_sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (map);
   const cpp_token *token;
   const cpp_token *token;
-  const char *new_file = map->to_file;
-  unsigned long new_lineno;
+  const char *new_file = ORDINARY_MAP_FILE_NAME (map);
+  linenum_type new_lineno;
 
   /* C99 raised the minimum limit on #line numbers.  */
 
   /* C99 raised the minimum limit on #line numbers.  */
-  unsigned int cap = CPP_OPTION (pfile, c99) ? 2147483647 : 32767;
+  linenum_type cap = CPP_OPTION (pfile, c99) ? 2147483647 : 32767;
+  bool wrapped;
 
   /* #line commands expand macros.  */
   token = cpp_get_token (pfile);
   if (token->type != CPP_NUMBER
 
   /* #line commands expand macros.  */
   token = cpp_get_token (pfile);
   if (token->type != CPP_NUMBER
-      || strtoul_for_line (token->val.str.text, token->val.str.len,
-                          &new_lineno))
+      || strtolinenum (token->val.str.text, token->val.str.len,
+                      &new_lineno, &wrapped))
     {
     {
-      cpp_error (pfile, CPP_DL_ERROR,
-                "\"%s\" after #line is not a positive integer",
-                cpp_token_as_text (pfile, token));
+      if (token->type == CPP_EOF)
+       cpp_error (pfile, CPP_DL_ERROR, "unexpected end of file after #line");
+      else
+       cpp_error (pfile, CPP_DL_ERROR,
+                  "\"%s\" after #line is not a positive integer",
+                  cpp_token_as_text (pfile, token));
       return;
     }
 
       return;
     }
 
-  if (CPP_PEDANTIC (pfile) && (new_lineno == 0 || new_lineno > cap))
+  if (CPP_PEDANTIC (pfile) && (new_lineno == 0 || new_lineno > cap || wrapped))
     cpp_error (pfile, CPP_DL_PEDWARN, "line number out of range");
     cpp_error (pfile, CPP_DL_PEDWARN, "line number out of range");
+  else if (wrapped)
+    cpp_error (pfile, CPP_DL_WARNING, "line number out of range");
 
   token = cpp_get_token (pfile);
   if (token->type == CPP_STRING)
     {
       cpp_string s = { 0, 0 };
       if (cpp_interpret_string_notranslate (pfile, &token->val.str, 1,
 
   token = cpp_get_token (pfile);
   if (token->type == CPP_STRING)
     {
       cpp_string s = { 0, 0 };
       if (cpp_interpret_string_notranslate (pfile, &token->val.str, 1,
-                                           &s, false))
+                                           &s, CPP_STRING))
        new_file = (const char *)s.text;
        new_file = (const char *)s.text;
-      check_eol (pfile);
+      check_eol (pfile, true);
     }
   else if (token->type != CPP_EOF)
     {
     }
   else if (token->type != CPP_EOF)
     {
@@ -805,8 +990,9 @@ do_line (cpp_reader *pfile)
     }
 
   skip_rest_of_line (pfile);
     }
 
   skip_rest_of_line (pfile);
-  _cpp_do_file_change (pfile, LC_RENAME, new_file, new_lineno,
-                      map->sysp);
+  _cpp_do_file_change (pfile, LC_RENAME_VERBATIM, new_file, new_lineno,
+                      map_sysp);
+  line_table->seen_line_directive = true;
 }
 
 /* Interpret the # 44 "file" [flags] notation, which has slightly
 }
 
 /* Interpret the # 44 "file" [flags] notation, which has slightly
@@ -815,14 +1001,15 @@ do_line (cpp_reader *pfile)
 static void
 do_linemarker (cpp_reader *pfile)
 {
 static void
 do_linemarker (cpp_reader *pfile)
 {
-  const struct line_maps *line_table = pfile->line_table;
-  const struct line_map *map = &line_table->maps[line_table->used - 1];
+  struct line_maps *line_table = pfile->line_table;
+  const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
   const cpp_token *token;
   const cpp_token *token;
-  const char *new_file = map->to_file;
-  unsigned long new_lineno;
-  unsigned int new_sysp = map->sysp;
-  enum lc_reason reason = LC_RENAME;
+  const char *new_file = ORDINARY_MAP_FILE_NAME (map);
+  linenum_type new_lineno;
+  unsigned int new_sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (map);
+  enum lc_reason reason = LC_RENAME_VERBATIM;
   int flag;
   int flag;
+  bool wrapped;
 
   /* Back up so we can get the number again.  Putting this in
      _cpp_handle_directive risks two calls to _cpp_backup_tokens in
 
   /* Back up so we can get the number again.  Putting this in
      _cpp_handle_directive risks two calls to _cpp_backup_tokens in
@@ -832,9 +1019,11 @@ do_linemarker (cpp_reader *pfile)
   /* #line commands expand macros.  */
   token = cpp_get_token (pfile);
   if (token->type != CPP_NUMBER
   /* #line commands expand macros.  */
   token = cpp_get_token (pfile);
   if (token->type != CPP_NUMBER
-      || strtoul_for_line (token->val.str.text, token->val.str.len,
-                          &new_lineno))
+      || strtolinenum (token->val.str.text, token->val.str.len,
+                      &new_lineno, &wrapped))
     {
     {
+      /* Unlike #line, there does not seem to be a way to get an EOF
+        here.  So, it should be safe to always spell the token.  */
       cpp_error (pfile, CPP_DL_ERROR,
                 "\"%s\" after # is not a positive integer",
                 cpp_token_as_text (pfile, token));
       cpp_error (pfile, CPP_DL_ERROR,
                 "\"%s\" after # is not a positive integer",
                 cpp_token_as_text (pfile, token));
@@ -846,7 +1035,7 @@ do_linemarker (cpp_reader *pfile)
     {
       cpp_string s = { 0, 0 };
       if (cpp_interpret_string_notranslate (pfile, &token->val.str,
     {
       cpp_string s = { 0, 0 };
       if (cpp_interpret_string_notranslate (pfile, &token->val.str,
-                                           1, &s, false))
+                                           1, &s, CPP_STRING))
        new_file = (const char *)s.text;
 
       new_sysp = 0;
        new_file = (const char *)s.text;
 
       new_sysp = 0;
@@ -869,10 +1058,10 @@ do_linemarker (cpp_reader *pfile)
          flag = read_flag (pfile, flag);
          if (flag == 4)
            new_sysp = 2;
          flag = read_flag (pfile, flag);
          if (flag == 4)
            new_sysp = 2;
-         pfile->buffer->sysp = new_sysp;
        }
        }
+      pfile->buffer->sysp = new_sysp;
 
 
-      check_eol (pfile);
+      check_eol (pfile, false);
     }
   else if (token->type != CPP_EOF)
     {
     }
   else if (token->type != CPP_EOF)
     {
@@ -882,7 +1071,33 @@ do_linemarker (cpp_reader *pfile)
     }
 
   skip_rest_of_line (pfile);
     }
 
   skip_rest_of_line (pfile);
+
+  if (reason == LC_LEAVE)
+    {
+      /* Reread map since cpp_get_token can invalidate it with a
+        reallocation.  */
+      map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+      const line_map_ordinary *from
+       = linemap_included_from_linemap (line_table, map);
+      if (MAIN_FILE_P (map)
+         || (from
+             && filename_cmp (ORDINARY_MAP_FILE_NAME (from), new_file) != 0))
+       {
+         cpp_warning (pfile, CPP_W_NONE,
+                      "file \"%s\" linemarker ignored due to "
+                      "incorrect nesting", new_file);
+         return;
+       }
+    }
+  /* Compensate for the increment in linemap_add that occurs in
+     _cpp_do_file_change.  We're currently at the start of the line
+     *following* the #line directive.  A separate location_t for this
+     location makes no sense (until we do the LC_LEAVE), and
+     complicates LAST_SOURCE_LINE_LOCATION.  */
+  pfile->line_table->highest_location--;
+
   _cpp_do_file_change (pfile, reason, new_file, new_lineno, new_sysp);
   _cpp_do_file_change (pfile, reason, new_file, new_lineno, new_sysp);
+  line_table->seen_line_directive = true;
 }
 
 /* Arrange the file_change callback.  pfile->line has changed to
 }
 
 /* Arrange the file_change callback.  pfile->line has changed to
@@ -891,44 +1106,63 @@ do_linemarker (cpp_reader *pfile)
    and zero otherwise.  */
 void
 _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason,
    and zero otherwise.  */
 void
 _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason,
-                    const char *to_file, unsigned int file_line,
+                    const char *to_file, linenum_type file_line,
                     unsigned int sysp)
 {
                     unsigned int sysp)
 {
+  linemap_assert (reason != LC_ENTER_MACRO);
   const struct line_map *map = linemap_add (pfile->line_table, reason, sysp,
                                            to_file, file_line);
   const struct line_map *map = linemap_add (pfile->line_table, reason, sysp,
                                            to_file, file_line);
+  const line_map_ordinary *ord_map = NULL;
   if (map != NULL)
   if (map != NULL)
-    linemap_line_start (pfile->line_table, map->to_line, 127);
+    {
+      ord_map = linemap_check_ordinary (map);
+      linemap_line_start (pfile->line_table,
+                         ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map),
+                         127);
+    }
 
   if (pfile->cb.file_change)
 
   if (pfile->cb.file_change)
-    pfile->cb.file_change (pfile, map);
+    pfile->cb.file_change (pfile, ord_map);
 }
 
 /* Report a warning or error detected by the program we are
    processing.  Use the directive's tokens in the error message.  */
 static void
 }
 
 /* Report a warning or error detected by the program we are
    processing.  Use the directive's tokens in the error message.  */
 static void
-do_diagnostic (cpp_reader *pfile, int code, int print_dir)
+do_diagnostic (cpp_reader *pfile, enum cpp_diagnostic_level code,
+              enum cpp_warning_reason reason, int print_dir)
 {
 {
-  if (_cpp_begin_message (pfile, code, pfile->cur_token[-1].src_loc, 0))
-    {
-      if (print_dir)
-       fprintf (stderr, "#%s ", pfile->directive->name);
-      pfile->state.prevent_expansion++;
-      cpp_output_line (pfile, stderr);
-      pfile->state.prevent_expansion--;
-    }
+  const unsigned char *dir_name;
+  unsigned char *line;
+  location_t src_loc = pfile->cur_token[-1].src_loc;
+
+  if (print_dir)
+    dir_name = pfile->directive->name;
+  else
+    dir_name = NULL;
+  pfile->state.prevent_expansion++;
+  line = cpp_output_line_to_string (pfile, dir_name);
+  pfile->state.prevent_expansion--;
+
+  if (code == CPP_DL_WARNING_SYSHDR && reason)
+    cpp_warning_with_line_syshdr (pfile, reason, src_loc, 0, "%s", line);
+  else if (code == CPP_DL_WARNING && reason)
+    cpp_warning_with_line (pfile, reason, src_loc, 0, "%s", line);
+  else
+    cpp_error_with_line (pfile, code, src_loc, 0, "%s", line);
+  free (line);
 }
 
 static void
 do_error (cpp_reader *pfile)
 {
 }
 
 static void
 do_error (cpp_reader *pfile)
 {
-  do_diagnostic (pfile, CPP_DL_ERROR, 1);
+  do_diagnostic (pfile, CPP_DL_ERROR, CPP_W_NONE, 1);
 }
 
 static void
 do_warning (cpp_reader *pfile)
 {
   /* We want #warning diagnostics to be emitted in system headers too.  */
 }
 
 static void
 do_warning (cpp_reader *pfile)
 {
   /* We want #warning diagnostics to be emitted in system headers too.  */
-  do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, 1);
+  do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, CPP_W_WARNING_DIRECTIVE, 1);
 }
 
 /* Report program identification.  */
 }
 
 /* Report program identification.  */
@@ -938,11 +1172,12 @@ do_ident (cpp_reader *pfile)
   const cpp_token *str = cpp_get_token (pfile);
 
   if (str->type != CPP_STRING)
   const cpp_token *str = cpp_get_token (pfile);
 
   if (str->type != CPP_STRING)
-    cpp_error (pfile, CPP_DL_ERROR, "invalid #ident directive");
+    cpp_error (pfile, CPP_DL_ERROR, "invalid #%s directive",
+              pfile->directive->name);
   else if (pfile->cb.ident)
     pfile->cb.ident (pfile, pfile->directive_line, &str->val.str);
 
   else if (pfile->cb.ident)
     pfile->cb.ident (pfile, pfile->directive_line, &str->val.str);
 
-  check_eol (pfile);
+  check_eol (pfile, false);
 }
 
 /* Lookup a PRAGMA name in a singly-linked CHAIN.  Returns the
 }
 
 /* Lookup a PRAGMA name in a singly-linked CHAIN.  Returns the
@@ -957,105 +1192,159 @@ lookup_pragma_entry (struct pragma_entry *chain, const cpp_hashnode *pragma)
   return chain;
 }
 
   return chain;
 }
 
-/* Create and insert a pragma entry for NAME at the beginning of a
-   singly-linked CHAIN.  If handler is NULL, it is a namespace,
-   otherwise it is a pragma and its handler.  If INTERNAL is true
-   this pragma is being inserted by libcpp itself. */
+/* Create and insert a blank pragma entry at the beginning of a
+   singly-linked CHAIN.  */
 static struct pragma_entry *
 static struct pragma_entry *
-insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain,
-                    const cpp_hashnode *pragma, pragma_cb handler,
-                    bool internal)
+new_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain)
 {
 {
-  struct pragma_entry *new;
+  struct pragma_entry *new_entry;
 
 
-  new = (struct pragma_entry *)
+  new_entry = (struct pragma_entry *)
     _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
     _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
-  new->pragma = pragma;
-  if (handler)
-    {
-      new->is_nspace = 0;
-      new->u.handler = handler;
-    }
-  else
-    {
-      new->is_nspace = 1;
-      new->u.space = NULL;
-    }
 
 
-  new->is_internal = internal;
-  new->next = *chain;
-  *chain = new;
-  return new;
+  memset (new_entry, 0, sizeof (struct pragma_entry));
+  new_entry->next = *chain;
+
+  *chain = new_entry;
+  return new_entry;
 }
 
 /* Register a pragma NAME in namespace SPACE.  If SPACE is null, it
 }
 
 /* Register a pragma NAME in namespace SPACE.  If SPACE is null, it
-   goes in the global namespace.  HANDLER is the handler it will call,
-   which must be non-NULL.  INTERNAL is true if this is a pragma
-   registered by cpplib itself, false if it is registered via
-   cpp_register_pragma */
-static void
-register_pragma (cpp_reader *pfile, const char *space, const char *name,
-                pragma_cb handler, bool internal)
+   goes in the global namespace.  */
+static struct pragma_entry *
+register_pragma_1 (cpp_reader *pfile, const char *space, const char *name,
+                  bool allow_name_expansion)
 {
   struct pragma_entry **chain = &pfile->pragmas;
   struct pragma_entry *entry;
   const cpp_hashnode *node;
 
 {
   struct pragma_entry **chain = &pfile->pragmas;
   struct pragma_entry *entry;
   const cpp_hashnode *node;
 
-  if (!handler)
-    abort ();
-
   if (space)
     {
   if (space)
     {
-      node = cpp_lookup (pfile, U space, strlen (space));
+      node = cpp_lookup (pfile, UC space, strlen (space));
       entry = lookup_pragma_entry (*chain, node);
       if (!entry)
       entry = lookup_pragma_entry (*chain, node);
       if (!entry)
-       entry = insert_pragma_entry (pfile, chain, node, NULL, internal);
+       {
+         entry = new_pragma_entry (pfile, chain);
+         entry->pragma = node;
+         entry->is_nspace = true;
+         entry->allow_expansion = allow_name_expansion;
+       }
       else if (!entry->is_nspace)
        goto clash;
       else if (!entry->is_nspace)
        goto clash;
+      else if (entry->allow_expansion != allow_name_expansion)
+       {
+         cpp_error (pfile, CPP_DL_ICE,
+                    "registering pragmas in namespace \"%s\" with mismatched "
+                    "name expansion", space);
+         return NULL;
+       }
       chain = &entry->u.space;
     }
       chain = &entry->u.space;
     }
+  else if (allow_name_expansion)
+    {
+      cpp_error (pfile, CPP_DL_ICE,
+                "registering pragma \"%s\" with name expansion "
+                "and no namespace", name);
+      return NULL;
+    }
 
   /* Check for duplicates.  */
 
   /* Check for duplicates.  */
-  node = cpp_lookup (pfile, U name, strlen (name));
+  node = cpp_lookup (pfile, UC name, strlen (name));
   entry = lookup_pragma_entry (*chain, node);
   entry = lookup_pragma_entry (*chain, node);
-  if (entry)
+  if (entry == NULL)
     {
     {
-      if (entry->is_nspace)
-       clash:
-       cpp_error (pfile, CPP_DL_ICE,
-                "registering \"%s\" as both a pragma and a pragma namespace",
-                NODE_NAME (node));
-      else if (space)
-       cpp_error (pfile, CPP_DL_ICE, "#pragma %s %s is already registered",
-                  space, name);
-      else
-       cpp_error (pfile, CPP_DL_ICE, "#pragma %s is already registered", name);
+      entry = new_pragma_entry (pfile, chain);
+      entry->pragma = node;
+      return entry;
     }
     }
+
+  if (entry->is_nspace)
+    clash:
+    cpp_error (pfile, CPP_DL_ICE,
+              "registering \"%s\" as both a pragma and a pragma namespace",
+              NODE_NAME (node));
+  else if (space)
+    cpp_error (pfile, CPP_DL_ICE, "#pragma %s %s is already registered",
+              space, name);
   else
   else
-    insert_pragma_entry (pfile, chain, node, handler, internal);
+    cpp_error (pfile, CPP_DL_ICE, "#pragma %s is already registered", name);
+
+  return NULL;
+}
+
+/* Register a cpplib internal pragma SPACE NAME with HANDLER.  */
+static void
+register_pragma_internal (cpp_reader *pfile, const char *space,
+                         const char *name, pragma_cb handler)
+{
+  struct pragma_entry *entry;
+
+  entry = register_pragma_1 (pfile, space, name, false);
+  entry->is_internal = true;
+  entry->u.handler = handler;
 }
 
 /* Register a pragma NAME in namespace SPACE.  If SPACE is null, it
    goes in the global namespace.  HANDLER is the handler it will call,
 }
 
 /* Register a pragma NAME in namespace SPACE.  If SPACE is null, it
    goes in the global namespace.  HANDLER is the handler it will call,
-   which must be non-NULL.  This function is exported from libcpp. */
+   which must be non-NULL.  If ALLOW_EXPANSION is set, allow macro
+   expansion while parsing pragma NAME.  This function is exported
+   from libcpp. */
 void
 cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
 void
 cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
-                    pragma_cb handler)
+                    pragma_cb handler, bool allow_expansion)
 {
 {
-  register_pragma (pfile, space, name, handler, false);
+  struct pragma_entry *entry;
+
+  if (!handler)
+    {
+      cpp_error (pfile, CPP_DL_ICE, "registering pragma with NULL handler");
+      return;
+    }
+
+  entry = register_pragma_1 (pfile, space, name, false);
+  if (entry)
+    {
+      entry->allow_expansion = allow_expansion;
+      entry->u.handler = handler;
+    }
 }
 
 }
 
+/* Similarly, but create mark the pragma for deferred processing.
+   When found, a CPP_PRAGMA token will be insertted into the stream
+   with IDENT in the token->u.pragma slot.  */
+void
+cpp_register_deferred_pragma (cpp_reader *pfile, const char *space,
+                             const char *name, unsigned int ident,
+                             bool allow_expansion, bool allow_name_expansion)
+{
+  struct pragma_entry *entry;
+
+  entry = register_pragma_1 (pfile, space, name, allow_name_expansion);
+  if (entry)
+    {
+      entry->is_deferred = true;
+      entry->allow_expansion = allow_expansion;
+      entry->u.ident = ident;
+    }
+}  
+
 /* Register the pragmas the preprocessor itself handles.  */
 void
 _cpp_init_internal_pragmas (cpp_reader *pfile)
 {
   /* Pragmas in the global namespace.  */
 /* Register the pragmas the preprocessor itself handles.  */
 void
 _cpp_init_internal_pragmas (cpp_reader *pfile)
 {
   /* Pragmas in the global namespace.  */
-  register_pragma (pfile, 0, "once", do_pragma_once, true);
+  register_pragma_internal (pfile, 0, "once", do_pragma_once);
+  register_pragma_internal (pfile, 0, "push_macro", do_pragma_push_macro);
+  register_pragma_internal (pfile, 0, "pop_macro", do_pragma_pop_macro);
 
   /* New GCC-specific pragmas should be put in the GCC namespace.  */
 
   /* New GCC-specific pragmas should be put in the GCC namespace.  */
-  register_pragma (pfile, "GCC", "poison", do_pragma_poison, true);
-  register_pragma (pfile, "GCC", "system_header", do_pragma_system_header, true);
-  register_pragma (pfile, "GCC", "dependency", do_pragma_dependency, true);
+  register_pragma_internal (pfile, "GCC", "poison", do_pragma_poison);
+  register_pragma_internal (pfile, "GCC", "system_header",
+                           do_pragma_system_header);
+  register_pragma_internal (pfile, "GCC", "dependency", do_pragma_dependency);
+  register_pragma_internal (pfile, "GCC", "warning", do_pragma_warning);
+  register_pragma_internal (pfile, "GCC", "error", do_pragma_error);
 }
 
 /* Return the number of registered pragmas in PE.  */
 }
 
 /* Return the number of registered pragmas in PE.  */
@@ -1083,9 +1372,9 @@ save_registered_pragmas (struct pragma_entry *pe, char **sd)
     {
       if (pe->is_nspace)
        sd = save_registered_pragmas (pe->u.space, sd);
     {
       if (pe->is_nspace)
        sd = save_registered_pragmas (pe->u.space, sd);
-      *sd++ = xmemdup (HT_STR (&pe->pragma->ident),
-                      HT_LEN (&pe->pragma->ident),
-                      HT_LEN (&pe->pragma->ident) + 1);
+      *sd++ = (char *) xmemdup (HT_STR (&pe->pragma->ident),
+                                HT_LEN (&pe->pragma->ident),
+                                HT_LEN (&pe->pragma->ident) + 1);
     }
   return sd;
 }
     }
   return sd;
 }
@@ -1113,7 +1402,7 @@ restore_registered_pragmas (cpp_reader *pfile, struct pragma_entry *pe,
     {
       if (pe->is_nspace)
        sd = restore_registered_pragmas (pfile, pe->u.space, sd);
     {
       if (pe->is_nspace)
        sd = restore_registered_pragmas (pfile, pe->u.space, sd);
-      pe->pragma = cpp_lookup (pfile, U *sd, strlen (*sd));
+      pe->pragma = cpp_lookup (pfile, UC *sd, strlen (*sd));
       free (*sd);
       sd++;
     }
       free (*sd);
       sd++;
     }
@@ -1133,75 +1422,88 @@ _cpp_restore_pragma_names (cpp_reader *pfile, char **saved)
    front end.  C99 defines three pragmas and says that no macro
    expansion is to be performed on them; whether or not macro
    expansion happens for other pragmas is implementation defined.
    front end.  C99 defines three pragmas and says that no macro
    expansion is to be performed on them; whether or not macro
    expansion happens for other pragmas is implementation defined.
-   This implementation never macro-expands the text after #pragma.
-
-   The library user has the option of deferring execution of
-   #pragmas not handled by cpplib, in which case they are converted
-   to CPP_PRAGMA tokens and inserted into the output stream.  */
+   This implementation allows for a mix of both, since GCC did not
+   traditionally macro expand its (few) pragmas, whereas OpenMP
+   specifies that macro expansion should happen.  */
 static void
 do_pragma (cpp_reader *pfile)
 {
   const struct pragma_entry *p = NULL;
 static void
 do_pragma (cpp_reader *pfile)
 {
   const struct pragma_entry *p = NULL;
-  const cpp_token *token, *pragma_token = pfile->cur_token;
+  const cpp_token *token, *pragma_token;
+  location_t pragma_token_virt_loc = 0;
+  cpp_token ns_token;
   unsigned int count = 1;
 
   unsigned int count = 1;
 
-  /* Save the current position so that defer_pragmas mode can
-     copy the entire current line to a string.  It will not work
-     to use _cpp_backup_tokens as that does not reverse buffer->cur.  */
-  const uchar *line_start = CPP_BUFFER (pfile)->cur;
-
   pfile->state.prevent_expansion++;
 
   pfile->state.prevent_expansion++;
 
-  token = cpp_get_token (pfile);
+  pragma_token = token = cpp_get_token_with_location (pfile,
+                                                     &pragma_token_virt_loc);
+  ns_token = *token;
   if (token->type == CPP_NAME)
     {
   if (token->type == CPP_NAME)
     {
-      p = lookup_pragma_entry (pfile->pragmas, token->val.node);
+      p = lookup_pragma_entry (pfile->pragmas, token->val.node.node);
       if (p && p->is_nspace)
        {
       if (p && p->is_nspace)
        {
-         count = 2;
+         bool allow_name_expansion = p->allow_expansion;
+         if (allow_name_expansion)
+           pfile->state.prevent_expansion--;
+
          token = cpp_get_token (pfile);
          if (token->type == CPP_NAME)
          token = cpp_get_token (pfile);
          if (token->type == CPP_NAME)
-           p = lookup_pragma_entry (p->u.space, token->val.node);
+           p = lookup_pragma_entry (p->u.space, token->val.node.node);
          else
            p = NULL;
          else
            p = NULL;
+         if (allow_name_expansion)
+           pfile->state.prevent_expansion++;
+         count = 2;
        }
     }
 
        }
     }
 
-  if (p && (p->is_internal || !CPP_OPTION (pfile, defer_pragmas)))
-    {
-      /* Since the handler below doesn't get the line number, that it
-        might need for diagnostics, make sure it has the right
-        numbers in place.  */
-      if (pfile->cb.line_change)
-       (*pfile->cb.line_change) (pfile, pragma_token, false);
-      (*p->u.handler) (pfile);
-    }
-  else if (CPP_OPTION (pfile, defer_pragmas))
+  if (p)
     {
     {
-      /* Squirrel away the pragma text.  Pragmas are newline-terminated. */
-      const uchar *line_end;
-      uchar *s;
-      cpp_string body;
-      cpp_token *ptok;
-
-      line_end = ustrchr (line_start, '\n');
-
-      body.len = (line_end - line_start) + 1;
-      s = _cpp_unaligned_alloc (pfile, body.len + 1);
-      memcpy (s, line_start, body.len);
-      s[body.len] = '\0';
-      body.text = s;
-
-      /* Create a CPP_PRAGMA token.  */
-      ptok = &pfile->directive_result;
-      ptok->src_loc = pragma_token->src_loc;
-      ptok->type = CPP_PRAGMA;
-      ptok->flags = pragma_token->flags | NO_EXPAND;
-      ptok->val.str = body;
+      if (p->is_deferred)
+       {
+         pfile->directive_result.src_loc = pragma_token_virt_loc;
+         pfile->directive_result.type = CPP_PRAGMA;
+         pfile->directive_result.flags = pragma_token->flags;
+         pfile->directive_result.val.pragma = p->u.ident;
+         pfile->state.in_deferred_pragma = true;
+         pfile->state.pragma_allow_expansion = p->allow_expansion;
+         if (!p->allow_expansion)
+           pfile->state.prevent_expansion++;
+       }
+      else
+       {
+         /* Since the handler below doesn't get the line number, that
+            it might need for diagnostics, make sure it has the right
+            numbers in place.  */
+         if (pfile->cb.line_change)
+           (*pfile->cb.line_change) (pfile, pragma_token, false);
+         if (p->allow_expansion)
+           pfile->state.prevent_expansion--;
+         (*p->u.handler) (pfile);
+         if (p->allow_expansion)
+           pfile->state.prevent_expansion++;
+       }
     }
   else if (pfile->cb.def_pragma)
     {
     }
   else if (pfile->cb.def_pragma)
     {
-      _cpp_backup_tokens (pfile, count);
+      if (count == 1 || pfile->context->prev == NULL)
+       _cpp_backup_tokens (pfile, count);
+      else
+       {
+         /* Invalid name comes from macro expansion, _cpp_backup_tokens
+            won't allow backing 2 tokens.  */
+         /* ??? The token buffer is leaked.  Perhaps if def_pragma hook
+            reads both tokens, we could perhaps free it, but if it doesn't,
+            we don't know the exact lifespan.  */
+         cpp_token *toks = XNEWVEC (cpp_token, 2);
+         toks[0] = ns_token;
+         toks[0].flags |= NO_EXPAND;
+         toks[1] = *token;
+         toks[1].flags |= NO_EXPAND;
+         _cpp_push_token_context (pfile, NULL, toks, 2);
+       }
       pfile->cb.def_pragma (pfile, pfile->directive_line);
     }
 
       pfile->cb.def_pragma (pfile, pfile->directive_line);
     }
 
@@ -1212,13 +1514,123 @@ do_pragma (cpp_reader *pfile)
 static void
 do_pragma_once (cpp_reader *pfile)
 {
 static void
 do_pragma_once (cpp_reader *pfile)
 {
-  if (pfile->buffer->prev == NULL)
+  if (cpp_in_primary_file (pfile))
     cpp_error (pfile, CPP_DL_WARNING, "#pragma once in main file");
 
     cpp_error (pfile, CPP_DL_WARNING, "#pragma once in main file");
 
-  check_eol (pfile);
+  check_eol (pfile, false);
   _cpp_mark_file_once_only (pfile, pfile->buffer->file);
 }
 
   _cpp_mark_file_once_only (pfile, pfile->buffer->file);
 }
 
+/* Handle #pragma push_macro(STRING).  */
+static void
+do_pragma_push_macro (cpp_reader *pfile)
+{
+  cpp_hashnode *node;
+  size_t defnlen;
+  const uchar *defn = NULL;
+  char *macroname, *dest;
+  const char *limit, *src;
+  const cpp_token *txt;
+  struct def_pragma_macro *c;
+
+  txt = get__Pragma_string (pfile);
+  if (!txt)
+    {
+      location_t src_loc = pfile->cur_token[-1].src_loc;
+      cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
+                "invalid #pragma push_macro directive");
+      check_eol (pfile, false);
+      skip_rest_of_line (pfile);
+      return;
+    }
+  dest = macroname = (char *) alloca (txt->val.str.len + 2);
+  src = (const char *) (txt->val.str.text + 1 + (txt->val.str.text[0] == 'L'));
+  limit = (const char *) (txt->val.str.text + txt->val.str.len - 1);
+  while (src < limit)
+    {
+      /* We know there is a character following the backslash.  */
+      if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
+       src++;
+      *dest++ = *src++;
+    }
+  *dest = 0;
+  check_eol (pfile, false);
+  skip_rest_of_line (pfile);
+  c = XNEW (struct def_pragma_macro);
+  memset (c, 0, sizeof (struct def_pragma_macro));
+  c->name = XNEWVAR (char, strlen (macroname) + 1);
+  strcpy (c->name, macroname);
+  c->next = pfile->pushed_macros;
+  node = _cpp_lex_identifier (pfile, c->name);
+  if (node->type == NT_VOID)
+    c->is_undef = 1;
+  else
+    {
+      defn = cpp_macro_definition (pfile, node);
+      defnlen = ustrlen (defn);
+      c->definition = XNEWVEC (uchar, defnlen + 2);
+      c->definition[defnlen] = '\n';
+      c->definition[defnlen + 1] = 0;
+      c->line = node->value.macro->line;
+      c->syshdr = node->value.macro->syshdr;
+      c->used = node->value.macro->used;
+      memcpy (c->definition, defn, defnlen);
+    }
+
+  pfile->pushed_macros = c;
+}
+
+/* Handle #pragma pop_macro(STRING).  */
+static void
+do_pragma_pop_macro (cpp_reader *pfile)
+{
+  char *macroname, *dest;
+  const char *limit, *src;
+  const cpp_token *txt;
+  struct def_pragma_macro *l = NULL, *c = pfile->pushed_macros;
+  txt = get__Pragma_string (pfile);
+  if (!txt)
+    {
+      location_t src_loc = pfile->cur_token[-1].src_loc;
+      cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
+                "invalid #pragma pop_macro directive");
+      check_eol (pfile, false);
+      skip_rest_of_line (pfile);
+      return;
+    }
+  dest = macroname = (char *) alloca (txt->val.str.len + 2);
+  src = (const char *) (txt->val.str.text + 1 + (txt->val.str.text[0] == 'L'));
+  limit = (const char *) (txt->val.str.text + txt->val.str.len - 1);
+  while (src < limit)
+    {
+      /* We know there is a character following the backslash.  */
+      if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
+       src++;
+      *dest++ = *src++;
+    }
+  *dest = 0;
+  check_eol (pfile, false);
+  skip_rest_of_line (pfile);
+
+  while (c != NULL)
+    {
+      if (!strcmp (c->name, macroname))
+       {
+         if (!l)
+           pfile->pushed_macros = c->next;
+         else
+           l->next = c->next;
+         cpp_pop_definition (pfile, c);
+         free (c->definition);
+         free (c->name);
+         free (c);
+         break;
+       }
+      l = c;
+      c = c->next;
+    }
+}
+
 /* Handle #pragma GCC poison, to poison one or more identifiers so
    that the lexer produces a hard error for each subsequent usage.  */
 static void
 /* Handle #pragma GCC poison, to poison one or more identifiers so
    that the lexer produces a hard error for each subsequent usage.  */
 static void
@@ -1240,11 +1652,11 @@ do_pragma_poison (cpp_reader *pfile)
          break;
        }
 
          break;
        }
 
-      hp = tok->val.node;
+      hp = tok->val.node.node;
       if (hp->flags & NODE_POISONED)
        continue;
 
       if (hp->flags & NODE_POISONED)
        continue;
 
-      if (hp->type == NT_MACRO)
+      if (cpp_macro_p (hp))
        cpp_error (pfile, CPP_DL_WARNING, "poisoning existing macro \"%s\"",
                   NODE_NAME (hp));
       _cpp_free_definition (hp);
        cpp_error (pfile, CPP_DL_WARNING, "poisoning existing macro \"%s\"",
                   NODE_NAME (hp));
       _cpp_free_definition (hp);
@@ -1262,14 +1674,12 @@ do_pragma_poison (cpp_reader *pfile)
 static void
 do_pragma_system_header (cpp_reader *pfile)
 {
 static void
 do_pragma_system_header (cpp_reader *pfile)
 {
-  cpp_buffer *buffer = pfile->buffer;
-
-  if (buffer->prev == 0)
+  if (cpp_in_primary_file (pfile))
     cpp_error (pfile, CPP_DL_WARNING,
               "#pragma system_header ignored outside include file");
   else
     {
     cpp_error (pfile, CPP_DL_WARNING,
               "#pragma system_header ignored outside include file");
   else
     {
-      check_eol (pfile);
+      check_eol (pfile, false);
       skip_rest_of_line (pfile);
       cpp_make_system_header (pfile, 1, 0);
     }
       skip_rest_of_line (pfile);
       cpp_make_system_header (pfile, 1, 0);
     }
@@ -1283,8 +1693,9 @@ do_pragma_dependency (cpp_reader *pfile)
 {
   const char *fname;
   int angle_brackets, ordering;
 {
   const char *fname;
   int angle_brackets, ordering;
+  location_t location;
 
 
-  fname = parse_include (pfile, &angle_brackets);
+  fname = parse_include (pfile, &angle_brackets, NULL, &location);
   if (!fname)
     return;
 
   if (!fname)
     return;
 
@@ -1298,13 +1709,49 @@ do_pragma_dependency (cpp_reader *pfile)
       if (cpp_get_token (pfile)->type != CPP_EOF)
        {
          _cpp_backup_tokens (pfile, 1);
       if (cpp_get_token (pfile)->type != CPP_EOF)
        {
          _cpp_backup_tokens (pfile, 1);
-         do_diagnostic (pfile, CPP_DL_WARNING, 0);
+         do_diagnostic (pfile, CPP_DL_WARNING, CPP_W_NONE, 0);
        }
     }
 
   free ((void *) fname);
 }
 
        }
     }
 
   free ((void *) fname);
 }
 
+/* Issue a diagnostic with the message taken from the pragma.  If
+   ERROR is true, the diagnostic is a warning, otherwise, it is an
+   error.  */
+static void
+do_pragma_warning_or_error (cpp_reader *pfile, bool error)
+{
+  const cpp_token *tok = _cpp_lex_token (pfile);
+  cpp_string str;
+  if (tok->type != CPP_STRING
+      || !cpp_interpret_string_notranslate (pfile, &tok->val.str, 1, &str,
+                                           CPP_STRING)
+      || str.len == 0)
+    {
+      cpp_error (pfile, CPP_DL_ERROR, "invalid \"#pragma GCC %s\" directive",
+                error ? "error" : "warning");
+      return;
+    }
+  cpp_error (pfile, error ? CPP_DL_ERROR : CPP_DL_WARNING,
+            "%s", str.text);
+  free ((void *)str.text);
+}
+
+/* Issue a warning diagnostic.  */
+static void
+do_pragma_warning (cpp_reader *pfile)
+{
+  do_pragma_warning_or_error (pfile, false);
+}
+
+/* Issue an error diagnostic.  */
+static void
+do_pragma_error (cpp_reader *pfile)
+{
+  do_pragma_warning_or_error (pfile, true);
+}
+
 /* Get a token but skip padding.  */
 static const cpp_token *
 get_token_no_padding (cpp_reader *pfile)
 /* Get a token but skip padding.  */
 static const cpp_token *
 get_token_no_padding (cpp_reader *pfile)
@@ -1323,15 +1770,26 @@ static const cpp_token *
 get__Pragma_string (cpp_reader *pfile)
 {
   const cpp_token *string;
 get__Pragma_string (cpp_reader *pfile)
 {
   const cpp_token *string;
+  const cpp_token *paren;
 
 
-  if (get_token_no_padding (pfile)->type != CPP_OPEN_PAREN)
+  paren = get_token_no_padding (pfile);
+  if (paren->type == CPP_EOF)
+    _cpp_backup_tokens (pfile, 1);
+  if (paren->type != CPP_OPEN_PAREN)
     return NULL;
 
   string = get_token_no_padding (pfile);
     return NULL;
 
   string = get_token_no_padding (pfile);
-  if (string->type != CPP_STRING && string->type != CPP_WSTRING)
+  if (string->type == CPP_EOF)
+    _cpp_backup_tokens (pfile, 1);
+  if (string->type != CPP_STRING && string->type != CPP_WSTRING
+      && string->type != CPP_STRING32 && string->type != CPP_STRING16
+      && string->type != CPP_UTF8STRING)
     return NULL;
 
     return NULL;
 
-  if (get_token_no_padding (pfile)->type != CPP_CLOSE_PAREN)
+  paren = get_token_no_padding (pfile);
+  if (paren->type == CPP_EOF)
+    _cpp_backup_tokens (pfile, 1);
+  if (paren->type != CPP_CLOSE_PAREN)
     return NULL;
 
   return string;
     return NULL;
 
   return string;
@@ -1340,12 +1798,19 @@ get__Pragma_string (cpp_reader *pfile)
 /* Destringize IN into a temporary buffer, by removing the first \ of
    \" and \\ sequences, and process the result as a #pragma directive.  */
 static void
 /* Destringize IN into a temporary buffer, by removing the first \ of
    \" and \\ sequences, and process the result as a #pragma directive.  */
 static void
-destringize_and_run (cpp_reader *pfile, const cpp_string *in)
+destringize_and_run (cpp_reader *pfile, const cpp_string *in,
+                    location_t expansion_loc)
 {
   const unsigned char *src, *limit;
   char *dest, *result;
 {
   const unsigned char *src, *limit;
   char *dest, *result;
-
-  dest = result = alloca (in->len - 1);
+  cpp_context *saved_context;
+  cpp_token *saved_cur_token;
+  tokenrun *saved_cur_run;
+  cpp_token *toks;
+  int count;
+  const struct directive *save_directive;
+
+  dest = result = (char *) alloca (in->len - 1);
   src = in->text + 1 + (in->text[0] == 'L');
   limit = in->text + in->len - 1;
   while (src < limit)
   src = in->text + 1 + (in->text[0] == 'L');
   limit = in->text + in->len - 1;
   while (src < limit)
@@ -1365,83 +1830,108 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in)
 
      Something like line-at-a-time lexing should remove the need for
      this.  */
 
      Something like line-at-a-time lexing should remove the need for
      this.  */
-  {
-    cpp_context *saved_context = pfile->context;
-    cpp_token *saved_cur_token = pfile->cur_token;
-    tokenrun *saved_cur_run = pfile->cur_run;
-
-    pfile->context = XNEW (cpp_context);
-    pfile->context->macro = 0;
-    pfile->context->prev = 0;
-    run_directive (pfile, T_PRAGMA, result, dest - result);
-    XDELETE (pfile->context);
-    pfile->context = saved_context;
-    pfile->cur_token = saved_cur_token;
-    pfile->cur_run = saved_cur_run;
-  }
-
-  /* See above comment.  For the moment, we'd like
-
-     token1 _Pragma ("foo") token2
+  saved_context = pfile->context;
+  saved_cur_token = pfile->cur_token;
+  saved_cur_run = pfile->cur_run;
 
 
-     to be output as
+  pfile->context = XCNEW (cpp_context);
 
 
-               token1
-               # 7 "file.c"
-               #pragma foo
-               # 7 "file.c"
-                              token2
+  /* Inline run_directive, since we need to delay the _cpp_pop_buffer
+     until we've read all of the tokens that we want.  */
+  cpp_push_buffer (pfile, (const uchar *) result, dest - result,
+                  /* from_stage3 */ true);
+  /* ??? Antique Disgusting Hack.  What does this do?  */
+  if (pfile->buffer->prev)
+    pfile->buffer->file = pfile->buffer->prev->file;
 
 
-      Getting the line markers is a little tricky.  */
-  if (pfile->cb.line_change)
-    pfile->cb.line_change (pfile, pfile->cur_token, false);
-}
+  start_directive (pfile);
+  _cpp_clean_line (pfile);
+  save_directive = pfile->directive;
+  pfile->directive = &dtable[T_PRAGMA];
+  do_pragma (pfile);
+  end_directive (pfile, 1);
+  pfile->directive = save_directive;
+
+  /* We always insert at least one token, the directive result.  It'll
+     either be a CPP_PADDING or a CPP_PRAGMA.  In the later case, we 
+     need to insert *all* of the tokens, including the CPP_PRAGMA_EOL.  */
+
+  /* If we're not handling the pragma internally, read all of the tokens from
+     the string buffer now, while the string buffer is still installed.  */
+  /* ??? Note that the token buffer allocated here is leaked.  It's not clear
+     to me what the true lifespan of the tokens are.  It would appear that
+     the lifespan is the entire parse of the main input stream, in which case
+     this may not be wrong.  */
+  if (pfile->directive_result.type == CPP_PRAGMA)
+    {
+      int maxcount;
 
 
-/* Handle the _Pragma operator.  */
-void
-_cpp_do__Pragma (cpp_reader *pfile)
-{
-  const cpp_token *string = get__Pragma_string (pfile);
-  pfile->directive_result.type = CPP_PADDING;
+      count = 1;
+      maxcount = 50;
+      toks = XNEWVEC (cpp_token, maxcount);
+      toks[0] = pfile->directive_result;
 
 
-  if (string)
-    destringize_and_run (pfile, &string->val.str);
+      do
+       {
+         if (count == maxcount)
+           {
+             maxcount = maxcount * 3 / 2;
+             toks = XRESIZEVEC (cpp_token, toks, maxcount);
+           }
+         toks[count] = *cpp_get_token (pfile);
+         /* _Pragma is a builtin, so we're not within a macro-map, and so
+            the token locations are set to bogus ordinary locations
+            near to, but after that of the "_Pragma".
+            Paper over this by setting them equal to the location of the
+            _Pragma itself (PR preprocessor/69126).  */
+         toks[count].src_loc = expansion_loc;
+         /* Macros have been already expanded by cpp_get_token
+            if the pragma allowed expansion.  */
+         toks[count++].flags |= NO_EXPAND;
+       }
+      while (toks[count-1].type != CPP_PRAGMA_EOL);
+    }
   else
   else
-    cpp_error (pfile, CPP_DL_ERROR,
-              "_Pragma takes a parenthesized string literal");
-}
-
-/* Handle a pragma that the front end deferred until now. */
-void
-cpp_handle_deferred_pragma (cpp_reader *pfile, const cpp_string *s)
-{
-  cpp_context *saved_context = pfile->context;
-  cpp_token *saved_cur_token = pfile->cur_token;
-  tokenrun *saved_cur_run = pfile->cur_run;
-  bool saved_defer_pragmas = CPP_OPTION (pfile, defer_pragmas);
-  void (*saved_line_change) (cpp_reader *, const cpp_token *, int)
-    = pfile->cb.line_change;
+    {
+      count = 1;
+      toks = XNEW (cpp_token);
+      toks[0] = pfile->directive_result;
 
 
-  pfile->context = XNEW (cpp_context);
-  pfile->context->macro = 0;
-  pfile->context->prev = 0;
-  pfile->cb.line_change = NULL;
-  CPP_OPTION (pfile, defer_pragmas) = false;
+      /* If we handled the entire pragma internally, make sure we get the
+        line number correct for the next token.  */
+      if (pfile->cb.line_change)
+       pfile->cb.line_change (pfile, pfile->cur_token, false);
+    }
 
 
-  run_directive (pfile, T_PRAGMA, s->text, s->len);
+  /* Finish inlining run_directive.  */
+  pfile->buffer->file = NULL;
+  _cpp_pop_buffer (pfile);
 
 
+  /* Reset the old macro state before ...  */
   XDELETE (pfile->context);
   pfile->context = saved_context;
   pfile->cur_token = saved_cur_token;
   pfile->cur_run = saved_cur_run;
   XDELETE (pfile->context);
   pfile->context = saved_context;
   pfile->cur_token = saved_cur_token;
   pfile->cur_run = saved_cur_run;
-  pfile->cb.line_change = saved_line_change;
-  CPP_OPTION (pfile, defer_pragmas) = saved_defer_pragmas;
+
+  /* ... inserting the new tokens we collected.  */
+  _cpp_push_token_context (pfile, NULL, toks, count);
 }
 
 }
 
-/* Ignore #sccs on all systems.  */
-static void
-do_sccs (cpp_reader *pfile ATTRIBUTE_UNUSED)
+/* Handle the _Pragma operator.  Return 0 on error, 1 if ok.  */
+int
+_cpp_do__Pragma (cpp_reader *pfile, location_t expansion_loc)
 {
 {
+  const cpp_token *string = get__Pragma_string (pfile);
+  pfile->directive_result.type = CPP_PADDING;
+
+  if (string)
+    {
+      destringize_and_run (pfile, &string->val.str, expansion_loc);
+      return 1;
+    }
+  cpp_error (pfile, CPP_DL_ERROR,
+            "_Pragma takes a parenthesized string literal");
+  return 0;
 }
 
 /* Handle #ifdef.  */
 }
 
 /* Handle #ifdef.  */
@@ -1452,13 +1942,20 @@ do_ifdef (cpp_reader *pfile)
 
   if (! pfile->state.skipping)
     {
 
   if (! pfile->state.skipping)
     {
-      const cpp_hashnode *node = lex_macro_node (pfile);
+      cpp_hashnode *node = lex_macro_node (pfile, false);
 
       if (node)
        {
 
       if (node)
        {
-         skip = node->type != NT_MACRO;
+         /* Do not treat conditional macros as being defined.  This is due to
+            the powerpc and spu ports using conditional macros for 'vector',
+            'bool', and 'pixel' to act as conditional keywords.  This messes
+            up tests like #ifndef bool.  */
+         skip = !cpp_macro_p (node) || (node->flags & NODE_CONDITIONAL);
          _cpp_mark_macro_used (node);
          _cpp_mark_macro_used (node);
-         check_eol (pfile);
+         _cpp_maybe_notify_macro_use (pfile, node);
+         if (pfile->cb.used)
+           pfile->cb.used (pfile, pfile->directive_line, node);
+         check_eol (pfile, false);
        }
     }
 
        }
     }
 
@@ -1470,17 +1967,25 @@ static void
 do_ifndef (cpp_reader *pfile)
 {
   int skip = 1;
 do_ifndef (cpp_reader *pfile)
 {
   int skip = 1;
-  const cpp_hashnode *node = 0;
+  cpp_hashnode *node = 0;
 
   if (! pfile->state.skipping)
     {
 
   if (! pfile->state.skipping)
     {
-      node = lex_macro_node (pfile);
+      node = lex_macro_node (pfile, false);
 
       if (node)
        {
 
       if (node)
        {
-         skip = node->type == NT_MACRO;
+         /* Do not treat conditional macros as being defined.  This is due to
+            the powerpc and spu ports using conditional macros for 'vector',
+            'bool', and 'pixel' to act as conditional keywords.  This messes
+            up tests like #ifndef bool.  */
+         skip = (cpp_macro_p (node)
+                 && !(node->flags & NODE_CONDITIONAL));
          _cpp_mark_macro_used (node);
          _cpp_mark_macro_used (node);
-         check_eol (pfile);
+         _cpp_maybe_notify_macro_use (pfile, node);
+         if (pfile->cb.used)
+           pfile->cb.used (pfile, pfile->directive_line, node);
+         check_eol (pfile, false);
        }
     }
 
        }
     }
 
@@ -1498,7 +2003,7 @@ do_if (cpp_reader *pfile)
   int skip = 1;
 
   if (! pfile->state.skipping)
   int skip = 1;
 
   if (! pfile->state.skipping)
-    skip = _cpp_parse_expr (pfile) == false;
+    skip = _cpp_parse_expr (pfile, true) == false;
 
   push_conditional (pfile, skip, T_IF, pfile->mi_ind_cmacro);
 }
 
   push_conditional (pfile, skip, T_IF, pfile->mi_ind_cmacro);
 }
@@ -1533,7 +2038,7 @@ do_else (cpp_reader *pfile)
 
       /* Only check EOL if was not originally skipping.  */
       if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
 
       /* Only check EOL if was not originally skipping.  */
       if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
-       check_eol (pfile);
+       check_eol_endif_labels (pfile);
     }
 }
 
     }
 }
 
@@ -1557,14 +2062,15 @@ do_elif (cpp_reader *pfile)
        }
       ifs->type = T_ELIF;
 
        }
       ifs->type = T_ELIF;
 
-      /* Only evaluate this if we aren't skipping elses.  During
-        evaluation, set skipping to false to get lexer warnings.  */
+      /* See DR#412: "Only the first group whose control condition
+        evaluates to true (nonzero) is processed; any following groups
+        are skipped and their controlling directives are processed as
+        if they were in a group that is skipped."  */
       if (ifs->skip_elses)
        pfile->state.skipping = 1;
       else
        {
       if (ifs->skip_elses)
        pfile->state.skipping = 1;
       else
        {
-         pfile->state.skipping = 0;
-         pfile->state.skipping = ! _cpp_parse_expr (pfile);
+         pfile->state.skipping = ! _cpp_parse_expr (pfile, false);
          ifs->skip_elses = ! pfile->state.skipping;
        }
 
          ifs->skip_elses = ! pfile->state.skipping;
        }
 
@@ -1586,7 +2092,7 @@ do_endif (cpp_reader *pfile)
     {
       /* Only check EOL if was not originally skipping.  */
       if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
     {
       /* Only check EOL if was not originally skipping.  */
       if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
-       check_eol (pfile);
+       check_eol_endif_labels (pfile);
 
       /* If potential control macro, we go back outside again.  */
       if (ifs->next == 0 && ifs->mi_cmacro)
 
       /* If potential control macro, we go back outside again.  */
       if (ifs->next == 0 && ifs->mi_cmacro)
@@ -1631,17 +2137,15 @@ push_conditional (cpp_reader *pfile, int skip, int type,
 /* Read the tokens of the answer into the macro pool, in a directive
    of type TYPE.  Only commit the memory if we intend it as permanent
    storage, i.e. the #assert case.  Returns 0 on success, and sets
 /* Read the tokens of the answer into the macro pool, in a directive
    of type TYPE.  Only commit the memory if we intend it as permanent
    storage, i.e. the #assert case.  Returns 0 on success, and sets
-   ANSWERP to point to the answer.  */
-static int
-parse_answer (cpp_reader *pfile, struct answer **answerp, int type)
+   ANSWERP to point to the answer.  PRED_LOC is the location of the
+   predicate.  */
+static bool
+parse_answer (cpp_reader *pfile, int type, location_t pred_loc,
+             cpp_macro **answer_ptr)
 {
 {
-  const cpp_token *paren;
-  struct answer *answer;
-  unsigned int acount;
-
   /* In a conditional, it is legal to not have an open paren.  We
      should save the following token in this case.  */
   /* In a conditional, it is legal to not have an open paren.  We
      should save the following token in this case.  */
-  paren = cpp_get_token (pfile);
+  const cpp_token *paren = cpp_get_token (pfile);
 
   /* If not a paren, see if we're OK.  */
   if (paren->type != CPP_OPEN_PAREN)
 
   /* If not a paren, see if we're OK.  */
   if (paren->type != CPP_OPEN_PAREN)
@@ -1651,22 +2155,26 @@ parse_answer (cpp_reader *pfile, struct answer **answerp, int type)
       if (type == T_IF)
        {
          _cpp_backup_tokens (pfile, 1);
       if (type == T_IF)
        {
          _cpp_backup_tokens (pfile, 1);
-         return 0;
+         return true;
        }
 
       /* #unassert with no answer is valid - it removes all answers.  */
       if (type == T_UNASSERT && paren->type == CPP_EOF)
        }
 
       /* #unassert with no answer is valid - it removes all answers.  */
       if (type == T_UNASSERT && paren->type == CPP_EOF)
-       return 0;
+       return true;
 
 
-      cpp_error (pfile, CPP_DL_ERROR, "missing '(' after predicate");
-      return 1;
+      cpp_error_with_line (pfile, CPP_DL_ERROR, pred_loc, 0,
+                          "missing '(' after predicate");
+      return false;
     }
 
     }
 
-  for (acount = 0;; acount++)
+  cpp_macro *answer = _cpp_new_macro (pfile, cmk_assert,
+                                     _cpp_reserve_room (pfile, 0,
+                                                        sizeof (cpp_macro)));
+  answer->parm.next = NULL;
+  unsigned count = 0;
+  for (;;)
     {
     {
-      size_t room_needed;
       const cpp_token *token = cpp_get_token (pfile);
       const cpp_token *token = cpp_get_token (pfile);
-      cpp_token *dest;
 
       if (token->type == CPP_CLOSE_PAREN)
        break;
 
       if (token->type == CPP_CLOSE_PAREN)
        break;
@@ -1674,86 +2182,84 @@ parse_answer (cpp_reader *pfile, struct answer **answerp, int type)
       if (token->type == CPP_EOF)
        {
          cpp_error (pfile, CPP_DL_ERROR, "missing ')' to complete answer");
       if (token->type == CPP_EOF)
        {
          cpp_error (pfile, CPP_DL_ERROR, "missing ')' to complete answer");
-         return 1;
+         return false;
        }
 
        }
 
-      /* struct answer includes the space for one token.  */
-      room_needed = (sizeof (struct answer) + acount * sizeof (cpp_token));
-
-      if (BUFF_ROOM (pfile->a_buff) < room_needed)
-       _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (struct answer));
-
-      dest = &((struct answer *) BUFF_FRONT (pfile->a_buff))->first[acount];
-      *dest = *token;
-
-      /* Drop whitespace at start, for answer equivalence purposes.  */
-      if (acount == 0)
-       dest->flags &= ~PREV_WHITE;
+      answer = (cpp_macro *)_cpp_reserve_room
+       (pfile, sizeof (cpp_macro) + count * sizeof (cpp_token),
+        sizeof (cpp_token));
+      answer->exp.tokens[count++] = *token;
     }
 
     }
 
-  if (acount == 0)
+  if (!count)
     {
       cpp_error (pfile, CPP_DL_ERROR, "predicate's answer is empty");
     {
       cpp_error (pfile, CPP_DL_ERROR, "predicate's answer is empty");
-      return 1;
+      return false;
     }
 
     }
 
-  answer = (struct answer *) BUFF_FRONT (pfile->a_buff);
-  answer->count = acount;
-  answer->next = NULL;
-  *answerp = answer;
+  /* Drop whitespace at start, for answer equivalence purposes.  */
+  answer->exp.tokens[0].flags &= ~PREV_WHITE;
 
 
-  return 0;
+  answer->count = count;
+  *answer_ptr = answer;
+
+  return true;
 }
 
 /* Parses an assertion directive of type TYPE, returning a pointer to
 }
 
 /* Parses an assertion directive of type TYPE, returning a pointer to
-   the hash node of the predicate, or 0 on error.  If an answer was
-   supplied, it is placed in ANSWERP, otherwise it is set to 0.  */
+   the hash node of the predicate, or 0 on error.  The node is
+   guaranteed to be disjoint from the macro namespace, so can only
+   have type 'NT_VOID'.  If an answer was supplied, it is placed in
+   *ANSWER_PTR, which is otherwise set to 0.  */
 static cpp_hashnode *
 static cpp_hashnode *
-parse_assertion (cpp_reader *pfile, struct answer **answerp, int type)
+parse_assertion (cpp_reader *pfile, int type, cpp_macro **answer_ptr)
 {
   cpp_hashnode *result = 0;
 {
   cpp_hashnode *result = 0;
-  const cpp_token *predicate;
 
   /* We don't expand predicates or answers.  */
   pfile->state.prevent_expansion++;
 
 
   /* We don't expand predicates or answers.  */
   pfile->state.prevent_expansion++;
 
-  *answerp = 0;
-  predicate = cpp_get_token (pfile);
+  *answer_ptr = NULL;
+
+  const cpp_token *predicate = cpp_get_token (pfile);
   if (predicate->type == CPP_EOF)
     cpp_error (pfile, CPP_DL_ERROR, "assertion without predicate");
   else if (predicate->type != CPP_NAME)
   if (predicate->type == CPP_EOF)
     cpp_error (pfile, CPP_DL_ERROR, "assertion without predicate");
   else if (predicate->type != CPP_NAME)
-    cpp_error (pfile, CPP_DL_ERROR, "predicate must be an identifier");
-  else if (parse_answer (pfile, answerp, type) == 0)
+    cpp_error_with_line (pfile, CPP_DL_ERROR, predicate->src_loc, 0,
+                        "predicate must be an identifier");
+  else if (parse_answer (pfile, type, predicate->src_loc, answer_ptr))
     {
     {
-      unsigned int len = NODE_LEN (predicate->val.node);
-      unsigned char *sym = alloca (len + 1);
+      unsigned int len = NODE_LEN (predicate->val.node.node);
+      unsigned char *sym = (unsigned char *) alloca (len + 1);
 
       /* Prefix '#' to get it out of macro namespace.  */
       sym[0] = '#';
 
       /* Prefix '#' to get it out of macro namespace.  */
       sym[0] = '#';
-      memcpy (sym + 1, NODE_NAME (predicate->val.node), len);
+      memcpy (sym + 1, NODE_NAME (predicate->val.node.node), len);
       result = cpp_lookup (pfile, sym, len + 1);
     }
 
   pfile->state.prevent_expansion--;
       result = cpp_lookup (pfile, sym, len + 1);
     }
 
   pfile->state.prevent_expansion--;
+
   return result;
 }
 
 /* Returns a pointer to the pointer to CANDIDATE in the answer chain,
    or a pointer to NULL if the answer is not in the chain.  */
   return result;
 }
 
 /* Returns a pointer to the pointer to CANDIDATE in the answer chain,
    or a pointer to NULL if the answer is not in the chain.  */
-static struct answer **
-find_answer (cpp_hashnode *node, const struct answer *candidate)
+static cpp_macro **
+find_answer (cpp_hashnode *node, const cpp_macro *candidate)
 {
   unsigned int i;
 {
   unsigned int i;
-  struct answer **result;
+  cpp_macro **result = NULL;
 
 
-  for (result = &node->value.answers; *result; result = &(*result)->next)
+  for (result = &node->value.answers; *result; result = &(*result)->parm.next)
     {
     {
-      struct answer *answer = *result;
+      cpp_macro *answer = *result;
 
       if (answer->count == candidate->count)
        {
          for (i = 0; i < answer->count; i++)
 
       if (answer->count == candidate->count)
        {
          for (i = 0; i < answer->count; i++)
-           if (! _cpp_equiv_tokens (&answer->first[i], &candidate->first[i]))
+           if (!_cpp_equiv_tokens (&answer->exp.tokens[i],
+                                   &candidate->exp.tokens[i]))
              break;
 
          if (i == answer->count)
              break;
 
          if (i == answer->count)
@@ -1770,18 +2276,18 @@ find_answer (cpp_hashnode *node, const struct answer *candidate)
 int
 _cpp_test_assertion (cpp_reader *pfile, unsigned int *value)
 {
 int
 _cpp_test_assertion (cpp_reader *pfile, unsigned int *value)
 {
-  struct answer *answer;
-  cpp_hashnode *node;
-
-  node = parse_assertion (pfile, &answer, T_IF);
+  cpp_macro *answer;
+  cpp_hashnode *node = parse_assertion (pfile, T_IF, &answer);
 
   /* For recovery, an erroneous assertion expression is handled as a
      failing assertion.  */
   *value = 0;
 
   if (node)
 
   /* For recovery, an erroneous assertion expression is handled as a
      failing assertion.  */
   *value = 0;
 
   if (node)
-    *value = (node->type == NT_ASSERTION &&
-             (answer == 0 || *find_answer (node, answer) != 0));
+    {
+      if (node->value.answers)
+       *value = !answer || *find_answer (node, answer);
+    }
   else if (pfile->cur_token[-1].type == CPP_EOF)
     _cpp_backup_tokens (pfile, 1);
 
   else if (pfile->cur_token[-1].type == CPP_EOF)
     _cpp_backup_tokens (pfile, 1);
 
@@ -1793,43 +2299,30 @@ _cpp_test_assertion (cpp_reader *pfile, unsigned int *value)
 static void
 do_assert (cpp_reader *pfile)
 {
 static void
 do_assert (cpp_reader *pfile)
 {
-  struct answer *new_answer;
-  cpp_hashnode *node;
+  cpp_macro *answer;
+  cpp_hashnode *node = parse_assertion (pfile, T_ASSERT, &answer);
 
 
-  node = parse_assertion (pfile, &new_answer, T_ASSERT);
   if (node)
     {
   if (node)
     {
-      size_t answer_size;
-
       /* Place the new answer in the answer list.  First check there
          is not a duplicate.  */
       /* Place the new answer in the answer list.  First check there
          is not a duplicate.  */
-      new_answer->next = 0;
-      if (node->type == NT_ASSERTION)
+      if (*find_answer (node, answer))
        {
        {
-         if (*find_answer (node, new_answer))
-           {
-             cpp_error (pfile, CPP_DL_WARNING, "\"%s\" re-asserted",
-                        NODE_NAME (node) + 1);
-             return;
-           }
-         new_answer->next = node->value.answers;
+         cpp_error (pfile, CPP_DL_WARNING, "\"%s\" re-asserted",
+                    NODE_NAME (node) + 1);
+         return;
        }
 
        }
 
-      answer_size = sizeof (struct answer) + ((new_answer->count - 1)
-                                             * sizeof (cpp_token));
-      /* Commit or allocate storage for the object.  */
-      if (pfile->hash_table->alloc_subobject)
-       {
-         struct answer *temp_answer = new_answer;
-         new_answer = pfile->hash_table->alloc_subobject (answer_size);
-         memcpy (new_answer, temp_answer, answer_size);
-       }
-      else
-       BUFF_FRONT (pfile->a_buff) += answer_size;
+      /* Commit or allocate storage for the answer.  */
+      answer = (cpp_macro *)_cpp_commit_buff
+       (pfile, sizeof (cpp_macro) - sizeof (cpp_token)
+        + sizeof (cpp_token) * answer->count);
+
+      /* Chain into the list.  */
+      answer->parm.next = node->value.answers;
+      node->value.answers = answer;
 
 
-      node->type = NT_ASSERTION;
-      node->value.answers = new_answer;
-      check_eol (pfile);
+      check_eol (pfile, false);
     }
 }
 
     }
 }
 
@@ -1837,27 +2330,21 @@ do_assert (cpp_reader *pfile)
 static void
 do_unassert (cpp_reader *pfile)
 {
 static void
 do_unassert (cpp_reader *pfile)
 {
-  cpp_hashnode *node;
-  struct answer *answer;
+  cpp_macro *answer;
+  cpp_hashnode *node = parse_assertion (pfile, T_UNASSERT, &answer);
 
 
-  node = parse_assertion (pfile, &answer, T_UNASSERT);
   /* It isn't an error to #unassert something that isn't asserted.  */
   /* It isn't an error to #unassert something that isn't asserted.  */
-  if (node && node->type == NT_ASSERTION)
+  if (node)
     {
       if (answer)
        {
     {
       if (answer)
        {
-         struct answer **p = find_answer (node, answer), *temp;
-
-         /* Remove the answer from the list.  */
-         temp = *p;
-         if (temp)
-           *p = temp->next;
+         cpp_macro **p = find_answer (node, answer);
 
 
-         /* Did we free the last answer?  */
-         if (node->value.answers == 0)
-           node->type = NT_VOID;
+         /* Remove the assert from the list.  */
+         if (cpp_macro *temp = *p)
+           *p = temp->parm.next;
 
 
-         check_eol (pfile);
+         check_eol (pfile, false);
        }
       else
        _cpp_free_definition (node);
        }
       else
        _cpp_free_definition (node);
@@ -1875,7 +2362,8 @@ do_unassert (cpp_reader *pfile)
 void
 cpp_define (cpp_reader *pfile, const char *str)
 {
 void
 cpp_define (cpp_reader *pfile, const char *str)
 {
-  char *buf, *p;
+  char *buf;
+  const char *p;
   size_t count;
 
   /* Copy the entire option so we can modify it.
   size_t count;
 
   /* Copy the entire option so we can modify it.
@@ -1883,7 +2371,7 @@ cpp_define (cpp_reader *pfile, const char *str)
      tack " 1" on the end.  */
 
   count = strlen (str);
      tack " 1" on the end.  */
 
   count = strlen (str);
-  buf = alloca (count + 3);
+  buf = (char *) alloca (count + 3);
   memcpy (buf, str, count);
 
   p = strchr (str, '=');
   memcpy (buf, str, count);
 
   p = strchr (str, '=');
@@ -1899,12 +2387,32 @@ cpp_define (cpp_reader *pfile, const char *str)
   run_directive (pfile, T_DEFINE, buf, count);
 }
 
   run_directive (pfile, T_DEFINE, buf, count);
 }
 
+
+/* Use to build macros to be run through cpp_define() as
+   described above.
+   Example: cpp_define_formatted (pfile, "MACRO=%d", value);  */
+
+void
+cpp_define_formatted (cpp_reader *pfile, const char *fmt, ...)
+{
+  char *ptr;
+
+  va_list ap;
+  va_start (ap, fmt);
+  ptr = xvasprintf (fmt, ap);
+  va_end (ap);
+
+  cpp_define (pfile, ptr);
+  free (ptr);
+}
+
+
 /* Slight variant of the above for use by initialize_builtins.  */
 void
 _cpp_define_builtin (cpp_reader *pfile, const char *str)
 {
   size_t len = strlen (str);
 /* Slight variant of the above for use by initialize_builtins.  */
 void
 _cpp_define_builtin (cpp_reader *pfile, const char *str)
 {
   size_t len = strlen (str);
-  char *buf = alloca (len + 1);
+  char *buf = (char *) alloca (len + 1);
   memcpy (buf, str, len);
   buf[len] = '\n';
   run_directive (pfile, T_DEFINE, buf, len);
   memcpy (buf, str, len);
   buf[len] = '\n';
   run_directive (pfile, T_DEFINE, buf, len);
@@ -1915,12 +2423,63 @@ void
 cpp_undef (cpp_reader *pfile, const char *macro)
 {
   size_t len = strlen (macro);
 cpp_undef (cpp_reader *pfile, const char *macro)
 {
   size_t len = strlen (macro);
-  char *buf = alloca (len + 1);
+  char *buf = (char *) alloca (len + 1);
   memcpy (buf, macro, len);
   buf[len] = '\n';
   run_directive (pfile, T_UNDEF, buf, len);
 }
 
   memcpy (buf, macro, len);
   buf[len] = '\n';
   run_directive (pfile, T_UNDEF, buf, len);
 }
 
+/* Replace a previous definition DEF of the macro STR.  If DEF is NULL,
+   or first element is zero, then the macro should be undefined.  */
+static void
+cpp_pop_definition (cpp_reader *pfile, struct def_pragma_macro *c)
+{
+  cpp_hashnode *node = _cpp_lex_identifier (pfile, c->name);
+  if (node == NULL)
+    return;
+
+  if (pfile->cb.before_define)
+    pfile->cb.before_define (pfile);
+
+  if (cpp_macro_p (node))
+    {
+      if (pfile->cb.undef)
+       pfile->cb.undef (pfile, pfile->directive_line, node);
+      if (CPP_OPTION (pfile, warn_unused_macros))
+       _cpp_warn_if_unused_macro (pfile, node, NULL);
+      _cpp_free_definition (node);
+    }
+
+  if (c->is_undef)
+    return;
+
+  {
+    size_t namelen;
+    const uchar *dn;
+    cpp_hashnode *h = NULL;
+    cpp_buffer *nbuf;
+
+    namelen = ustrcspn (c->definition, "( \n");
+    h = cpp_lookup (pfile, c->definition, namelen);
+    dn = c->definition + namelen;
+
+    nbuf = cpp_push_buffer (pfile, dn, ustrchr (dn, '\n') - dn, true);
+    if (nbuf != NULL)
+      {
+       _cpp_clean_line (pfile);
+       nbuf->sysp = 1;
+       if (!_cpp_create_definition (pfile, h))
+         abort ();
+       _cpp_pop_buffer (pfile);
+      }
+    else
+      abort ();
+    h->value.macro->line = c->line;
+    h->value.macro->syshdr = c->syshdr;
+    h->value.macro->used = c->used;
+  }
+}
+
 /* Process the string STR as if it appeared as the body of a #assert.  */
 void
 cpp_assert (cpp_reader *pfile, const char *str)
 /* Process the string STR as if it appeared as the body of a #assert.  */
 void
 cpp_assert (cpp_reader *pfile, const char *str)
@@ -1944,7 +2503,7 @@ handle_assertion (cpp_reader *pfile, const char *str, int type)
 
   /* Copy the entire option so we can modify it.  Change the first
      "=" in the string to a '(', and tack a ')' on the end.  */
 
   /* Copy the entire option so we can modify it.  Change the first
      "=" in the string to a '(', and tack a ')' on the end.  */
-  char *buf = alloca (count + 2);
+  char *buf = (char *) alloca (count + 2);
 
   memcpy (buf, str, count);
   if (p)
 
   memcpy (buf, str, count);
   if (p)
@@ -1958,13 +2517,6 @@ handle_assertion (cpp_reader *pfile, const char *str, int type)
   run_directive (pfile, type, str, count);
 }
 
   run_directive (pfile, type, str, count);
 }
 
-/* The number of errors for a given reader.  */
-unsigned int
-cpp_errors (cpp_reader *pfile)
-{
-  return pfile->errors;
-}
-
 /* The options structure.  */
 cpp_options *
 cpp_get_options (cpp_reader *pfile)
 /* The options structure.  */
 cpp_options *
 cpp_get_options (cpp_reader *pfile)
@@ -2002,20 +2554,20 @@ cpp_buffer *
 cpp_push_buffer (cpp_reader *pfile, const uchar *buffer, size_t len,
                 int from_stage3)
 {
 cpp_push_buffer (cpp_reader *pfile, const uchar *buffer, size_t len,
                 int from_stage3)
 {
-  cpp_buffer *new = XOBNEW (&pfile->buffer_ob, cpp_buffer);
+  cpp_buffer *new_buffer = XOBNEW (&pfile->buffer_ob, cpp_buffer);
 
   /* Clears, amongst other things, if_stack and mi_cmacro.  */
 
   /* Clears, amongst other things, if_stack and mi_cmacro.  */
-  memset (new, 0, sizeof (cpp_buffer));
+  memset (new_buffer, 0, sizeof (cpp_buffer));
 
 
-  new->next_line = new->buf = buffer;
-  new->rlimit = buffer + len;
-  new->from_stage3 = from_stage3;
-  new->prev = pfile->buffer;
-  new->need_line = true;
+  new_buffer->next_line = new_buffer->buf = buffer;
+  new_buffer->rlimit = buffer + len;
+  new_buffer->from_stage3 = from_stage3;
+  new_buffer->prev = pfile->buffer;
+  new_buffer->need_line = true;
 
 
-  pfile->buffer = new;
+  pfile->buffer = new_buffer;
 
 
-  return new;
+  return new_buffer;
 }
 
 /* Pops a single buffer, with a file change call-back if appropriate.
 }
 
 /* Pops a single buffer, with a file change call-back if appropriate.
@@ -2026,6 +2578,7 @@ _cpp_pop_buffer (cpp_reader *pfile)
   cpp_buffer *buffer = pfile->buffer;
   struct _cpp_file *inc = buffer->file;
   struct if_stack *ifs;
   cpp_buffer *buffer = pfile->buffer;
   struct _cpp_file *inc = buffer->file;
   struct if_stack *ifs;
+  const unsigned char *to_free;
 
   /* Walk back up the conditional stack till we reach its level at
      entry to this file, issuing error messages.  */
 
   /* Walk back up the conditional stack till we reach its level at
      entry to this file, issuing error messages.  */
@@ -2039,6 +2592,7 @@ _cpp_pop_buffer (cpp_reader *pfile)
   /* _cpp_do_file_change expects pfile->buffer to be the new one.  */
   pfile->buffer = buffer->prev;
 
   /* _cpp_do_file_change expects pfile->buffer to be the new one.  */
   pfile->buffer = buffer->prev;
 
+  to_free = buffer->to_free;
   free (buffer->notes);
 
   /* Free the buffer object now; we may want to push a new buffer
   free (buffer->notes);
 
   /* Free the buffer object now; we may want to push a new buffer
@@ -2047,10 +2601,12 @@ _cpp_pop_buffer (cpp_reader *pfile)
 
   if (inc)
     {
 
   if (inc)
     {
-      _cpp_pop_file_buffer (pfile, inc);
+      _cpp_pop_file_buffer (pfile, inc, to_free);
 
       _cpp_do_file_change (pfile, LC_LEAVE, 0, 0, 0);
     }
 
       _cpp_do_file_change (pfile, LC_LEAVE, 0, 0, 0);
     }
+  else if (to_free)
+    free ((void *)to_free);
 }
 
 /* Enter all recognized directives in the hash table.  */
 }
 
 /* Enter all recognized directives in the hash table.  */
@@ -2067,3 +2623,12 @@ _cpp_init_directives (cpp_reader *pfile)
       node->directive_index = i;
     }
 }
       node->directive_index = i;
     }
 }
+
+/* Extract header file from a bracket include. Parsing starts after '<'.
+   The string is malloced and must be freed by the caller.  */
+char *
+_cpp_bracket_include(cpp_reader *pfile)
+{
+  return glue_header_name (pfile);
+}
+