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 *);
/* 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, 0, 0, 0, 1, 1, 1, 1 },
+ /* 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, 0, 0, 1, 1, 0, 1, 1 },
+ /* 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 },
/* 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 },
- /* GNUCXX2A */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0 },
- /* CXX2A */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 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 }
};
CPP_OPTION (pfile, discard_comments) = 1;
CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
CPP_OPTION (pfile, max_include_depth) = 200;
- CPP_OPTION (pfile, tabstop) = 8;
CPP_OPTION (pfile, operator_names) = 1;
CPP_OPTION (pfile, warn_trigraphs) = 2;
CPP_OPTION (pfile, warn_endif_labels) = 1;
/* 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);
/* Do not force token locations by default. */
pfile->forced_token_location = 0;
- /* Initialize source_date_epoch to -2 (not yet set). */
- pfile->source_date_epoch = (time_t) -2;
+ /* 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);
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),
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))
if (CPP_OPTION (pfile, cplusplus))
{
- if (CPP_OPTION (pfile, lang) == CLK_CXX2A
- || CPP_OPTION (pfile, lang) == CLK_GNUCXX2A)
+ 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)
if (CPP_OPTION (pfile, objc))
_cpp_define_builtin (pfile, "__OBJC__ 1");
-
- /* These two behave as macros for #ifdef, but are evaluated
- specially inside #if. */
- _cpp_define_builtin (pfile, "__has_include __has_include");
- _cpp_define_builtin (pfile, "__has_include_next __has_include_next");
- pfile->spec_nodes.n__has_include
- = cpp_lookup (pfile, DSC("__has_include"));
- pfile->spec_nodes.n__has_include->flags |= NODE_DIAGNOSTIC;
- pfile->spec_nodes.n__has_include_next
- = cpp_lookup (pfile, DSC("__has_include_next"));
- pfile->spec_nodes.n__has_include_next->flags |= NODE_DIAGNOSTIC;
}
/* Sanity-checks are dependent on command-line options, so it is
}
/* 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)
{
- const location_t loc = 0;
-
- 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, /*angle=*/0,
- /*fake=*/false, /*preinclude=*/false, /*hasinclude=*/false,
- loc);
+ = _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, IT_MAIN, 0);
+ _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
while (pfile->buffer)
_cpp_pop_buffer (pfile);
- if (CPP_OPTION (pfile, deps.style) != DEPS_NONE && deps_stream)
- deps_write (pfile->deps, deps_stream,
- CPP_OPTION (pfile, deps.phony_targets), 72);
+ 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))
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;
+ }
+ }
}