aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog46
-rw-r--r--gcc/Makefile.in4
-rw-r--r--gcc/c-common.c4
-rw-r--r--gcc/c-common.h2
-rw-r--r--gcc/c-lex.c13
-rw-r--r--gcc/c-parser.c244
-rw-r--r--gcc/c-pch.c12
-rw-r--r--gcc/c-pragma.c58
-rw-r--r--gcc/c-pragma.h25
-rw-r--r--gcc/cp/ChangeLog39
-rw-r--r--gcc/cp/lex.c2
-rw-r--r--gcc/cp/parser.c502
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/parse/pragma2.C4
-rw-r--r--libcpp/ChangeLog37
-rw-r--r--libcpp/directives.c412
-rw-r--r--libcpp/include/cpplib.h14
-rw-r--r--libcpp/internal.h14
-rw-r--r--libcpp/lex.c24
-rw-r--r--libcpp/macro.c23
20 files changed, 989 insertions, 495 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b818536..a9a6e92 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 6c7ca28..82e5de2 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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@
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 76e9096..2a7c1e7 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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");
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 65a0107..735250f 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -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 */
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index af3695f..44e63d7 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -458,11 +458,11 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags)
type = lex_string (tok, value, false);
break;
}
+ *value = build_string (tok->val.str.len, (char *) tok->val.str.text);
+ break;
- /* FALLTHROUGH */
-
case CPP_PRAGMA:
- *value = build_string (tok->val.str.len, (char *) tok->val.str.text);
+ *value = build_int_cst (NULL, tok->val.pragma);
break;
/* These tokens should not be visible outside cpplib. */
@@ -490,13 +490,6 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags)
return type;
}
-enum cpp_ttype
-pragma_lex (tree *value)
-{
- location_t loc;
- return c_lex_with_flags (value, &loc, NULL);
-}
-
/* Returns the narrowest C-visible unsigned type, starting with the
minimum specified by FLAGS, that can fit HIGH:LOW, or itk_none if
there isn't one. */
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 8469eca..eff5b83 100644
--- a/gcc/c-parser.c
+++ b/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;
}
diff --git a/gcc/c-pch.c b/gcc/c-pch.c
index 1bbcab1..37c8c30 100644
--- a/gcc/c-pch.c
+++ b/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);
diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c
index 18eafcd..e2a4677 100644
--- a/gcc/c-pragma.c
+++ b/gcc/c-pragma.c
@@ -37,6 +37,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "vec.h"
#include "target.h"
+
#define GCC_BAD(gmsgid) \
do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
#define GCC_BAD2(gmsgid, arg) \
@@ -343,7 +344,7 @@ handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
t = pragma_lex (&x);
}
if (t != CPP_EOF)
- warning (OPT_Wpragmas, "junk at end of #pragma weak");
+ warning (OPT_Wpragmas, "junk at end of %<#pragma weak%>");
decl = identifier_global_value (name);
if (decl && DECL_P (decl))
@@ -416,7 +417,7 @@ handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
GCC_BAD ("malformed #pragma redefine_extname, ignored");
t = pragma_lex (&x);
if (t != CPP_EOF)
- warning (OPT_Wpragmas, "junk at end of #pragma redefine_extname");
+ warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
if (!flag_mudflap && !targetm.handle_pragma_redefine_extname)
{
@@ -484,7 +485,7 @@ handle_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy))
GCC_BAD ("malformed #pragma extern_prefix, ignored");
t = pragma_lex (&x);
if (t != CPP_EOF)
- warning (OPT_Wpragmas, "junk at end of #pragma extern_prefix");
+ warning (OPT_Wpragmas, "junk at end of %<#pragma extern_prefix%>");
if (targetm.handle_pragma_extern_prefix)
/* Note that the length includes the null terminator. */
@@ -667,26 +668,65 @@ handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED)
#endif
+/* A vector of registered pragma callbacks. */
+
+DEF_VEC_O (pragma_handler);
+DEF_VEC_ALLOC_O (pragma_handler, heap);
+
+static VEC(pragma_handler, heap) *registered_pragmas;
+
/* Front-end wrappers for pragma registration to avoid dragging
cpplib.h in almost everywhere. */
+
+static void
+c_register_pragma_1 (const char *space, const char *name,
+ pragma_handler handler, bool allow_expansion)
+{
+ unsigned id;
+
+ VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
+ id = VEC_length (pragma_handler, registered_pragmas);
+ id += PRAGMA_FIRST_EXTERNAL - 1;
+
+ /* The C++ front end allocates 6 bits in cp_token; the C front end
+ allocates 7 bits in c_token. At present this is sufficient. */
+ gcc_assert (id < 64);
+
+ cpp_register_deferred_pragma (parse_in, space, name, id,
+ allow_expansion, false);
+}
+
void
-c_register_pragma (const char *space, const char *name,
- void (*handler) (struct cpp_reader *))
+c_register_pragma (const char *space, const char *name, pragma_handler handler)
{
- cpp_register_pragma (parse_in, space, name, handler, 0);
+ c_register_pragma_1 (space, name, handler, false);
}
void
c_register_pragma_with_expansion (const char *space, const char *name,
- void (*handler) (struct cpp_reader *))
+ pragma_handler handler)
+{
+ c_register_pragma_1 (space, name, handler, true);
+}
+
+void
+c_invoke_pragma_handler (unsigned int id)
{
- cpp_register_pragma (parse_in, space, name, handler, 1);
+ pragma_handler handler;
+
+ id -= PRAGMA_FIRST_EXTERNAL;
+ handler = *VEC_index (pragma_handler, registered_pragmas, id);
+
+ handler (parse_in);
}
/* Set up front-end pragmas. */
void
init_pragma (void)
{
+ cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
+ PRAGMA_GCC_PCH_PREPROCESS, false, false);
+
#ifdef HANDLE_PRAGMA_PACK
#ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
@@ -704,8 +744,6 @@ init_pragma (void)
c_register_pragma (0, "redefine_extname", handle_pragma_redefine_extname);
c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix);
- c_register_pragma ("GCC", "pch_preprocess", c_common_pch_pragma);
-
#ifdef REGISTER_TARGET_PRAGMAS
REGISTER_TARGET_PRAGMAS ();
#endif
diff --git a/gcc/c-pragma.h b/gcc/c-pragma.h
index 057aca6..9876555 100644
--- a/gcc/c-pragma.h
+++ b/gcc/c-pragma.h
@@ -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.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 29389f4..1dbf600 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 469efc8..a800432 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -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)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bfcf261..86763eb 100644
--- a/gcc/cp/parser.c
+++ b/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);
-
- /* Tell cpplib we want CPP_PRAGMA tokens. */
- cpp_get_options (parse_in)->defer_pragmas = true;
+ /* 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 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;
- break;
- }
+ case CPP_EOF:
+ case CPP_PRAGMA_EOL:
+ /* If we've run out of tokens, then there is no closing `)'. */
+ return 0;
- token = cp_lexer_peek_token (parser->lexer);
+ case CPP_SEMICOLON:
+ /* This matches the processing in skip_to_end_of_statement. */
+ if (!brace_depth)
+ return 0;
+ break;
- /* 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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1e33d4c..07b9a0d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/parse/pragma2.C b/gcc/testsuite/g++.dg/parse/pragma2.C
index 9cab9d8..c5616ff 100644
--- a/gcc/testsuite/g++.dg/parse/pragma2.C
+++ b/gcc/testsuite/g++.dg/parse/pragma2.C
@@ -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 *-*-* } }
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index b2f0c9a..ad66535 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -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).
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 2de65fb..0eea67d 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -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,101 +1275,46 @@ 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)
+ {
+ 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
{
- /* Since the handler below doesn't get the line number, that it
- might need for diagnostics, make sure it has the right
+ /* 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)
+ if (p->allow_expansion)
pfile->state.prevent_expansion--;
(*p->u.handler) (pfile);
- if (p->allow_expansion && !pfile->state.in_deferred_pragma)
+ 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;
- }
}
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;
-
- 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;
- }
+ saved_context = pfile->context;
+ saved_cur_token = pfile->cur_token;
+ saved_cur_run = pfile->cur_run;
- /* See above comment. For the moment, we'd like
+ pfile->context = XNEW (cpp_context);
+ pfile->context->macro = 0;
+ pfile->context->prev = 0;
- token1 _Pragma ("foo") token2
+ /* 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;
- to be output as
+ start_directive (pfile);
+ _cpp_clean_line (pfile);
+ do_pragma (pfile);
+ end_directive (pfile, 1);
- token1
- # 7 "file.c"
- #pragma foo
- # 7 "file.c"
- token2
+ /* 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. */
+
+ /* 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;
+
+ count = 1;
+ maxcount = 50;
+ toks = XNEWVEC (cpp_token, maxcount);
+ toks[0] = pfile->directive_result;
- Getting the line markers is a little tricky. */
- if (pfile->cb.line_change)
- pfile->cb.line_change (pfile, pfile->cur_token, false);
+ 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)
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 0ab6635..f1b5eab 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -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 *);
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 4aa6dcc..8ac1103 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -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 *);
diff --git a/libcpp/lex.c b/libcpp/lex.c
index 0313161..cae9b03 100644
--- a/libcpp/lex.c
+++ b/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;
diff --git a/libcpp/macro.c b/libcpp/macro.c
index a0aa93e..2f1a974 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -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);