summaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authoraustern <austern@138bc75d-0d04-0410-961f-82ee72b054a4>2004-09-27 22:24:35 +0000
committeraustern <austern@138bc75d-0d04-0410-961f-82ee72b054a4>2004-09-27 22:24:35 +0000
commit2e1f41a9715c471f4681d98cac6cc8f76ac0a1a3 (patch)
treeeaabda6d357ad0b18ff320a27dd73bc59f30f80b /gcc/cp/parser.c
parent0ff89ae1c734efa3ef15396372ce4d97dd50cc01 (diff)
downloadgcc-2e1f41a9715c471f4681d98cac6cc8f76ac0a1a3.tar.gz
Fix implicit extern "C" breakage introduced by tokenization patch.
* cp/parser.c (struct cp_token): new one-bit field , implicit_extern_c (cp_lexer_get_preprocessor_token): Set implicit_extern_c for tokens that come from headers that are implicitly extern "C". (struct cp_parser): new one-bit field, implicit_extern_c. (cp_parser_new): Set parser's implicit_extern_c to false. (cp_parser_translation_unit): Pop lang context if we were in a header that was implicitly extern "C". (cp_parser_declaration_seq_opt): Push/pop lang context as required by the token's and parser's implicit_extern_c. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@88203 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 89a96014d49..184ae5434e4 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -55,6 +55,8 @@ typedef struct cp_token GTY (())
unsigned char flags;
/* 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" */
+ BOOL_BITFIELD implicit_extern_c : 1;
/* The value associated with this token, if any. */
tree value;
/* The location at which this token was found. */
@@ -418,6 +420,7 @@ static void
cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
cp_token *token)
{
+ static int is_extern_c = 0;
bool done;
done = false;
@@ -445,6 +448,13 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
token->location = input_location;
token->in_system_header = in_system_header;
+ /* On some systems, some header files are surrounded by an
+ implicit extern "C" block. Set a flag in the token if it
+ comes from such a header. */
+ is_extern_c += pending_lang_change;
+ pending_lang_change = 0;
+ token->implicit_extern_c = is_extern_c > 0;
+
/* Check to see if this token is a keyword. */
if (token->type == CPP_NAME
&& C_IS_RESERVED_WORD (token->value))
@@ -1317,6 +1327,10 @@ typedef struct cp_parser GTY(())
alternatives. */
bool in_type_id_in_expr_p;
+ /* TRUE if we are currently in a header file where declarations are
+ implicitly extern "C". */
+ bool implicit_extern_c;
+
/* TRUE if strings in expressions should be translated to the execution
character set. */
bool translate_strings_p;
@@ -2425,6 +2439,9 @@ cp_parser_new (void)
/* We are not parsing a type-id inside an expression. */
parser->in_type_id_in_expr_p = false;
+ /* Declarations aren't implicitly extern "C". */
+ parser->implicit_extern_c = false;
+
/* String literals should be translated to the execution character set. */
parser->translate_strings_p = true;
@@ -2625,6 +2642,14 @@ cp_parser_translation_unit (cp_parser* parser)
cp_lexer_destroy (parser->lexer);
parser->lexer = NULL;
+ /* This file might have been a context that's implicitly extern
+ "C". If so, pop the lang context. (Only relevant for PCH.) */
+ if (parser->implicit_extern_c)
+ {
+ pop_lang_context ();
+ parser->implicit_extern_c = false;
+ }
+
/* Finish up. */
finish_translation_unit ();
@@ -6634,6 +6659,19 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
continue;
}
+ /* If we're entering or exiting a region that's implicitly
+ extern "C", modify the lang context appropriately. */
+ if (!parser->implicit_extern_c && token->implicit_extern_c)
+ {
+ push_lang_context (lang_name_c);
+ parser->implicit_extern_c = true;
+ }
+ else if (parser->implicit_extern_c && !token->implicit_extern_c)
+ {
+ pop_lang_context ();
+ parser->implicit_extern_c = false;
+ }
+
if (token->type == CPP_PRAGMA)
{
/* A top-level declaration can consist solely of a #pragma.
@@ -6644,19 +6682,6 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
continue;
}
- /* The C lexer modifies PENDING_LANG_CHANGE when it wants the
- parser to enter or exit implicit `extern "C"' blocks. */
- while (pending_lang_change > 0)
- {
- push_lang_context (lang_name_c);
- --pending_lang_change;
- }
- while (pending_lang_change < 0)
- {
- pop_lang_context ();
- ++pending_lang_change;
- }
-
/* Parse the declaration itself. */
cp_parser_declaration (parser);
}