aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-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
14 files changed, 710 insertions, 250 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 *-*-* } }