Daily bump.
[gcc.git] / libcpp / init.c
index c3fa4af178beba492fc963ea8f38e1980cb660d8..f77dc26a003dc784c2b1585353681ee992ce7a0b 100644 (file)
@@ -1,5 +1,5 @@
 /* CPP Library.
-   Copyright (C) 1986-2013 Free Software Foundation, Inc.
+   Copyright (C) 1986-2020 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
@@ -27,12 +27,16 @@ along with this program; see the file COPYING3.  If not see
 #include "filenames.h"
 
 #ifndef ENABLE_CANONICAL_SYSTEM_HEADERS
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+#define ENABLE_CANONICAL_SYSTEM_HEADERS 1
+#else
 #define ENABLE_CANONICAL_SYSTEM_HEADERS 0
 #endif
+#endif
 
 static void init_library (void);
 static void mark_named_operators (cpp_reader *, int);
-static void read_original_filename (cpp_reader *);
+static bool read_original_filename (cpp_reader *);
 static void read_original_directory (cpp_reader *);
 static void post_options (cpp_reader *);
 
@@ -77,34 +81,45 @@ struct lang_flags
   char cplusplus;
   char extended_numbers;
   char extended_identifiers;
+  char c11_identifiers;
   char std;
-  char cplusplus_comments;
   char digraphs;
   char uliterals;
   char rliterals;
   char user_literals;
+  char binary_constants;
+  char digit_separators;
+  char trigraphs;
+  char utf8_char_literals;
+  char va_opt;
+  char scope;
+  char dfp_constants;
 };
 
 static const struct lang_flags lang_defaults[] =
-{ /*              c99 c++ xnum xid std  //   digr ulit rlit user_literals */
-  /* GNUC89   */  { 0,  0,  1,   0,  0,   1,   1,   0,   0,    0 },
-  /* GNUC99   */  { 1,  0,  1,   0,  0,   1,   1,   1,   1,    0 },
-  /* GNUC11   */  { 1,  0,  1,   0,  0,   1,   1,   1,   1,    0 },
-  /* STDC89   */  { 0,  0,  0,   0,  1,   0,   0,   0,   0,    0 },
-  /* STDC94   */  { 0,  0,  0,   0,  1,   0,   1,   0,   0,    0 },
-  /* STDC99   */  { 1,  0,  1,   0,  1,   1,   1,   0,   0,    0 },
-  /* STDC11   */  { 1,  0,  1,   0,  1,   1,   1,   1,   0,    0 },
-  /* GNUCXX   */  { 0,  1,  1,   0,  0,   1,   1,   0,   0,    0 },
-  /* CXX98    */  { 0,  1,  1,   0,  1,   1,   1,   0,   0,    0 },
-  /* GNUCXX11 */  { 1,  1,  1,   0,  0,   1,   1,   1,   1,    1 },
-  /* CXX11    */  { 1,  1,  1,   0,  1,   1,   1,   1,   1,    1 },
-  /* GNUCXX1Y */  { 1,  1,  1,   0,  0,   1,   1,   1,   1,    1 },
-  /* CXX1Y    */  { 1,  1,  1,   0,  1,   1,   1,   1,   1,    1 },
-  /* ASM      */  { 0,  0,  1,   0,  0,   1,   0,   0,   0,    0 }
-  /* xid should be 1 for GNUC99, STDC99, GNUCXX, CXX98, GNUCXX11, CXX11,
-     GNUCXX1Y, and CXX1Y when no longer experimental (when all uses of
-     identifiers in the compiler have been audited for correct handling
-     of extended identifiers).  */
+{ /*              c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt scope dfp */
+  /* GNUC89   */  { 0,  0,  1,  0,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
+  /* GNUC99   */  { 1,  0,  1,  1,  0,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
+  /* GNUC11   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
+  /* GNUC17   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    0,     0,     0,   0,      1,   1,     0 },
+  /* GNUC2X   */  { 1,  0,  1,  1,  1,  0,  1,   1,   1,   0,    1,     0,     0,   1,      1,   1,     1 },
+  /* STDC89   */  { 0,  0,  0,  0,  0,  1,  0,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
+  /* STDC94   */  { 0,  0,  0,  0,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
+  /* STDC99   */  { 1,  0,  1,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
+  /* STDC11   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
+  /* STDC17   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    0,     0,     1,   0,      0,   0,     0 },
+  /* STDC2X   */  { 1,  0,  1,  1,  1,  1,  1,   1,   0,   0,    1,     0,     1,   1,      0,   1,     1 },
+  /* GNUCXX   */  { 0,  1,  1,  1,  0,  0,  1,   0,   0,   0,    0,     0,     0,   0,      1,   1,     0 },
+  /* CXX98    */  { 0,  1,  0,  1,  0,  1,  1,   0,   0,   0,    0,     0,     1,   0,      0,   1,     0 },
+  /* GNUCXX11 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    0,     0,     0,   0,      1,   1,     0 },
+  /* CXX11    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    0,     0,     1,   0,      0,   1,     0 },
+  /* GNUCXX14 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   0,      1,   1,     0 },
+  /* CXX14    */  { 1,  1,  0,  1,  1,  1,  1,   1,   1,   1,    1,     1,     1,   0,      0,   1,     0 },
+  /* GNUCXX17 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
+  /* CXX17    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      0,   1,     0 },
+  /* GNUCXX20 */  { 1,  1,  1,  1,  1,  0,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
+  /* CXX20    */  { 1,  1,  1,  1,  1,  1,  1,   1,   1,   1,    1,     1,     0,   1,      1,   1,     0 },
+  /* ASM      */  { 0,  0,  1,  0,  0,  0,  0,   0,   0,   0,    0,     0,     0,   0,      0,   0,     0 }
 };
 
 /* Sets internal flags correctly for a given language.  */
@@ -119,13 +134,19 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
   CPP_OPTION (pfile, cplusplus)                         = l->cplusplus;
   CPP_OPTION (pfile, extended_numbers)          = l->extended_numbers;
   CPP_OPTION (pfile, extended_identifiers)      = l->extended_identifiers;
+  CPP_OPTION (pfile, c11_identifiers)           = l->c11_identifiers;
   CPP_OPTION (pfile, std)                       = l->std;
-  CPP_OPTION (pfile, trigraphs)                         = l->std;
-  CPP_OPTION (pfile, cplusplus_comments)        = l->cplusplus_comments;
   CPP_OPTION (pfile, digraphs)                  = l->digraphs;
   CPP_OPTION (pfile, uliterals)                         = l->uliterals;
   CPP_OPTION (pfile, rliterals)                         = l->rliterals;
   CPP_OPTION (pfile, user_literals)             = l->user_literals;
+  CPP_OPTION (pfile, binary_constants)          = l->binary_constants;
+  CPP_OPTION (pfile, digit_separators)          = l->digit_separators;
+  CPP_OPTION (pfile, trigraphs)                         = l->trigraphs;
+  CPP_OPTION (pfile, utf8_char_literals)        = l->utf8_char_literals;
+  CPP_OPTION (pfile, va_opt)                    = l->va_opt;
+  CPP_OPTION (pfile, scope)                     = l->scope;
+  CPP_OPTION (pfile, dfp_constants)             = l->dfp_constants;
 }
 
 /* Initialize library global state.  */
@@ -154,7 +175,7 @@ init_library (void)
 /* Initialize a cpp_reader structure.  */
 cpp_reader *
 cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
-                  struct line_maps *line_table)
+                  class line_maps *line_table)
 {
   cpp_reader *pfile;
 
@@ -168,16 +189,20 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
   CPP_OPTION (pfile, warn_multichar) = 1;
   CPP_OPTION (pfile, discard_comments) = 1;
   CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
-  CPP_OPTION (pfile, tabstop) = 8;
+  CPP_OPTION (pfile, max_include_depth) = 200;
   CPP_OPTION (pfile, operator_names) = 1;
   CPP_OPTION (pfile, warn_trigraphs) = 2;
   CPP_OPTION (pfile, warn_endif_labels) = 1;
+  CPP_OPTION (pfile, cpp_warn_c90_c99_compat) = -1;
+  CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) = -1;
+  CPP_OPTION (pfile, cpp_warn_cxx11_compat) = 0;
   CPP_OPTION (pfile, cpp_warn_deprecated) = 1;
   CPP_OPTION (pfile, cpp_warn_long_long) = 0;
   CPP_OPTION (pfile, dollars_in_ident) = 1;
   CPP_OPTION (pfile, warn_dollars) = 1;
   CPP_OPTION (pfile, warn_variadic_macros) = 1;
   CPP_OPTION (pfile, warn_builtin_macro_redefined) = 1;
+  CPP_OPTION (pfile, cpp_warn_implicit_fallthrough) = 0;
   /* By default, track locations of tokens resulting from macro
      expansion.  The '2' means, track the locations with the highest
      accuracy.  Read the comments for struct
@@ -189,6 +214,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
   CPP_OPTION (pfile, canonical_system_headers)
       = ENABLE_CANONICAL_SYSTEM_HEADERS;
   CPP_OPTION (pfile, ext_numeric_literals) = 1;
+  CPP_OPTION (pfile, warn_date_time) = 0;
 
   /* Default CPP arithmetic to something sensible for the host for the
      benefit of dumb users like fix-header.  */
@@ -222,8 +248,10 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
   /* Set up static tokens.  */
   pfile->avoid_paste.type = CPP_PADDING;
   pfile->avoid_paste.val.source = NULL;
-  pfile->eof.type = CPP_EOF;
-  pfile->eof.flags = 0;
+  pfile->avoid_paste.src_loc = 0;
+  pfile->endarg.type = CPP_EOF;
+  pfile->endarg.flags = 0;
+  pfile->endarg.src_loc = 0;
 
   /* Create a token buffer for the lexer.  */
   _cpp_init_tokenrun (&pfile->base_run, 250);
@@ -243,15 +271,17 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
   pfile->pushed_macros = 0;
 
   /* Do not force token locations by default.  */
-  pfile->forced_token_location_p = NULL;
+  pfile->forced_token_location = 0;
+
+  /* Note the timestamp is unset.  */
+  pfile->time_stamp = time_t (-1);
+  pfile->time_stamp_kind = 0;
 
   /* The expression parser stack.  */
   _cpp_expand_op_stack (pfile);
 
   /* Initialize the buffer obstack.  */
-  _obstack_begin (&pfile->buffer_ob, 0, 0,
-                 (void *(*) (long)) xmalloc,
-                 (void (*) (void *)) free);
+  obstack_specify_allocation (&pfile->buffer_ob, 0, 0, xmalloc, free);
 
   _cpp_init_files (pfile);
 
@@ -263,7 +293,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
 /* Set the line_table entry in PFILE.  This is called after reading a
    PCH file, as the old line_table will be incorrect.  */
 void
-cpp_set_line_map (cpp_reader *pfile, struct line_maps *line_table)
+cpp_set_line_map (cpp_reader *pfile, class line_maps *line_table)
 {
   pfile->line_table = line_table;
 }
@@ -373,6 +403,15 @@ static const struct builtin_macro builtin_array[] =
   B("__LINE__",                 BT_SPECLINE,      true),
   B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL, true),
   B("__COUNTER__",      BT_COUNTER,       true),
+  /* Make sure to update the list of built-in
+     function-like macros in traditional.c:
+     fun_like_macro() when adding more following */
+  B("__has_attribute",  BT_HAS_ATTRIBUTE, true),
+  B("__has_c_attribute", BT_HAS_STD_ATTRIBUTE, true),
+  B("__has_cpp_attribute", BT_HAS_ATTRIBUTE, true),
+  B("__has_builtin",    BT_HAS_BUILTIN,   true),
+  B("__has_include",    BT_HAS_INCLUDE,   true),
+  B("__has_include_next",BT_HAS_INCLUDE_NEXT,   true),
   /* Keep builtins not used for -traditional-cpp at the end, and
      update init_builtins() if any more are added.  */
   B("_Pragma",          BT_PRAGMA,        true),
@@ -453,16 +492,39 @@ cpp_init_special_builtins (cpp_reader *pfile)
 
   for (b = builtin_array; b < builtin_array + n; b++)
     {
+      if ((b->value == BT_HAS_ATTRIBUTE
+          || b->value == BT_HAS_STD_ATTRIBUTE
+          || b->value == BT_HAS_BUILTIN)
+         && (CPP_OPTION (pfile, lang) == CLK_ASM
+             || pfile->cb.has_attribute == NULL))
+       continue;
       cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
-      hp->type = NT_MACRO;
-      hp->flags |= NODE_BUILTIN;
-      if (b->always_warn_if_redefined
-          || CPP_OPTION (pfile, warn_builtin_macro_redefined))
+      hp->type = NT_BUILTIN_MACRO;
+      if (b->always_warn_if_redefined)
        hp->flags |= NODE_WARN;
       hp->value.builtin = (enum cpp_builtin_type) b->value;
     }
 }
 
+/* Restore macro C to builtin macro definition.  */
+
+void
+_cpp_restore_special_builtin (cpp_reader *pfile, struct def_pragma_macro *c)
+{
+  size_t len = strlen (c->name);
+
+  for (const struct builtin_macro *b = builtin_array;
+       b < builtin_array + ARRAY_SIZE (builtin_array); b++)
+    if (b->len == len && memcmp (c->name, b->name, len + 1) == 0)
+      {
+       cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
+       hp->type = NT_BUILTIN_MACRO;
+       if (b->always_warn_if_redefined)
+         hp->flags |= NODE_WARN;
+       hp->value.builtin = (enum cpp_builtin_type) b->value;
+      }
+}
+
 /* Read the builtins table above and enter them, and language-specific
    macros, into the hash table.  HOSTED is true if this is a hosted
    environment.  */
@@ -478,9 +540,15 @@ cpp_init_builtins (cpp_reader *pfile, int hosted)
 
   if (CPP_OPTION (pfile, cplusplus))
     {
-      if (CPP_OPTION (pfile, lang) == CLK_CXX1Y
-         || CPP_OPTION (pfile, lang) == CLK_GNUCXX1Y)
-       _cpp_define_builtin (pfile, "__cplusplus 201300L");
+      if (CPP_OPTION (pfile, lang) == CLK_CXX20
+         || CPP_OPTION (pfile, lang) == CLK_GNUCXX20)
+       _cpp_define_builtin (pfile, "__cplusplus 201709L");
+      else if (CPP_OPTION (pfile, lang) == CLK_CXX17
+         || CPP_OPTION (pfile, lang) == CLK_GNUCXX17)
+       _cpp_define_builtin (pfile, "__cplusplus 201703L");
+      else if (CPP_OPTION (pfile, lang) == CLK_CXX14
+         || CPP_OPTION (pfile, lang) == CLK_GNUCXX14)
+       _cpp_define_builtin (pfile, "__cplusplus 201402L");
       else if (CPP_OPTION (pfile, lang) == CLK_CXX11
               || CPP_OPTION (pfile, lang) == CLK_GNUCXX11)
        _cpp_define_builtin (pfile, "__cplusplus 201103L");
@@ -491,6 +559,12 @@ cpp_init_builtins (cpp_reader *pfile, int hosted)
     _cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
   else if (CPP_OPTION (pfile, lang) == CLK_STDC94)
     _cpp_define_builtin (pfile, "__STDC_VERSION__ 199409L");
+  else if (CPP_OPTION (pfile, lang) == CLK_STDC2X
+          || CPP_OPTION (pfile, lang) == CLK_GNUC2X)
+    _cpp_define_builtin (pfile, "__STDC_VERSION__ 202000L");
+  else if (CPP_OPTION (pfile, lang) == CLK_STDC17
+          || CPP_OPTION (pfile, lang) == CLK_GNUC17)
+    _cpp_define_builtin (pfile, "__STDC_VERSION__ 201710L");
   else if (CPP_OPTION (pfile, lang) == CLK_STDC11
           || CPP_OPTION (pfile, lang) == CLK_GNUC11)
     _cpp_define_builtin (pfile, "__STDC_VERSION__ 201112L");
@@ -498,7 +572,9 @@ cpp_init_builtins (cpp_reader *pfile, int hosted)
     _cpp_define_builtin (pfile, "__STDC_VERSION__ 199901L");
 
   if (CPP_OPTION (pfile, uliterals)
-      && !CPP_OPTION (pfile, cplusplus))
+      && !(CPP_OPTION (pfile, cplusplus)
+          && (CPP_OPTION (pfile, lang) == CLK_GNUCXX
+           || CPP_OPTION (pfile, lang) == CLK_CXX98)))
     {
       _cpp_define_builtin (pfile, "__STDC_UTF_16__ 1");
       _cpp_define_builtin (pfile, "__STDC_UTF_32__ 1");
@@ -514,8 +590,8 @@ cpp_init_builtins (cpp_reader *pfile, int hosted)
 }
 
 /* Sanity-checks are dependent on command-line options, so it is
-   called as a subroutine of cpp_read_main_file ().  */
-#if ENABLE_CHECKING
+   called as a subroutine of cpp_read_main_file.  */
+#if CHECKING_P
 static void sanity_checks (cpp_reader *);
 static void sanity_checks (cpp_reader *pfile)
 {
@@ -588,117 +664,146 @@ cpp_post_options (cpp_reader *pfile)
 }
 
 /* Setup for processing input from the file named FNAME, or stdin if
-   it is the empty string.  Return the original filename
-   on success (e.g. foo.i->foo.c), or NULL on failure.  */
+   it is the empty string.  Return the original filename on success
+   (e.g. foo.i->foo.c), or NULL on failure.  INJECTING is true if
+   there may be injected headers before line 1 of the main file.  */
 const char *
-cpp_read_main_file (cpp_reader *pfile, const char *fname)
+cpp_read_main_file (cpp_reader *pfile, const char *fname, bool injecting)
 {
-  if (CPP_OPTION (pfile, deps.style) != DEPS_NONE)
-    {
-      if (!pfile->deps)
-       pfile->deps = deps_init ();
-
-      /* Set the default target (if there is none already).  */
-      deps_add_default_target (pfile->deps, fname);
-    }
+  if (mkdeps *deps = cpp_get_deps (pfile))
+    /* Set the default target (if there is none already).  */
+    deps_add_default_target (deps, fname);
 
   pfile->main_file
-    = _cpp_find_file (pfile, fname, &pfile->no_search_path, false, 0, false);
+    = _cpp_find_file (pfile, fname,
+                     CPP_OPTION (pfile, preprocessed) ? &pfile->no_search_path
+                     : CPP_OPTION (pfile, main_search) == CMS_user
+                     ? pfile->quote_include
+                     : CPP_OPTION (pfile, main_search) == CMS_system
+                     ? pfile->bracket_include : &pfile->no_search_path,
+                     /*angle=*/0, _cpp_FFK_NORMAL, 0);
+
   if (_cpp_find_failed (pfile->main_file))
     return NULL;
 
-  _cpp_stack_file (pfile, pfile->main_file, false);
+  _cpp_stack_file (pfile, pfile->main_file,
+                  injecting || CPP_OPTION (pfile, preprocessed)
+                  ? IT_PRE_MAIN : IT_MAIN, 0);
 
   /* For foo.i, read the original filename foo.c now, for the benefit
      of the front ends.  */
   if (CPP_OPTION (pfile, preprocessed))
-    {
-      read_original_filename (pfile);
-      fname =
-       ORDINARY_MAP_FILE_NAME
-       ((LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table)));
-    }
-  return fname;
+    if (!read_original_filename (pfile))
+      {
+       /* We're on line 1 after all.  */
+       auto *last = linemap_check_ordinary
+         (LINEMAPS_LAST_MAP (pfile->line_table, false));
+       last->to_line = 1;
+       /* Inform of as-if a file change.  */
+       _cpp_do_file_change (pfile, LC_RENAME_VERBATIM, LINEMAP_FILE (last),
+                            LINEMAP_LINE (last), LINEMAP_SYSP (last));
+      }
+
+  auto *map = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table);
+  pfile->main_loc = MAP_START_LOCATION (map);
+
+  return ORDINARY_MAP_FILE_NAME (map);
 }
 
