I needed a set of hook interfacing the preprocessor to the language.
they get called from pieces in c-family.
preprocess_main_file: we need to know when any forced headers have been
parsed in order to deal with linemaps and macro visibility
preprocess_options: A way for the language to adjust any preprocessor
options and alter direct callbacks
preprocess_undef: We need visibility of #undefs
preprocess_deferred_macro: macros from header-units are instantiated
lazily. This is the hook for the preprocessor to get that done.
preprocess_token: Even in -E processing, we need to observe the token
stream in order to load up the macro tables of header units.
c-family's c-lex.c, c-opts.c & c-ppoutput.c get to call these hooks in
various cases
--
Nathan Sidwell
diff --git c/gcc/c-family/c-lex.c w/gcc/c-family/c-lex.c
index e81e16ddc26..44575473719 100644
--- c/gcc/c-family/c-lex.c
+++ w/gcc/c-family/c-lex.c
@@ -28,7 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-pragma.h"
#include "debug.h"
#include "file-prefix-map.h" /* remap_macro_filename() */
-
+#include "langhooks.h"
#include "attribs.h"
/* We may keep statistics about how long which files took to compile. */
@@ -274,9 +274,11 @@ cb_define (cpp_reader *pfile, location_t loc, cpp_hashnode *node)
/* #undef callback for DWARF and DWARF2 debug info. */
static void
-cb_undef (cpp_reader * ARG_UNUSED (pfile), location_t loc,
- cpp_hashnode *node)
+cb_undef (cpp_reader *pfile, location_t loc, cpp_hashnode *node)
{
+ if (lang_hooks.preprocess_undef)
+ lang_hooks.preprocess_undef (pfile, loc, node);
+
const struct line_map *map = linemap_lookup (line_table, loc);
(*debug_hooks->undef) (SOURCE_LINE (linemap_check_ordinary (map), loc),
(const char *) NODE_NAME (node));
diff --git c/gcc/c-family/c-opts.c w/gcc/c-family/c-opts.c
index 120f4489f6c..c8f08d9e014 100644
--- c/gcc/c-family/c-opts.c
+++ w/gcc/c-family/c-opts.c
@@ -1105,9 +1116,11 @@ c_common_post_options (const char **pfilename)
input_location = UNKNOWN_LOCATION;
}
- struct cpp_callbacks *cb = cpp_get_callbacks (parse_in);
+ struct cpp_callbacks *cb = cpp_get_callbacks (parse_in);
cb->file_change = cb_file_change;
cb->dir_change = cb_dir_change;
+ if (lang_hooks.preprocess_options)
+ lang_hooks.preprocess_options (parse_in);
cpp_post_options (parse_in);
init_global_opts_from_cpp (&global_options, cpp_get_options (parse_in));
@@ -1169,6 +1182,11 @@ c_common_init (void)
/* Has to wait until now so that cpplib has its hash table. */
init_pragma ();
+ struct cpp_callbacks *cb = cpp_get_callbacks (parse_in);
+ cb->user_deferred_macro = lang_hooks.preprocess_deferred_macro;
+ if (!cb->undef)
+ cb->undef = lang_hooks.preprocess_undef;
+
if (flag_preprocess_only)
{
c_finish_options ();
@@ -1550,7 +1568,13 @@ push_command_line_include (void)
cpp_opts->warn_unused_macros = cpp_warn_unused_macros;
/* Restore the line map back to the main file. */
if (!cpp_opts->preprocessed)
- cpp_change_file (parse_in, LC_RENAME, this_input_filename);
+ {
+ cpp_change_file (parse_in, LC_RENAME, this_input_filename);
+ if (lang_hooks.preprocess_main_file)
+ /* We're starting the main file. Inform the FE of that. */
+ lang_hooks.preprocess_main_file
+ (parse_in, line_table, LINEMAPS_LAST_ORDINARY_MAP (line_table));
+ }
/* Set this here so the client can change the option if it wishes,
and after stacking the main file so we don't trace the main file. */
@@ -1560,14 +1584,19 @@ push_command_line_include (void)
/* File change callback. Has to handle -include files. */
static void
-cb_file_change (cpp_reader * ARG_UNUSED (pfile),
- const line_map_ordinary *new_map)
+cb_file_change (cpp_reader *reader, const line_map_ordinary *new_map)
{
if (flag_preprocess_only)
pp_file_change (new_map);
else
fe_file_change (new_map);
+ if (new_map && cpp_opts->preprocessed
+ && lang_hooks.preprocess_main_file && MAIN_FILE_P (new_map)
+ && ORDINARY_MAP_STARTING_LINE_NUMBER (new_map))
+ /* We're starting the main file. Inform the FE of that. */
+ lang_hooks.preprocess_main_file (reader, line_table, new_map);
+
if (new_map
&& (new_map->reason == LC_ENTER || new_map->reason == LC_RENAME))
{
diff --git c/gcc/c-family/c-ppoutput.c w/gcc/c-family/c-ppoutput.c
index 44c6f30e06b..e3e0e59fcc7 100644
--- c/gcc/c-family/c-ppoutput.c
+++ w/gcc/c-family/c-ppoutput.c
@@ -21,6 +21,7 @@
#include "coretypes.h"
#include "c-common.h" /* For flags. */
#include "../libcpp/internal.h"
+#include "langhooks.h"
#include "c-pragma.h" /* For parse_in. */
#include "file-prefix-map.h" /* remap_macro_filename() */
@@ -301,125 +302,48 @@ token_streamer::stream (cpp_reader *pfile, const cpp_token *token,
/* Writes out the preprocessed file, handling spacing and paste
avoidance issues. */
+
static void
scan_translation_unit (cpp_reader *pfile)
{
- bool avoid_paste = false;
- bool do_line_adjustments
- = cpp_get_options (parse_in)->lang != CLK_ASM
- && !flag_no_line_commands;
- bool in_pragma = false;
- bool line_marker_emitted = false;
+ token_streamer streamer (pfile);
+ uintptr_t filter = 0;
+
+ if (lang_hooks.preprocess_token)
+ filter = lang_hooks.preprocess_token (pfile, NULL, filter);
print.source = NULL;
for (;;)
{
- location_t loc;
- const cpp_token *token = cpp_get_token_with_location (pfile, &loc);
+ location_t spelling_loc;
+ const cpp_token *token
+ = cpp_get_token_with_location (pfile, &spelling_loc);
- if (token->type == CPP_PADDING)
+ streamer.stream (pfile, token, spelling_loc);
+ if (filter)
{
- avoid_paste = true;
- if (print.source == NULL
- || (!(print.source->flags & PREV_WHITE)
- && token->val.source == NULL))
- print.source = token->val.source;
- continue;
+ unsigned flags = lang_hooks.preprocess_token (pfile, token, filter);
+ if (flags & lang_hooks::PT_begin_pragma)
+ streamer.begin_pragma ();
}
-
if (token->type == CPP_EOF)
break;
+ }
- /* Subtle logic to output a space if and only if necessary. */
- if (avoid_paste)
- {
- int src_line = LOCATION_LINE (loc);
-
- if (print.source == NULL)
- print.source = token;
-
- if (src_line != print.src_line
- && do_line_adjustments
- && !in_pragma)
- {
- line_marker_emitted = do_line_change (pfile, token, loc, false);
- putc (' ', print.outf);
- print.printed = true;
- }
- else if (print.source->flags & PREV_WHITE
- || (print.prev
- && cpp_avoid_paste (pfile, print.prev, token))
- || (print.prev == NULL && token->type == CPP_HASH))
- {
- putc (' ', print.outf);
- print.printed = true;
- }
- }
- else if (token->flags & PREV_WHITE)
- {
- int src_line = LOCATION_LINE (loc);
-
- if (src_line != print.src_line
- && do_line_adjustments
- && !in_pragma)
- line_marker_emitted = do_line_change (pfile, token, loc, false);
- putc (' ', print.outf);
- print.printed = true;
- }
+ if (filter)
+ lang_hooks.preprocess_token (pfile, NULL, filter);
+}
- avoid_paste = false;
- print.source = NULL;
- print.prev = token;
- if (token->type == CPP_PRAGMA)
- {
- const char *space;
- const char *name;
-
- line_marker_emitted = maybe_print_line (token->src_loc);
- fputs ("#pragma ", print.outf);
- c_pp_lookup_pragma (token->val.pragma, &space, &name);
- if (space)
- fprintf (print.outf, "%s %s", space, name);
- else
- fprintf (print.outf, "%s", name);
- print.printed = true;
- in_pragma = true;
- }
- else if (token->type == CPP_PRAGMA_EOL)
- {
- maybe_print_line (token->src_loc);
- in_pragma = false;
- }
- else
- {
- if (cpp_get_options (parse_in)->debug)
- linemap_dump_location (line_table, token->src_loc, print.outf);
-
- if (do_line_adjustments
- && !in_pragma
- && !line_marker_emitted
- && print.prev_was_system_token != !!in_system_header_at (loc)
- && !is_location_from_builtin_token (loc))
- /* The system-ness of this token is different from the one
- of the previous token. Let's emit a line change to
- mark the new system-ness before we emit the token. */
- {
- do_line_change (pfile, token, loc, false);
- print.prev_was_system_token = !!in_system_header_at (loc);
- }
- cpp_output_token (token, print.outf);
- line_marker_emitted = false;
- print.printed = true;
- }
+class do_streamer : public token_streamer
+{
+ public:
+ uintptr_t filter;
- /* CPP_COMMENT tokens and raw-string literal tokens can
- have embedded new-line characters. Rather than enumerating
- all the possible token types just check if token uses
- val.str union member. */
- if (cpp_token_val_index (token) == CPP_TOKEN_FLD_STR)
- account_for_newlines (token->val.str.text, token->val.str.len);
+ do_streamer (cpp_reader *pfile, uintptr_t filter)
+ :token_streamer (pfile), filter (filter)
+ {
}
-}
+};
static void
directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
@@ -427,7 +351,7 @@ directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
va_list args;
va_start (args, data_);
- token_streamer *streamer = reinterpret_cast <token_streamer *> (data_);
+ do_streamer *streamer = reinterpret_cast <do_streamer *> (data_);
switch (task)
{
default:
@@ -452,6 +376,13 @@ directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
const cpp_token *token = va_arg (args, const cpp_token *);
location_t spelling_loc = va_arg (args, location_t);
streamer->stream (pfile, token, spelling_loc);
+ if (streamer->filter)
+ {
+ unsigned flags = lang_hooks.preprocess_token
+ (pfile, token, streamer->filter);
+ if (flags & lang_hooks::PT_begin_pragma)
+ streamer->begin_pragma ();
+ }
}
break;
}
@@ -464,8 +395,13 @@ directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
static void
scan_translation_unit_directives_only (cpp_reader *pfile)
{
- token_streamer streamer (pfile);
+ uintptr_t filter = 0;
+ if (lang_hooks.preprocess_token)
+ filter = lang_hooks.preprocess_token (pfile, NULL, filter);
+ do_streamer streamer (pfile, filter);
cpp_directive_only_process (pfile, &streamer, directives_only_cb);
+ if (streamer.filter)
+ lang_hooks.preprocess_token (pfile, NULL, streamer.filter);
}
/* Adjust print.src_line for newlines embedded in output. */
@@ -564,15 +500,16 @@ print_line_1 (location_t src_loc, const char *special_flags, FILE *stream)
unsigned char *to_file_quoted =
(unsigned char *) alloca (to_file_len * 4 + 1);
- print.src_line = LOCATION_LINE (src_loc);
- print.src_file = file_path;
-
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
unsigned char *p = cpp_quote_string (to_file_quoted,
(const unsigned char *) file_path,
to_file_len);
*p = '\0';
+
+ print.src_line = LOCATION_LINE (src_loc);
+ print.src_file = file_path;
+
fprintf (stream, "# %u \"%s\"%s",
print.src_line, to_file_quoted, special_flags);
@@ -678,9 +615,10 @@ cb_define (cpp_reader *pfile, location_t line, cpp_hashnode *node)
}
static void
-cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
- cpp_hashnode *node)
+cb_undef (cpp_reader *pfile, location_t line, cpp_hashnode *node)
{
+ if (lang_hooks.preprocess_undef)
+ lang_hooks.preprocess_undef (pfile, line, node);
maybe_print_line (line);
fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
print.src_line++;
diff --git c/gcc/langhooks-def.h w/gcc/langhooks-def.h
index a909915d018..1285d548050 100644
--- c/gcc/langhooks-def.h
+++ w/gcc/langhooks-def.h
@@ -103,6 +103,11 @@ extern void lhd_finalize_early_debug (void);
#define LANG_HOOKS_INIT_OPTIONS_STRUCT hook_void_gcc_optionsp
#define LANG_HOOKS_INIT_OPTIONS lhd_init_options
#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS lhd_initialize_diagnostics
+#define LANG_HOOKS_PREPROCESS_MAIN_FILE NULL
+#define LANG_HOOKS_PREPROCESS_OPTIONS NULL
+#define LANG_HOOKS_PREPROCESS_UNDEF NULL
+#define LANG_HOOKS_PREPROCESS_DEFERRED_MACRO NULL
+#define LANG_HOOKS_PREPROCESS_TOKEN NULL
#define LANG_HOOKS_REGISTER_DUMPS lhd_register_dumps
#define LANG_HOOKS_COMPLAIN_WRONG_LANG_P lhd_complain_wrong_lang_p
#define LANG_HOOKS_HANDLE_OPTION lhd_handle_option
@@ -317,6 +322,11 @@ extern void lhd_end_section (void);
LANG_HOOKS_INIT_OPTIONS_STRUCT, \
LANG_HOOKS_INIT_OPTIONS, \
LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \
+ LANG_HOOKS_PREPROCESS_MAIN_FILE, \
+ LANG_HOOKS_PREPROCESS_OPTIONS, \
+ LANG_HOOKS_PREPROCESS_UNDEF, \
+ LANG_HOOKS_PREPROCESS_DEFERRED_MACRO, \
+ LANG_HOOKS_PREPROCESS_TOKEN, \
LANG_HOOKS_REGISTER_DUMPS, \
LANG_HOOKS_COMPLAIN_WRONG_LANG_P, \
LANG_HOOKS_HANDLE_OPTION, \
diff --git c/gcc/langhooks.h w/gcc/langhooks.h
index a35cf21b673..c70c2317c32 100644
--- c/gcc/langhooks.h
+++ w/gcc/langhooks.h
@@ -356,6 +356,29 @@ struct lang_hooks
global diagnostic context structure. */
void (*initialize_diagnostics) (diagnostic_context *);
+ /* Beginning the main source file. */
+ void (*preprocess_main_file) (cpp_reader *, line_maps *,
+ const line_map_ordinary *);
+
+ /* Adjust libcpp options and callbacks. */
+ void (*preprocess_options) (cpp_reader *);
+
+ /* Undefining a macro. */
+ void (*preprocess_undef) (cpp_reader *, location_t, cpp_hashnode *);
+
+ /* Define a deferred macro. */
+ struct cpp_macro *(*preprocess_deferred_macro) (cpp_reader *, location_t,
+ cpp_hashnode *);
+
+ /* Observer for preprocessing stream. */
+ uintptr_t (*preprocess_token) (cpp_reader *, const cpp_token *, uintptr_t);
+ /* Various flags it can return about the token. */
+ enum PT_flags
+ {
+ PT_begin_pragma = 1 << 0
+ };
+
+
/* Register language-specific dumps. */
void (*register_dumps) (gcc::dump_manager *);