summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/parser.c')
-rw-r--r--contrib/gcc/cp/parser.c288
1 files changed, 176 insertions, 112 deletions
diff --git a/contrib/gcc/cp/parser.c b/contrib/gcc/cp/parser.c
index fb0d1e3..032cbd7 100644
--- a/contrib/gcc/cp/parser.c
+++ b/contrib/gcc/cp/parser.c
@@ -1672,6 +1672,8 @@ static bool cp_parser_declares_only_class_p
(cp_parser *);
static bool cp_parser_friend_p
(tree);
+static bool cp_parser_typedef_p
+ (tree);
static cp_token *cp_parser_require
(cp_parser *, enum cpp_ttype, const char *);
static cp_token *cp_parser_require_keyword
@@ -1717,7 +1719,7 @@ static bool cp_parser_simulate_error
static void cp_parser_check_type_definition
(cp_parser *);
static void cp_parser_check_for_definition_in_return_type
- (tree, int);
+ (tree, tree);
static void cp_parser_check_for_invalid_template_id
(cp_parser *, tree);
static bool cp_parser_non_integral_constant_expression
@@ -1849,14 +1851,13 @@ cp_parser_check_type_definition (cp_parser* parser)
error ("%s", parser->type_definition_forbidden_message);
}
-/* This function is called when a declaration is parsed. If
- DECLARATOR is a function declarator and DECLARES_CLASS_OR_ENUM
- indicates that a type was defined in the decl-specifiers for DECL,
- then an error is issued. */
+/* This function is called when the DECLARATOR is processed. The TYPE
+ was a type defined in the decl-specifiers. If it is invalid to
+ define a type in the decl-specifiers for DECLARATOR, an error is
+ issued. */
static void
-cp_parser_check_for_definition_in_return_type (tree declarator,
- int declares_class_or_enum)
+cp_parser_check_for_definition_in_return_type (tree declarator, tree type)
{
/* [dcl.fct] forbids type definitions in return types.
Unfortunately, it's not easy to know whether or not we are
@@ -1866,9 +1867,12 @@ cp_parser_check_for_definition_in_return_type (tree declarator,
|| TREE_CODE (declarator) == ADDR_EXPR))
declarator = TREE_OPERAND (declarator, 0);
if (declarator
- && TREE_CODE (declarator) == CALL_EXPR
- && declares_class_or_enum & 2)
- error ("new types may not be defined in a return type");
+ && TREE_CODE (declarator) == CALL_EXPR)
+ {
+ error ("new types may not be defined in a return type");
+ inform ("(perhaps a semicolon is missing after the definition of `%T')",
+ type);
+ }
}
/* A type-specifier (TYPE) has been parsed which cannot be followed by
@@ -3548,52 +3552,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
case RID_TYPENAME:
{
- 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. 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
- identifier. */
- cp_parser_parse_tentatively (parser);
- /* Try a template-id. */
- id = cp_parser_template_id (parser, template_p,
- /*check_dependency_p=*/true,
- /*is_declaration=*/true);
- /* 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. */
- 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
- functional cast is being performed. */
- else
- type = make_typename_type (parser->scope, id,
- /*complain=*/1);
+ /* The syntax permitted here is the same permitted for an
+ elaborated-type-specifier. */
+ type = cp_parser_elaborated_type_specifier (parser,
+ /*is_friend=*/false,
+ /*is_declaration=*/false);
postfix_expression = cp_parser_functional_cast (parser, type);
}
break;
@@ -3964,20 +3929,29 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
if (parser->scope)
idk = CP_ID_KIND_QUALIFIED;
- if (name != error_mark_node
- && !BASELINK_P (name)
- && parser->scope)
+ /* If the name is a template-id that names a type, we will
+ get a TYPE_DECL here. That is invalid code. */
+ if (TREE_CODE (name) == TYPE_DECL)
{
- name = build_nt (SCOPE_REF, parser->scope, name);
- parser->scope = NULL_TREE;
- parser->qualifying_scope = NULL_TREE;
- parser->object_scope = NULL_TREE;
+ error ("invalid use of `%D'", name);
+ postfix_expression = error_mark_node;
+ }
+ else
+ {
+ if (name != error_mark_node && !BASELINK_P (name)
+ && parser->scope)
+ {
+ name = build_nt (SCOPE_REF, parser->scope, name);
+ parser->scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ }
+ if (scope && name && BASELINK_P (name))
+ adjust_result_of_qualified_name_lookup
+ (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
+ postfix_expression = finish_class_member_access_expr
+ (postfix_expression, name);
}
- if (scope && name && BASELINK_P (name))
- adjust_result_of_qualified_name_lookup
- (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
- postfix_expression
- = finish_class_member_access_expr (postfix_expression, name);
}
/* We no longer need to look up names in the scope of the
@@ -6523,6 +6497,13 @@ cp_parser_simple_declaration (cp_parser* parser,
/* Give up. */
goto done;
}
+
+ /* If we have seen at least one decl-specifier, and the next token
+ is not a parenthesis, then we must be looking at a declaration.
+ (After "int (" we might be looking at a functional cast.) */
+ if (decl_specifiers
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
+ cp_parser_commit_to_tentative_parse (parser);
/* Keep going until we hit the `;' at the end of the simple
declaration. */
@@ -6576,7 +6557,12 @@ cp_parser_simple_declaration (cp_parser* parser,
/* Anything else is an error. */
else
{
- cp_parser_error (parser, "expected `,' or `;'");
+ /* If we have already issued an error message we don't need
+ to issue another one. */
+ if (decl != error_mark_node
+ || (cp_parser_parsing_tentatively (parser)
+ && !cp_parser_committed_to_tentative_parse (parser)))
+ cp_parser_error (parser, "expected `,' or `;'");
/* Skip tokens until we reach the end of the statement. */
cp_parser_skip_to_end_of_statement (parser);
/* If the next token is now a `;', consume it. */
@@ -7802,9 +7788,15 @@ cp_parser_type_parameter (cp_parser* parser)
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
&& cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER)
&& cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
- identifier = cp_parser_identifier (parser);
+ {
+ identifier = cp_parser_identifier (parser);
+ /* Treat invalid names as if the parameter were nameless. */
+ if (identifier == error_mark_node)
+ identifier = NULL_TREE;
+ }
else
identifier = NULL_TREE;
+
/* Create the template parameter. */
parameter = finish_template_template_parm (class_type_node,
identifier);
@@ -7846,15 +7838,13 @@ cp_parser_type_parameter (cp_parser* parser)
/* Create the combined representation of the parameter and the
default argument. */
- parameter = build_tree_list (default_argument, parameter);
+ parameter = build_tree_list (default_argument, parameter);
}
break;
default:
- /* Anything else is an error. */
- cp_parser_error (parser,
- "expected `class', `typename', or `template'");
- parameter = error_mark_node;
+ abort ();
+ break;
}
return parameter;
@@ -8610,8 +8600,9 @@ cp_parser_explicit_instantiation (cp_parser* parser)
/*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false);
- cp_parser_check_for_definition_in_return_type (declarator,
- declares_class_or_enum);
+ if (declares_class_or_enum & 2)
+ cp_parser_check_for_definition_in_return_type
+ (declarator, TREE_VALUE (decl_specifiers));
if (declarator != error_mark_node)
{
decl = grokdeclarator (declarator, decl_specifiers,
@@ -9218,7 +9209,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
}
/* For a `typename', we needn't call xref_tag. */
- if (tag_type == typename_type)
+ if (tag_type == typename_type
+ && TREE_CODE (parser->scope) != NAMESPACE_DECL)
return make_typename_type (parser->scope, identifier,
/*complain=*/1);
/* Look up a qualified name in the usual way. */
@@ -9262,7 +9254,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
if (TREE_CODE (decl) != TYPE_DECL)
{
- error ("expected type-name");
+ cp_parser_diagnose_invalid_type_name (parser);
return error_mark_node;
}
@@ -9514,6 +9506,9 @@ cp_parser_namespace_name (cp_parser* parser)
if (namespace_decl == error_mark_node
|| TREE_CODE (namespace_decl) != NAMESPACE_DECL)
{
+ if (!cp_parser_parsing_tentatively (parser)
+ || cp_parser_committed_to_tentative_parse (parser))
+ error ("`%D' is not a namespace-name", identifier);
cp_parser_error (parser, "expected namespace-name");
namespace_decl = error_mark_node;
}
@@ -9982,8 +9977,9 @@ cp_parser_init_declarator (cp_parser* parser,
if (declarator == error_mark_node)
return error_mark_node;
- cp_parser_check_for_definition_in_return_type (declarator,
- declares_class_or_enum);
+ if (declares_class_or_enum & 2)
+ cp_parser_check_for_definition_in_return_type
+ (declarator, TREE_VALUE (decl_specifiers));
/* Figure out what scope the entity declared by the DECLARATOR is
located in. `grokdeclarator' sometimes changes the scope, so
@@ -10069,7 +10065,7 @@ cp_parser_init_declarator (cp_parser* parser,
&& token->type != CPP_COMMA
&& token->type != CPP_SEMICOLON)
{
- cp_parser_error (parser, "expected init-declarator");
+ cp_parser_error (parser, "expected initializer");
return error_mark_node;
}
@@ -10909,7 +10905,7 @@ cp_parser_declarator_id (cp_parser* parser)
/*declarator_p=*/true);
/* If the name was qualified, create a SCOPE_REF to represent
that. */
- if (parser->scope)
+ if (parser->scope && id_expression != error_mark_node)
{
id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
parser->scope = NULL_TREE;
@@ -12483,8 +12479,13 @@ cp_parser_member_declaration (cp_parser* parser)
/* Check for a template-declaration. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
{
- /* Parse the template-declaration. */
- cp_parser_template_declaration (parser, /*member_p=*/true);
+ /* An explicit specialization here is an error condition, and we
+ expect the specialization handler to detect and report this. */
+ if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_LESS
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_GREATER)
+ cp_parser_explicit_specialization (parser);
+ else
+ cp_parser_template_declaration (parser, /*member_p=*/true);
return;
}
@@ -12685,8 +12686,9 @@ cp_parser_member_declaration (cp_parser* parser)
return;
}
- cp_parser_check_for_definition_in_return_type
- (declarator, declares_class_or_enum);
+ if (declares_class_or_enum & 2)
+ cp_parser_check_for_definition_in_return_type
+ (declarator, TREE_VALUE (decl_specifiers));
/* Look for an asm-specification. */
asm_specification = cp_parser_asm_specification_opt (parser);
@@ -13639,7 +13641,10 @@ cp_parser_label_declaration (cp_parser* parser)
/* Look for an identifier. */
identifier = cp_parser_identifier (parser);
- /* Declare it as a lobel. */
+ /* If we failed, stop. */
+ if (identifier == error_mark_node)
+ break;
+ /* Declare it as a label. */
finish_label_decl (identifier);
/* If the next token is a `;', stop. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -13689,6 +13694,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
bool is_type, bool is_template, bool is_namespace,
bool check_dependency)
{
+ int flags = 0;
tree decl;
tree object_type = parser->context->object_type;
@@ -13700,6 +13706,10 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
if (name == error_mark_node)
return error_mark_node;
+ if (!cp_parser_parsing_tentatively (parser)
+ || cp_parser_committed_to_tentative_parse (parser))
+ flags |= LOOKUP_COMPLAIN;
+
/* A template-id has already been resolved; there is no lookup to
do. */
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
@@ -13813,8 +13823,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
/*protect=*/0, is_type);
/* Look it up in the enclosing context, too. */
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
- is_namespace,
- /*flags=*/0);
+ is_namespace, flags);
parser->object_scope = object_type;
parser->qualifying_scope = NULL_TREE;
if (object_decl)
@@ -13823,8 +13832,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
else
{
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
- is_namespace,
- /*flags=*/0);
+ is_namespace, flags);
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
}
@@ -14508,6 +14516,12 @@ cp_parser_single_declaration (cp_parser* parser,
tree attributes;
bool function_definition_p = false;
+ /* This function is only used when processing a template
+ declaration. */
+ if (innermost_scope_kind () != sk_template_parms
+ && innermost_scope_kind () != sk_template_spec)
+ abort ();
+
/* Defer access checks until we know what is being declared. */
push_deferring_access_checks (dk_deferred);
@@ -14520,6 +14534,14 @@ cp_parser_single_declaration (cp_parser* parser,
&declares_class_or_enum);
if (friend_p)
*friend_p = cp_parser_friend_p (decl_specifiers);
+
+ /* There are no template typedefs. */
+ if (cp_parser_typedef_p (decl_specifiers))
+ {
+ error ("template declaration of `typedef'");
+ decl = error_mark_node;
+ }
+
/* Gather up the access checks that occurred the
decl-specifier-seq. */
stop_deferring_access_checks ();
@@ -14536,8 +14558,6 @@ cp_parser_single_declaration (cp_parser* parser,
decl = error_mark_node;
}
}
- else
- decl = NULL_TREE;
/* If it's not a template class, try for a template function. If
the next token is a `;', then this declaration does not declare
anything. But, if there were errors in the decl-specifiers, then
@@ -14563,7 +14583,8 @@ cp_parser_single_declaration (cp_parser* parser,
parser->object_scope = NULL_TREE;
/* Look for a trailing `;' after the declaration. */
if (!function_definition_p
- && !cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
+ && (decl == error_mark_node
+ || !cp_parser_require (parser, CPP_SEMICOLON, "`;'")))
cp_parser_skip_to_end_of_block_or_statement (parser);
return decl;
@@ -14593,8 +14614,10 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
cast = build_functional_cast (type, expression_list);
/* [expr.const]/1: In an integral constant expression "only type
conversions to integral or enumeration type can be used". */
- if (cast != error_mark_node && !type_dependent_expression_p (type)
- && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (type)))
+ if (TREE_CODE (type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+ if (cast != error_mark_node && !dependent_type_p (type)
+ && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
if (cp_parser_non_integral_constant_expression
(parser, "a call to a constructor"))
@@ -14716,8 +14739,8 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
cp_lexer_consume_token (parser->lexer);
}
}
- else if (!cp_parser_require (parser, CPP_GREATER, "`>'"))
- error ("missing `>' to terminate the template argument list");
+ else
+ cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
/* The `>' token might be a greater-than operator again now. */
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
@@ -14768,9 +14791,10 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
tokens = DECL_PENDING_INLINE_INFO (member_function);
DECL_PENDING_INLINE_INFO (member_function) = NULL;
DECL_PENDING_INLINE_P (member_function) = 0;
- /* If this was an inline function in a local class, enter the scope
- of the containing function. */
- function_scope = decl_function_context (member_function);
+
+ /* If this is a local class, enter the scope of the containing
+ function. */
+ function_scope = current_function_decl;
if (function_scope)
push_function_context_to (function_scope);
@@ -14851,33 +14875,49 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
parameters;
parameters = TREE_CHAIN (parameters))
{
- if (!TREE_PURPOSE (parameters)
- || TREE_CODE (TREE_PURPOSE (parameters)) != DEFAULT_ARG)
+ tree default_arg = TREE_PURPOSE (parameters);
+ tree parsed_arg;
+
+ if (!default_arg)
+ continue;
+
+ if (TREE_CODE (default_arg) != DEFAULT_ARG)
+ /* This can happen for a friend declaration for a function
+ already declared with default arguments. */
continue;
- /* Save away the current lexer. */
+ /* Save away the current lexer. */
saved_lexer = parser->lexer;
- /* Create a new one, using the tokens we have saved. */
- tokens = DEFARG_TOKENS (TREE_PURPOSE (parameters));
+ /* Create a new one, using the tokens we have saved. */
+ tokens = DEFARG_TOKENS (default_arg);
parser->lexer = cp_lexer_new_from_tokens (tokens);
- /* Set the current source position to be the location of the
- first token in the default argument. */
+ /* Set the current source position to be the location of the
+ first token in the default argument. */
cp_lexer_peek_token (parser->lexer);
- /* Local variable names (and the `this' keyword) may not appear
- in a default argument. */
+ /* Local variable names (and the `this' keyword) may not appear
+ in a default argument. */
saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
- /* Parse the assignment-expression. */
+
+ /* Parse the assignment-expression. */
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);
+ parsed_arg = cp_parser_assignment_expression (parser);
if (DECL_FRIEND_CONTEXT (fn) || DECL_CLASS_SCOPE_P (fn))
pop_nested_class ();
-
+
+ TREE_PURPOSE (parameters) = parsed_arg;
+
+ /* Update any instantiations we've already created. */
+ for (default_arg = TREE_CHAIN (default_arg);
+ default_arg;
+ default_arg = TREE_CHAIN (default_arg))
+ TREE_PURPOSE (TREE_PURPOSE (default_arg)) = parsed_arg;
+
/* If the token stream has not been completely used up, then
there was extra junk after the end of the default
argument. */
@@ -14889,6 +14929,9 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
}
+ /* Make sure no default arg is missing. */
+ check_default_args (fn);
+
/* Restore the queue. */
parser->unparsed_functions_queues
= TREE_CHAIN (parser->unparsed_functions_queues);
@@ -15012,6 +15055,27 @@ cp_parser_friend_p (tree decl_specifiers)
return false;
}
+/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
+ Returns TRUE iff `typedef' appears among the DECL_SPECIFIERS. */
+
+static bool
+cp_parser_typedef_p (tree decl_specifiers)
+{
+ while (decl_specifiers)
+ {
+ /* See if this decl-specifier is `typedef'. */
+ if (TREE_CODE (TREE_VALUE (decl_specifiers)) == IDENTIFIER_NODE
+ && C_RID_CODE (TREE_VALUE (decl_specifiers)) == RID_TYPEDEF)
+ return true;
+
+ /* Go on to the next decl-specifier. */
+ decl_specifiers = TREE_CHAIN (decl_specifiers);
+ }
+
+ return false;
+}
+
+
/* If the next token is of the indicated TYPE, consume it. Otherwise,
issue an error message indicating that TOKEN_DESC was expected.
OpenPOWER on IntegriCloud