-/* For preprocessed files, if the first tokens are of the form # NUM.
-   handle the directive so we know the original file name.  This will
-   generate file_change callbacks, which the front ends must handle
-   appropriately given their state of initialization.  */
-static void
-read_original_filename (cpp_reader *pfile)
+location_t
+cpp_main_loc (const cpp_reader *pfile)
 {
-  const cpp_token *token, *token1;
+  return pfile->main_loc;
+}
 
-  /* Lex ahead; if the first tokens are of the form # NUM, then
-     process the directive, otherwise back up.  */
-  token = _cpp_lex_direct (pfile);
-  if (token->type == CPP_HASH)
+/* For preprocessed files, if the very first characters are
+   '#<SPACE>[01]<SPACE>', then handle a line directive so we know the
+   original file name.  This will generate file_change callbacks,
+   which the front ends must handle appropriately given their state of
+   initialization.  We peek directly into the character buffer, so
+   that we're not confused by otherwise-skipped white space &
+   comments.  We can be very picky, because this should have been
+   machine-generated text (by us, no less).  This way we do not
+   interfere with the module directive state machine.  */
+
+static bool
+read_original_filename (cpp_reader *pfile)
+{
+  auto *buf = pfile->buffer->next_line;
+
+  if (pfile->buffer->rlimit - buf > 4
+      && buf[0] == '#'
+      && buf[1] == ' '
+      // Also permit '1', as that's what used to be here
+      && (buf[2] == '0' || buf[2] == '1')
+      && buf[3] == ' ')
     {
-      pfile->state.in_directive = 1;
-      token1 = _cpp_lex_direct (pfile);
-      _cpp_backup_tokens (pfile, 1);
-      pfile->state.in_directive = 0;
-
-      /* If it's a #line directive, handle it.  */
-      if (token1->type == CPP_NUMBER
-         && _cpp_handle_directive (pfile, token->flags & PREV_WHITE))
+      const cpp_token *token = _cpp_lex_direct (pfile);
+      gcc_checking_assert (token->type == CPP_HASH);
+      if (_cpp_handle_directive (pfile, token->flags & PREV_WHITE))
        {
          read_original_directory (pfile);
-         return;
+         return true;
        }
     }
 
-  /* Backup as if nothing happened.  */
-  _cpp_backup_tokens (pfile, 1);
+  return false;
 }
 
 /* For preprocessed files, if the tokens following the first filename
    line is of the form # <line> "/path/name//", handle the
-   directive so we know the original current directory.  */
+   directive so we know the original current directory.
+
+   As with the first line peeking, we can do this without lexing by
+   being picky.  */
 static void
 read_original_directory (cpp_reader *pfile)
 {
-  const cpp_token *hash, *token;
-
-  /* Lex ahead; if the first tokens are of the form # NUM, then
-     process the directive, otherwise back up.  */
-  hash = _cpp_lex_direct (pfile);
-  if (hash->type != CPP_HASH)
+  auto *buf = pfile->buffer->next_line;
+
+  if (pfile->buffer->rlimit - buf > 4
+      && buf[0] == '#'
+      && buf[1] == ' '
+      // Also permit '1', as that's what used to be here
+      && (buf[2] == '0' || buf[2] == '1')
+      && buf[3] == ' ')
     {
-      _cpp_backup_tokens (pfile, 1);
-      return;
-    }
-
-  token = _cpp_lex_direct (pfile);
+      const cpp_token *hash = _cpp_lex_direct (pfile);
+      gcc_checking_assert (hash->type == CPP_HASH);
+      pfile->state.in_directive = 1;
+      const cpp_token *number = _cpp_lex_direct (pfile);
+      gcc_checking_assert (number->type == CPP_NUMBER);
+      const cpp_token *string = _cpp_lex_direct (pfile);
+      pfile->state.in_directive = 0;
 
-  if (token->type != CPP_NUMBER)
-    {
-      _cpp_backup_tokens (pfile, 2);
-      return;
-    }
+      const unsigned char *text = nullptr;
+      size_t len = 0;
+      if (string->type == CPP_STRING)
+       {
+         /* The string value includes the quotes.  */
+         text = string->val.str.text;
+         len = string->val.str.len;
+       }
+      if (len < 5
+         || !IS_DIR_SEPARATOR (text[len - 2])
+         || !IS_DIR_SEPARATOR (text[len - 3]))
+       {
+         /* That didn't work out, back out.   */
+         _cpp_backup_tokens (pfile, 3);
+         return;
+       }
 
-  token = _cpp_lex_direct (pfile);
+      if (pfile->cb.dir_change)
+       {
+         /* Smash the string directly, it's dead at this point  */
+         char *smashy = (char *)text;
+         smashy[len - 3] = 0;
+         
+         pfile->cb.dir_change (pfile, smashy + 1);
+       }
 
-  if (token->type != CPP_STRING
-      || ! (token->val.str.len >= 5
-           && IS_DIR_SEPARATOR (token->val.str.text[token->val.str.len-2])
-           && IS_DIR_SEPARATOR (token->val.str.text[token->val.str.len-3])))
-    {
-      _cpp_backup_tokens (pfile, 3);
-      return;
+      /* We should be at EOL.  */
     }
-
-  if (pfile->cb.dir_change)
-    {
-      char *debugdir = (char *) alloca (token->val.str.len - 3);
-
-      memcpy (debugdir, (const char *) token->val.str.text + 1,
-             token->val.str.len - 4);
-      debugdir[token->val.str.len - 4] = '\0';
-
-      pfile->cb.dir_change (pfile, debugdir);
-    }      
 }
 
 /* This is called at the end of preprocessing.  It pops the last
@@ -721,14 +826,8 @@ cpp_finish (cpp_reader *pfile, FILE *deps_stream)
   while (pfile->buffer)
     _cpp_pop_buffer (pfile);
 
-  if (CPP_OPTION (pfile, deps.style) != DEPS_NONE
-      && deps_stream)
-    {
-      deps_write (pfile->deps, deps_stream, 72);
-
-      if (CPP_OPTION (pfile, deps.phony_targets))
-       deps_phony_targets (pfile->deps, deps_stream);
-    }
+  if (deps_stream)
+    deps_write (pfile, deps_stream, 72);
 
   /* Report on headers that could use multiple include guards.  */
   if (CPP_OPTION (pfile, print_include_names))
