diff options
Diffstat (limited to 'contrib/gcc/cp/parser.c')
-rw-r--r-- | contrib/gcc/cp/parser.c | 288 |
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. |