aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c192
1 files changed, 125 insertions, 67 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bbbc55ce250..620ec00246d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1,5 +1,6 @@
/* C++ Parser.
- Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004,
+ 2005 Free Software Foundation, Inc.
Written by Mark Mitchell <mark@codesourcery.com>.
This file is part of GCC.
@@ -2850,6 +2851,7 @@ cp_parser_unqualified_id (cp_parser* parser,
tree qualifying_scope;
tree object_scope;
tree scope;
+ bool done;
/* Consume the `~' token. */
cp_lexer_consume_token (parser->lexer);
@@ -2906,6 +2908,8 @@ cp_parser_unqualified_id (cp_parser* parser,
/* If there was an explicit qualification (S::~T), first look
in the scope given by the qualification (i.e., S). */
+ done = false;
+ type_decl = NULL_TREE;
if (scope)
{
cp_parser_parse_tentatively (parser);
@@ -2917,10 +2921,10 @@ cp_parser_unqualified_id (cp_parser* parser,
/*class_head_p=*/false,
declarator_p);
if (cp_parser_parse_definitely (parser))
- return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+ done = true;
}
/* In "N::S::~S", look in "N" as well. */
- if (scope && qualifying_scope)
+ if (!done && scope && qualifying_scope)
{
cp_parser_parse_tentatively (parser);
parser->scope = qualifying_scope;
@@ -2935,10 +2939,10 @@ cp_parser_unqualified_id (cp_parser* parser,
/*class_head_p=*/false,
declarator_p);
if (cp_parser_parse_definitely (parser))
- return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+ done = true;
}
/* In "p->S::~T", look in the scope given by "*p" as well. */
- else if (object_scope)
+ else if (!done && object_scope)
{
cp_parser_parse_tentatively (parser);
parser->scope = object_scope;
@@ -2953,20 +2957,23 @@ cp_parser_unqualified_id (cp_parser* parser,
/*class_head_p=*/false,
declarator_p);
if (cp_parser_parse_definitely (parser))
- return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+ done = true;
}
/* Look in the surrounding context. */
- parser->scope = NULL_TREE;
- parser->object_scope = NULL_TREE;
- parser->qualifying_scope = NULL_TREE;
- type_decl
- = cp_parser_class_name (parser,
- /*typename_keyword_p=*/false,
- /*template_keyword_p=*/false,
- /*type_p=*/false,
- /*check_dependency=*/false,
- /*class_head_p=*/false,
- declarator_p);
+ if (!done)
+ {
+ parser->scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
+ type_decl
+ = cp_parser_class_name (parser,
+ /*typename_keyword_p=*/false,
+ /*template_keyword_p=*/false,
+ /*type_p=*/false,
+ /*check_dependency=*/false,
+ /*class_head_p=*/false,
+ declarator_p);
+ }
/* If an error occurred, assume that the name of the
destructor is the same as the name of the qualifying
class. That allows us to keep parsing after running
@@ -3544,18 +3551,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
bool template_p = false;
tree id;
tree type;
+ tree scope;
/* Consume the `typename' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false);
- /* Look for the nested-name-specifier. */
- cp_parser_nested_name_specifier (parser,
- /*typename_keyword_p=*/true,
- /*check_dependency_p=*/true,
- /*type_p=*/true,
- /*is_declaration=*/true);
+ /* Look for the nested-name-specifier. In case of error here,
+ consume the trailing id to avoid subsequent error messages
+ for usual cases. */
+ scope = cp_parser_nested_name_specifier (parser,
+ /*typename_keyword_p=*/true,
+ /*check_dependency_p=*/true,
+ /*type_p=*/true,
+ /*is_declaration=*/true);
+
/* Look for the optional `template' keyword. */
template_p = cp_parser_optional_template_keyword (parser);
/* We don't know whether we're looking at a template-id or an
@@ -3568,9 +3579,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* If that didn't work, try an identifier. */
if (!cp_parser_parse_definitely (parser))
id = cp_parser_identifier (parser);
+
+ /* Don't process id if nested name specifier is invalid. */
+ if (scope == error_mark_node)
+ return error_mark_node;
/* If we look up a template-id in a non-dependent qualifying
scope, there's no need to create a dependent type. */
- if (TREE_CODE (id) == TYPE_DECL
+ else if (TREE_CODE (id) == TYPE_DECL
&& !dependent_type_p (parser->scope))
type = TREE_TYPE (id);
/* Create a TYPENAME_TYPE to represent the type to which the
@@ -8035,6 +8050,13 @@ cp_parser_template_id (cp_parser *parser,
token->keyword = RID_MAX;
/* Purge all subsequent tokens. */
cp_lexer_purge_tokens_after (parser->lexer, token);
+
+ /* ??? Can we actually assume that, if template_id ==
+ error_mark_node, we will have issued a diagnostic to the
+ user, as opposed to simply marking the tentative parse as
+ failed? */
+ if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
+ error ("parse error in template argument list");
}
pop_deferring_access_checks ();
@@ -8214,6 +8236,8 @@ cp_parser_template_name (cp_parser* parser,
;
else
{
+ tree fn = NULL_TREE;
+
/* The standard does not explicitly indicate whether a name that
names a set of overloaded declarations, some of which are
templates, is a template-name. However, such a name should
@@ -8221,14 +8245,11 @@ cp_parser_template_name (cp_parser* parser,
template-id for the overloaded templates. */
fns = BASELINK_P (decl) ? BASELINK_FUNCTIONS (decl) : decl;
if (TREE_CODE (fns) == OVERLOAD)
- {
- tree fn;
-
- for (fn = fns; fn; fn = OVL_NEXT (fn))
- if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
- break;
- }
- else
+ for (fn = fns; fn; fn = OVL_NEXT (fn))
+ if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
+ break;
+
+ if (!fn)
{
/* Otherwise, the name does not name a template. */
cp_parser_error (parser, "expected template-name");
@@ -8729,21 +8750,40 @@ cp_parser_type_specifier (cp_parser* parser,
keyword = token->keyword;
switch (keyword)
{
+ case RID_ENUM:
+ /* 'enum' [identifier] '{' introduces an enum-specifier;
+ 'enum' <anything else> introduces an elaborated-type-specifier. */
+ if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_BRACE
+ || (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type
+ == CPP_OPEN_BRACE))
+ {
+ if (parser->num_template_parameter_lists)
+ {
+ error ("template declaration of `enum'");
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ type_spec = error_mark_node;
+ }
+ else
+ type_spec = cp_parser_enum_specifier (parser);
+
+ if (declares_class_or_enum)
+ *declares_class_or_enum = 2;
+ return type_spec;
+ }
+ else
+ goto elaborated_type_specifier;
+
/* Any of these indicate either a class-specifier, or an
elaborated-type-specifier. */
case RID_CLASS:
case RID_STRUCT:
case RID_UNION:
- case RID_ENUM:
/* Parse tentatively so that we can back up if we don't find a
class-specifier or enum-specifier. */
cp_parser_parse_tentatively (parser);
- /* Look for the class-specifier or enum-specifier. */
- if (keyword == RID_ENUM)
- type_spec = cp_parser_enum_specifier (parser);
- else
- type_spec = cp_parser_class_specifier (parser);
-
+ /* Look for the class-specifier. */
+ type_spec = cp_parser_class_specifier (parser);
/* If that worked, we're done. */
if (cp_parser_parse_definitely (parser))
{
@@ -8755,6 +8795,7 @@ cp_parser_type_specifier (cp_parser* parser,
/* Fall through. */
case RID_TYPENAME:
+ elaborated_type_specifier:
/* Look for an elaborated-type-specifier. */
type_spec = cp_parser_elaborated_type_specifier (parser,
is_friend,
@@ -11526,6 +11567,9 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
{
tree initializer = NULL_TREE;
+ /* Assume the expression is constant. */
+ *non_constant_p = false;
+
/* If it is not a `{', then we are looking at an
assignment-expression. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
@@ -12159,6 +12203,15 @@ cp_parser_class_head (cp_parser* parser,
else if (nested_name_specifier)
{
tree scope;
+
+ /* Reject typedef-names in class heads. */
+ if (!DECL_IMPLICIT_TYPEDEF_P (type))
+ {
+ error ("invalid class name in declaration of `%D'", type);
+ type = NULL_TREE;
+ goto done;
+ }
+
/* Figure out in what scope the declaration is being placed. */
scope = current_scope ();
if (!scope)
@@ -13499,36 +13552,39 @@ cp_parser_attribute_list (cp_parser* parser)
/* Look for the identifier. We also allow keywords here; for
example `__attribute__ ((const))' is legal. */
token = cp_lexer_peek_token (parser->lexer);
- if (token->type != CPP_NAME
- && token->type != CPP_KEYWORD)
- return error_mark_node;
- /* Consume the token. */
- token = cp_lexer_consume_token (parser->lexer);
-
- /* Save away the identifier that indicates which attribute this is. */
- identifier = token->value;
- attribute = build_tree_list (identifier, NULL_TREE);
-
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If it's an `(', then parse the attribute arguments. */
- if (token->type == CPP_OPEN_PAREN)
+ if (token->type == CPP_NAME
+ || token->type == CPP_KEYWORD)
{
- tree arguments;
+ /* Consume the token. */
+ token = cp_lexer_consume_token (parser->lexer);
- arguments = (cp_parser_parenthesized_expression_list
- (parser, true, /*non_constant_p=*/NULL));
- /* Save the identifier and arguments away. */
- TREE_VALUE (attribute) = arguments;
- }
+ /* Save away the identifier that indicates which attribute
+ this is. */
+ identifier = token->value;
+ attribute = build_tree_list (identifier, NULL_TREE);
- /* Add this attribute to the list. */
- TREE_CHAIN (attribute) = attribute_list;
- attribute_list = attribute;
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ /* If it's an `(', then parse the attribute arguments. */
+ if (token->type == CPP_OPEN_PAREN)
+ {
+ tree arguments;
- /* Now, look for more attributes. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If the next token isn't a `,', we're done. */
+ arguments = (cp_parser_parenthesized_expression_list
+ (parser, true, /*non_constant_p=*/NULL));
+ /* Save the identifier and arguments away. */
+ TREE_VALUE (attribute) = arguments;
+ }
+
+ /* Add this attribute to the list. */
+ TREE_CHAIN (attribute) = attribute_list;
+ attribute_list = attribute;
+
+ /* Now, look for more attributes. */
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+ /* Now, look for more attributes. If the next token isn't a
+ `,', we're done. */
if (token->type != CPP_COMMA)
break;
@@ -14818,10 +14874,12 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
/* Parse the assignment-expression. */
- if (DECL_CLASS_SCOPE_P (fn))
+ if (DECL_FRIEND_CONTEXT (fn))
+ push_nested_class (DECL_FRIEND_CONTEXT (fn));
+ else if (DECL_CLASS_SCOPE_P (fn))
push_nested_class (DECL_CONTEXT (fn));
TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
- if (DECL_CLASS_SCOPE_P (fn))
+ if (DECL_FRIEND_CONTEXT (fn) || DECL_CLASS_SCOPE_P (fn))
pop_nested_class ();
/* If the token stream has not been completely used up, then