aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorGiovanni Bajo <giovannibajo@gcc.gnu.org>2004-01-29 04:23:37 +0000
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>2004-01-29 04:23:37 +0000
commitf4abade9fe297572fefc4484ac5f0c723c0c29df (patch)
tree93c7e64317cfb596c406d2a37ca8a432c8bd2d10 /gcc
parent7625e73d5799718ee9cda40a17896a3335e76d6f (diff)
downloadgcc-f4abade9fe297572fefc4484ac5f0c723c0c29df.zip
gcc-f4abade9fe297572fefc4484ac5f0c723c0c29df.tar.gz
gcc-f4abade9fe297572fefc4484ac5f0c723c0c29df.tar.bz2
parser.c (cp_parser_template_id): Parse tentatively `[:' after a template name as it was `<::' (digraph typo).
* parser.c (cp_parser_template_id): Parse tentatively `[:' after a template name as it was `<::' (digraph typo). (cp_parser_nth_token_starts_template_argument_list_p): New function. (cp_parser_id_expression): Use it. (cp_parser_nested_name_specifier_opt): Likewise. (cp_parser_template_name): Likewise. (cp_parser_class_name): Likewise. (cp_lexer_get_preprocessor_token): Use c_lex_with_flags. From-SVN: r76845
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/parser.c106
2 files changed, 103 insertions, 14 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 873a79f..6ce445c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2004-01-28 Giovanni Bajo <giovannibajo@gcc.gnu.org>
+
+ * parser.c (cp_parser_template_id): Parse tentatively `[:' after a
+ template name as it was `<::' (digraph typo).
+ (cp_parser_nth_token_starts_template_argument_list_p): New function.
+ (cp_parser_id_expression): Use it.
+ (cp_parser_nested_name_specifier_opt): Likewise.
+ (cp_parser_template_name): Likewise.
+ (cp_parser_class_name): Likewise.
+ (cp_lexer_get_preprocessor_token): Use c_lex_with_flags.
+
2004-01-28 Mark Mitchell <mark@codesourcery.com>
PR c++/13791
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7c9be85..4964819 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -72,6 +72,8 @@ typedef struct cp_token GTY (())
/* If this token is a keyword, this value indicates which keyword.
Otherwise, this value is RID_MAX. */
ENUM_BITFIELD (rid) keyword : 8;
+ /* Token flags. */
+ unsigned char flags;
/* The value associated with this token, if any. */
tree value;
/* The location at which this token was found. */
@@ -597,7 +599,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
while (!done)
{
/* Get a new token from the preprocessor. */
- token->type = c_lex (&token->value);
+ token->type = c_lex_with_flags (&token->value, &token->flags);
/* Issue messages about tokens we cannot process. */
switch (token->type)
{
@@ -1681,6 +1683,8 @@ static bool cp_parser_next_token_starts_class_definition_p
(cp_parser *);
static bool cp_parser_next_token_ends_template_argument_p
(cp_parser *);
+static bool cp_parser_nth_token_starts_template_argument_list_p
+ (cp_parser *, size_t);
static enum tag_types cp_parser_token_is_class_key
(cp_token *);
static void cp_parser_check_class_key
@@ -2741,7 +2745,8 @@ cp_parser_id_expression (cp_parser *parser,
we can avoid the template-id case. This is an optimization
for this common case. */
if (token->type == CPP_NAME
- && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
+ && !cp_parser_nth_token_starts_template_argument_list_p
+ (parser, 2))
return cp_parser_identifier (parser);
cp_parser_parse_tentatively (parser);
@@ -3113,7 +3118,9 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
template-id), nor a `::', then we are not looking at a
nested-name-specifier. */
token = cp_lexer_peek_nth_token (parser->lexer, 2);
- if (token->type != CPP_LESS && token->type != CPP_SCOPE)
+ if (token->type != CPP_SCOPE
+ && !cp_parser_nth_token_starts_template_argument_list_p
+ (parser, 2))
break;
}
@@ -7769,7 +7776,7 @@ cp_parser_template_id (cp_parser *parser,
tree template_id;
ptrdiff_t start_of_id;
tree access_check = NULL_TREE;
- cp_token *next_token;
+ cp_token *next_token, *next_token_2;
bool is_identifier;
/* If the next token corresponds to a template-id, there is no need
@@ -7794,7 +7801,8 @@ cp_parser_template_id (cp_parser *parser,
finding a template-id. */
if ((next_token->type != CPP_NAME && next_token->keyword != RID_OPERATOR)
|| (next_token->type == CPP_NAME
- && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS))
+ && !cp_parser_nth_token_starts_template_argument_list_p
+ (parser, 2)))
{
cp_parser_error (parser, "expected template-id");
return error_mark_node;
@@ -7826,15 +7834,60 @@ cp_parser_template_id (cp_parser *parser,
return template;
}
- /* Look for the `<' that starts the template-argument-list. */
- if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+ /* If we find the sequence `[:' after a template-name, it's probably
+ a digraph-typo for `< ::'. Substitute the tokens and check if we can
+ parse correctly the argument list. */
+ next_token = cp_lexer_peek_nth_token (parser->lexer, 1);
+ next_token_2 = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (next_token->type == CPP_OPEN_SQUARE
+ && next_token->flags & DIGRAPH
+ && next_token_2->type == CPP_COLON
+ && !(next_token_2->flags & PREV_WHITE))
{
- pop_deferring_access_checks ();
- return error_mark_node;
+ cp_parser_parse_tentatively (parser);
+ /* Change `:' into `::'. */
+ next_token_2->type = CPP_SCOPE;
+ /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
+ CPP_LESS. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the arguments. */
+ arguments = cp_parser_enclosed_template_argument_list (parser);
+ if (!cp_parser_parse_definitely (parser))
+ {
+ /* If we couldn't parse an argument list, then we revert our changes
+ and return simply an error. Maybe this is not a template-id
+ after all. */
+ next_token_2->type = CPP_COLON;
+ cp_parser_error (parser, "expected `<'");
+ pop_deferring_access_checks ();
+ return error_mark_node;
+ }
+ /* Otherwise, emit an error about the invalid digraph, but continue
+ parsing because we got our argument list. */
+ pedwarn ("`<::' cannot begin a template-argument list");
+ inform ("`<:' is an alternate spelling for `['. Insert whitespace "
+ "between `<' and `::'");
+ if (!flag_permissive)
+ {
+ static bool hint;
+ if (!hint)
+ {
+ inform ("(if you use `-fpermissive' G++ will accept your code)");
+ hint = true;
+ }
+ }
+ }
+ else
+ {
+ /* Look for the `<' that starts the template-argument-list. */
+ if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+ {
+ pop_deferring_access_checks ();
+ return error_mark_node;
+ }
+ /* Parse the arguments. */
+ arguments = cp_parser_enclosed_template_argument_list (parser);
}
-
- /* Parse the arguments. */
- arguments = cp_parser_enclosed_template_argument_list (parser);
/* Build a representation of the specialization. */
if (TREE_CODE (template) == IDENTIFIER_NODE)
@@ -7974,7 +8027,7 @@ cp_parser_template_name (cp_parser* parser,
-- but we do not if there is no `<'. */
if (processing_template_decl
- && cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+ && cp_parser_nth_token_starts_template_argument_list_p (parser, 1))
{
/* In a declaration, in a dependent context, we pretend that the
"template" keyword was present in order to improve error
@@ -11496,7 +11549,7 @@ cp_parser_class_name (cp_parser *parser,
/* Handle the common case (an identifier, but not a template-id)
efficiently. */
if (token->type == CPP_NAME
- && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
+ && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
{
tree identifier;
@@ -14847,6 +14900,31 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
return (token->type == CPP_COMMA || token->type == CPP_GREATER
|| token->type == CPP_RSHIFT);
}
+
+/* Returns TRUE iff the n-th token is a ">", or the n-th is a "[" and the
+ (n+1)-th is a ":" (which is a possible digraph typo for "< ::"). */
+
+static bool
+cp_parser_nth_token_starts_template_argument_list_p (cp_parser * parser,
+ size_t n)
+{
+ cp_token *token;
+
+ token = cp_lexer_peek_nth_token (parser->lexer, n);
+ if (token->type == CPP_LESS)
+ return true;
+ /* Check for the sequence `<::' in the original code. It would be lexed as
+ `[:', where `[' is a digraph, and there is no whitespace before
+ `:'. */
+ if (token->type == CPP_OPEN_SQUARE && token->flags & DIGRAPH)
+ {
+ cp_token *token2;
+ token2 = cp_lexer_peek_nth_token (parser->lexer, n+1);
+ if (token2->type == CPP_COLON && !(token2->flags & PREV_WHITE))
+ return true;
+ }
+ return false;
+}
/* Returns the kind of tag indicated by TOKEN, if it is a class-key,
or none_type otherwise. */