@@ -756,9 +855,30 @@ post_options (cpp_reader *pfile)
 
   if (CPP_OPTION (pfile, traditional))
     {
-      CPP_OPTION (pfile, cplusplus_comments) = 0;
-
       CPP_OPTION (pfile, trigraphs) = 0;
       CPP_OPTION (pfile, warn_trigraphs) = 0;
     }
+
+  if (CPP_OPTION (pfile, module_directives))
+    {
+      /* These unspellable tokens have a leading space.  */
+      const char *const inits[spec_nodes::M_HWM]
+       = {"export ", "module ", "import ", "__import"};
+
+      for (int ix = 0; ix != spec_nodes::M_HWM; ix++)
+       {
+         cpp_hashnode *node = cpp_lookup (pfile, UC (inits[ix]),
+                                          strlen (inits[ix]));
+
+         /* Token we pass to the compiler.  */
+         pfile->spec_nodes.n_modules[ix][1] = node;
+
+         if (ix != spec_nodes::M__IMPORT)
+           /* Token we recognize when lexing, drop the trailing ' '.  */
+           node = cpp_lookup (pfile, NODE_NAME (node), NODE_LEN (node) - 1);
+
+         node->flags |= NODE_MODULE;
+         pfile->spec_nodes.n_modules[ix][0] = node;
+       }
+    }
 }