mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-05 08:00:26 +08:00
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:
parent
59bb84ef39
commit
bc4071dd66
@ -1,3 +1,49 @@
|
||||
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 */
|
||||
|
15
gcc/c-lex.c
15
gcc/c-lex.c
@ -458,12 +458,12 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags)
|
||||
type = lex_string (tok, value, false);
|
||||
break;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case CPP_PRAGMA:
|
||||
*value = build_string (tok->val.str.len, (char *) tok->val.str.text);
|
||||
break;
|
||||
|
||||
case CPP_PRAGMA:
|
||||
*value = build_int_cst (NULL, tok->val.pragma);
|
||||
break;
|
||||
|
||||
/* These tokens should not be visible outside cpplib. */
|
||||
case CPP_HEADER_NAME:
|
||||
@ -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. */
|
||||
|
244
gcc/c-parser.c
244
gcc/c-parser.c
@ -42,6 +42,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "rtl.h"
|
||||
#include "langhooks.h"
|
||||
#include "input.h"
|
||||
#include "cpplib.h"
|
||||
@ -53,6 +54,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
#include "toplev.h"
|
||||
#include "ggc.h"
|
||||
#include "c-common.h"
|
||||
#include "vec.h"
|
||||
#include "target.h"
|
||||
|
||||
|
||||
/* Miscellaneous data and functions needed for the parser. */
|
||||
@ -266,6 +269,9 @@ typedef struct c_token GTY (())
|
||||
/* If this token is a keyword, this value indicates which keyword.
|
||||
Otherwise, this value is RID_MAX. */
|
||||
ENUM_BITFIELD (rid) keyword : 8;
|
||||
/* If this token is a CPP_PRAGMA, this indicates the pragma that
|
||||
was seen. Otherwise it is PRAGMA_NONE. */
|
||||
ENUM_BITFIELD (pragma_kind) pragma_kind : 7;
|
||||
/* True if this token is from a system header. */
|
||||
BOOL_BITFIELD in_system_header : 1;
|
||||
/* The value associated with this token, if any. */
|
||||
@ -287,21 +293,34 @@ typedef struct c_parser GTY(())
|
||||
c_parser_error sets this flag. It should clear this flag when
|
||||
enough tokens have been consumed to recover from the error. */
|
||||
BOOL_BITFIELD error : 1;
|
||||
/* True if we're processing a pragma, and shouldn't automatically
|
||||
consume CPP_PRAGMA_EOL. */
|
||||
BOOL_BITFIELD in_pragma : 1;
|
||||
} c_parser;
|
||||
|
||||
|
||||
/* The actual parser and external interface. ??? Does this need to be
|
||||
garbage-collected? */
|
||||
|
||||
static GTY (()) c_parser *the_parser;
|
||||
|
||||
|
||||
/* Read in and lex a single token, storing it in *TOKEN. */
|
||||
|
||||
static void
|
||||
c_lex_one_token (c_token *token)
|
||||
{
|
||||
timevar_push (TV_LEX);
|
||||
|
||||
token->type = c_lex_with_flags (&token->value, &token->location, NULL);
|
||||
token->id_kind = C_ID_NONE;
|
||||
token->keyword = RID_MAX;
|
||||
token->pragma_kind = PRAGMA_NONE;
|
||||
token->in_system_header = in_system_header;
|
||||
|
||||
switch (token->type)
|
||||
{
|
||||
case CPP_NAME:
|
||||
token->id_kind = C_ID_NONE;
|
||||
token->keyword = RID_MAX;
|
||||
{
|
||||
tree decl;
|
||||
|
||||
@ -358,13 +377,12 @@ c_lex_one_token (c_token *token)
|
||||
break;
|
||||
}
|
||||
}
|
||||
token->id_kind = C_ID_ID;
|
||||
}
|
||||
token->id_kind = C_ID_ID;
|
||||
break;
|
||||
case CPP_AT_NAME:
|
||||
/* This only happens in Objective-C; it must be a keyword. */
|
||||
token->type = CPP_KEYWORD;
|
||||
token->id_kind = C_ID_NONE;
|
||||
token->keyword = C_RID_CODE (token->value);
|
||||
break;
|
||||
case CPP_COLON:
|
||||
@ -374,12 +392,13 @@ c_lex_one_token (c_token *token)
|
||||
/* These tokens may affect the interpretation of any identifiers
|
||||
following, if doing Objective-C. */
|
||||
OBJC_NEED_RAW_IDENTIFIER (0);
|
||||
token->id_kind = C_ID_NONE;
|
||||
token->keyword = RID_MAX;
|
||||
break;
|
||||
case CPP_PRAGMA:
|
||||
/* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
|
||||
token->pragma_kind = TREE_INT_CST_LOW (token->value);
|
||||
token->value = NULL;
|
||||
break;
|
||||
default:
|
||||
token->id_kind = C_ID_NONE;
|
||||
token->keyword = RID_MAX;
|
||||
break;
|
||||
}
|
||||
timevar_pop (TV_LEX);
|
||||
@ -582,6 +601,7 @@ c_parser_peek_2nd_token (c_parser *parser)
|
||||
return &parser->tokens[1];
|
||||
gcc_assert (parser->tokens_avail == 1);
|
||||
gcc_assert (parser->tokens[0].type != CPP_EOF);
|
||||
gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
|
||||
c_lex_one_token (&parser->tokens[1]);
|
||||
parser->tokens_avail = 2;
|
||||
return &parser->tokens[1];
|
||||
@ -592,16 +612,30 @@ c_parser_peek_2nd_token (c_parser *parser)
|
||||
static void
|
||||
c_parser_consume_token (c_parser *parser)
|
||||
{
|
||||
gcc_assert (parser->tokens_avail >= 1);
|
||||
gcc_assert (parser->tokens[0].type != CPP_EOF);
|
||||
gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
|
||||
gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
|
||||
if (parser->tokens_avail == 2)
|
||||
parser->tokens[0] = parser->tokens[1];
|
||||
else
|
||||
{
|
||||
gcc_assert (parser->tokens_avail == 1);
|
||||
gcc_assert (parser->tokens[0].type != CPP_EOF);
|
||||
}
|
||||
parser->tokens_avail--;
|
||||
}
|
||||
|
||||
/* Expect the current token to be a #pragma. Consume it and remember
|
||||
that we've begun parsing a pragma. */
|
||||
|
||||
static void
|
||||
c_parser_consume_pragma (c_parser *parser)
|
||||
{
|
||||
gcc_assert (!parser->in_pragma);
|
||||
gcc_assert (parser->tokens_avail >= 1);
|
||||
gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
|
||||
if (parser->tokens_avail == 2)
|
||||
parser->tokens[0] = parser->tokens[1];
|
||||
parser->tokens_avail--;
|
||||
parser->in_pragma = true;
|
||||
}
|
||||
|
||||
/* Update the globals input_location and in_system_header from
|
||||
TOKEN. */
|
||||
static inline void
|
||||
@ -614,23 +648,6 @@ c_parser_set_source_position_from_token (c_token *token)
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a new parser. */
|
||||
|
||||
static c_parser *
|
||||
c_parser_new (void)
|
||||
{
|
||||
/* Use local storage to lex the first token because loading a PCH
|
||||
file may cause garbage collection. */
|
||||
c_parser tparser;
|
||||
c_parser *ret;
|
||||
memset (&tparser, 0, sizeof tparser);
|
||||
c_lex_one_token (&tparser.tokens[0]);
|
||||
tparser.tokens_avail = 1;
|
||||
ret = GGC_NEW (c_parser);
|
||||
memcpy (ret, &tparser, sizeof tparser);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Issue a diagnostic of the form
|
||||
FILE:LINE: MESSAGE before TOKEN
|
||||
where TOKEN is the next token in the input stream of PARSER.
|
||||
@ -732,9 +749,12 @@ c_parser_skip_until_found (c_parser *parser,
|
||||
c_parser_consume_token (parser);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we've run out of tokens, stop. */
|
||||
if (token->type == CPP_EOF)
|
||||
return;
|
||||
if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
|
||||
return;
|
||||
if (token->type == CPP_OPEN_BRACE
|
||||
|| token->type == CPP_OPEN_PAREN
|
||||
|| token->type == CPP_OPEN_SQUARE)
|
||||
@ -769,6 +789,8 @@ c_parser_skip_to_end_of_parameter (c_parser *parser)
|
||||
/* If we've run out of tokens, stop. */
|
||||
if (token->type == CPP_EOF)
|
||||
return;
|
||||
if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
|
||||
return;
|
||||
if (token->type == CPP_OPEN_BRACE
|
||||
|| token->type == CPP_OPEN_PAREN
|
||||
|| token->type == CPP_OPEN_SQUARE)
|
||||
@ -803,6 +825,8 @@ c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
|
||||
/* If we've run out of tokens, stop. */
|
||||
if (token->type == CPP_EOF)
|
||||
return;
|
||||
if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
|
||||
return;
|
||||
/* If the next token is a ';', we have reached the end of the
|
||||
statement. */
|
||||
if (token->type == CPP_SEMICOLON && !nesting_depth)
|
||||
@ -828,6 +852,31 @@ c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
|
||||
parser->error = false;
|
||||
}
|
||||
|
||||
/* Expect to be at the end of the pragma directive and consume an
|
||||
end of line marker. */
|
||||
|
||||
static void
|
||||
c_parser_skip_to_pragma_eol (c_parser *parser)
|
||||
{
|
||||
gcc_assert (parser->in_pragma);
|
||||
parser->in_pragma = false;
|
||||
|
||||
if (!c_parser_require (parser, CPP_PRAGMA_EOL, "expected end of line"))
|
||||
while (true)
|
||||
{
|
||||
c_token *token = c_parser_peek_token (parser);
|
||||
if (token->type == CPP_EOF)
|
||||
break;
|
||||
if (token->type == CPP_PRAGMA_EOL)
|
||||
{
|
||||
c_parser_consume_token (parser);
|
||||
break;
|
||||
}
|
||||
c_parser_consume_token (parser);
|
||||
}
|
||||
|
||||
parser->error = false;
|
||||
}
|
||||
|
||||
/* Save the warning flags which are controlled by __extension__. */
|
||||
|
||||
@ -932,6 +981,9 @@ static struct c_expr c_parser_expression (c_parser *);
|
||||
static struct c_expr c_parser_expression_conv (c_parser *);
|
||||
static tree c_parser_expr_list (c_parser *, bool);
|
||||
|
||||
enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
|
||||
static bool c_parser_pragma (c_parser *, enum pragma_context);
|
||||
|
||||
/* These Objective-C parser functions are only ever called when
|
||||
compiling Objective-C. */
|
||||
static void c_parser_objc_class_definition (c_parser *);
|
||||
@ -1063,6 +1115,9 @@ c_parser_external_declaration (c_parser *parser)
|
||||
pedwarn ("ISO C does not allow extra %<;%> outside of a function");
|
||||
c_parser_consume_token (parser);
|
||||
break;
|
||||
case CPP_PRAGMA:
|
||||
c_parser_pragma (parser, pragma_external);
|
||||
break;
|
||||
case CPP_PLUS:
|
||||
case CPP_MINUS:
|
||||
if (c_dialect_objc ())
|
||||
@ -1082,6 +1137,7 @@ c_parser_external_declaration (c_parser *parser)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
|
||||
6.7, 6.9.1). If FNDEF_OK is true, a function definition is
|
||||
accepted; otherwise (old-style parameter declarations) only other
|
||||
@ -1142,6 +1198,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
|
||||
tree prefix_attrs;
|
||||
tree all_prefix_attrs;
|
||||
bool diagnosed_no_specs = false;
|
||||
|
||||
specs = build_null_declspecs ();
|
||||
c_parser_declspecs (parser, specs, true, true, start_attr_ok);
|
||||
if (parser->error)
|
||||
@ -1808,6 +1865,12 @@ c_parser_struct_or_union_specifier (c_parser *parser)
|
||||
c_parser_consume_token (parser);
|
||||
break;
|
||||
}
|
||||
/* Accept #pragmas at struct scope. */
|
||||
if (c_parser_next_token_is (parser, CPP_PRAGMA))
|
||||
{
|
||||
c_parser_pragma (parser, pragma_external);
|
||||
continue;
|
||||
}
|
||||
/* Parse some comma-separated declarations, but not the
|
||||
trailing semicolon if any. */
|
||||
decls = c_parser_struct_declaration (parser);
|
||||
@ -3268,11 +3331,6 @@ c_parser_compound_statement_nostart (c_parser *parser)
|
||||
while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
|
||||
{
|
||||
location_t loc = c_parser_peek_token (parser)->location;
|
||||
if (c_parser_next_token_is (parser, CPP_EOF))
|
||||
{
|
||||
c_parser_error (parser, "expected declaration or statement");
|
||||
return;
|
||||
}
|
||||
if (c_parser_next_token_is_keyword (parser, RID_CASE)
|
||||
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT)
|
||||
|| (c_parser_next_token_is (parser, CPP_NAME)
|
||||
@ -3325,6 +3383,21 @@ c_parser_compound_statement_nostart (c_parser *parser)
|
||||
else
|
||||
goto statement;
|
||||
}
|
||||
else if (c_parser_next_token_is (parser, CPP_PRAGMA))
|
||||
{
|
||||
/* External pragmas, and some omp pragmas, are not associated
|
||||
with regular c code, and so are not to be considered statements
|
||||
syntactically. This ensures that the user doesn't put them
|
||||
places that would turn into syntax errors if the directive
|
||||
were ignored. */
|
||||
if (c_parser_pragma (parser, pragma_compound))
|
||||
last_label = false, last_stmt = true;
|
||||
}
|
||||
else if (c_parser_next_token_is (parser, CPP_EOF))
|
||||
{
|
||||
c_parser_error (parser, "expected declaration or statement");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
statement:
|
||||
@ -3578,6 +3651,9 @@ c_parser_statement_after_labels (c_parser *parser)
|
||||
c_parser_error (parser, "expected statement");
|
||||
c_parser_consume_token (parser);
|
||||
break;
|
||||
case CPP_PRAGMA:
|
||||
c_parser_pragma (parser, pragma_stmt);
|
||||
break;
|
||||
default:
|
||||
expr_stmt:
|
||||
stmt = c_finish_expr_stmt (c_parser_expression_conv (parser).value);
|
||||
@ -5558,6 +5634,12 @@ c_parser_objc_class_instance_variables (c_parser *parser)
|
||||
objc_set_visibility (1);
|
||||
continue;
|
||||
}
|
||||
else if (c_parser_next_token_is (parser, CPP_PRAGMA))
|
||||
{
|
||||
c_parser_pragma (parser, pragma_external);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Parse some comma-separated declarations. */
|
||||
decls = c_parser_struct_declaration (parser);
|
||||
{
|
||||
@ -6262,17 +6344,101 @@ c_parser_objc_keywordexpr (c_parser *parser)
|
||||
}
|
||||
|
||||
|
||||
/* The actual parser and external interface. ??? Does this need to be
|
||||
garbage-collected? */
|
||||
/* Handle pragmas. ALLOW_STMT is true if we're within the context of
|
||||
a function and such pragmas are to be allowed. Returns true if we
|
||||
actually parsed such a pragma. */
|
||||
|
||||
static GTY (()) c_parser *the_parser;
|
||||
static bool
|
||||
c_parser_pragma (c_parser *parser, enum pragma_context context ATTRIBUTE_UNUSED)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
id = c_parser_peek_token (parser)->pragma_kind;
|
||||
gcc_assert (id != PRAGMA_NONE);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case PRAGMA_GCC_PCH_PREPROCESS:
|
||||
c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
|
||||
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
|
||||
return false;
|
||||
|
||||
default:
|
||||
gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
|
||||
break;
|
||||
}
|
||||
|
||||
c_parser_consume_pragma (parser);
|
||||
c_invoke_pragma_handler (id);
|
||||
|
||||
/* Skip to EOL, but suppress any error message. Those will have been
|
||||
generated by the handler routine through calling error, as opposed
|
||||
to calling c_parser_error. */
|
||||
parser->error = true;
|
||||
c_parser_skip_to_pragma_eol (parser);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The interface the pragma parsers have to the lexer. */
|
||||
|
||||
enum cpp_ttype
|
||||
pragma_lex (tree *value)
|
||||
{
|
||||
c_token *tok = c_parser_peek_token (the_parser);
|
||||
enum cpp_ttype ret = tok->type;
|
||||
|
||||
*value = tok->value;
|
||||
if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
|
||||
ret = CPP_EOF;
|
||||
else
|
||||
{
|
||||
if (ret == CPP_KEYWORD)
|
||||
ret = CPP_NAME;
|
||||
c_parser_consume_token (the_parser);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
c_parser_pragma_pch_preprocess (c_parser *parser)
|
||||
{
|
||||
tree name = NULL;
|
||||
|
||||
c_parser_consume_pragma (parser);
|
||||
if (c_parser_next_token_is (parser, CPP_STRING))
|
||||
{
|
||||
name = c_parser_peek_token (parser)->value;
|
||||
c_parser_consume_token (parser);
|
||||
}
|
||||
else
|
||||
c_parser_error (parser, "expected string literal");
|
||||
c_parser_skip_to_pragma_eol (parser);
|
||||
|
||||
if (name)
|
||||
c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
|
||||
}
|
||||
|
||||
/* Parse a single source file. */
|
||||
|
||||
void
|
||||
c_parse_file (void)
|
||||
{
|
||||
the_parser = c_parser_new ();
|
||||
/* Use local storage to begin. If the first token is a pragma, parse it.
|
||||
If it is #pragma GCC pch_preprocess, then this will load a PCH file
|
||||
which will cause garbage collection. */
|
||||
c_parser tparser;
|
||||
|
||||
memset (&tparser, 0, sizeof tparser);
|
||||
the_parser = &tparser;
|
||||
|
||||
if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
|
||||
c_parser_pragma_pch_preprocess (&tparser);
|
||||
|
||||
the_parser = GGC_NEW (c_parser);
|
||||
*the_parser = tparser;
|
||||
|
||||
c_parser_translation_unit (the_parser);
|
||||
the_parser = NULL;
|
||||
}
|
||||
|
12
gcc/c-pch.c
12
gcc/c-pch.c
@ -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. */
|
||||
void
|
||||
c_register_pragma (const char *space, const char *name,
|
||||
void (*handler) (struct cpp_reader *))
|
||||
|
||||
static void
|
||||
c_register_pragma_1 (const char *space, const char *name,
|
||||
pragma_handler handler, bool allow_expansion)
|
||||
{
|
||||
cpp_register_pragma (parse_in, space, name, handler, 0);
|
||||
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, pragma_handler handler)
|
||||
{
|
||||
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)
|
||||
{
|
||||
cpp_register_pragma (parse_in, space, name, handler, 1);
|
||||
c_register_pragma_1 (space, name, handler, true);
|
||||
}
|
||||
|
||||
void
|
||||
c_invoke_pragma_handler (unsigned int id)
|
||||
{
|
||||
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.
|
||||
|
@ -1,4 +1,41 @@
|
||||
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)
|
||||
|
502
gcc/cp/parser.c
502
gcc/cp/parser.c
@ -55,6 +55,8 @@ typedef struct cp_token GTY (())
|
||||
ENUM_BITFIELD (rid) keyword : 8;
|
||||
/* Token flags. */
|
||||
unsigned char flags;
|
||||
/* Identifier for the pragma. */
|
||||
ENUM_BITFIELD (pragma_kind) pragma_kind : 6;
|
||||
/* True if this token is from a system header. */
|
||||
BOOL_BITFIELD in_system_header : 1;
|
||||
/* True if this token is from a context where it is implicitly extern "C" */
|
||||
@ -76,7 +78,7 @@ DEF_VEC_ALLOC_P (cp_token_position,heap);
|
||||
|
||||
static const cp_token eof_token =
|
||||
{
|
||||
CPP_EOF, RID_MAX, 0, 0, 0, false, NULL_TREE,
|
||||
CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, NULL_TREE,
|
||||
#if USE_MAPPED_LOCATION
|
||||
0
|
||||
#else
|
||||
@ -112,11 +114,15 @@ typedef struct cp_lexer GTY (())
|
||||
tokens. */
|
||||
VEC(cp_token_position,heap) *GTY ((skip)) saved_tokens;
|
||||
|
||||
/* The next lexer in a linked list of lexers. */
|
||||
struct cp_lexer *next;
|
||||
|
||||
/* True if we should output debugging information. */
|
||||
bool debugging_p;
|
||||
|
||||
/* The next lexer in a linked list of lexers. */
|
||||
struct cp_lexer *next;
|
||||
/* True if we're in the context of parsing a pragma, and should not
|
||||
increment past the end-of-line marker. */
|
||||
bool in_pragma;
|
||||
} cp_lexer;
|
||||
|
||||
/* cp_token_cache is a range of tokens. There is no need to represent
|
||||
@ -166,8 +172,6 @@ static void cp_lexer_purge_token
|
||||
(cp_lexer *);
|
||||
static void cp_lexer_purge_tokens_after
|
||||
(cp_lexer *, cp_token_position);
|
||||
static void cp_lexer_handle_pragma
|
||||
(cp_lexer *);
|
||||
static void cp_lexer_save_tokens
|
||||
(cp_lexer *);
|
||||
static void cp_lexer_commit_tokens
|
||||
@ -196,6 +200,9 @@ static void cp_lexer_stop_debugging
|
||||
static cp_token_cache *cp_token_cache_new
|
||||
(cp_token *, cp_token *);
|
||||
|
||||
static void cp_parser_initial_pragma
|
||||
(cp_token *);
|
||||
|
||||
/* Manifest constants. */
|
||||
#define CP_LEXER_BUFFER_SIZE 10000
|
||||
#define CP_SAVED_TOKEN_STACK 5
|
||||
@ -244,17 +251,12 @@ cp_lexer_new_main (void)
|
||||
size_t space;
|
||||
cp_token *buffer;
|
||||
|
||||
/* It's possible that lexing the first token will load a PCH file,
|
||||
which is a GC collection point. So we have to grab the first
|
||||
token before allocating any memory. Pragmas must not be deferred
|
||||
as -fpch-preprocess can generate a pragma to load the PCH file in
|
||||
the preprocessed output used by -save-temps. */
|
||||
cp_lexer_get_preprocessor_token (NULL, &first_token);
|
||||
/* It's possible that parsing the first pragma will load a PCH file,
|
||||
which is a GC collection point. So we have to do that before
|
||||
allocating any memory. */
|
||||
cp_parser_initial_pragma (&first_token);
|
||||
|
||||
/* Tell cpplib we want CPP_PRAGMA tokens. */
|
||||
cpp_get_options (parse_in)->defer_pragmas = true;
|
||||
|
||||
/* Tell pragma_lex not to merge string constants. */
|
||||
/* Tell c_lex_with_flags not to merge string constants. */
|
||||
c_lex_return_raw_strings = true;
|
||||
|
||||
c_common_no_more_pch ();
|
||||
@ -296,11 +298,6 @@ cp_lexer_new_main (void)
|
||||
lexer->last_token = pos;
|
||||
lexer->next_token = lexer->buffer_length ? buffer : (cp_token *)&eof_token;
|
||||
|
||||
/* Pragma processing (via cpp_handle_deferred_pragma) may result in
|
||||
direct calls to pragma_lex. Those callers all expect pragma_lex
|
||||
to do string constant concatenation. */
|
||||
c_lex_return_raw_strings = false;
|
||||
|
||||
/* Subsequent preprocessor diagnostics should use compiler
|
||||
diagnostic functions to get the compiler source location. */
|
||||
cpp_get_options (parse_in)->client_diagnostic = true;
|
||||
@ -395,6 +392,8 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
|
||||
/* Get a new token from the preprocessor. */
|
||||
token->type
|
||||
= c_lex_with_flags (&token->value, &token->location, &token->flags);
|
||||
token->keyword = RID_MAX;
|
||||
token->pragma_kind = PRAGMA_NONE;
|
||||
token->in_system_header = in_system_header;
|
||||
|
||||
/* On some systems, some header files are surrounded by an
|
||||
@ -442,8 +441,12 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
|
||||
default: token->keyword = C_RID_CODE (token->value);
|
||||
}
|
||||
}
|
||||
else
|
||||
token->keyword = RID_MAX;
|
||||
else if (token->type == CPP_PRAGMA)
|
||||
{
|
||||
/* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
|
||||
token->pragma_kind = TREE_INT_CST_LOW (token->value);
|
||||
token->value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the globals input_location and in_system_header from TOKEN. */
|
||||
@ -553,6 +556,7 @@ cp_lexer_consume_token (cp_lexer* lexer)
|
||||
cp_token *token = lexer->next_token;
|
||||
|
||||
gcc_assert (token != &eof_token);
|
||||
gcc_assert (!lexer->in_pragma || token->type != CPP_PRAGMA_EOL);
|
||||
|
||||
do
|
||||
{
|
||||
@ -630,25 +634,6 @@ cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok)
|
||||
}
|
||||
}
|
||||
|
||||
/* Consume and handle a pragma token. */
|
||||
static void
|
||||
cp_lexer_handle_pragma (cp_lexer *lexer)
|
||||
{
|
||||
cpp_string s;
|
||||
cp_token *token = cp_lexer_consume_token (lexer);
|
||||
gcc_assert (token->type == CPP_PRAGMA);
|
||||
gcc_assert (token->value);
|
||||
|
||||
s.len = TREE_STRING_LENGTH (token->value);
|
||||
s.text = (const unsigned char *) TREE_STRING_POINTER (token->value);
|
||||
|
||||
cpp_handle_deferred_pragma (parse_in, &s);
|
||||
|
||||
/* Clearing token->value here means that we will get an ICE if we
|
||||
try to process this #pragma again (which should be impossible). */
|
||||
token->value = NULL;
|
||||
}
|
||||
|
||||
/* Begin saving tokens. All tokens consumed after this point will be
|
||||
preserved. */
|
||||
|
||||
@ -731,7 +716,6 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
|
||||
|
||||
case CPP_STRING:
|
||||
case CPP_WSTRING:
|
||||
case CPP_PRAGMA:
|
||||
fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->value));
|
||||
break;
|
||||
|
||||
@ -1463,9 +1447,9 @@ static tree cp_parser_builtin_offsetof
|
||||
/* Statements [gram.stmt.stmt] */
|
||||
|
||||
static void cp_parser_statement
|
||||
(cp_parser *, tree);
|
||||
(cp_parser *, tree, bool);
|
||||
static tree cp_parser_labeled_statement
|
||||
(cp_parser *, tree);
|
||||
(cp_parser *, tree, bool);
|
||||
static tree cp_parser_expression_statement
|
||||
(cp_parser *, tree);
|
||||
static tree cp_parser_compound_statement
|
||||
@ -1685,6 +1669,10 @@ static bool cp_parser_extension_opt
|
||||
static void cp_parser_label_declaration
|
||||
(cp_parser *);
|
||||
|
||||
enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
|
||||
static bool cp_parser_pragma
|
||||
(cp_parser *, enum pragma_context);
|
||||
|
||||
/* Objective-C++ Productions */
|
||||
|
||||
static tree cp_parser_objc_message_receiver
|
||||
@ -1828,6 +1816,8 @@ static void cp_parser_skip_to_closing_brace
|
||||
(cp_parser *);
|
||||
static void cp_parser_skip_until_found
|
||||
(cp_parser *, enum cpp_ttype, const char *);
|
||||
static void cp_parser_skip_to_pragma_eol
|
||||
(cp_parser*, cp_token *);
|
||||
static bool cp_parser_error_occurred
|
||||
(cp_parser *);
|
||||
static bool cp_parser_allow_gnu_extensions_p
|
||||
@ -1888,12 +1878,14 @@ cp_parser_error (cp_parser* parser, const char* message)
|
||||
/* This diagnostic makes more sense if it is tagged to the line
|
||||
of the token we just peeked at. */
|
||||
cp_lexer_set_source_position_from_token (token);
|
||||
|
||||
if (token->type == CPP_PRAGMA)
|
||||
{
|
||||
error ("%<#pragma%> is not allowed here");
|
||||
cp_lexer_purge_token (parser->lexer);
|
||||
cp_parser_skip_to_pragma_eol (parser, token);
|
||||
return;
|
||||
}
|
||||
|
||||
c_parse_error (message,
|
||||
/* Because c_parser_error does not understand
|
||||
CPP_KEYWORD, keywords are treated like
|
||||
@ -2187,7 +2179,6 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
|
||||
{
|
||||
unsigned paren_depth = 0;
|
||||
unsigned brace_depth = 0;
|
||||
int result;
|
||||
|
||||
if (recovering && !or_comma
|
||||
&& cp_parser_uncommitted_to_tentative_parse_p (parser))
|
||||
@ -2195,62 +2186,55 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
|
||||
|
||||
while (true)
|
||||
{
|
||||
cp_token *token;
|
||||
cp_token * token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
/* If we've run out of tokens, then there is no closing `)'. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
|
||||
switch (token->type)
|
||||
{
|
||||
result = 0;
|
||||
case CPP_EOF:
|
||||
case CPP_PRAGMA_EOL:
|
||||
/* If we've run out of tokens, then there is no closing `)'. */
|
||||
return 0;
|
||||
|
||||
case CPP_SEMICOLON:
|
||||
/* This matches the processing in skip_to_end_of_statement. */
|
||||
if (!brace_depth)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
/* This matches the processing in skip_to_end_of_statement. */
|
||||
if (token->type == CPP_SEMICOLON && !brace_depth)
|
||||
{
|
||||
result = 0;
|
||||
case CPP_OPEN_BRACE:
|
||||
++brace_depth;
|
||||
break;
|
||||
}
|
||||
if (token->type == CPP_OPEN_BRACE)
|
||||
++brace_depth;
|
||||
if (token->type == CPP_CLOSE_BRACE)
|
||||
{
|
||||
case CPP_CLOSE_BRACE:
|
||||
if (!brace_depth--)
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (recovering && or_comma && token->type == CPP_COMMA
|
||||
&& !brace_depth && !paren_depth)
|
||||
{
|
||||
result = -1;
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!brace_depth)
|
||||
{
|
||||
/* If it is an `(', we have entered another level of nesting. */
|
||||
if (token->type == CPP_OPEN_PAREN)
|
||||
case CPP_COMMA:
|
||||
if (recovering && or_comma && !brace_depth && !paren_depth)
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case CPP_OPEN_PAREN:
|
||||
if (!brace_depth)
|
||||
++paren_depth;
|
||||
/* If it is a `)', then we might be done. */
|
||||
else if (token->type == CPP_CLOSE_PAREN && !paren_depth--)
|
||||
break;
|
||||
|
||||
case CPP_CLOSE_PAREN:
|
||||
if (!brace_depth && !paren_depth--)
|
||||
{
|
||||
if (consume_paren)
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
{
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Consume the token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Consume tokens until we reach the end of the current statement.
|
||||
@ -2264,31 +2248,34 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser)
|
||||
|
||||
while (true)
|
||||
{
|
||||
cp_token *token;
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
/* Peek at the next token. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
/* If we've run out of tokens, stop. */
|
||||
if (token->type == CPP_EOF)
|
||||
break;
|
||||
/* If the next token is a `;', we have reached the end of the
|
||||
statement. */
|
||||
if (token->type == CPP_SEMICOLON && !nesting_depth)
|
||||
break;
|
||||
/* If the next token is a non-nested `}', then we have reached
|
||||
the end of the current block. */
|
||||
if (token->type == CPP_CLOSE_BRACE)
|
||||
switch (token->type)
|
||||
{
|
||||
/* If this is a non-nested `}', stop before consuming it.
|
||||
case CPP_EOF:
|
||||
case CPP_PRAGMA_EOL:
|
||||
/* If we've run out of tokens, stop. */
|
||||
return;
|
||||
|
||||
case CPP_SEMICOLON:
|
||||
/* If the next token is a `;', we have reached the end of the
|
||||
statement. */
|
||||
if (!nesting_depth)
|
||||
return;
|
||||
break;
|
||||
|
||||
case CPP_CLOSE_BRACE:
|
||||
/* If this is a non-nested '}', stop before consuming it.
|
||||
That way, when confronted with something like:
|
||||
|
||||
{ 3 + }
|
||||
|
||||
we stop before consuming the closing `}', even though we
|
||||
we stop before consuming the closing '}', even though we
|
||||
have not yet reached a `;'. */
|
||||
if (nesting_depth == 0)
|
||||
break;
|
||||
/* If it is the closing `}' for a block that we have
|
||||
return;
|
||||
|
||||
/* If it is the closing '}' for a block that we have
|
||||
scanned, stop -- but only after consuming the token.
|
||||
That way given:
|
||||
|
||||
@ -2301,13 +2288,17 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser)
|
||||
if (--nesting_depth == 0)
|
||||
{
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
case CPP_OPEN_BRACE:
|
||||
++nesting_depth;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* If it the next token is a `{', then we are entering a new
|
||||
block. Consume the entire block. */
|
||||
else if (token->type == CPP_OPEN_BRACE)
|
||||
++nesting_depth;
|
||||
|
||||
/* Consume the token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
}
|
||||
@ -2344,15 +2335,12 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
|
||||
{
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
if (token->type == CPP_EOF)
|
||||
break;
|
||||
|
||||
switch (token->type)
|
||||
{
|
||||
case CPP_EOF:
|
||||
case CPP_PRAGMA_EOL:
|
||||
/* If we've run out of tokens, stop. */
|
||||
nesting_depth = -1;
|
||||
continue;
|
||||
return;
|
||||
|
||||
case CPP_SEMICOLON:
|
||||
/* Stop if this is an unnested ';'. */
|
||||
@ -2379,7 +2367,6 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
|
||||
|
||||
/* Consume the token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -2393,26 +2380,56 @@ cp_parser_skip_to_closing_brace (cp_parser *parser)
|
||||
|
||||
while (true)
|
||||
{
|
||||
cp_token *token;
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
switch (token->type)
|
||||
{
|
||||
case CPP_EOF:
|
||||
case CPP_PRAGMA_EOL:
|
||||
/* If we've run out of tokens, stop. */
|
||||
return;
|
||||
|
||||
case CPP_CLOSE_BRACE:
|
||||
/* If the next token is a non-nested `}', then we have reached
|
||||
the end of the current block. */
|
||||
if (nesting_depth-- == 0)
|
||||
return;
|
||||
break;
|
||||
|
||||
case CPP_OPEN_BRACE:
|
||||
/* If it the next token is a `{', then we are entering a new
|
||||
block. Consume the entire block. */
|
||||
++nesting_depth;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Peek at the next token. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
/* If we've run out of tokens, stop. */
|
||||
if (token->type == CPP_EOF)
|
||||
break;
|
||||
/* If the next token is a non-nested `}', then we have reached
|
||||
the end of the current block. */
|
||||
if (token->type == CPP_CLOSE_BRACE && nesting_depth-- == 0)
|
||||
break;
|
||||
/* If it the next token is a `{', then we are entering a new
|
||||
block. Consume the entire block. */
|
||||
else if (token->type == CPP_OPEN_BRACE)
|
||||
++nesting_depth;
|
||||
/* Consume the token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Consume tokens until we reach the end of the pragma. The PRAGMA_TOK
|
||||
parameter is the PRAGMA token, allowing us to purge the entire pragma
|
||||
sequence. */
|
||||
|
||||
static void
|
||||
cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok)
|
||||
{
|
||||
cp_token *token;
|
||||
|
||||
parser->lexer->in_pragma = false;
|
||||
|
||||
do
|
||||
token = cp_lexer_consume_token (parser->lexer);
|
||||
while (token->type != CPP_PRAGMA_EOL && token->type != CPP_EOF);
|
||||
|
||||
/* Ensure that the pragma is not parsed again. */
|
||||
cp_lexer_purge_tokens_after (parser->lexer, pragma_tok);
|
||||
}
|
||||
|
||||
/* This is a simple wrapper around make_typename_type. When the id is
|
||||
an unresolved identifier node, we can provide a superior diagnostic
|
||||
using cp_parser_diagnose_invalid_type_name. */
|
||||
@ -6005,15 +6022,20 @@ cp_parser_builtin_offsetof (cp_parser *parser)
|
||||
iteration-statement
|
||||
jump-statement
|
||||
declaration-statement
|
||||
try-block */
|
||||
try-block
|
||||
|
||||
IN_COMPOUND is true when the statement is nested inside a
|
||||
cp_parser_compound_statement; this matters for certain pragmas. */
|
||||
|
||||
static void
|
||||
cp_parser_statement (cp_parser* parser, tree in_statement_expr)
|
||||
cp_parser_statement (cp_parser* parser, tree in_statement_expr,
|
||||
bool in_compound)
|
||||
{
|
||||
tree statement;
|
||||
cp_token *token;
|
||||
location_t statement_location;
|
||||
|
||||
restart:
|
||||
/* There is no statement yet. */
|
||||
statement = NULL_TREE;
|
||||
/* Peek at the next token. */
|
||||
@ -6030,8 +6052,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
|
||||
{
|
||||
case RID_CASE:
|
||||
case RID_DEFAULT:
|
||||
statement = cp_parser_labeled_statement (parser,
|
||||
in_statement_expr);
|
||||
statement = cp_parser_labeled_statement (parser, in_statement_expr,
|
||||
in_compound);
|
||||
break;
|
||||
|
||||
case RID_IF:
|
||||
@ -6077,7 +6099,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
|
||||
labeled-statement. */
|
||||
token = cp_lexer_peek_nth_token (parser->lexer, 2);
|
||||
if (token->type == CPP_COLON)
|
||||
statement = cp_parser_labeled_statement (parser, in_statement_expr);
|
||||
statement = cp_parser_labeled_statement (parser, in_statement_expr,
|
||||
in_compound);
|
||||
}
|
||||
/* Anything that starts with a `{' must be a compound-statement. */
|
||||
else if (token->type == CPP_OPEN_BRACE)
|
||||
@ -6086,7 +6109,15 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
|
||||
a statement all its own. */
|
||||
else if (token->type == CPP_PRAGMA)
|
||||
{
|
||||
cp_lexer_handle_pragma (parser->lexer);
|
||||
/* Only certain OpenMP pragmas are attached to statements, and thus
|
||||
are considered statements themselves. All others are not. In
|
||||
the context of a compound, accept the pragma as a "statement" and
|
||||
return so that we can check for a close brace. Otherwise we
|
||||
require a real statement and must go back and read one. */
|
||||
if (in_compound)
|
||||
cp_parser_pragma (parser, pragma_compound);
|
||||
else if (!cp_parser_pragma (parser, pragma_stmt))
|
||||
goto restart;
|
||||
return;
|
||||
}
|
||||
else if (token->type == CPP_EOF)
|
||||
@ -6132,10 +6163,14 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
|
||||
case constant-expression ... constant-expression : statement
|
||||
|
||||
Returns the new CASE_LABEL_EXPR, for a `case' or `default' label.
|
||||
For an ordinary label, returns a LABEL_EXPR. */
|
||||
For an ordinary label, returns a LABEL_EXPR.
|
||||
|
||||
IN_COMPOUND is as for cp_parser_statement: true when we're nested
|
||||
inside a compound. */
|
||||
|
||||
static tree
|
||||
cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
|
||||
cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
|
||||
bool in_compound)
|
||||
{
|
||||
cp_token *token;
|
||||
tree statement = error_mark_node;
|
||||
@ -6178,20 +6213,21 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
|
||||
else
|
||||
expr_hi = NULL_TREE;
|
||||
|
||||
if (!parser->in_switch_statement_p)
|
||||
error ("case label %qE not within a switch statement", expr);
|
||||
else
|
||||
if (parser->in_switch_statement_p)
|
||||
statement = finish_case_label (expr, expr_hi);
|
||||
else
|
||||
error ("case label %qE not within a switch statement", expr);
|
||||
}
|
||||
break;
|
||||
|
||||
case RID_DEFAULT:
|
||||
/* Consume the `default' token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
if (!parser->in_switch_statement_p)
|
||||
error ("case label not within a switch statement");
|
||||
else
|
||||
|
||||
if (parser->in_switch_statement_p)
|
||||
statement = finish_case_label (NULL_TREE, NULL_TREE);
|
||||
else
|
||||
error ("case label not within a switch statement");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -6203,7 +6239,7 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
|
||||
/* Require the `:' token. */
|
||||
cp_parser_require (parser, CPP_COLON, "`:'");
|
||||
/* Parse the labeled statement. */
|
||||
cp_parser_statement (parser, in_statement_expr);
|
||||
cp_parser_statement (parser, in_statement_expr, in_compound);
|
||||
|
||||
/* Return the label, in the case of a `case' or `default' label. */
|
||||
return statement;
|
||||
@ -6285,13 +6321,16 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
|
||||
/* Scan statements until there aren't any more. */
|
||||
while (true)
|
||||
{
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
/* If we're looking at a `}', then we've run out of statements. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
|
||||
|| cp_lexer_next_token_is (parser->lexer, CPP_EOF))
|
||||
if (token->type == CPP_CLOSE_BRACE
|
||||
|| token->type == CPP_EOF
|
||||
|| token->type == CPP_PRAGMA_EOL)
|
||||
break;
|
||||
|
||||
/* Parse the statement. */
|
||||
cp_parser_statement (parser, in_statement_expr);
|
||||
cp_parser_statement (parser, in_statement_expr, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6788,7 +6827,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
|
||||
/* Create a compound-statement. */
|
||||
statement = begin_compound_stmt (0);
|
||||
/* Parse the dependent-statement. */
|
||||
cp_parser_statement (parser, false);
|
||||
cp_parser_statement (parser, NULL_TREE, false);
|
||||
/* Finish the dummy compound-statement. */
|
||||
finish_compound_stmt (statement);
|
||||
}
|
||||
@ -6810,13 +6849,13 @@ cp_parser_already_scoped_statement (cp_parser* parser)
|
||||
{
|
||||
/* If the token is a `{', then we must take special action. */
|
||||
if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
|
||||
cp_parser_statement (parser, false);
|
||||
cp_parser_statement (parser, NULL_TREE, false);
|
||||
else
|
||||
{
|
||||
/* Avoid calling cp_parser_compound_statement, so that we
|
||||
don't create a new scope. Do everything else by hand. */
|
||||
cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
|
||||
cp_parser_statement_seq_opt (parser, false);
|
||||
cp_parser_statement_seq_opt (parser, NULL_TREE);
|
||||
cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
|
||||
}
|
||||
}
|
||||
@ -6839,7 +6878,8 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
|
||||
if (token->type == CPP_CLOSE_BRACE
|
||||
|| token->type == CPP_EOF)
|
||||
|| token->type == CPP_EOF
|
||||
|| token->type == CPP_PRAGMA_EOL)
|
||||
break;
|
||||
|
||||
if (token->type == CPP_SEMICOLON)
|
||||
@ -6871,7 +6911,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
|
||||
A nested declaration cannot, so this is done here and not
|
||||
in cp_parser_declaration. (A #pragma at block scope is
|
||||
handled in cp_parser_statement.) */
|
||||
cp_lexer_handle_pragma (parser->lexer);
|
||||
cp_parser_pragma (parser, pragma_external);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -12207,6 +12247,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
|
||||
|
||||
/* If we run out of tokens, issue an error message. */
|
||||
case CPP_EOF:
|
||||
case CPP_PRAGMA_EOL:
|
||||
error ("file ends in default argument");
|
||||
done = true;
|
||||
break;
|
||||
@ -13242,7 +13283,9 @@ cp_parser_member_specification_opt (cp_parser* parser)
|
||||
/* Peek at the next token. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
/* If it's a `}', or EOF then we've seen all the members. */
|
||||
if (token->type == CPP_CLOSE_BRACE || token->type == CPP_EOF)
|
||||
if (token->type == CPP_CLOSE_BRACE
|
||||
|| token->type == CPP_EOF
|
||||
|| token->type == CPP_PRAGMA_EOL)
|
||||
break;
|
||||
|
||||
/* See if this token is a keyword. */
|
||||
@ -13264,7 +13307,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
|
||||
/* Accept #pragmas at class scope. */
|
||||
if (token->type == CPP_PRAGMA)
|
||||
{
|
||||
cp_lexer_handle_pragma (parser->lexer);
|
||||
cp_parser_pragma (parser, pragma_external);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -15185,9 +15228,15 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
|
||||
/* Issue an error message. */
|
||||
error ("named return values are no longer supported");
|
||||
/* Skip tokens until we reach the start of the function body. */
|
||||
while (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
|
||||
&& cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
while (true)
|
||||
{
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
if (token->type == CPP_OPEN_BRACE
|
||||
|| token->type == CPP_EOF
|
||||
|| token->type == CPP_PRAGMA_EOL)
|
||||
break;
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
}
|
||||
}
|
||||
/* The `extern' in `extern "C" void f () { ... }' does not apply to
|
||||
anything declared inside `f'. */
|
||||
@ -16002,27 +16051,38 @@ cp_parser_skip_until_found (cp_parser* parser,
|
||||
{
|
||||
/* Peek at the next token. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
/* If we've reached the token we want, consume it and
|
||||
stop. */
|
||||
|
||||
/* If we've reached the token we want, consume it and stop. */
|
||||
if (token->type == type && !nesting_depth)
|
||||
{
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
return;
|
||||
}
|
||||
/* If we've run out of tokens, stop. */
|
||||
if (token->type == CPP_EOF)
|
||||
return;
|
||||
if (token->type == CPP_OPEN_BRACE
|
||||
|| token->type == CPP_OPEN_PAREN
|
||||
|| token->type == CPP_OPEN_SQUARE)
|
||||
++nesting_depth;
|
||||
else if (token->type == CPP_CLOSE_BRACE
|
||||
|| token->type == CPP_CLOSE_PAREN
|
||||
|| token->type == CPP_CLOSE_SQUARE)
|
||||
|
||||
switch (token->type)
|
||||
{
|
||||
case CPP_EOF:
|
||||
case CPP_PRAGMA_EOL:
|
||||
/* If we've run out of tokens, stop. */
|
||||
return;
|
||||
|
||||
case CPP_OPEN_BRACE:
|
||||
case CPP_OPEN_PAREN:
|
||||
case CPP_OPEN_SQUARE:
|
||||
++nesting_depth;
|
||||
break;
|
||||
|
||||
case CPP_CLOSE_BRACE:
|
||||
case CPP_CLOSE_PAREN:
|
||||
case CPP_CLOSE_SQUARE:
|
||||
if (nesting_depth-- == 0)
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Consume this token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
}
|
||||
@ -16241,7 +16301,9 @@ cp_parser_cache_group (cp_parser *parser,
|
||||
&& cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
|
||||
return;
|
||||
/* If we've reached the end of the file, stop. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)
|
||||
|| (end != CPP_PRAGMA_EOL
|
||||
&& cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL)))
|
||||
return;
|
||||
/* Consume the next token. */
|
||||
token = cp_lexer_consume_token (parser->lexer);
|
||||
@ -16254,6 +16316,8 @@ cp_parser_cache_group (cp_parser *parser,
|
||||
}
|
||||
else if (token->type == CPP_OPEN_PAREN)
|
||||
cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1);
|
||||
else if (token->type == CPP_PRAGMA)
|
||||
cp_parser_cache_group (parser, CPP_PRAGMA_EOL, depth + 1);
|
||||
else if (token->type == end)
|
||||
return;
|
||||
}
|
||||
@ -16990,7 +17054,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
|
||||
cp_parser_linkage_specification (parser);
|
||||
/* Handle #pragma, if any. */
|
||||
else if (token->type == CPP_PRAGMA)
|
||||
cp_lexer_handle_pragma (parser->lexer);
|
||||
cp_parser_pragma (parser, pragma_external);
|
||||
/* Allow stray semicolons. */
|
||||
else if (token->type == CPP_SEMICOLON)
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
@ -17482,11 +17546,111 @@ cp_parser_objc_statement (cp_parser * parser) {
|
||||
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* The parser. */
|
||||
|
||||
static GTY (()) cp_parser *the_parser;
|
||||
|
||||
|
||||
/* Special handling for the first token or line in the file. The first
|
||||
thing in the file might be #pragma GCC pch_preprocess, which loads a
|
||||
PCH file, which is a GC collection point. So we need to handle this
|
||||
first pragma without benefit of an existing lexer structure.
|
||||
|
||||
Always returns one token to the caller in *FIRST_TOKEN. This is
|
||||
either the true first token of the file, or the first token after
|
||||
the initial pragma. */
|
||||
|
||||
static void
|
||||
cp_parser_initial_pragma (cp_token *first_token)
|
||||
{
|
||||
tree name = NULL;
|
||||
|
||||
cp_lexer_get_preprocessor_token (NULL, first_token);
|
||||
if (first_token->pragma_kind != PRAGMA_GCC_PCH_PREPROCESS)
|
||||
return;
|
||||
|
||||
cp_lexer_get_preprocessor_token (NULL, first_token);
|
||||
if (first_token->type == CPP_STRING)
|
||||
{
|
||||
name = first_token->value;
|
||||
|
||||
cp_lexer_get_preprocessor_token (NULL, first_token);
|
||||
if (first_token->type != CPP_PRAGMA_EOL)
|
||||
error ("junk at end of %<#pragma GCC pch_preprocess%>");
|
||||
}
|
||||
else
|
||||
error ("expected string literal");
|
||||
|
||||
/* Skip to the end of the pragma. */
|
||||
while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
|
||||
cp_lexer_get_preprocessor_token (NULL, first_token);
|
||||
|
||||
/* Read one more token to return to our caller. */
|
||||
cp_lexer_get_preprocessor_token (NULL, first_token);
|
||||
|
||||
/* Now actually load the PCH file. */
|
||||
if (name)
|
||||
c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
|
||||
}
|
||||
|
||||
/* Normal parsing of a pragma token. Here we can (and must) use the
|
||||
regular lexer. */
|
||||
|
||||
static bool
|
||||
cp_parser_pragma (cp_parser *parser, enum pragma_context context ATTRIBUTE_UNUSED)
|
||||
{
|
||||
cp_token *pragma_tok;
|
||||
unsigned int id;
|
||||
|
||||
pragma_tok = cp_lexer_consume_token (parser->lexer);
|
||||
gcc_assert (pragma_tok->type == CPP_PRAGMA);
|
||||
parser->lexer->in_pragma = true;
|
||||
|
||||
id = pragma_tok->pragma_kind;
|
||||
switch (id)
|
||||
{
|
||||
case PRAGMA_GCC_PCH_PREPROCESS:
|
||||
error ("%<#pragma GCC pch_preprocess%> must be first");
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
|
||||
c_invoke_pragma_handler (id);
|
||||
break;
|
||||
}
|
||||
|
||||
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The interface the pragma parsers have to the lexer. */
|
||||
|
||||
enum cpp_ttype
|
||||
pragma_lex (tree *value)
|
||||
{
|
||||
cp_token *tok;
|
||||
enum cpp_ttype ret;
|
||||
|
||||
tok = cp_lexer_peek_token (the_parser->lexer);
|
||||
|
||||
ret = tok->type;
|
||||
*value = tok->value;
|
||||
|
||||
if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
|
||||
ret = CPP_EOF;
|
||||
else if (ret == CPP_STRING)
|
||||
*value = cp_parser_string_literal (the_parser, false, false);
|
||||
else
|
||||
{
|
||||
cp_lexer_consume_token (the_parser->lexer);
|
||||
if (ret == CPP_KEYWORD)
|
||||
ret = CPP_NAME;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* External interface. */
|
||||
|
||||
/* Parse one entire translation unit. */
|
||||
|
@ -1,3 +1,8 @@
|
||||
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 *-*-* } }
|
||||
|
@ -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).
|
||||
|
@ -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)
|
||||
|
@ -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 *);
|
||||
|
24
libcpp/lex.c
24
libcpp/lex.c
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user