Commit bc4071dd by Richard Henderson

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
parent 59bb84ef
2006-01-04 Richard Henderson <rth@redhat.com>
Merge from gomp branch:
* 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.
2005-01-04 Jeff Law <law@redhat.com>
PR ada/24994
......
......@@ -1516,7 +1516,8 @@ c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TM_P_H)
c-parser.o : c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(GGC_H) $(TIMEVAR_H) $(C_TREE_H) input.h $(FLAGS_H) toplev.h output.h \
$(CPPLIB_H) gt-c-parser.h langhooks.h $(C_COMMON_H) $(C_PRAGMA_H)
$(CPPLIB_H) gt-c-parser.h langhooks.h $(C_COMMON_H) $(C_PRAGMA_H) \
vec.h $(TARGET_H)
srcextra: gcc.srcextra lang.srcextra
......@@ -2811,6 +2812,7 @@ GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/tree-profile.c $(srcdir)/tree-nested.c \
$(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \
$(srcdir)/tree-ssa-structalias.c \
$(srcdir)/c-pragma.h \
$(srcdir)/targhooks.c $(out_file) \
@all_gtfiles@
......
......@@ -5803,6 +5803,10 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
free (message);
message = NULL;
}
else if (token == CPP_PRAGMA)
message = catenate_messages (gmsgid, " before %<#pragma%>");
else if (token == CPP_PRAGMA_EOL)
message = catenate_messages (gmsgid, " before end of line");
else if (token < N_TTYPES)
{
message = catenate_messages (gmsgid, " before %qs token");
......
......@@ -854,7 +854,7 @@ extern void c_common_read_pch (cpp_reader *pfile, const char *name, int fd,
const char *orig);
extern void c_common_write_pch (void);
extern void c_common_no_more_pch (void);
extern void c_common_pch_pragma (cpp_reader *pfile);
extern void c_common_pch_pragma (cpp_reader *pfile, const char *);
extern void c_common_print_pch_checksum (FILE *f);
/* In *-checksum.c */
......
......@@ -458,11 +458,11 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags)
type = lex_string (tok, value, false);
break;
}
*value = build_string (tok->val.str.len, (char *) tok->val.str.text);
break;
/* FALLTHROUGH */
case CPP_PRAGMA:
*value = build_string (tok->val.str.len, (char *) tok->val.str.text);
*value = build_int_cst (NULL, tok->val.pragma);
break;
/* These tokens should not be visible outside cpplib. */
......@@ -490,13 +490,6 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags)
return type;
}
enum cpp_ttype
pragma_lex (tree *value)
{
location_t loc;
return c_lex_with_flags (value, &loc, NULL);
}
/* Returns the narrowest C-visible unsigned type, starting with the
minimum specified by FLAGS, that can fit HIGH:LOW, or itk_none if
there isn't one. */
......
......@@ -441,18 +441,10 @@ c_common_no_more_pch (void)
#endif
void
c_common_pch_pragma (cpp_reader *pfile)
c_common_pch_pragma (cpp_reader *pfile, const char *name)
{
tree name_t;
const char *name;
int fd;
if (pragma_lex (&name_t) != CPP_STRING)
{
error ("malformed #pragma GCC pch_preprocess, ignored");
return;
}
if (!cpp_get_options (pfile)->preprocessed)
{
error ("pch_preprocess pragma should only be used with -fpreprocessed");
......@@ -460,8 +452,6 @@ c_common_pch_pragma (cpp_reader *pfile)
return;
}
name = TREE_STRING_POINTER (name_t);
fd = open (name, O_RDONLY | O_BINARY, 0666);
if (fd == -1)
fatal_error ("%s: couldn%'t open PCH file: %m", name);
......
......@@ -37,6 +37,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "vec.h"
#include "target.h"
#define GCC_BAD(gmsgid) \
do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
#define GCC_BAD2(gmsgid, arg) \
......@@ -343,7 +344,7 @@ handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
t = pragma_lex (&x);
}
if (t != CPP_EOF)
warning (OPT_Wpragmas, "junk at end of #pragma weak");
warning (OPT_Wpragmas, "junk at end of %<#pragma weak%>");
decl = identifier_global_value (name);
if (decl && DECL_P (decl))
......@@ -416,7 +417,7 @@ handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
GCC_BAD ("malformed #pragma redefine_extname, ignored");
t = pragma_lex (&x);
if (t != CPP_EOF)
warning (OPT_Wpragmas, "junk at end of #pragma redefine_extname");
warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
if (!flag_mudflap && !targetm.handle_pragma_redefine_extname)
{
......@@ -484,7 +485,7 @@ handle_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy))
GCC_BAD ("malformed #pragma extern_prefix, ignored");
t = pragma_lex (&x);
if (t != CPP_EOF)
warning (OPT_Wpragmas, "junk at end of #pragma extern_prefix");
warning (OPT_Wpragmas, "junk at end of %<#pragma extern_prefix%>");
if (targetm.handle_pragma_extern_prefix)
/* Note that the length includes the null terminator. */
......@@ -667,26 +668,65 @@ handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED)
#endif
/* A vector of registered pragma callbacks. */
DEF_VEC_O (pragma_handler);
DEF_VEC_ALLOC_O (pragma_handler, heap);
static VEC(pragma_handler, heap) *registered_pragmas;
/* Front-end wrappers for pragma registration to avoid dragging
cpplib.h in almost everywhere. */
static void
c_register_pragma_1 (const char *space, const char *name,
pragma_handler handler, bool allow_expansion)
{
unsigned id;
VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
id = VEC_length (pragma_handler, registered_pragmas);
id += PRAGMA_FIRST_EXTERNAL - 1;
/* The C++ front end allocates 6 bits in cp_token; the C front end
allocates 7 bits in c_token. At present this is sufficient. */
gcc_assert (id < 64);
cpp_register_deferred_pragma (parse_in, space, name, id,
allow_expansion, false);
}
void
c_register_pragma (const char *space, const char *name,
void (*handler) (struct cpp_reader *))
c_register_pragma (const char *space, const char *name, pragma_handler handler)
{
cpp_register_pragma (parse_in, space, name, handler, 0);
c_register_pragma_1 (space, name, handler, false);
}
void
c_register_pragma_with_expansion (const char *space, const char *name,
void (*handler) (struct cpp_reader *))
pragma_handler handler)
{
c_register_pragma_1 (space, name, handler, true);
}
void
c_invoke_pragma_handler (unsigned int id)
{
cpp_register_pragma (parse_in, space, name, handler, 1);
pragma_handler handler;
id -= PRAGMA_FIRST_EXTERNAL;
handler = *VEC_index (pragma_handler, registered_pragmas, id);
handler (parse_in);
}
/* Set up front-end pragmas. */
void
init_pragma (void)
{
cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
PRAGMA_GCC_PCH_PREPROCESS, false, false);
#ifdef HANDLE_PRAGMA_PACK
#ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
......@@ -704,8 +744,6 @@ init_pragma (void)
c_register_pragma (0, "redefine_extname", handle_pragma_redefine_extname);
c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix);
c_register_pragma ("GCC", "pch_preprocess", c_common_pch_pragma);
#ifdef REGISTER_TARGET_PRAGMAS
REGISTER_TARGET_PRAGMAS ();
#endif
......
......@@ -24,6 +24,16 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include <cpplib.h> /* For enum cpp_ttype. */
/* Pragma identifiers built in to the front end parsers. Identifiers
for anciliary handlers will follow these. */
typedef enum pragma_kind {
PRAGMA_NONE = 0,
PRAGMA_GCC_PCH_PREPROCESS,
PRAGMA_FIRST_EXTERNAL
} pragma_kind;
/* Cause the `yydebug' variable to be defined. */
#define YYDEBUG 1
extern int yydebug;
......@@ -53,18 +63,23 @@ extern struct cpp_reader* parse_in;
extern void init_pragma (void);
/* Front-end wrappers for pragma registration to avoid dragging
cpplib.h in almost everywhere. */
extern void c_register_pragma (const char *, const char *,
void (*) (struct cpp_reader *));
/* Front-end wrappers for pragma registration. */
typedef void (*pragma_handler)(struct cpp_reader *);
extern void c_register_pragma (const char *, const char *, pragma_handler);
extern void c_register_pragma_with_expansion (const char *, const char *,
void (*) (struct cpp_reader *));
pragma_handler);
extern void c_invoke_pragma_handler (unsigned int);
extern void maybe_apply_pragma_weak (tree);
extern void maybe_apply_pending_pragma_weaks (void);
extern tree maybe_apply_renaming_pragma (tree, tree);
extern void add_to_renaming_pragma_list (tree, tree);
extern enum cpp_ttype pragma_lex (tree *);
/* This is not actually available to pragma parsers. It's merely a
convenient location to declare this function for c-lex, after
having enum cpp_ttype declared. */
extern enum cpp_ttype c_lex_with_flags (tree *, location_t *, unsigned char *);
/* If 1, then lex strings into the execution character set.
......
2002-01-04 Dirk Mueller <dmueller@suse.com>
2006-01-04 Richard Henderson <rth@redhat.com>
Merge from gomp branch.
* 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.
2006-01-04 Dirk Mueller <dmueller@suse.com>
* decl.c (finish_constructor_body): create simple
compound stmt instead of a if(1) { } construct.
......
......@@ -580,7 +580,7 @@ handle_pragma_implementation (cpp_reader* dfile ATTRIBUTE_UNUSED )
/* Indicate that this file uses Java-personality exception handling. */
static void
handle_pragma_java_exceptions (cpp_reader* dfile ATTRIBUTE_UNUSED )
handle_pragma_java_exceptions (cpp_reader* dfile ATTRIBUTE_UNUSED)
{
tree x;
if (pragma_lex (&x) != CPP_EOF)
......
2006-01-04 Richard Henderson <rth@redhat.com>
Merge from gomp branch.
* g++.dg/parse/pragma2.C: Update expected error lines.
2006-01-04 Jakub Jelinek <jakub@redhat.com>
* g++.dg/other/i386-2.C: New test.
......@@ -2,7 +2,7 @@
// Ideally, the #pragma error would come one line further down, but it
// does not.
int f(int x, // { dg-error "not allowed here" }
#pragma interface
int f(int x,
#pragma interface // { dg-error "not allowed here" }
// The parser gets confused and issues an error on the next line.
int y); // { dg-bogus "" "" { xfail *-*-* } }
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).
......
......@@ -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 *);
......
......@@ -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 *);
......
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment