directives.c (struct pragma_entry): Add is_deferred.

libcpp/
	* directives.c (struct pragma_entry): Add is_deferred.  Add ident
	entry to value union.
	(end_directive): Don't eat the line if in_deferred_pragma.
	(run_directive): Remove pragma hacks.
	(insert_pragma_entry): Remove.
	(new_pragma_entry): New.
	(register_pragma_1): Split out of register_pragma.  Only handle
	the lookup tree and return the new entry.
	(cpp_register_pragma): Fill in the pragma entry here.
	(cpp_register_deferred_pragma): New.
	(register_pragma_internal): New.
	(_cpp_init_internal_pragmas): Use register_pragma_internal.
	(do_pragma): Allow pragma expansion after namespace.  For deferred
	pragmas, don't slurp the line into a string.
	(destringize_and_run): Save tokens for deferred pragmas.
	(cpp_handle_deferred_pragma): Remove.
	* macro.c (builtin_macro): Remove pragma token hack.
	(_cpp_push_token_context): Rename from push_token_context and export.
	* internal.h (struct lexer_state): Add pragma_allow_expansion.
	(_cpp_push_token_context): Declare.
	* lex.c (_cpp_lex_token): Allow _cpp_handle_directive to return
	a token.  Update the line number correctly if so.
	(_cpp_lex_direct): Emit CPP_PRAGMA_EOL tokens.
	(cpp_token_val_index): Return CPP_TOKEN_FLD_PRAGMA for pragmas.
	* include/cpplib.h (PRAGMA_EOL): New.
	(CPP_TOKEN_FLD_PRAGMA): New.
	(struct cpp_token): Add val.pragma.
	(struct cpp_options): Remove defer_pragmas.
	(cpp_handle_deferred_pragma): Remove.
	(cpp_register_deferred_pragma): Declare.

gcc/
	* c-lex.c (c_lex_with_flags) <CPP_PRAGMA>: Smuggle pragma id
	via integer constant.
	(pragma_lex): Remove.
	* c-pch.c (c_common_pch_pragma): Accept the name as an argument,
	rather than parsing it.
	* c-pragma.c (handle_pragma_weak, handle_pragma_redefine_extname,
	handle_pragma_extern_prefix): Add %< %> quotes.
	(registered_pragmas): New.
	(c_register_pragma_1): New.
	(c_register_pragma): Use it.
	(c_register_pragma_with_expansion): Likewise.
	(c_invoke_pragma_handler): New.
	(init_pragma): Use cpp_register_deferred_pragma directly for
	pch_preprocess.
	* c-pragma.h (enum pragma_kind): New.
	(pragma_handler): New.
	(c_invoke_pragma_handler): Declare.
	* c-common.c (c_parse_error): Pretty print CPP_PRAGMA and
	CPP_PRAGMA_EOL.
	* c-common.h (c_common_pch_pragma): Update decl.
	* Makefile.in (c-parser.o): Update dependencies.
	(GTFILES): Add c-pragma.h.
	* c-parser.c (struct c_token): Add pragma_kind.
	(struct c_parser): Add in_pragma.
	(c_lex_one_token): Always initialize keyword and pragma_kind.
	Extract data for CPP_PRAGMA.
	(c_parser_peek_2nd_token): Deny CPP_PRAGMA_EOL.
	(c_parser_consume_token): Don't allow CPP_PRAGMA unless errors.
	Don't allow CPP_PRAGMA_EOL if in_pragma.
	(c_parser_consume_pragma): New.
	(c_parser_skip_until_found): Stop on CPP_PRAGMA_EOL.
	(c_parser_skip_to_end_of_parameter): Likewise.
	(c_parser_skip_to_end_of_block_or_statement): Likewise.
	(c_parser_skip_to_pragma_eol): New.
	(c_parser_external_declaration): Handle CPP_PRAGMA.
	(c_parser_compound_statement_nostart): Likewise.
	(c_parser_statement_after_labels): Likewise.
	(c_parser_pragma): New.
	(pragma_lex): Likewise.
	(c_parser_pragma_pch_preprocess): New.
	(c_parser_new): Merge into ...
	(c_parse_file): ... here.  Call c_parser_pragma_pch_preprocess.

gcc/cp/
	* lex.c (handle_pragma_java_exceptions): Fix whitespace.
	* parser.c (struct cp_token): Add pragma_kind.
	(eof_token): Update to match.
	(struct cp_lexer): Add in_pragma; rearrange next for better packing.
	(cp_parser_initial_pragma): New.
	(cp_lexer_new_main): Use it.  Don't bother clearing
	c_lex_return_raw_strings.
	(cp_lexer_get_preprocessor_token): Always initialize keyword
	and pragma_kind fields.  Handle CPP_PRAGMA.
	(cp_lexer_consume_token): Don't allow CPP_PRAGMA_EOL when 
	in_pragma is set.
	(cp_lexer_handle_pragma): Remove.  Update callers to cp_parser_pragma.
	(cp_lexer_print_token) <CPP_PRAGMA>: Don't print as a string.
	(cp_parser_skip_to_pragma_eol): New.
	(cp_parser_error): Use it.
	(cp_parser_skip_to_closing_parenthesis): Stop at CPP_PRAGMA_EOL;
	rearrange with switch statement.
	(cp_parser_skip_to_end_of_statement): Likewise.
	(cp_parser_skip_to_end_of_block_or_statement): Likewise.
	(cp_parser_skip_to_closing_brace): Likewise.
	(cp_parser_skip_until_found): Likewise.
	(cp_parser_statement): Add in_compound argument; update callers.
	Use it to decide how to handle pragma parsing.
	(cp_parser_labeled_statement): Add in_compound argument; pass
	it on to cp_parser_statement.
	(cp_parser_statement_seq_opt): Stop at CPP_PRAGMA_EOL.
	(cp_parser_declaration_seq_opt): Likewise.
	(cp_parser_parameter_declaration): Likewise.
	(cp_parser_member_specification_opt): Likewise.
	(cp_parser_function_definition_after_decl): Likewise.
	(cp_parser_cache_group): Handle CPP_PRAGMA/CPP_PRAGMA_EOL pairs.
	(cp_parser_pragma): New.
	(pragma_lex): New.

gcc/testsuite/
	* g++.dg/parse/pragma2.C: Update expected error lines.

From-SVN: r109336
This commit is contained in:
Richard Henderson
2006-01-04 08:33:38 -08:00
parent 59bb84ef39
commit bc4071dd66
20 changed files with 992 additions and 498 deletions
+36 -1
View File
@@ -1,3 +1,38 @@
2006-01-04 Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
Richard Henderson <rth@redhat.com>
Merge from gomp branch:
* directives.c (struct pragma_entry): Add is_deferred. Add ident
entry to value union.
(end_directive): Don't eat the line if in_deferred_pragma.
(run_directive): Remove pragma hacks.
(insert_pragma_entry): Remove.
(new_pragma_entry): New.
(register_pragma_1): Split out of register_pragma. Only handle
the lookup tree and return the new entry.
(cpp_register_pragma): Fill in the pragma entry here.
(cpp_register_deferred_pragma): New.
(register_pragma_internal): New.
(_cpp_init_internal_pragmas): Use register_pragma_internal.
(do_pragma): Allow pragma expansion after namespace. For deferred
pragmas, don't slurp the line into a string.
(destringize_and_run): Save tokens for deferred pragmas.
(cpp_handle_deferred_pragma): Remove.
* macro.c (builtin_macro): Remove pragma token hack.
(_cpp_push_token_context): Rename from push_token_context and export.
* internal.h (struct lexer_state): Add pragma_allow_expansion.
(_cpp_push_token_context): Declare.
* lex.c (_cpp_lex_token): Allow _cpp_handle_directive to return
a token. Update the line number correctly if so.
(_cpp_lex_direct): Emit CPP_PRAGMA_EOL tokens.
(cpp_token_val_index): Return CPP_TOKEN_FLD_PRAGMA for pragmas.
* include/cpplib.h (PRAGMA_EOL): New.
(CPP_TOKEN_FLD_PRAGMA): New.
(struct cpp_token): Add val.pragma.
(struct cpp_options): Remove defer_pragmas.
(cpp_handle_deferred_pragma): Remove.
(cpp_register_deferred_pragma): Declare.
2006-01-01 Jakub Jelinek <jakub@redhat.com>
PR c++/25294
@@ -19,7 +54,7 @@
(cpp_classify_number): Disallow hexadecimal DFP constants.
2005-11-14 Gerald Pfeifer <gerald@pfeifer.com>
Ian Lance Taylor <ian@airs.com>
Ian Lance Taylor <ian@airs.com>
* include/cpplib.h (struct cpp_callbacks): Annotate error with
ATTRIBUTE_FPTR_PRINTF(3,0) instead of ATTRIBUTE_PRINTF(3,0).
+203 -211
View File
@@ -1,7 +1,6 @@
/* CPP Library. (Directive handling.)
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
1999, 2000, 2001, 2002, 2003, 2004, 2005 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
@@ -46,11 +45,13 @@ struct pragma_entry
struct pragma_entry *next;
const cpp_hashnode *pragma; /* Name and length. */
bool is_nspace;
bool allow_expansion;
bool is_internal;
bool is_deferred;
bool allow_expansion;
union {
pragma_cb handler;
struct pragma_entry *space;
unsigned int ident;
} u;
};
@@ -106,13 +107,6 @@ 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, bool);
static void register_pragma (cpp_reader *, const char *, const char *,
pragma_cb, bool, 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 *,
@@ -278,7 +272,9 @@ start_directive (cpp_reader *pfile)
static void
end_directive (cpp_reader *pfile, int skip_line)
{
if (CPP_OPTION (pfile, traditional))
if (pfile->state.in_deferred_pragma)
;
else if (CPP_OPTION (pfile, traditional))
{
/* Revert change of prepare_directive_trad. */
pfile->state.prevent_expansion--;
@@ -491,9 +487,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);
/* 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
@@ -505,8 +498,6 @@ 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);
if (dir_no == T_PRAGMA)
pfile->buffer->file = NULL;
_cpp_pop_buffer (pfile);
}
@@ -1040,86 +1031,97 @@ lookup_pragma_entry (struct pragma_entry *chain, const cpp_hashnode *pragma)
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 *
insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain,
const cpp_hashnode *pragma, pragma_cb handler,
bool allow_expansion, bool internal)
new_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain)
{
struct pragma_entry *new_entry;
new_entry = (struct pragma_entry *)
_cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
new_entry->pragma = pragma;
if (handler)
{
new_entry->is_nspace = 0;
new_entry->u.handler = handler;
}
else
{
new_entry->is_nspace = 1;
new_entry->u.space = NULL;
}
new_entry->allow_expansion = allow_expansion;
new_entry->is_internal = internal;
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
goes in the global namespace. HANDLER is the handler it will call,
which must be non-NULL. If ALLOW_EXPANSION is set, allow macro
expansion while parsing pragma NAME. 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 allow_expansion, 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;
if (!handler)
abort ();
if (space)
{
node = cpp_lookup (pfile, U space, strlen (space));
entry = lookup_pragma_entry (*chain, node);
if (!entry)
entry = insert_pragma_entry (pfile, chain, node, NULL,
allow_expansion, 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->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;
}
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. */
node = cpp_lookup (pfile, U name, strlen (name));
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
insert_pragma_entry (pfile, chain, node, handler, allow_expansion,
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
@@ -1131,22 +1133,53 @@ void
cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
pragma_cb handler, bool allow_expansion)
{
register_pragma (pfile, space, name, handler, allow_expansion, 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_pragma (pfile, 0, "once", do_pragma_once, false, true);
register_pragma_internal (pfile, 0, "once", do_pragma_once);
/* New GCC-specific pragmas should be put in the GCC namespace. */
register_pragma (pfile, "GCC", "poison", do_pragma_poison, false, true);
register_pragma (pfile, "GCC", "system_header", do_pragma_system_header,
false, true);
register_pragma (pfile, "GCC", "dependency", do_pragma_dependency,
false, 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);
}
/* Return the number of registered pragmas in PE. */
@@ -1224,11 +1257,9 @@ _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.
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)
{
@@ -1236,11 +1267,6 @@ do_pragma (cpp_reader *pfile)
const cpp_token *token, *pragma_token = pfile->cur_token;
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++;
token = cpp_get_token (pfile);
@@ -1249,100 +1275,45 @@ do_pragma (cpp_reader *pfile)
p = lookup_pragma_entry (pfile->pragmas, token->val.node);
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)
p = lookup_pragma_entry (p->u.space, token->val.node);
else
p = NULL;
if (allow_name_expansion)
pfile->state.prevent_expansion++;
count = 2;
}
}
if (p)
{
if (p->is_internal || !CPP_OPTION (pfile, defer_pragmas))
if (p->is_deferred)
{
/* 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);
/* Never expand macros if handling a deferred pragma, since
the macro definitions now applicable may be different
from those at the point the pragma appeared. */
if (p->allow_expansion && !pfile->state.in_deferred_pragma)
pfile->state.prevent_expansion--;
(*p->u.handler) (pfile);
if (p->allow_expansion && !pfile->state.in_deferred_pragma)
pfile->directive_result.src_loc = pragma_token->src_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
{
/* Squirrel away the pragma text. Pragmas are
newline-terminated. */
const uchar *line_end;
uchar *s, c, cc;
cpp_string body;
cpp_token *ptok;
for (line_end = line_start; (c = *line_end) != '\n'; line_end++)
if (c == '"' || c == '\'')
{
/* Skip over string literal. */
do
{
cc = *++line_end;
if (cc == '\\' && line_end[1] != '\n')
line_end++;
else if (cc == '\n')
{
line_end--;
break;
}
}
while (cc != c);
}
else if (c == '/')
{
if (line_end[1] == '*')
{
/* Skip over C block comment, unless it is multi-line.
When encountering multi-line block comment, terminate
the pragma token right before that block comment. */
const uchar *le = line_end + 2;
while (*le != '\n')
if (*le++ == '*' && *le == '/')
{
line_end = le;
break;
}
if (line_end < le)
break;
}
else if (line_end[1] == '/'
&& (CPP_OPTION (pfile, cplusplus_comments)
|| cpp_in_system_header (pfile)))
{
line_end += 2;
while (*line_end != '\n')
line_end++;
break;
}
}
body.len = (line_end - line_start) + 1;
s = _cpp_unaligned_alloc (pfile, body.len + 1);
memcpy (s, line_start, body.len - 1);
s[body.len - 1] = '\n';
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;
/* 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)
@@ -1490,6 +1461,11 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in)
{
const unsigned char *src, *limit;
char *dest, *result;
cpp_context *saved_context;
cpp_token *saved_cur_token;
tokenrun *saved_cur_run;
cpp_token *toks;
int count;
dest = result = (char *) alloca (in->len - 1);
src = in->text + 1 + (in->text[0] == 'L');
@@ -1511,36 +1487,81 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in)
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;
saved_context = pfile->context;
saved_cur_token = pfile->cur_token;
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;
}
pfile->context = XNEW (cpp_context);
pfile->context->macro = 0;
pfile->context->prev = 0;
/* See above comment. For the moment, we'd like
/* 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;
token1 _Pragma ("foo") token2
start_directive (pfile);
_cpp_clean_line (pfile);
do_pragma (pfile);
end_directive (pfile, 1);
to be output as
/* 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. */
token1
# 7 "file.c"
#pragma foo
# 7 "file.c"
token2
/* 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;
Getting the line markers is a little tricky. */
if (pfile->cb.line_change)
pfile->cb.line_change (pfile, pfile->cur_token, false);
count = 1;
maxcount = 50;
toks = XNEWVEC (cpp_token, maxcount);
toks[0] = pfile->directive_result;
do
{
if (count == maxcount)
{
maxcount = maxcount * 3 / 2;
toks = XRESIZEVEC (cpp_token, toks, maxcount);
}
toks[count++] = *cpp_get_token (pfile);
}
while (toks[count-1].type != CPP_PRAGMA_EOL);
}
else
{
count = 1;
toks = XNEW (cpp_token);
toks[0] = pfile->directive_result;
/* 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);
}
/* 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;
/* ... inserting the new tokens we collected. */
_cpp_push_token_context (pfile, NULL, toks, count);
}
/* Handle the _Pragma operator. */
@@ -1557,35 +1578,6 @@ _cpp_do__Pragma (cpp_reader *pfile)
"_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;
pfile->context = XNEW (cpp_context);
pfile->context->macro = 0;
pfile->context->prev = 0;
pfile->cb.line_change = NULL;
pfile->state.in_deferred_pragma = true;
CPP_OPTION (pfile, defer_pragmas) = false;
run_directive (pfile, T_PRAGMA, (const char *)s->text, s->len);
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;
pfile->state.in_deferred_pragma = false;
CPP_OPTION (pfile, defer_pragmas) = saved_defer_pragmas;
}
/* Handle #ifdef. */
static void
do_ifdef (cpp_reader *pfile)
+8 -6
View File
@@ -134,7 +134,8 @@ struct _cpp_file;
TK(COMMENT, LITERAL) /* Only if output comments. */ \
/* SPELL_LITERAL happens to DTRT. */ \
TK(MACRO_ARG, NONE) /* Macro argument. */ \
TK(PRAGMA, NONE) /* Only if deferring pragmas */ \
TK(PRAGMA, NONE) /* Only for deferred pragmas. */ \
TK(PRAGMA_EOL, NONE) /* End-of-line for deferred pragmas. */ \
TK(PADDING, NONE) /* Whitespace for -E. */
#define OP(e, s) CPP_ ## e,
@@ -182,6 +183,7 @@ enum cpp_token_fld_kind {
CPP_TOKEN_FLD_SOURCE,
CPP_TOKEN_FLD_STR,
CPP_TOKEN_FLD_ARG_NO,
CPP_TOKEN_FLD_PRAGMA,
CPP_TOKEN_FLD_NONE
};
@@ -211,6 +213,9 @@ struct cpp_token GTY(())
/* Argument no. for a CPP_MACRO_ARG. */
unsigned int GTY ((tag ("CPP_TOKEN_FLD_ARG_NO"))) arg_no;
/* Caller-supplied identifier for a CPP_PRAGMA. */
unsigned int GTY ((tag ("CPP_TOKEN_FLD_PRAGMA"))) pragma;
} GTY ((desc ("cpp_token_val_index (&%1)"))) val;
};
@@ -434,10 +439,6 @@ struct cpp_options
/* Nonzero means __STDC__ should have the value 0 in system headers. */
unsigned char stdc_0_in_system_headers;
/* True means return pragmas as tokens rather than processing
them directly. */
bool defer_pragmas;
/* True means error callback should be used for diagnostics. */
bool client_diagnostic;
};
@@ -673,7 +674,8 @@ extern unsigned char *cpp_spell_token (cpp_reader *, const cpp_token *,
unsigned char *, bool);
extern void cpp_register_pragma (cpp_reader *, const char *, const char *,
void (*) (cpp_reader *), bool);
extern void cpp_handle_deferred_pragma (cpp_reader *, const cpp_string *);
extern void cpp_register_deferred_pragma (cpp_reader *, const char *,
const char *, unsigned, bool, bool);
extern int cpp_avoid_paste (cpp_reader *, const cpp_token *,
const cpp_token *);
extern const cpp_token *cpp_get_token (cpp_reader *);
+10 -4
View File
@@ -205,9 +205,6 @@ struct lexer_state
/* Nonzero to prevent macro expansion. */
unsigned char prevent_expansion;
/* Nonzero when handling a deferred pragma. */
unsigned char in_deferred_pragma;
/* Nonzero when parsing arguments to a function-like macro. */
unsigned char parsing_args;
@@ -217,6 +214,12 @@ struct lexer_state
/* Nonzero to skip evaluating part of an expression. */
unsigned int skip_eval;
/* Nonzero when handling a deferred pragma. */
unsigned char in_deferred_pragma;
/* Nonzero if the deferred pragma being handled allows macro expansion. */
unsigned char pragma_allow_expansion;
};
/* Special nodes - identifiers with predefined significance. */
@@ -496,7 +499,10 @@ extern bool _cpp_arguments_ok (cpp_reader *, cpp_macro *, const cpp_hashnode *,
unsigned int);
extern const unsigned char *_cpp_builtin_macro_text (cpp_reader *,
cpp_hashnode *);
int _cpp_warn_if_unused_macro (cpp_reader *, cpp_hashnode *, void *);
extern int _cpp_warn_if_unused_macro (cpp_reader *, cpp_hashnode *, void *);
extern void _cpp_push_token_context (cpp_reader *, cpp_hashnode *,
const cpp_token *, unsigned int);
/* In identifiers.c */
extern void _cpp_init_hashtable (cpp_reader *, hash_table *);
extern void _cpp_destroy_hashtable (cpp_reader *);
+16 -8
View File
@@ -767,24 +767,24 @@ _cpp_lex_token (cpp_reader *pfile)
/* 6.10.3 p 11: Directives in a list of macro arguments
gives undefined behavior. This implementation
handles the directive as normal. */
&& pfile->state.parsing_args != 1
&& _cpp_handle_directive (pfile, result->flags & PREV_WHITE))
&& pfile->state.parsing_args != 1)
{
if (pfile->directive_result.type == CPP_PADDING)
continue;
else
if (_cpp_handle_directive (pfile, result->flags & PREV_WHITE))
{
if (pfile->directive_result.type == CPP_PADDING)
continue;
result = &pfile->directive_result;
break;
}
}
else if (pfile->state.in_deferred_pragma)
result = &pfile->directive_result;
if (pfile->cb.line_change && !pfile->state.skipping)
pfile->cb.line_change (pfile, result, pfile->state.parsing_args);
}
/* We don't skip tokens in directives. */
if (pfile->state.in_directive)
if (pfile->state.in_directive || pfile->state.in_deferred_pragma)
break;
/* Outside a directive, invalidate controlling macros. At file
@@ -878,6 +878,14 @@ _cpp_lex_direct (cpp_reader *pfile)
buffer = pfile->buffer;
if (buffer->need_line)
{
if (pfile->state.in_deferred_pragma)
{
result->type = CPP_PRAGMA_EOL;
pfile->state.in_deferred_pragma = false;
if (!pfile->state.pragma_allow_expansion)
pfile->state.prevent_expansion--;
return result;
}
if (!_cpp_get_fresh_line (pfile))
{
result->type = CPP_EOF;
@@ -1697,7 +1705,7 @@ cpp_token_val_index (cpp_token *tok)
else if (tok->type == CPP_PADDING)
return CPP_TOKEN_FLD_SOURCE;
else if (tok->type == CPP_PRAGMA)
return CPP_TOKEN_FLD_STR;
return CPP_TOKEN_FLD_PRAGMA;
/* else fall through */
default:
return CPP_TOKEN_FLD_NONE;
+7 -16
View File
@@ -42,8 +42,6 @@ struct macro_arg
static int enter_macro_context (cpp_reader *, cpp_hashnode *);
static int builtin_macro (cpp_reader *, cpp_hashnode *);
static void push_token_context (cpp_reader *, cpp_hashnode *,
const cpp_token *, unsigned int);
static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
const cpp_token **, unsigned int);
static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *);
@@ -261,13 +259,6 @@ builtin_macro (cpp_reader *pfile, cpp_hashnode *node)
return 0;
_cpp_do__Pragma (pfile);
if (pfile->directive_result.type == CPP_PRAGMA)
{
cpp_token *tok = _cpp_temp_token (pfile);
*tok = pfile->directive_result;
push_token_context (pfile, NULL, tok, 1);
}
return 1;
}
@@ -282,7 +273,7 @@ builtin_macro (cpp_reader *pfile, cpp_hashnode *node)
/* Set pfile->cur_token as required by _cpp_lex_direct. */
pfile->cur_token = _cpp_temp_token (pfile);
push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
_cpp_push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
if (pfile->buffer->cur != pfile->buffer->rlimit)
cpp_error (pfile, CPP_DL_ICE, "invalid built-in macro \"%s\"",
NODE_NAME (node));
@@ -480,7 +471,7 @@ paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
while (rhs->flags & PASTE_LEFT);
/* Put the resulting token in its own context. */
push_token_context (pfile, NULL, lhs, 1);
_cpp_push_token_context (pfile, NULL, lhs, 1);
}
/* Returns TRUE if the number of arguments ARGC supplied in an
@@ -694,7 +685,7 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
too difficult. We re-insert it in its own context. */
_cpp_backup_tokens (pfile, 1);
if (padding)
push_token_context (pfile, NULL, padding, 1);
_cpp_push_token_context (pfile, NULL, padding, 1);
}
return NULL;
@@ -750,7 +741,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
macro->used = 1;
if (macro->paramc == 0)
push_token_context (pfile, node, macro->exp.tokens, macro->count);
_cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count);
return 1;
}
@@ -943,9 +934,9 @@ push_ptoken_context (cpp_reader *pfile, cpp_hashnode *macro, _cpp_buff *buff,
}
/* Push a list of tokens. */
static void
push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
const cpp_token *first, unsigned int count)
void
_cpp_push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
const cpp_token *first, unsigned int count)
{
cpp_context *context = next_context (pfile);