X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Fparser.c;h=1b12d7999a2d23aeba5b6386b9241ca3e1523761;hb=f04755301385186ff70270c700a7f68cc1e01968;hp=0bd33d692a19b700d013311bff433396ebfc401b;hpb=62116ec373e786a0b9dcb16c8afbd62fa2f45006;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 0bd33d692a1..f497d664783 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1,13 +1,13 @@ /* C++ Parser. Copyright (C) 2000, 2001, 2002, 2003, 2004, - 2005 Free Software Foundation, Inc. + 2005, 2007, 2008 Free Software Foundation, Inc. Written by Mark Mitchell . This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but @@ -15,10 +15,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -72,16 +71,12 @@ typedef struct cp_token GTY (()) unsigned char flags; /* Identifier for the pragma. */ ENUM_BITFIELD (pragma_kind) pragma_kind : 6; - /* 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; /* True for a CPP_NAME token that is not a keyword (i.e., for which KEYWORD is RID_MAX) iff this name was looked up and found to be ambiguous. An error has already been reported. */ BOOL_BITFIELD ambiguous_p : 1; - /* The input file stack index at which this token was found. */ - unsigned input_file_stack_index : INPUT_FILE_STACK_BITS; /* The value associated with this token, if any. */ union cp_token_value { /* Used for CPP_NESTED_NAME_SPECIFIER and CPP_TEMPLATE_ID. */ @@ -98,14 +93,10 @@ typedef struct cp_token *cp_token_position; DEF_VEC_P (cp_token_position); DEF_VEC_ALLOC_P (cp_token_position,heap); -static const cp_token eof_token = +static cp_token eof_token = { - CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, 0, { NULL }, -#if USE_MAPPED_LOCATION + CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, { NULL }, 0 -#else - {0, 0} -#endif }; /* The cp_lexer structure represents the C++ lexer. It is responsible @@ -278,9 +269,6 @@ cp_lexer_new_main (void) allocating any memory. */ cp_parser_initial_pragma (&first_token); - /* Tell c_lex_with_flags not to merge string constants. */ - c_lex_return_raw_strings = true; - c_common_no_more_pch (); /* Allocate the memory. */ @@ -318,7 +306,7 @@ cp_lexer_new_main (void) lexer->buffer = buffer; lexer->buffer_length = alloc - space; lexer->last_token = pos; - lexer->next_token = lexer->buffer_length ? buffer : (cp_token *)&eof_token; + lexer->next_token = lexer->buffer_length ? buffer : &eof_token; /* Subsequent preprocessor diagnostics should use compiler diagnostic functions to get the compiler source location. */ @@ -342,7 +330,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache) /* We do not own the buffer. */ lexer->buffer = NULL; lexer->buffer_length = 0; - lexer->next_token = first == last ? (cp_token *)&eof_token : first; + lexer->next_token = first == last ? &eof_token : first; lexer->last_token = last; lexer->saved_tokens = VEC_alloc (cp_token_position, heap, @@ -403,21 +391,21 @@ cp_lexer_saving_tokens (const cp_lexer* lexer) } /* Store the next token from the preprocessor in *TOKEN. Return true - if we reach EOF. */ + if we reach EOF. If LEXER is NULL, assume we are handling an + initial #pragma pch_preprocess, and thus want the lexer to return + processed strings. */ static void -cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED , - cp_token *token) +cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token) { static int is_extern_c = 0; /* Get a new token from the preprocessor. */ token->type - = c_lex_with_flags (&token->u.value, &token->location, &token->flags); - token->input_file_stack_index = input_file_stack_tick; + = c_lex_with_flags (&token->u.value, &token->location, &token->flags, + lexer == NULL ? 0 : C_LEX_RAW_STRINGS); token->keyword = RID_MAX; token->pragma_kind = PRAGMA_NONE; - 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 @@ -455,7 +443,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED , /* Clear out the C_RID_CODE so we don't warn about this particular identifier-turned-keyword again. */ - C_RID_CODE (token->u.value) = RID_MAX; + C_SET_RID_CODE (token->u.value, RID_MAX); } token->ambiguous_p = false; @@ -487,16 +475,13 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED , } } -/* Update the globals input_location and in_system_header and the - input file stack from TOKEN. */ +/* Update the globals input_location and the input file stack from TOKEN. */ static inline void cp_lexer_set_source_position_from_token (cp_token *token) { if (token->type != CPP_EOF) { input_location = token->location; - in_system_header = token->in_system_header; - restore_input_file_stack (token->input_file_stack_index); } } @@ -539,6 +524,14 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword) return cp_lexer_peek_token (lexer)->keyword == keyword; } +/* Return true if the next token is not the indicated KEYWORD. */ + +static inline bool +cp_lexer_next_token_is_not_keyword (cp_lexer* lexer, enum rid keyword) +{ + return cp_lexer_peek_token (lexer)->keyword != keyword; +} + /* Return true if the next token is a keyword for a decl-specifier. */ static bool @@ -549,8 +542,10 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) token = cp_lexer_peek_token (lexer); switch (token->keyword) { - /* Storage classes. */ + /* auto specifier: storage-class-specifier in C++, + simple-type-specifier in C++0x. */ case RID_AUTO: + /* Storage classes. */ case RID_REGISTER: case RID_STATIC: case RID_EXTERN: @@ -564,6 +559,8 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) case RID_TYPENAME: /* Simple type specifiers. */ case RID_CHAR: + case RID_CHAR16: + case RID_CHAR32: case RID_WCHAR: case RID_BOOL: case RID_SHORT: @@ -577,6 +574,8 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) /* GNU extensions. */ case RID_ATTRIBUTE: case RID_TYPEOF: + /* C++0x extensions. */ + case RID_DECLTYPE: return true; default: @@ -610,7 +609,7 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n) ++token; if (token == lexer->last_token) { - token = (cp_token *)&eof_token; + token = &eof_token; break; } @@ -643,7 +642,7 @@ cp_lexer_consume_token (cp_lexer* lexer) lexer->next_token++; if (lexer->next_token == lexer->last_token) { - lexer->next_token = (cp_token *)&eof_token; + lexer->next_token = &eof_token; break; } @@ -683,7 +682,7 @@ cp_lexer_purge_token (cp_lexer *lexer) tok++; if (tok == lexer->last_token) { - tok = (cp_token *)&eof_token; + tok = &eof_token; break; } } @@ -795,6 +794,8 @@ cp_lexer_print_token (FILE * stream, cp_token *token) break; case CPP_STRING: + case CPP_STRING16: + case CPP_STRING32: case CPP_WSTRING: fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value)); break; @@ -852,7 +853,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs) VAR_DECLs or FUNCTION_DECLs) should do that directly. */ static cp_declarator *make_call_declarator - (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree); + (cp_declarator *, tree, cp_cv_quals, tree, tree); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator @@ -1012,9 +1013,10 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, cp_declarator * make_call_declarator (cp_declarator *target, - cp_parameter_declarator *parms, + tree parms, cp_cv_quals cv_qualifiers, - tree exception_specification) + tree exception_specification, + tree late_return_type) { cp_declarator *declarator; @@ -1023,6 +1025,7 @@ make_call_declarator (cp_declarator *target, declarator->u.function.parameters = parms; declarator->u.function.qualifiers = cv_qualifiers; declarator->u.function.exception_specification = exception_specification; + declarator->u.function.late_return_type = late_return_type; if (target) { declarator->parameter_pack_p = target->parameter_pack_p; @@ -1071,12 +1074,13 @@ declarator_can_be_parameter_pack (cp_declarator *declarator) switch ((int)declarator->kind) { case cdk_id: - case cdk_error: case cdk_array: - case cdk_ptrmem: found = true; break; - + + case cdk_error: + return true; + default: declarator = declarator->declarator; break; @@ -1370,7 +1374,7 @@ cp_parser_context_new (cp_parser_context* next) /* No errors have occurred yet in this context. */ context->status = CP_PARSER_STATUS_KIND_NO_ERROR; - /* If this is not the bottomost context, copy information that we + /* If this is not the bottommost context, copy information that we need from the previous context. */ if (next) { @@ -1579,14 +1583,14 @@ static tree cp_parser_nested_name_specifier_opt (cp_parser *, bool, bool, bool, bool); static tree cp_parser_nested_name_specifier (cp_parser *, bool, bool, bool, bool); -static tree cp_parser_class_or_namespace_name +static tree cp_parser_qualifying_entity (cp_parser *, bool, bool, bool, bool, bool); static tree cp_parser_postfix_expression - (cp_parser *, bool, bool); + (cp_parser *, bool, bool, bool); static tree cp_parser_postfix_open_square_expression (cp_parser *, tree, bool); static tree cp_parser_postfix_dot_deref_expression - (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *); + (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t); static tree cp_parser_parenthesized_expression_list (cp_parser *, bool, bool, bool, bool *); static void cp_parser_pseudo_destructor_name @@ -1612,7 +1616,7 @@ static tree cp_parser_delete_expression static tree cp_parser_cast_expression (cp_parser *, bool, bool); static tree cp_parser_binary_expression - (cp_parser *, bool); + (cp_parser *, bool, enum cp_parser_prec); static tree cp_parser_question_colon_clause (cp_parser *, tree); static tree cp_parser_assignment_expression @@ -1679,6 +1683,8 @@ static tree cp_parser_simple_type_specifier (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags); static tree cp_parser_type_name (cp_parser *); +static tree cp_parser_nonclass_name + (cp_parser* parser); static tree cp_parser_elaborated_type_specifier (cp_parser *, bool, bool); static tree cp_parser_enum_specifier @@ -1707,6 +1713,8 @@ static void cp_parser_linkage_specification (cp_parser *); static void cp_parser_static_assert (cp_parser *, bool); +static tree cp_parser_decltype + (cp_parser *); /* Declarators [gram.dcl.decl] */ @@ -1720,24 +1728,30 @@ static enum tree_code cp_parser_ptr_operator (cp_parser *, tree *, cp_cv_quals *); static cp_cv_quals cp_parser_cv_qualifier_seq_opt (cp_parser *); +static tree cp_parser_late_return_type_opt + (cp_parser *); static tree cp_parser_declarator_id (cp_parser *, bool); static tree cp_parser_type_id (cp_parser *); static void cp_parser_type_specifier_seq (cp_parser *, bool, cp_decl_specifier_seq *); -static cp_parameter_declarator *cp_parser_parameter_declaration_clause +static tree cp_parser_parameter_declaration_clause (cp_parser *); -static cp_parameter_declarator *cp_parser_parameter_declaration_list +static tree cp_parser_parameter_declaration_list (cp_parser *, bool *); static cp_parameter_declarator *cp_parser_parameter_declaration (cp_parser *, bool, bool *); +static tree cp_parser_default_argument + (cp_parser *, bool); static void cp_parser_function_body (cp_parser *); static tree cp_parser_initializer (cp_parser *, bool *, bool *); static tree cp_parser_initializer_clause (cp_parser *, bool *); +static tree cp_parser_braced_list + (cp_parser*, bool*); static VEC(constructor_elt,gc) *cp_parser_initializer_list (cp_parser *, bool *); @@ -1889,15 +1903,15 @@ static tree cp_parser_objc_statement /* Utility Routines */ static tree cp_parser_lookup_name - (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *); + (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *, location_t); static tree cp_parser_lookup_name_simple - (cp_parser *, tree); + (cp_parser *, tree, location_t); static tree cp_parser_maybe_treat_template_as_class (tree, bool); static bool cp_parser_check_declarator_template_parameters - (cp_parser *, cp_declarator *); + (cp_parser *, cp_declarator *, location_t); static bool cp_parser_check_template_parameters - (cp_parser *, unsigned); + (cp_parser *, unsigned, location_t); static tree cp_parser_simple_cast_expression (cp_parser *); static tree cp_parser_global_scope_opt @@ -1933,9 +1947,9 @@ static tree cp_parser_trait_expr static bool cp_parser_declares_only_class_p (cp_parser *); static void cp_parser_set_storage_class - (cp_parser *, cp_decl_specifier_seq *, enum rid); + (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t); static void cp_parser_set_decl_spec_type - (cp_decl_specifier_seq *, tree, bool); + (cp_decl_specifier_seq *, tree, location_t, bool); static bool cp_parser_friend_p (const cp_decl_specifier_seq *); static cp_token *cp_parser_require @@ -1955,12 +1969,12 @@ static enum tag_types cp_parser_token_is_class_key static void cp_parser_check_class_key (enum tag_types, tree type); static void cp_parser_check_access_in_redeclaration - (tree type); + (tree type, location_t location); static bool cp_parser_optional_template_keyword (cp_parser *); static void cp_parser_pre_parsed_nested_name_specifier (cp_parser *); -static void cp_parser_cache_group +static bool cp_parser_cache_group (cp_parser *, enum cpp_ttype, unsigned); static void cp_parser_parse_tentatively (cp_parser *); @@ -1977,19 +1991,19 @@ static bool cp_parser_uncommitted_to_tentative_parse_p static void cp_parser_error (cp_parser *, const char *); static void cp_parser_name_lookup_error - (cp_parser *, tree, tree, const char *); + (cp_parser *, tree, tree, const char *, location_t); static bool cp_parser_simulate_error (cp_parser *); static bool cp_parser_check_type_definition (cp_parser *); static void cp_parser_check_for_definition_in_return_type - (cp_declarator *, tree); + (cp_declarator *, tree, location_t type_location); static void cp_parser_check_for_invalid_template_id - (cp_parser *, tree); + (cp_parser *, tree, location_t location); static bool cp_parser_non_integral_constant_expression (cp_parser *, const char *); static void cp_parser_diagnose_invalid_type_name - (cp_parser *, tree, tree); + (cp_parser *, tree, tree, location_t); static bool cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *); static int cp_parser_skip_to_closing_parenthesis @@ -2015,7 +2029,7 @@ static bool cp_parser_is_string_literal static bool cp_parser_is_keyword (cp_token *, enum rid); static tree cp_parser_make_typename_type - (cp_parser *, tree, tree); + (cp_parser *, tree, tree, location_t location); static cp_declarator * cp_parser_make_indirect_declarator (enum tree_code, tree, cp_cv_quals, cp_declarator *); @@ -2032,7 +2046,10 @@ cp_parser_parsing_tentatively (cp_parser* parser) static bool cp_parser_is_string_literal (cp_token* token) { - return (token->type == CPP_STRING || token->type == CPP_WSTRING); + return (token->type == CPP_STRING || + token->type == CPP_STRING16 || + token->type == CPP_STRING32 || + token->type == CPP_WSTRING); } /* Returns nonzero if TOKEN is the indicated KEYWORD. */ @@ -2061,7 +2078,7 @@ cp_parser_error (cp_parser* parser, const char* message) if (token->type == CPP_PRAGMA) { - error ("%<#pragma%> is not allowed here"); + error ("%H%<#pragma%> is not allowed here", &token->location); cp_parser_skip_to_pragma_eol (parser, token); return; } @@ -2084,33 +2101,34 @@ static void cp_parser_name_lookup_error (cp_parser* parser, tree name, tree decl, - const char* desired) + const char* desired, + location_t location) { /* If name lookup completely failed, tell the user that NAME was not declared. */ if (decl == error_mark_node) { if (parser->scope && parser->scope != global_namespace) - error ("%<%E::%E%> has not been declared", - parser->scope, name); + error ("%H%<%E::%E%> has not been declared", + &location, parser->scope, name); else if (parser->scope == global_namespace) - error ("%<::%E%> has not been declared", name); + error ("%H%<::%E%> has not been declared", &location, name); else if (parser->object_scope && !CLASS_TYPE_P (parser->object_scope)) - error ("request for member %qE in non-class type %qT", - name, parser->object_scope); + error ("%Hrequest for member %qE in non-class type %qT", + &location, name, parser->object_scope); else if (parser->object_scope) - error ("%<%T::%E%> has not been declared", - parser->object_scope, name); + error ("%H%<%T::%E%> has not been declared", + &location, parser->object_scope, name); else - error ("%qE has not been declared", name); + error ("%H%qE has not been declared", &location, name); } else if (parser->scope && parser->scope != global_namespace) - error ("%<%E::%E%> %s", parser->scope, name, desired); + error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired); else if (parser->scope == global_namespace) - error ("%<::%E%> %s", name, desired); + error ("%H%<::%E%> %s", &location, name, desired); else - error ("%qE %s", name, desired); + error ("%H%qE %s", &location, name, desired); } /* If we are parsing tentatively, remember that an error has occurred @@ -2131,7 +2149,8 @@ cp_parser_simulate_error (cp_parser* parser) /* Check for repeated decl-specifiers. */ static void -cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs) +cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs, + location_t location) { cp_decl_spec ds; @@ -2144,9 +2163,11 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs) if (ds == ds_long) { if (count > 2) - error ("% is too long for GCC"); - else if (pedantic && !in_system_header && warn_long_long) - pedwarn ("ISO C++ does not support %"); + error ("%H% is too long for GCC", &location); + else if (pedantic && !in_system_header && warn_long_long + && cxx_dialect == cxx98) + pedwarn (location, OPT_Wlong_long, + "ISO C++ 1998 does not support %"); } else if (count > 1) { @@ -2166,7 +2187,7 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs) "__complex", "__thread" }; - error ("duplicate %qs", decl_spec_names[(int)ds]); + error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]); } } } @@ -2181,9 +2202,9 @@ cp_parser_check_type_definition (cp_parser* parser) /* If types are forbidden here, issue a message. */ if (parser->type_definition_forbidden_message) { - /* Use `%s' to print the string in case there are any escape - characters in the message. */ - error ("%s", parser->type_definition_forbidden_message); + /* Don't use `%s' to print the string, because quotations (`%<', `%>') + in the message need to be interpreted. */ + error (parser->type_definition_forbidden_message); return false; } return true; @@ -2192,11 +2213,12 @@ cp_parser_check_type_definition (cp_parser* parser) /* 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. */ + issued. TYPE_LOCATION is the location of TYPE and is used + for error reporting. */ static void cp_parser_check_for_definition_in_return_type (cp_declarator *declarator, - tree type) + tree type, location_t type_location) { /* [dcl.fct] forbids type definitions in return types. Unfortunately, it's not easy to know whether or not we are @@ -2209,8 +2231,9 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator, if (declarator && declarator->kind == cdk_function) { - error ("new types may not be defined in a return type"); - inform ("(perhaps a semicolon is missing after the definition of %qT)", + error ("%Hnew types may not be defined in a return type", &type_location); + inform (type_location, + "(perhaps a semicolon is missing after the definition of %qT)", type); } } @@ -2218,22 +2241,23 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator, /* A type-specifier (TYPE) has been parsed which cannot be followed by "<" in any valid C++ program. If the next token is indeed "<", issue a message warning the user about what appears to be an - invalid attempt to form a template-id. */ + invalid attempt to form a template-id. LOCATION is the location + of the type-specifier (TYPE) */ static void cp_parser_check_for_invalid_template_id (cp_parser* parser, - tree type) + tree type, location_t location) { cp_token_position start = 0; if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) { if (TYPE_P (type)) - error ("%qT is not a template", type); + error ("%H%qT is not a template", &location, type); else if (TREE_CODE (type) == IDENTIFIER_NODE) - error ("%qE is not a template", type); + error ("%H%qE is not a template", &location, type); else - error ("invalid template-id"); + error ("%Hinvalid template-id", &location); /* Remember the location of the invalid "<". */ if (cp_parser_uncommitted_to_tentative_parse_p (parser)) start = cp_lexer_token_position (parser->lexer, true); @@ -2262,7 +2286,13 @@ cp_parser_non_integral_constant_expression (cp_parser *parser, { if (!parser->allow_non_integral_constant_expression_p) { - error ("%s cannot appear in a constant-expression", thing); + /* Don't use `%s' to print THING, because quotations (`%<', `%>') + in the message need to be interpreted. */ + char *message = concat (thing, + " cannot appear in a constant-expression", + NULL); + error (message); + free (message); return true; } } @@ -2273,30 +2303,34 @@ cp_parser_non_integral_constant_expression (cp_parser *parser, qualifying scope (or NULL, if none) for ID. This function commits to the current active tentative parse, if any. (Otherwise, the problematic construct might be encountered again later, resulting - in duplicate error messages.) */ + in duplicate error messages.) LOCATION is the location of ID. */ static void -cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id) +cp_parser_diagnose_invalid_type_name (cp_parser *parser, + tree scope, tree id, + location_t location) { tree decl, old_scope; /* Try to lookup the identifier. */ old_scope = parser->scope; parser->scope = scope; - decl = cp_parser_lookup_name_simple (parser, id); + decl = cp_parser_lookup_name_simple (parser, id, location); parser->scope = old_scope; /* If the lookup found a template-name, it means that the user forgot to specify an argument list. Emit a useful error message. */ if (TREE_CODE (decl) == TEMPLATE_DECL) - error ("invalid use of template-name %qE without an argument list", decl); + error ("%Hinvalid use of template-name %qE without an argument list", + &location, decl); else if (TREE_CODE (id) == BIT_NOT_EXPR) - error ("invalid use of destructor %qD as a type", id); + error ("%Hinvalid use of destructor %qD as a type", &location, id); else if (TREE_CODE (decl) == TYPE_DECL) /* Something like 'unsigned A a;' */ - error ("invalid combination of multiple type-specifiers"); + error ("%Hinvalid combination of multiple type-specifiers", + &location); else if (!parser->scope) { /* Issue an error message. */ - error ("%qE does not name a type", id); + error ("%H%qE does not name a type", &location, id); /* If we're in a template class, it's possible that the user was referring to a type from a base class. For example: @@ -2328,7 +2362,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id) if (TREE_CODE (field) == TYPE_DECL && DECL_NAME (field) == id) { - inform ("(perhaps % was intended)", + inform (location, + "(perhaps % was intended)", BINFO_TYPE (b), id); break; } @@ -2343,10 +2378,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id) else if (parser->scope != error_mark_node) { if (TREE_CODE (parser->scope) == NAMESPACE_DECL) - error ("%qE in namespace %qE does not name a type", - id, parser->scope); + error ("%H%qE in namespace %qE does not name a type", + &location, id, parser->scope); else if (TYPE_P (parser->scope)) - error ("%qE in class %qT does not name a type", id, parser->scope); + error ("%H%qE in class %qT does not name a type", + &location, id, parser->scope); else gcc_unreachable (); } @@ -2367,6 +2403,7 @@ static bool cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) { tree id; + cp_token *token = cp_lexer_peek_token (parser->lexer); cp_parser_parse_tentatively (parser); id = cp_parser_id_expression (parser, @@ -2390,7 +2427,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) return false; /* Emit a diagnostic for the invalid type. */ - cp_parser_diagnose_invalid_type_name (parser, parser->scope, id); + cp_parser_diagnose_invalid_type_name (parser, parser->scope, + id, token->location); /* Skip to the end of the declaration; there's no point in trying to process it. */ cp_parser_skip_to_end_of_block_or_statement (parser); @@ -2543,7 +2581,7 @@ static void cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser) { /* Look for the trailing `;'. */ - if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'")) + if (!cp_parser_require (parser, CPP_SEMICOLON, "%<;%>")) { /* If there is additional (erroneous) input, skip to the end of the statement. */ @@ -2678,7 +2716,8 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok) using cp_parser_diagnose_invalid_type_name. */ static tree -cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id) +cp_parser_make_typename_type (cp_parser *parser, tree scope, + tree id, location_t id_location) { tree result; if (TREE_CODE (id) == IDENTIFIER_NODE) @@ -2686,7 +2725,7 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id) result = make_typename_type (scope, id, typename_type, /*complain=*/tf_none); if (result == error_mark_node) - cp_parser_diagnose_invalid_type_name (parser, scope, id); + cp_parser_diagnose_invalid_type_name (parser, scope, id, id_location); return result; } return make_typename_type (scope, id, typename_type, tf_error); @@ -2702,6 +2741,9 @@ cp_parser_make_indirect_declarator (enum tree_code code, tree class_type, cp_cv_quals cv_qualifiers, cp_declarator *target) { + if (code == ERROR_MARK) + return cp_error_declarator; + if (code == INDIRECT_REF) if (class_type == NULL_TREE) return make_pointer_declarator (cv_qualifiers, target); @@ -2856,11 +2898,11 @@ static tree cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) { tree value; - bool wide = false; size_t count; struct obstack str_ob; cpp_string str, istr, *strs; cp_token *tok; + enum cpp_ttype type; tok = cp_lexer_peek_token (parser->lexer); if (!cp_parser_is_string_literal (tok)) @@ -2869,6 +2911,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) return error_mark_node; } + type = tok->type; + /* Try to avoid the overhead of creating and destroying an obstack for the common case of just one string. */ if (!cp_parser_is_string_literal @@ -2879,8 +2923,6 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value); str.len = TREE_STRING_LENGTH (tok->u.value); count = 1; - if (tok->type == CPP_WSTRING) - wide = true; strs = &str; } @@ -2893,10 +2935,17 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) { cp_lexer_consume_token (parser->lexer); count++; - str.text = (unsigned char *)TREE_STRING_POINTER (tok->u.value); + str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value); str.len = TREE_STRING_LENGTH (tok->u.value); - if (tok->type == CPP_WSTRING) - wide = true; + + if (type != tok->type) + { + if (type == CPP_STRING) + type = tok->type; + else if (tok->type != CPP_STRING) + error ("%Hunsupported non-standard concatenation " + "of string literals", &tok->location); + } obstack_grow (&str_ob, &str, sizeof (cpp_string)); @@ -2907,19 +2956,35 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) strs = (cpp_string *) obstack_finish (&str_ob); } - if (wide && !wide_ok) + if (type != CPP_STRING && !wide_ok) { cp_parser_error (parser, "a wide string is invalid in this context"); - wide = false; + type = CPP_STRING; } if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate) - (parse_in, strs, count, &istr, wide)) + (parse_in, strs, count, &istr, type)) { - value = build_string (istr.len, (char *)istr.text); - free ((void *)istr.text); + value = build_string (istr.len, (const char *)istr.text); + free (CONST_CAST (unsigned char *, istr.text)); + + switch (type) + { + default: + case CPP_STRING: + TREE_TYPE (value) = char_array_type_node; + break; + case CPP_STRING16: + TREE_TYPE (value) = char16_array_type_node; + break; + case CPP_STRING32: + TREE_TYPE (value) = char32_array_type_node; + break; + case CPP_WSTRING: + TREE_TYPE (value) = wchar_array_type_node; + break; + } - TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node; value = fix_string_type (value); } else @@ -3058,7 +3123,7 @@ cp_parser_primary_expression (cp_parser *parser, bool template_arg_p, cp_id_kind *idk) { - cp_token *token; + cp_token *token = NULL; /* Assume the primary expression is not an id-expression. */ *idk = CP_ID_KIND_NONE; @@ -3074,6 +3139,8 @@ cp_parser_primary_expression (cp_parser *parser, string-literal boolean-literal */ case CPP_CHAR: + case CPP_CHAR16: + case CPP_CHAR32: case CPP_WCHAR: case CPP_NUMBER: token = cp_lexer_consume_token (parser->lexer); @@ -3125,6 +3192,8 @@ cp_parser_primary_expression (cp_parser *parser, return token->u.value; case CPP_STRING: + case CPP_STRING16: + case CPP_STRING32: case CPP_WSTRING: /* ??? Should wide strings be allowed when parser->translate_strings_p is false (i.e. in attributes)? If not, we can kill the third @@ -3151,8 +3220,8 @@ cp_parser_primary_expression (cp_parser *parser, && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { /* Statement-expressions are not allowed by the standard. */ - if (pedantic) - pedwarn ("ISO C++ forbids braced-groups within expressions"); + pedwarn (token->location, OPT_pedantic, + "ISO C++ forbids braced-groups within expressions"); /* And they're not allowed outside of a function-body; you cannot, for example, write: @@ -3160,9 +3229,12 @@ cp_parser_primary_expression (cp_parser *parser, int i = ({ int j = 3; j + 1; }); at class or namespace scope. */ - if (!parser->in_function_body) + if (!parser->in_function_body + || parser->in_template_argument_list_p) { - error ("statement-expressions are allowed only inside functions"); + error ("%Hstatement-expressions are not allowed outside " + "functions nor in template-argument lists", + &token->location); cp_parser_skip_to_end_of_block_or_statement (parser); expr = error_mark_node; } @@ -3192,7 +3264,7 @@ cp_parser_primary_expression (cp_parser *parser, parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; /* Consume the `)'. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>")) cp_parser_skip_to_end_of_statement (parser); return expr; @@ -3219,12 +3291,12 @@ cp_parser_primary_expression (cp_parser *parser, cp_lexer_consume_token (parser->lexer); if (parser->local_variables_forbidden_p) { - error ("% may not be used in this context"); + error ("%H% may not be used in this context", + &token->location); return error_mark_node; } /* Pointers cannot appear in constant-expressions. */ - if (cp_parser_non_integral_constant_expression (parser, - "`this'")) + if (cp_parser_non_integral_constant_expression (parser, "%")) return error_mark_node; return finish_this_expr (); @@ -3236,16 +3308,39 @@ cp_parser_primary_expression (cp_parser *parser, case RID_FUNCTION_NAME: case RID_PRETTY_FUNCTION_NAME: case RID_C99_FUNCTION_NAME: - /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and - __func__ are the names of variables -- but they are - treated specially. Therefore, they are handled here, - rather than relying on the generic id-expression logic - below. Grammatically, these names are id-expressions. + { + const char *name; - Consume the token. */ - token = cp_lexer_consume_token (parser->lexer); - /* Look up the name. */ - return finish_fname (token->u.value); + /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and + __func__ are the names of variables -- but they are + treated specially. Therefore, they are handled here, + rather than relying on the generic id-expression logic + below. Grammatically, these names are id-expressions. + + Consume the token. */ + token = cp_lexer_consume_token (parser->lexer); + + switch (token->keyword) + { + case RID_FUNCTION_NAME: + name = "%<__FUNCTION__%>"; + break; + case RID_PRETTY_FUNCTION_NAME: + name = "%<__PRETTY_FUNCTION__%>"; + break; + case RID_C99_FUNCTION_NAME: + name = "%<__func__%>"; + break; + default: + gcc_unreachable (); + } + + if (cp_parser_non_integral_constant_expression (parser, name)) + return error_mark_node; + + /* Look up the name. */ + return finish_fname (token->u.value); + } case RID_VA_ARG: { @@ -3256,20 +3351,20 @@ cp_parser_primary_expression (cp_parser *parser, `va_arg'. Consume the `__builtin_va_arg' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the opening `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); /* Now, parse the assignment-expression. */ expression = cp_parser_assignment_expression (parser, /*cast_p=*/false); /* Look for the `,'. */ - cp_parser_require (parser, CPP_COMMA, "`,'"); + cp_parser_require (parser, CPP_COMMA, "%<,%>"); /* Parse the type-id. */ type = cp_parser_type_id (parser); /* Look for the closing `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); /* Using `va_arg' in a constant-expression is not allowed. */ if (cp_parser_non_integral_constant_expression (parser, - "`va_arg'")) + "%")) return error_mark_node; return build_x_va_arg (expression, type); } @@ -3320,6 +3415,7 @@ cp_parser_primary_expression (cp_parser *parser, const char *error_msg; bool template_p; bool done; + cp_token *id_expr_token; id_expression: /* Parse the id-expression. */ @@ -3332,6 +3428,7 @@ cp_parser_primary_expression (cp_parser *parser, /*optional_p=*/false); if (id_expression == error_mark_node) return error_mark_node; + id_expr_token = token; token = cp_lexer_peek_token (parser->lexer); done = (token->type != CPP_OPEN_SQUARE && token->type != CPP_OPEN_PAREN @@ -3355,7 +3452,8 @@ cp_parser_primary_expression (cp_parser *parser, template_p, /*is_namespace=*/false, /*check_dependency=*/true, - &ambiguous_decls); + &ambiguous_decls, + id_expr_token->location); /* If the lookup was ambiguous, an error will already have been issued. */ if (ambiguous_decls) @@ -3402,8 +3500,8 @@ cp_parser_primary_expression (cp_parser *parser, decl = check_for_out_of_scope_variable (decl); if (local_variable_p (decl)) { - error ("local variable %qD may not appear in this context", - decl); + error ("%Hlocal variable %qD may not appear in this context", + &id_expr_token->location, decl); return error_mark_node; } } @@ -3417,7 +3515,8 @@ cp_parser_primary_expression (cp_parser *parser, &parser->non_integral_constant_expression_p, template_p, done, address_p, template_arg_p, - &error_msg)); + &error_msg, + id_expr_token->location)); if (error_msg) cp_parser_error (parser, error_msg); return decl; @@ -3701,7 +3800,8 @@ cp_parser_unqualified_id (cp_parser* parser, if (scope && TREE_CODE (scope) == NAMESPACE_DECL) { if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) - error ("scope %qT before %<~%> is not a class-name", scope); + error ("%Hscope %qT before %<~%> is not a class-name", + &token->location, scope); cp_parser_simulate_error (parser); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) cp_lexer_consume_token (parser->lexer); @@ -3802,8 +3902,8 @@ cp_parser_unqualified_id (cp_parser* parser, if (declarator_p && scope && !check_dtor_name (scope, type_decl)) { if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) - error ("declaration of %<~%T%> as member of %qT", - type_decl, scope); + error ("%Hdeclaration of %<~%T%> as member of %qT", + &token->location, type_decl, scope); cp_parser_simulate_error (parser); return error_mark_node; } @@ -3816,8 +3916,8 @@ cp_parser_unqualified_id (cp_parser* parser, && !DECL_IMPLICIT_TYPEDEF_P (type_decl) && !DECL_SELF_REFERENCE_P (type_decl) && !cp_parser_uncommitted_to_tentative_parse_p (parser)) - error ("typedef-name %qD used as destructor declarator", - type_decl); + error ("%Htypedef-name %qD used as destructor declarator", + &token->location, type_decl); return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl)); } @@ -3859,10 +3959,16 @@ cp_parser_unqualified_id (cp_parser* parser, /* Parse an (optional) nested-name-specifier. - nested-name-specifier: + nested-name-specifier: [C++98] class-or-namespace-name :: nested-name-specifier [opt] class-or-namespace-name :: template nested-name-specifier [opt] + nested-name-specifier: [C++0x] + type-name :: + namespace-name :: + nested-name-specifier identifier :: + nested-name-specifier template [opt] simple-template-id :: + PARSER->SCOPE should be set appropriately before this function is called. TYPENAME_KEYWORD_P is TRUE if the `typename' keyword is in effect. TYPE_P is TRUE if we non-type bindings should be ignored @@ -3919,7 +4025,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, { new_scope = resolve_typename_type (parser->scope, /*only_current_p=*/false); - if (new_scope != error_mark_node) + if (TREE_CODE (new_scope) != TYPENAME_TYPE) parser->scope = new_scope; } success = true; @@ -3937,7 +4043,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, else { /* If the next token is not an identifier, then it is - definitely not a class-or-namespace-name. */ + definitely not a type-name or namespace-name. */ if (token->type != CPP_NAME) break; /* If the following token is neither a `<' (to begin a @@ -3977,14 +4083,14 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, /*only_current_p=*/false); /* Parse the qualifying entity. */ new_scope - = cp_parser_class_or_namespace_name (parser, - typename_keyword_p, - template_keyword_p, - check_dependency_p, - type_p, - is_declaration); + = cp_parser_qualifying_entity (parser, + typename_keyword_p, + template_keyword_p, + check_dependency_p, + type_p, + is_declaration); /* Look for the `::' token. */ - cp_parser_require (parser, CPP_SCOPE, "`::'"); + cp_parser_require (parser, CPP_SCOPE, "%<::%>"); /* If we found what we wanted, we keep going; otherwise, we're done. */ @@ -4021,20 +4127,27 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, /*is_template=*/false, /*is_namespace=*/false, /*check_dependency=*/true, - &ambiguous_decls); + &ambiguous_decls, + token->location); if (TREE_CODE (decl) == TEMPLATE_DECL) - error ("%qD used without template parameters", decl); + error ("%H%qD used without template parameters", + &token->location, decl); else if (ambiguous_decls) { - error ("reference to %qD is ambiguous", - token->u.value); + error ("%Hreference to %qD is ambiguous", + &token->location, token->u.value); print_candidates (ambiguous_decls); decl = error_mark_node; } else - cp_parser_name_lookup_error - (parser, token->u.value, decl, - "is not a class or namespace"); + { + const char* msg = "is not a class or namespace"; + if (cxx_dialect != cxx98) + msg = "is not a class, namespace, or enumeration"; + cp_parser_name_lookup_error + (parser, token->u.value, decl, msg, + token->location); + } } parser->scope = error_mark_node; error_p = true; @@ -4066,10 +4179,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, && !(TREE_CODE (new_scope) == TYPENAME_TYPE && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope)) == TEMPLATE_ID_EXPR))) - pedwarn (TYPE_P (new_scope) - ? "%qT is not a template" - : "%qD is not a template", - new_scope); + permerror (input_location, TYPE_P (new_scope) + ? "%qT is not a template" + : "%qD is not a template", + new_scope); /* If it is a class scope, try to complete it; we are about to be looking up names inside the class. */ if (TYPE_P (new_scope) @@ -4078,7 +4191,15 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, && !COMPLETE_TYPE_P (new_scope) /* Do not try to complete dependent types. */ && !dependent_type_p (new_scope)) - new_scope = complete_type (new_scope); + { + new_scope = complete_type (new_scope); + /* If it is a typedef to current class, use the current + class instead, as the typedef won't have any names inside + it yet. */ + if (!COMPLETE_TYPE_P (new_scope) + && currently_open_class (new_scope)) + new_scope = TYPE_MAIN_VARIANT (new_scope); + } /* Make sure we look in the right scope the next time through the loop. */ parser->scope = new_scope; @@ -4145,11 +4266,11 @@ cp_parser_nested_name_specifier (cp_parser *parser, return scope; } -/* Parse a class-or-namespace-name. - - class-or-namespace-name: - class-name - namespace-name +/* Parse the qualifying entity in a nested-name-specifier. For C++98, + this is either a class-name or a namespace-name (which corresponds + to the class-or-namespace-name production in the grammar). For + C++0x, it can also be a type-name that refers to an enumeration + type. TYPENAME_KEYWORD_P is TRUE iff the `typename' keyword is in effect. TEMPLATE_KEYWORD_P is TRUE iff the `template' keyword is in effect. @@ -4163,18 +4284,19 @@ cp_parser_nested_name_specifier (cp_parser *parser, ERROR_MARK_NODE is returned. */ static tree -cp_parser_class_or_namespace_name (cp_parser *parser, - bool typename_keyword_p, - bool template_keyword_p, - bool check_dependency_p, - bool type_p, - bool is_declaration) +cp_parser_qualifying_entity (cp_parser *parser, + bool typename_keyword_p, + bool template_keyword_p, + bool check_dependency_p, + bool type_p, + bool is_declaration) { tree saved_scope; tree saved_qualifying_scope; tree saved_object_scope; tree scope; bool only_class_p; + bool successful_parse_p; /* Before we try to parse the class-name, we must save away the current PARSER->SCOPE since cp_parser_class_name will destroy @@ -4184,7 +4306,8 @@ cp_parser_class_or_namespace_name (cp_parser *parser, saved_object_scope = parser->object_scope; /* Try for a class-name first. If the SAVED_SCOPE is a type, then there is no need to look for a namespace-name. */ - only_class_p = template_keyword_p || (saved_scope && TYPE_P (saved_scope)); + only_class_p = template_keyword_p + || (saved_scope && TYPE_P (saved_scope) && cxx_dialect == cxx98); if (!only_class_p) cp_parser_parse_tentatively (parser); scope = cp_parser_class_name (parser, @@ -4194,8 +4317,26 @@ cp_parser_class_or_namespace_name (cp_parser *parser, check_dependency_p, /*class_head_p=*/false, is_declaration); + successful_parse_p = only_class_p || cp_parser_parse_definitely (parser); + /* If that didn't work and we're in C++0x mode, try for a type-name. */ + if (!only_class_p + && cxx_dialect != cxx98 + && !successful_parse_p) + { + /* Restore the saved scope. */ + parser->scope = saved_scope; + parser->qualifying_scope = saved_qualifying_scope; + parser->object_scope = saved_object_scope; + + /* Parse tentatively. */ + cp_parser_parse_tentatively (parser); + + /* Parse a typedef-name or enum-name. */ + scope = cp_parser_nonclass_name (parser); + successful_parse_p = cp_parser_parse_definitely (parser); + } /* If that didn't work, try for a namespace-name. */ - if (!only_class_p && !cp_parser_parse_definitely (parser)) + if (!only_class_p && !successful_parse_p) { /* Restore the saved scope. */ parser->scope = saved_scope; @@ -4251,15 +4392,20 @@ cp_parser_class_or_namespace_name (cp_parser *parser, `&' operator. CAST_P is true if this expression is the target of a cast. + If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are + class member access expressions [expr.ref]. + Returns a representation of the expression. */ static tree -cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) +cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, + bool member_access_only_p) { cp_token *token; enum rid keyword; cp_id_kind idk = CP_ID_KIND_NONE; tree postfix_expression = NULL_TREE; + bool is_member_access = false; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -4287,18 +4433,18 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) = "types may not be defined in casts"; /* Look for the opening `<'. */ - cp_parser_require (parser, CPP_LESS, "`<'"); + cp_parser_require (parser, CPP_LESS, "%<<%>"); /* Parse the type to which we are casting. */ type = cp_parser_type_id (parser); /* Look for the closing `>'. */ - cp_parser_require (parser, CPP_GREATER, "`>'"); + cp_parser_require (parser, CPP_GREATER, "%<>%>"); /* Restore the old message. */ parser->type_definition_forbidden_message = saved_message; /* And the expression which is being cast. */ - cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); expression = cp_parser_expression (parser, /*cast_p=*/true); - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); /* Only type conversions to integral or enumeration types can be used in constant-expressions. */ @@ -4313,19 +4459,20 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) { case RID_DYNCAST: postfix_expression - = build_dynamic_cast (type, expression); + = build_dynamic_cast (type, expression, tf_warning_or_error); break; case RID_STATCAST: postfix_expression - = build_static_cast (type, expression); + = build_static_cast (type, expression, tf_warning_or_error); break; case RID_REINTCAST: postfix_expression - = build_reinterpret_cast (type, expression); + = build_reinterpret_cast (type, expression, + tf_warning_or_error); break; case RID_CONSTCAST: postfix_expression - = build_const_cast (type, expression); + = build_const_cast (type, expression, tf_warning_or_error); break; default: gcc_unreachable (); @@ -4342,11 +4489,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) /* Consume the `typeid' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the `(' token. */ - cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); /* Types cannot be defined in a `typeid' expression. */ saved_message = parser->type_definition_forbidden_message; parser->type_definition_forbidden_message - = "types may not be defined in a `typeid\' expression"; + = "types may not be defined in a % expression"; /* We can't be sure yet whether we're looking at a type-id or an expression. */ cp_parser_parse_tentatively (parser); @@ -4358,7 +4505,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) /* Look for the `)' token. Otherwise, we can't be sure that we're not looking at an expression: consider `typeid (int (3))', for example. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); /* If all went well, simply lookup the type-id. */ if (cp_parser_parse_definitely (parser)) postfix_expression = get_typeid (type); @@ -4372,13 +4519,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) /* Compute its typeid. */ postfix_expression = build_typeid (expression); /* Look for the `)' token. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); } /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; /* `typeid' may not appear in an integral constant expression. */ if (cp_parser_non_integral_constant_expression(parser, - "`typeid' operator")) + "% operator")) return error_mark_node; } break; @@ -4433,9 +4580,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) type = cp_parser_type_id (parser); parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); /* Look for the `{'. */ - cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); + cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"); /* If things aren't going well, there's no need to keep going. */ if (!cp_parser_error_occurred (parser)) @@ -4448,7 +4595,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) cp_lexer_consume_token (parser->lexer); /* Look for the final `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); } /* If that worked, we're definitely looking at a compound-literal expression. */ @@ -4456,8 +4603,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) { /* Warn the user that a compound literal is not allowed in standard C++. */ - if (pedantic) - pedwarn ("ISO C++ forbids compound-literals"); + pedwarn (input_location, OPT_pedantic, "ISO C++ forbids compound-literals"); /* For simplicity, we disallow compound literals in constant-expressions. We could allow compound literals of integer type, whose @@ -4475,7 +4621,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) } /* Form the representation of the compound-literal. */ postfix_expression - = finish_compound_literal (type, initializer_list); + = (finish_compound_literal + (type, build_constructor (init_list_type_node, + initializer_list))); break; } } @@ -4510,6 +4658,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) postfix_expression, false); idk = CP_ID_KIND_NONE; + is_member_access = false; break; case CPP_OPEN_PAREN: @@ -4521,6 +4670,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) bool saved_non_integral_constant_expression_p = false; tree args; + is_member_access = false; + is_builtin_constant_p = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression); if (is_builtin_constant_p) @@ -4621,12 +4772,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) (instance, fn, args, NULL_TREE, (idk == CP_ID_KIND_QUALIFIED ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL), - /*fn_p=*/NULL)); + /*fn_p=*/NULL, + tf_warning_or_error)); else postfix_expression = finish_call_expr (postfix_expression, args, /*disallow_virtual=*/false, - /*koenig_p=*/false); + /*koenig_p=*/false, + tf_warning_or_error); } else if (TREE_CODE (postfix_expression) == OFFSET_REF || TREE_CODE (postfix_expression) == MEMBER_REF @@ -4639,13 +4792,18 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) postfix_expression = finish_call_expr (postfix_expression, args, /*disallow_virtual=*/true, - koenig_p); + koenig_p, + tf_warning_or_error); else /* All other function calls. */ postfix_expression = finish_call_expr (postfix_expression, args, /*disallow_virtual=*/false, - koenig_p); + koenig_p, + tf_warning_or_error); + + if (warn_disallowed_functions) + warn_if_disallowed_function_p (postfix_expression); /* The POSTFIX_EXPRESSION is certainly no longer an id. */ idk = CP_ID_KIND_NONE; @@ -4665,7 +4823,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) postfix_expression = cp_parser_postfix_dot_deref_expression (parser, token->type, postfix_expression, - false, &idk); + false, &idk, + token->location); + + is_member_access = true; break; case CPP_PLUS_PLUS: @@ -4681,6 +4842,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) "an increment")) postfix_expression = error_mark_node; idk = CP_ID_KIND_NONE; + is_member_access = false; break; case CPP_MINUS_MINUS: @@ -4696,10 +4858,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) "a decrement")) postfix_expression = error_mark_node; idk = CP_ID_KIND_NONE; + is_member_access = false; break; default: - return postfix_expression; + if (member_access_only_p) + return is_member_access? postfix_expression : error_mark_node; + else + return postfix_expression; } } @@ -4740,7 +4906,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser, index = cp_parser_expression (parser, /*cast_p=*/false); /* Look for the closing `]'. */ - cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); + cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>"); /* Build the ARRAY_REF. */ postfix_expression = grok_array_decl (postfix_expression, index); @@ -4772,7 +4938,8 @@ static tree cp_parser_postfix_dot_deref_expression (cp_parser *parser, enum cpp_ttype token_type, tree postfix_expression, - bool for_offsetof, cp_id_kind *idk) + bool for_offsetof, cp_id_kind *idk, + location_t location) { tree name; bool dependent_p; @@ -4804,7 +4971,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, /* The type of the POSTFIX_EXPRESSION must be complete. */ if (scope == unknown_type_node) { - error ("%qE does not have class type", postfix_expression); + error ("%H%qE does not have class type", &location, postfix_expression); scope = NULL_TREE; } else @@ -4828,8 +4995,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, pseudo_destructor_p = false; /* If the SCOPE is a scalar type, then, if this is a valid program, - we must be looking at a pseudo-destructor-name. */ - if (scope && SCALAR_TYPE_P (scope)) + we must be looking at a pseudo-destructor-name. If POSTFIX_EXPRESSION + is type dependent, it can be pseudo-destructor-name or something else. + Try to parse it as pseudo-destructor-name first. */ + if ((scope && SCALAR_TYPE_P (scope)) || dependent_p) { tree s; tree type; @@ -4838,7 +5007,12 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, /* Parse the pseudo-destructor-name. */ s = NULL_TREE; cp_parser_pseudo_destructor_name (parser, &s, &type); - if (cp_parser_parse_definitely (parser)) + if (dependent_p + && (cp_parser_error_occurred (parser) + || TREE_CODE (type) != TYPE_DECL + || !SCALAR_TYPE_P (TREE_TYPE (type)))) + cp_parser_abort_tentative_parse (parser); + else if (cp_parser_parse_definitely (parser)) { pseudo_destructor_p = true; postfix_expression @@ -4853,6 +5027,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, ordinary class member access expression, rather than a pseudo-destructor-name. */ bool template_p; + cp_token *token = cp_lexer_peek_token (parser->lexer); /* Parse the id-expression. */ name = (cp_parser_id_expression (parser, @@ -4880,7 +5055,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, TYPE_DECL here. That is invalid code. */ if (TREE_CODE (name) == TYPE_DECL) { - error ("invalid use of %qD", name); + error ("%Hinvalid use of %qD", &token->location, name); postfix_expression = error_mark_node; } else @@ -4900,7 +5075,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, (name, BINFO_TYPE (BASELINK_ACCESS_BINFO (name)), scope); postfix_expression = finish_class_member_access_expr (postfix_expression, name, - template_p); + template_p, + tf_warning_or_error); } } @@ -4912,7 +5088,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, constant-expressions. */ if (!for_offsetof && (cp_parser_non_integral_constant_expression - (parser, token_type == CPP_DEREF ? "'->'" : "`.'"))) + (parser, token_type == CPP_DEREF ? "%<->%>" : "%<.%>"))) postfix_expression = error_mark_node; return postfix_expression; @@ -4954,14 +5130,21 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, tree expression_list = NULL_TREE; bool fold_expr_p = is_attribute_list; tree identifier = NULL_TREE; + bool saved_greater_than_is_operator_p; /* Assume all the expressions will be constant. */ if (non_constant_p) *non_constant_p = false; - if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>")) return error_mark_node; + /* Within a parenthesized expression, a `>' token is always + the greater-than operator. */ + saved_greater_than_is_operator_p + = parser->greater_than_is_operator_p; + parser->greater_than_is_operator_p = true; + /* Consume expressions until there are no more. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) while (true) @@ -4982,10 +5165,19 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, } else { + bool expr_non_constant_p; + /* Parse the next assignment-expression. */ - if (non_constant_p) + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + /* A braced-init-list. */ + maybe_warn_cpp0x ("extended initializer lists"); + expr = cp_parser_braced_list (parser, &expr_non_constant_p); + if (non_constant_p && expr_non_constant_p) + *non_constant_p = true; + } + else if (non_constant_p) { - bool expr_non_constant_p; expr = (cp_parser_constant_expression (parser, /*allow_non_constant_p=*/true, &expr_non_constant_p)); @@ -5033,7 +5225,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, cp_lexer_consume_token (parser->lexer); } - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>")) { int ending; @@ -5047,9 +5239,16 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, if (ending < 0) goto get_comma; if (!ending) - return error_mark_node; + { + parser->greater_than_is_operator_p + = saved_greater_than_is_operator_p; + return error_mark_node; + } } + parser->greater_than_is_operator_p + = saved_greater_than_is_operator_p; + /* We built up the list in reverse order so we must reverse it now. */ expression_list = nreverse (expression_list); if (identifier) @@ -5088,7 +5287,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser, /*typename_keyword_p=*/false, /*check_dependency_p=*/true, /*type_p=*/false, - /*is_declaration=*/true) + /*is_declaration=*/false) != NULL_TREE); /* Now, if we saw a nested-name-specifier, we might be doing the second production. */ @@ -5103,41 +5302,42 @@ cp_parser_pseudo_destructor_name (cp_parser* parser, /*check_dependency_p=*/false, /*is_declaration=*/true); /* Look for the `::' token. */ - cp_parser_require (parser, CPP_SCOPE, "`::'"); + cp_parser_require (parser, CPP_SCOPE, "%<::%>"); } /* If the next token is not a `~', then there might be some additional qualification. */ else if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMPL)) { - /* Look for the type-name. */ - *scope = TREE_TYPE (cp_parser_type_name (parser)); - - if (*scope == error_mark_node) - return; - - /* If we don't have ::~, then something has gone wrong. Since - the only caller of this function is looking for something - after `.' or `->' after a scalar type, most likely the - program is trying to get a member of a non-aggregate - type. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE) - || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_COMPL) + /* At this point, we're looking for "type-name :: ~". The type-name + must not be a class-name, since this is a pseudo-destructor. So, + it must be either an enum-name, or a typedef-name -- both of which + are just identifiers. So, we peek ahead to check that the "::" + and "~" tokens are present; if they are not, then we can avoid + calling type_name. */ + if (cp_lexer_peek_token (parser->lexer)->type != CPP_NAME + || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE + || cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_COMPL) { - cp_parser_error (parser, "request for member of non-aggregate type"); + cp_parser_error (parser, "non-scalar type"); return; } + /* Look for the type-name. */ + *scope = TREE_TYPE (cp_parser_nonclass_name (parser)); + if (*scope == error_mark_node) + return; + /* Look for the `::' token. */ - cp_parser_require (parser, CPP_SCOPE, "`::'"); + cp_parser_require (parser, CPP_SCOPE, "%<::%>"); } else *scope = NULL_TREE; /* Look for the `~'. */ - cp_parser_require (parser, CPP_COMPL, "`~'"); + cp_parser_require (parser, CPP_COMPL, "%<~%>"); /* Look for the type-name again. We are not responsible for checking that it matches the first type-name. */ - *type = cp_parser_type_name (parser); + *type = cp_parser_nonclass_name (parser); } /* Parse a unary-expression. @@ -5198,7 +5398,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) if (TYPE_P (operand)) return cxx_sizeof_or_alignof_type (operand, op, true); else - return cxx_sizeof_or_alignof_expr (operand, op); + return cxx_sizeof_or_alignof_expr (operand, op, true); } case RID_NEW: @@ -5235,7 +5435,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) /* Create the complete representation. */ return build_x_unary_op ((keyword == RID_REALPART ? REALPART_EXPR : IMAGPART_EXPR), - expression); + expression, + tf_warning_or_error); } break; @@ -5278,13 +5479,19 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) && token->type == CPP_AND_AND) { tree identifier; + tree expression; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; /* Consume the '&&' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the identifier. */ identifier = cp_parser_identifier (parser); /* Create an expression representing the address. */ - return finish_label_address_expr (identifier); + expression = finish_label_address_expr (identifier, loc); + if (cp_parser_non_integral_constant_expression (parser, + "the address of a label")) + expression = error_mark_node; + return expression; } } if (unary_operator != ERROR_MARK) @@ -5304,21 +5511,23 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) switch (unary_operator) { case INDIRECT_REF: - non_constant_p = "`*'"; - expression = build_x_indirect_ref (cast_expression, "unary *"); + non_constant_p = "%<*%>"; + expression = build_x_indirect_ref (cast_expression, "unary *", + tf_warning_or_error); break; case ADDR_EXPR: - non_constant_p = "`&'"; + non_constant_p = "%<&%>"; /* Fall through. */ case BIT_NOT_EXPR: - expression = build_x_unary_op (unary_operator, cast_expression); + expression = build_x_unary_op (unary_operator, cast_expression, + tf_warning_or_error); break; case PREINCREMENT_EXPR: case PREDECREMENT_EXPR: non_constant_p = (unary_operator == PREINCREMENT_EXPR - ? "`++'" : "`--'"); + ? "%<++%>" : "%<--%>"); /* Fall through. */ case UNARY_PLUS_EXPR: case NEGATE_EXPR: @@ -5338,7 +5547,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) return expression; } - return cp_parser_postfix_expression (parser, address_p, cast_p); + return cp_parser_postfix_expression (parser, address_p, cast_p, + /*member_access_only_p=*/false); } /* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a @@ -5395,7 +5605,7 @@ cp_parser_new_expression (cp_parser* parser) /*current_scope_valid_p=*/false) != NULL_TREE); /* Look for the `new' operator. */ - cp_parser_require_keyword (parser, RID_NEW, "`new'"); + cp_parser_require_keyword (parser, RID_NEW, "%"); /* There's no easy way to tell a new-placement from the `( type-id )' construct. */ cp_parser_parse_tentatively (parser); @@ -5409,19 +5619,23 @@ cp_parser_new_expression (cp_parser* parser) type-id. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { + cp_token *token; /* Consume the `('. */ cp_lexer_consume_token (parser->lexer); /* Parse the type-id. */ type = cp_parser_type_id (parser); /* Look for the closing `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); + token = cp_lexer_peek_token (parser->lexer); /* There should not be a direct-new-declarator in this production, but GCC used to allowed this, so we check and emit a sensible error message for this case. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) { - error ("array bound forbidden after parenthesized type-id"); - inform ("try removing the parentheses around the type-id"); + error ("%Harray bound forbidden after parenthesized type-id", + &token->location); + inform (token->location, + "try removing the parentheses around the type-id"); cp_parser_direct_new_declarator (parser); } nelts = NULL_TREE; @@ -5430,19 +5644,21 @@ cp_parser_new_expression (cp_parser* parser) else type = cp_parser_new_type_id (parser, &nelts); - /* If the next token is a `(', then we have a new-initializer. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + /* If the next token is a `(' or '{', then we have a new-initializer. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN) + || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) initializer = cp_parser_new_initializer (parser); else initializer = NULL_TREE; /* A new-expression may not appear in an integral constant expression. */ - if (cp_parser_non_integral_constant_expression (parser, "`new'")) + if (cp_parser_non_integral_constant_expression (parser, "%")) return error_mark_node; /* Create a representation of the new-expression. */ - return build_new (placement, type, nelts, initializer, global_scope_p); + return build_new (placement, type, nelts, initializer, global_scope_p, + tf_warning_or_error); } /* Parse a new-placement. @@ -5592,10 +5808,11 @@ cp_parser_direct_new_declarator (cp_parser* parser) tree expression; /* Look for the opening `['. */ - cp_parser_require (parser, CPP_OPEN_SQUARE, "`['"); + cp_parser_require (parser, CPP_OPEN_SQUARE, "%<[%>"); /* The first expression is not required to be constant. */ if (!declarator) { + cp_token *token = cp_lexer_peek_token (parser->lexer); expression = cp_parser_expression (parser, /*cast_p=*/false); /* The standard requires that the expression have integral type. DR 74 adds enumeration types. We believe that the @@ -5611,8 +5828,8 @@ cp_parser_direct_new_declarator (cp_parser* parser) /*complain=*/true); if (!expression) { - error ("expression in new-declarator must have integral " - "or enumeration type"); + error ("%Hexpression in new-declarator must have integral " + "or enumeration type", &token->location); expression = error_mark_node; } } @@ -5624,7 +5841,7 @@ cp_parser_direct_new_declarator (cp_parser* parser) /*allow_non_constant=*/false, NULL); /* Look for the closing `]'. */ - cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); + cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>"); /* Add this bound to the declarator. */ declarator = make_array_declarator (declarator, expression); @@ -5642,6 +5859,7 @@ cp_parser_direct_new_declarator (cp_parser* parser) new-initializer: ( expression-list [opt] ) + braced-init-list Returns a representation of the expression-list. If there is no expression-list, VOID_ZERO_NODE is returned. */ @@ -5651,9 +5869,18 @@ cp_parser_new_initializer (cp_parser* parser) { tree expression_list; - expression_list = (cp_parser_parenthesized_expression_list - (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true, - /*non_constant_p=*/NULL)); + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + bool expr_non_constant_p; + maybe_warn_cpp0x ("extended initializer lists"); + expression_list = cp_parser_braced_list (parser, &expr_non_constant_p); + CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; + expression_list = build_tree_list (NULL_TREE, expression_list); + } + else + expression_list = (cp_parser_parenthesized_expression_list + (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true, + /*non_constant_p=*/NULL)); if (!expression_list) expression_list = void_zero_node; @@ -5681,14 +5908,14 @@ cp_parser_delete_expression (cp_parser* parser) /*current_scope_valid_p=*/false) != NULL_TREE); /* Look for the `delete' keyword. */ - cp_parser_require_keyword (parser, RID_DELETE, "`delete'"); + cp_parser_require_keyword (parser, RID_DELETE, "%"); /* See if the array syntax is in use. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) { /* Consume the `[' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the `]' token. */ - cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); + cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>"); /* Remember that this is the `[]' construct. */ array_p = true; } @@ -5700,12 +5927,67 @@ cp_parser_delete_expression (cp_parser* parser) /* A delete-expression may not appear in an integral constant expression. */ - if (cp_parser_non_integral_constant_expression (parser, "`delete'")) + if (cp_parser_non_integral_constant_expression (parser, "%")) return error_mark_node; return delete_sanity (expression, NULL_TREE, array_p, global_scope_p); } +/* Returns true if TOKEN may start a cast-expression and false + otherwise. */ + +static bool +cp_parser_token_starts_cast_expression (cp_token *token) +{ + switch (token->type) + { + case CPP_COMMA: + case CPP_SEMICOLON: + case CPP_QUERY: + case CPP_COLON: + case CPP_CLOSE_SQUARE: + case CPP_CLOSE_PAREN: + case CPP_CLOSE_BRACE: + case CPP_DOT: + case CPP_DOT_STAR: + case CPP_DEREF: + case CPP_DEREF_STAR: + case CPP_DIV: + case CPP_MOD: + case CPP_LSHIFT: + case CPP_RSHIFT: + case CPP_LESS: + case CPP_GREATER: + case CPP_LESS_EQ: + case CPP_GREATER_EQ: + case CPP_EQ_EQ: + case CPP_NOT_EQ: + case CPP_EQ: + case CPP_MULT_EQ: + case CPP_DIV_EQ: + case CPP_MOD_EQ: + case CPP_PLUS_EQ: + case CPP_MINUS_EQ: + case CPP_RSHIFT_EQ: + case CPP_LSHIFT_EQ: + case CPP_AND_EQ: + case CPP_XOR_EQ: + case CPP_OR_EQ: + case CPP_XOR: + case CPP_OR: + case CPP_OR_OR: + case CPP_EOF: + return false; + + /* '[' may start a primary-expression in obj-c++. */ + case CPP_OPEN_SQUARE: + return c_dialect_objc (); + + default: + return true; + } +} + /* Parse a cast-expression. cast-expression: @@ -5777,24 +6059,25 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p) /* Look for the type-id. */ type = cp_parser_type_id (parser); /* Look for the closing `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; } /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; - /* If ok so far, parse the dependent expression. We cannot be - sure it is a cast. Consider `(T ())'. It is a parenthesized - ctor of T, but looks like a cast to function returning T - without a dependent expression. */ - if (!cp_parser_error_occurred (parser)) - expr = cp_parser_cast_expression (parser, - /*address_p=*/false, - /*cast_p=*/true); - - if (cp_parser_parse_definitely (parser)) + /* At this point this can only be either a cast or a + parenthesized ctor such as `(T ())' that looks like a cast to + function returning T. */ + if (!cp_parser_error_occurred (parser) + && cp_parser_token_starts_cast_expression (cp_lexer_peek_token + (parser->lexer))) { + cp_parser_parse_definitely (parser); + expr = cp_parser_cast_expression (parser, + /*address_p=*/false, + /*cast_p=*/true); + /* Warn about old-style casts, if so requested. */ if (warn_old_style_cast && !in_system_header @@ -5815,6 +6098,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p) expr = build_c_cast (type, expr); return expr; } + else + cp_parser_abort_tentative_parse (parser); } /* If we get here, then it's not a cast, so it must be a @@ -5902,14 +6187,15 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p) : binops_by_token[token->type].prec) static tree -cp_parser_binary_expression (cp_parser* parser, bool cast_p) +cp_parser_binary_expression (cp_parser* parser, bool cast_p, + enum cp_parser_prec prec) { cp_parser_expression_stack stack; cp_parser_expression_stack_entry *sp = &stack[0]; tree lhs, rhs; cp_token *token; enum tree_code tree_type, lhs_type, rhs_type; - enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec; + enum cp_parser_prec new_prec, lookahead_prec; bool overloaded_p; /* Parse the first expression. */ @@ -6000,8 +6286,15 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p) } overloaded_p = false; + /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type == + ERROR_MARK for everything that is not a binary expression. + This makes warn_about_parentheses miss some warnings that + involve unary operators. For unary expressions we should + pass the correct tree_code unless the unary expression was + surrounded by parentheses. + */ lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type, - &overloaded_p); + &overloaded_p, tf_warning_or_error); lhs_type = tree_type; /* If the binary operator required the use of an overloaded operator, @@ -6050,14 +6343,15 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr) expr = cp_parser_expression (parser, /*cast_p=*/false); /* The next token should be a `:'. */ - cp_parser_require (parser, CPP_COLON, "`:'"); + cp_parser_require (parser, CPP_COLON, "%<:%>"); /* Parse the assignment-expression. */ assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false); /* Build the conditional-expression. */ return build_x_conditional_expr (logical_or_expr, expr, - assignment_expr); + assignment_expr, + tf_warning_or_error); } /* Parse an assignment-expression. @@ -6085,7 +6379,7 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p) else { /* Parse the binary expressions (logical-or-expression). */ - expr = cp_parser_binary_expression (parser, cast_p); + expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR); /* If the next token is a `?' then we're actually looking at a conditional-expression. */ if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY)) @@ -6100,10 +6394,14 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p) = cp_parser_assignment_operator_opt (parser); if (assignment_operator != ERROR_MARK) { - tree rhs; + bool non_constant_p; /* Parse the right-hand side of the assignment. */ - rhs = cp_parser_assignment_expression (parser, cast_p); + tree rhs = cp_parser_initializer_clause (parser, &non_constant_p); + + if (BRACE_ENCLOSED_INITIALIZER_P (rhs)) + maybe_warn_cpp0x ("extended initializer lists"); + /* An assignment may not appear in a constant-expression. */ if (cp_parser_non_integral_constant_expression (parser, @@ -6112,7 +6410,8 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p) /* Build the assignment expression. */ expr = build_x_modify_expr (expr, assignment_operator, - rhs); + rhs, + tf_warning_or_error); } } } @@ -6143,7 +6442,7 @@ cp_parser_assignment_operator_opt (cp_parser* parser) enum tree_code op; cp_token *token; - /* Peek at the next toen. */ + /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); switch (token->type) @@ -6232,7 +6531,8 @@ cp_parser_expression (cp_parser* parser, bool cast_p) expression = assignment_expression; else expression = build_x_compound_expr (expression, - assignment_expression); + assignment_expression, + tf_warning_or_error); /* If the next token is not a comma, then we are done with the expression. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) @@ -6335,6 +6635,7 @@ cp_parser_builtin_offsetof (cp_parser *parser) int save_ice_p, save_non_ice_p; tree type, expr; cp_id_kind dummy; + cp_token *token; /* We're about to accept non-integral-constant things, but will definitely yield an integral constant expression. Save and @@ -6345,21 +6646,23 @@ cp_parser_builtin_offsetof (cp_parser *parser) /* Consume the "__builtin_offsetof" token. */ cp_lexer_consume_token (parser->lexer); /* Consume the opening `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); /* Parse the type-id. */ type = cp_parser_type_id (parser); /* Look for the `,'. */ - cp_parser_require (parser, CPP_COMMA, "`,'"); + cp_parser_require (parser, CPP_COMMA, "%<,%>"); + token = cp_lexer_peek_token (parser->lexer); /* Build the (type *)null that begins the traditional offsetof macro. */ - expr = build_static_cast (build_pointer_type (type), null_pointer_node); + expr = build_static_cast (build_pointer_type (type), null_pointer_node, + tf_warning_or_error); /* Parse the offsetof-member-designator. We begin as if we saw "expr->". */ expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr, - true, &dummy); + true, &dummy, token->location); while (true) { - cp_token *token = cp_lexer_peek_token (parser->lexer); + token = cp_lexer_peek_token (parser->lexer); switch (token->type) { case CPP_OPEN_SQUARE: @@ -6371,7 +6674,8 @@ cp_parser_builtin_offsetof (cp_parser *parser) /* offsetof-member-designator "." identifier */ cp_lexer_consume_token (parser->lexer); expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr, - true, &dummy); + true, &dummy, + token->location); break; case CPP_CLOSE_PAREN: @@ -6382,7 +6686,7 @@ cp_parser_builtin_offsetof (cp_parser *parser) default: /* Error. We know the following require will fail, but that gives the proper error message. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); cp_parser_skip_to_closing_parenthesis (parser, true, false, true); expr = error_mark_node; goto failure; @@ -6476,10 +6780,13 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) /* Consume the token. */ cp_lexer_consume_token (parser->lexer); - cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); type1 = cp_parser_type_id (parser); + if (type1 == error_mark_node) + return error_mark_node; + /* Build a trivial decl-specifier-seq. */ clear_decl_specs (&decl_specs); decl_specs.type = type1; @@ -6490,10 +6797,13 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) if (binary) { - cp_parser_require (parser, CPP_COMMA, "`,'"); + cp_parser_require (parser, CPP_COMMA, "%<,%>"); type2 = cp_parser_type_id (parser); + if (type2 == error_mark_node) + return error_mark_node; + /* Build a trivial decl-specifier-seq. */ clear_decl_specs (&decl_specs); decl_specs.type = type2; @@ -6503,10 +6813,10 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) /*initialized=*/0, /*attrlist=*/NULL); } - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); - /* Complete the trait expr, which may mean either processing the - static assert now or saving it for template instantiation. */ + /* Complete the trait expression, which may mean either processing + the trait expr now or saving it for template instantiation. */ return finish_trait_expr (kind, type1, type2); } @@ -6727,7 +7037,8 @@ cp_parser_label_for_labeled_statement (cp_parser* parser) if (parser->in_switch_statement_p) finish_case_label (expr, expr_hi); else - error ("case label %qE not within a switch statement", expr); + error ("%Hcase label %qE not within a switch statement", + &token->location, expr); } break; @@ -6738,7 +7049,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser) if (parser->in_switch_statement_p) finish_case_label (NULL_TREE, NULL_TREE); else - error ("case label not within a switch statement"); + error ("%Hcase label not within a switch statement", &token->location); break; default: @@ -6748,7 +7059,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser) } /* Require the `:' token. */ - cp_parser_require (parser, CPP_COLON, "`:'"); + cp_parser_require (parser, CPP_COLON, "%<:%>"); } /* Parse an expression-statement. @@ -6792,6 +7103,15 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) compound-statement: { statement-seq [opt] } + GNU extension: + + compound-statement: + { label-declaration-seq [opt] statement-seq [opt] } + + label-declaration-seq: + label-declaration + label-declaration-seq label-declaration + Returns a tree representing the statement. */ static tree @@ -6801,16 +7121,19 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, tree compound_stmt; /* Consume the `{'. */ - if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'")) + if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>")) return error_mark_node; /* Begin the compound-statement. */ compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0); + /* If the next keyword is `__label__' we have a label declaration. */ + while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL)) + cp_parser_label_declaration (parser); /* Parse an (optional) statement-seq. */ cp_parser_statement_seq_opt (parser, in_statement_expr); /* Finish the compound-statement. */ finish_compound_stmt (compound_stmt); /* Consume the `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); return compound_stmt; } @@ -6844,7 +7167,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr) else { token = cp_lexer_consume_token (parser->lexer); - error ("% without a previous %"); + error ("%H% without a previous %", &token->location); } } @@ -6890,7 +7213,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) tree condition; /* Look for the `('. */ - if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>")) { cp_parser_skip_to_end_of_statement (parser); return error_mark_node; @@ -6905,7 +7228,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) /* Parse the condition. */ condition = cp_parser_condition (parser); /* Look for the `)'. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>")) cp_parser_skip_to_closing_parenthesis (parser, true, false, /*consume_paren=*/true); @@ -6920,7 +7243,18 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) /* Parse the then-clause. */ in_statement = parser->in_statement; parser->in_statement |= IN_IF_STMT; - cp_parser_implicitly_scoped_statement (parser, &nested_if); + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + { + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + add_stmt (build_empty_stmt ()); + cp_lexer_consume_token (parser->lexer); + if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE)) + warning_at (loc, OPT_Wempty_body, "suggest braces around " + "empty body in an % statement"); + nested_if = false; + } + else + cp_parser_implicitly_scoped_statement (parser, &nested_if); parser->in_statement = in_statement; finish_then_clause (statement); @@ -6933,7 +7267,17 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) cp_lexer_consume_token (parser->lexer); begin_else_clause (statement); /* Parse the else-clause. */ - cp_parser_implicitly_scoped_statement (parser, NULL); + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + { + warning_at (cp_lexer_peek_token (parser->lexer)->location, + OPT_Wempty_body, "suggest braces around " + "empty body in an % statement"); + add_stmt (build_empty_stmt ()); + cp_lexer_consume_token (parser->lexer); + } + else + cp_parser_implicitly_scoped_statement (parser, NULL); + finish_else_clause (statement); /* If we are currently parsing a then-clause, then @@ -6995,7 +7339,8 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) condition: expression - type-specifier-seq declarator = assignment-expression + type-specifier-seq declarator = initializer-clause + type-specifier-seq declarator braced-init-list GNU Extension: @@ -7041,31 +7386,47 @@ cp_parser_condition (cp_parser* parser) attributes = cp_parser_attributes_opt (parser); /* Parse the asm-specification. */ asm_specification = cp_parser_asm_specification_opt (parser); - /* If the next token is not an `=', then we might still be + /* If the next token is not an `=' or '{', then we might still be looking at an expression. For example: if (A(a).x) looks like a decl-specifier-seq and a declarator -- but then there is no `=', so this is an expression. */ - cp_parser_require (parser, CPP_EQ, "`='"); - /* If we did see an `=', then we are looking at a declaration + if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ) + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) + cp_parser_simulate_error (parser); + + /* If we did see an `=' or '{', then we are looking at a declaration for sure. */ if (cp_parser_parse_definitely (parser)) { tree pushed_scope; bool non_constant_p; + bool flags = LOOKUP_ONLYCONVERTING; /* Create the declaration. */ decl = start_decl (declarator, &type_specifiers, /*initialized_p=*/true, attributes, /*prefix_attributes=*/NULL_TREE, &pushed_scope); - /* Parse the assignment-expression. */ - initializer - = cp_parser_constant_expression (parser, - /*allow_non_constant_p=*/true, - &non_constant_p); + + /* Parse the initializer. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + initializer = cp_parser_braced_list (parser, &non_constant_p); + CONSTRUCTOR_IS_DIRECT_INIT (initializer) = 1; + flags = 0; + } + else + { + /* Consume the `='. */ + cp_parser_require (parser, CPP_EQ, "%<=%>"); + initializer = cp_parser_initializer_clause (parser, &non_constant_p); + } + if (BRACE_ENCLOSED_INITIALIZER_P (initializer)) + maybe_warn_cpp0x ("extended initializer lists"); + if (!non_constant_p) initializer = fold_non_dependent_expr (initializer); @@ -7073,7 +7434,7 @@ cp_parser_condition (cp_parser* parser) cp_finish_decl (decl, initializer, !non_constant_p, asm_specification, - LOOKUP_ONLYCONVERTING); + flags); if (pushed_scope) pop_scope (pushed_scope); @@ -7090,51 +7451,6 @@ cp_parser_condition (cp_parser* parser) return cp_parser_expression (parser, /*cast_p=*/false); } -/* We check for a ) immediately followed by ; with no whitespacing - between. This is used to issue a warning for: - - while (...); - - and: - - for (...); - - as the semicolon is probably extraneous. - - On parse errors, the next token might not be a ), so do nothing in - that case. */ - -static void -check_empty_body (cp_parser* parser, const char* type) -{ - cp_token *token; - cp_token *close_paren; - expanded_location close_loc; - expanded_location semi_loc; - - close_paren = cp_lexer_peek_token (parser->lexer); - if (close_paren->type != CPP_CLOSE_PAREN) - return; - - close_loc = expand_location (close_paren->location); - token = cp_lexer_peek_nth_token (parser->lexer, 2); - - if (token->type != CPP_SEMICOLON - || (token->flags & PREV_WHITE)) - return; - - semi_loc = expand_location (token->location); - if (close_loc.line == semi_loc.line -#ifdef USE_MAPPED_LOCATION - && close_loc.column+1 == semi_loc.column -#endif - ) - warning (OPT_Wempty_body, - "suggest a space before %<;%> or explicit braces around empty " - "body in %<%s%> statement", - type); -} - /* Parse an iteration-statement. iteration-statement: @@ -7173,13 +7489,12 @@ cp_parser_iteration_statement (cp_parser* parser) /* Begin the while-statement. */ statement = begin_while_stmt (); /* Look for the `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); /* Parse the condition. */ condition = cp_parser_condition (parser); finish_while_stmt_cond (condition, statement); - check_empty_body (parser, "while"); /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); /* Parse the dependent statement. */ parser->in_statement = IN_ITERATION_STMT; cp_parser_already_scoped_statement (parser); @@ -7201,17 +7516,17 @@ cp_parser_iteration_statement (cp_parser* parser) parser->in_statement = in_statement; finish_do_body (statement); /* Look for the `while' keyword. */ - cp_parser_require_keyword (parser, RID_WHILE, "`while'"); + cp_parser_require_keyword (parser, RID_WHILE, "%"); /* Look for the `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); /* Parse the expression. */ expression = cp_parser_expression (parser, /*cast_p=*/false); /* We're done with the do-statement. */ finish_do_stmt (expression, statement); /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); /* Look for the `;'. */ - cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); } break; @@ -7223,7 +7538,7 @@ cp_parser_iteration_statement (cp_parser* parser) /* Begin the for-statement. */ statement = begin_for_stmt (); /* Look for the `('. */ - cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); /* Parse the initialization. */ cp_parser_for_init_statement (parser); finish_for_init_stmt (statement); @@ -7233,15 +7548,14 @@ cp_parser_iteration_statement (cp_parser* parser) condition = cp_parser_condition (parser); finish_for_cond (condition, statement); /* Look for the `;'. */ - cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); /* If there's an expression, process it. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) expression = cp_parser_expression (parser, /*cast_p=*/false); finish_for_expr (expression, statement); - check_empty_body (parser, "for"); /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); /* Parse the body of the for-statement. */ parser->in_statement = IN_ITERATION_STMT; @@ -7300,6 +7614,7 @@ cp_parser_for_init_statement (cp_parser* parser) break ; continue ; return expression [opt] ; + return braced-init-list ; goto identifier ; GNU extension: @@ -7331,7 +7646,7 @@ cp_parser_jump_statement (cp_parser* parser) switch (in_statement) { case 0: - error ("break statement not within loop or switch"); + error ("%Hbreak statement not within loop or switch", &token->location); break; default: gcc_assert ((in_statement & IN_SWITCH_STMT) @@ -7339,10 +7654,10 @@ cp_parser_jump_statement (cp_parser* parser) statement = finish_break_stmt (); break; case IN_OMP_BLOCK: - error ("invalid exit from OpenMP structured block"); + error ("%Hinvalid exit from OpenMP structured block", &token->location); break; case IN_OMP_FOR: - error ("break statement used with OpenMP for loop"); + error ("%Hbreak statement used with OpenMP for loop", &token->location); break; } cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); @@ -7352,14 +7667,14 @@ cp_parser_jump_statement (cp_parser* parser) switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT)) { case 0: - error ("continue statement not within a loop"); + error ("%Hcontinue statement not within a loop", &token->location); break; case IN_ITERATION_STMT: case IN_OMP_FOR: statement = finish_continue_stmt (); break; case IN_OMP_BLOCK: - error ("invalid exit from OpenMP structured block"); + error ("%Hinvalid exit from OpenMP structured block", &token->location); break; default: gcc_unreachable (); @@ -7370,12 +7685,18 @@ cp_parser_jump_statement (cp_parser* parser) case RID_RETURN: { tree expr; + bool expr_non_constant_p; - /* If the next token is a `;', then there is no - expression. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + maybe_warn_cpp0x ("extended initializer lists"); + expr = cp_parser_braced_list (parser, &expr_non_constant_p); + } + else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) expr = cp_parser_expression (parser, /*cast_p=*/false); else + /* If the next token is a `;', then there is no + expression. */ expr = NULL_TREE; /* Build the return-statement. */ statement = finish_return_stmt (expr); @@ -7389,8 +7710,7 @@ cp_parser_jump_statement (cp_parser* parser) if (cp_lexer_next_token_is (parser->lexer, CPP_MULT)) { /* Issue a warning about this use of a GNU extension. */ - if (pedantic) - pedwarn ("ISO C++ forbids computed gotos"); + pedwarn (token->location, OPT_pedantic, "ISO C++ forbids computed gotos"); /* Consume the '*' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the dependent expression. */ @@ -7496,9 +7816,9 @@ cp_parser_already_scoped_statement (cp_parser* parser) { /* Avoid calling cp_parser_compound_statement, so that we don't create a new scope. Do everything else by hand. */ - cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); + cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"); cp_parser_statement_seq_opt (parser, NULL_TREE); - cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); } } @@ -7529,8 +7849,8 @@ cp_parser_declaration_seq_opt (cp_parser* parser) /* A declaration consisting of a single semicolon is invalid. Allow it unless we're being pedantic. */ cp_lexer_consume_token (parser->lexer); - if (pedantic && !in_system_header) - pedwarn ("extra %<;%>"); + if (!in_system_header) + pedwarn (input_location, OPT_pedantic, "extra %<;%>"); continue; } @@ -7656,6 +7976,10 @@ cp_parser_declaration (cp_parser* parser) || token2.type == CPP_OPEN_BRACE || token2.keyword == RID_ATTRIBUTE)) cp_parser_namespace_definition (parser); + /* An inline (associated) namespace definition. */ + else if (token1.keyword == RID_INLINE + && token2.keyword == RID_NAMESPACE) + cp_parser_namespace_definition (parser); /* Objective-C++ declaration/definition. */ else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword)) cp_parser_objc_declaration (parser); @@ -7682,7 +8006,6 @@ cp_parser_declaration (cp_parser* parser) block-declaration: __extension__ block-declaration - label-declaration C++0x Extension: @@ -7743,12 +8066,16 @@ cp_parser_block_declaration (cp_parser *parser, cp_parser_using_declaration (parser, /*access_declaration_p=*/false); } - /* If the next keyword is `__label__' we have a label declaration. */ + /* If the next keyword is `__label__' we have a misplaced label + declaration. */ else if (token1->keyword == RID_LABEL) { - if (statement_p) - cp_parser_commit_to_tentative_parse (parser); - cp_parser_label_declaration (parser); + cp_lexer_consume_token (parser->lexer); + error ("%H%<__label__%> not at the beginning of a block", &token1->location); + cp_parser_skip_to_end_of_statement (parser); + /* If the next token is now a `;', consume it. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + cp_lexer_consume_token (parser->lexer); } /* If the next token is `static_assert' we have a static assertion. */ else if (token1->keyword == RID_STATIC_ASSERT) @@ -7831,7 +8158,9 @@ cp_parser_simple_declaration (cp_parser* parser, 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.any_specifiers_p - && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN) + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE) + && !cp_parser_error_occurred (parser)) cp_parser_commit_to_tentative_parse (parser); /* Keep going until we hit the `;' at the end of the simple @@ -7877,7 +8206,11 @@ cp_parser_simple_declaration (cp_parser* parser, which is erroneous. */ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) - error ("mixing declarations and function-definitions is forbidden"); + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + error ("%Hmixing declarations and function-definitions is forbidden", + &token->location); + } /* Otherwise, we're done with the list of declarators. */ else { @@ -7929,7 +8262,7 @@ cp_parser_simple_declaration (cp_parser* parser, } /* Consume the `;'. */ - cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); done: pop_deferring_access_checks (); @@ -7973,6 +8306,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, int* declares_class_or_enum) { bool constructor_possible_p = !parser->in_declarator_p; + cp_token *start_token = NULL; /* Clear DECL_SPECS. */ clear_decl_specs (decl_specs); @@ -7989,6 +8323,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser, /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); + + /* Save the first token of the decl spec list for error + reporting. */ + if (!start_token) + start_token = token; /* Handle attributes. */ if (token->keyword == RID_ATTRIBUTE) { @@ -8009,7 +8348,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, case RID_FRIEND: if (!at_class_scope_p ()) { - error ("% used outside of class"); + error ("%H% used outside of class", &token->location); cp_lexer_purge_token (parser->lexer); } else @@ -8056,13 +8395,35 @@ cp_parser_decl_specifier_seq (cp_parser* parser, GNU Extension: thread */ case RID_AUTO: + if (cxx_dialect == cxx98) + { + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); + + /* Complain about `auto' as a storage specifier, if + we're complaining about C++0x compatibility. */ + warning + (OPT_Wc__0x_compat, + "%H% will change meaning in C++0x; please remove it", + &token->location); + + /* Set the storage class anyway. */ + cp_parser_set_storage_class (parser, decl_specs, RID_AUTO, + token->location); + } + else + /* C++0x auto type-specifier. */ + found_decl_spec = false; + break; + case RID_REGISTER: case RID_STATIC: case RID_EXTERN: case RID_MUTABLE: /* Consume the token. */ cp_lexer_consume_token (parser->lexer); - cp_parser_set_storage_class (parser, decl_specs, token->keyword); + cp_parser_set_storage_class (parser, decl_specs, token->keyword, + token->location); break; case RID_THREAD: /* Consume the token. */ @@ -8098,7 +8459,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser, /*is_declaration=*/true, &decl_spec_declares_class_or_enum, &is_cv_qualifier); - *declares_class_or_enum |= decl_spec_declares_class_or_enum; /* If this type-specifier referenced a user-defined type @@ -8158,12 +8518,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser, flags |= CP_PARSER_FLAGS_OPTIONAL; } - cp_parser_check_decl_spec (decl_specs); + cp_parser_check_decl_spec (decl_specs, start_token->location); /* Don't allow a friend specifier with a class definition. */ if (decl_specs->specs[(int) ds_friend] != 0 && (*declares_class_or_enum & 2)) - error ("class definition may not be declared a friend"); + error ("%Hclass definition may not be declared a friend", + &start_token->location); } /* Parse an (optional) storage-class-specifier. @@ -8188,6 +8549,10 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser) switch (cp_lexer_peek_token (parser->lexer)->keyword) { case RID_AUTO: + if (cxx_dialect != cxx98) + return NULL_TREE; + /* Fall through for C++98. */ + case RID_REGISTER: case RID_STATIC: case RID_EXTERN: @@ -8215,7 +8580,8 @@ static tree cp_parser_function_specifier_opt (cp_parser* parser, cp_decl_specifier_seq *decl_specs) { - switch (cp_lexer_peek_token (parser->lexer)->keyword) + cp_token *token = cp_lexer_peek_token (parser->lexer); + switch (token->keyword) { case RID_INLINE: if (decl_specs) @@ -8227,7 +8593,7 @@ cp_parser_function_specifier_opt (cp_parser* parser, A member function template shall not be virtual. */ if (PROCESSING_REAL_TEMPLATE_DECL_P ()) - error ("templates may not be %"); + error ("%Htemplates may not be %", &token->location); else if (decl_specs) ++decl_specs->specs[(int) ds_virtual]; break; @@ -8257,7 +8623,7 @@ cp_parser_linkage_specification (cp_parser* parser) tree linkage; /* Look for the `extern' keyword. */ - cp_parser_require_keyword (parser, RID_EXTERN, "`extern'"); + cp_parser_require_keyword (parser, RID_EXTERN, "%"); /* Look for the string-literal. */ linkage = cp_parser_string_literal (parser, false, false); @@ -8287,7 +8653,7 @@ cp_parser_linkage_specification (cp_parser* parser) /* Parse the declarations. */ cp_parser_declaration_seq_opt (parser); /* Look for the closing `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); } /* Otherwise, there's just one declaration. */ else @@ -8328,7 +8694,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) /* Look for the `static_assert' keyword. */ if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, - "`static_assert'")) + "%")) return; /* We know we are in a static assertion; commit to any tentative @@ -8337,7 +8703,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) cp_parser_commit_to_tentative_parse (parser); /* Parse the `(' starting the static assertion condition. */ - cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); /* Parse the constant-expression. */ condition = @@ -8346,7 +8712,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) /*non_constant_p=*/NULL); /* Parse the separating `,'. */ - cp_parser_require (parser, CPP_COMMA, "`,'"); + cp_parser_require (parser, CPP_COMMA, "%<,%>"); /* Parse the string-literal message. */ message = cp_parser_string_literal (parser, @@ -8354,20 +8720,189 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) /*wide_ok=*/true); /* A `)' completes the static assertion. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>")) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, /*consume_paren=*/true); /* A semicolon terminates the declaration. */ - cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); /* Complete the static assertion, which may mean either processing the static assert now or saving it for template instantiation. */ finish_static_assert (condition, message, saved_loc, member_p); } +/* Parse a `decltype' type. Returns the type. + + simple-type-specifier: + decltype ( expression ) */ + +static tree +cp_parser_decltype (cp_parser *parser) +{ + tree expr; + bool id_expression_or_member_access_p = false; + const char *saved_message; + bool saved_integral_constant_expression_p; + bool saved_non_integral_constant_expression_p; + cp_token *id_expr_start_token; + + /* Look for the `decltype' token. */ + if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%")) + return error_mark_node; + + /* Types cannot be defined in a `decltype' expression. Save away the + old message. */ + saved_message = parser->type_definition_forbidden_message; + + /* And create the new one. */ + parser->type_definition_forbidden_message + = "types may not be defined in % expressions"; + + /* The restrictions on constant-expressions do not apply inside + decltype expressions. */ + saved_integral_constant_expression_p + = parser->integral_constant_expression_p; + saved_non_integral_constant_expression_p + = parser->non_integral_constant_expression_p; + parser->integral_constant_expression_p = false; + + /* Do not actually evaluate the expression. */ + ++skip_evaluation; + + /* Parse the opening `('. */ + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>")) + return error_mark_node; + + /* First, try parsing an id-expression. */ + id_expr_start_token = cp_lexer_peek_token (parser->lexer); + cp_parser_parse_tentatively (parser); + expr = cp_parser_id_expression (parser, + /*template_keyword_p=*/false, + /*check_dependency_p=*/true, + /*template_p=*/NULL, + /*declarator_p=*/false, + /*optional_p=*/false); + + if (!cp_parser_error_occurred (parser) && expr != error_mark_node) + { + bool non_integral_constant_expression_p = false; + tree id_expression = expr; + cp_id_kind idk; + const char *error_msg; + + if (TREE_CODE (expr) == IDENTIFIER_NODE) + /* Lookup the name we got back from the id-expression. */ + expr = cp_parser_lookup_name (parser, expr, + none_type, + /*is_template=*/false, + /*is_namespace=*/false, + /*check_dependency=*/true, + /*ambiguous_decls=*/NULL, + id_expr_start_token->location); + + if (expr + && expr != error_mark_node + && TREE_CODE (expr) != TEMPLATE_ID_EXPR + && TREE_CODE (expr) != TYPE_DECL + && (TREE_CODE (expr) != BIT_NOT_EXPR + || !TYPE_P (TREE_OPERAND (expr, 0))) + && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) + { + /* Complete lookup of the id-expression. */ + expr = (finish_id_expression + (id_expression, expr, parser->scope, &idk, + /*integral_constant_expression_p=*/false, + /*allow_non_integral_constant_expression_p=*/true, + &non_integral_constant_expression_p, + /*template_p=*/false, + /*done=*/true, + /*address_p=*/false, + /*template_arg_p=*/false, + &error_msg, + id_expr_start_token->location)); + + if (expr == error_mark_node) + /* We found an id-expression, but it was something that we + should not have found. This is an error, not something + we can recover from, so note that we found an + id-expression and we'll recover as gracefully as + possible. */ + id_expression_or_member_access_p = true; + } + + if (expr + && expr != error_mark_node + && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) + /* We have an id-expression. */ + id_expression_or_member_access_p = true; + } + + if (!id_expression_or_member_access_p) + { + /* Abort the id-expression parse. */ + cp_parser_abort_tentative_parse (parser); + + /* Parsing tentatively, again. */ + cp_parser_parse_tentatively (parser); + + /* Parse a class member access. */ + expr = cp_parser_postfix_expression (parser, /*address_p=*/false, + /*cast_p=*/false, + /*member_access_only_p=*/true); + + if (expr + && expr != error_mark_node + && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) + /* We have an id-expression. */ + id_expression_or_member_access_p = true; + } + + if (id_expression_or_member_access_p) + /* We have parsed the complete id-expression or member access. */ + cp_parser_parse_definitely (parser); + else + { + /* Abort our attempt to parse an id-expression or member access + expression. */ + cp_parser_abort_tentative_parse (parser); + + /* Parse a full expression. */ + expr = cp_parser_expression (parser, /*cast_p=*/false); + } + + /* Go back to evaluating expressions. */ + --skip_evaluation; + + /* Restore the old message and the integral constant expression + flags. */ + parser->type_definition_forbidden_message = saved_message; + parser->integral_constant_expression_p + = saved_integral_constant_expression_p; + parser->non_integral_constant_expression_p + = saved_non_integral_constant_expression_p; + + if (expr == error_mark_node) + { + /* Skip everything up to the closing `)'. */ + cp_parser_skip_to_closing_parenthesis (parser, true, false, + /*consume_paren=*/true); + return error_mark_node; + } + + /* Parse to the closing `)'. */ + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>")) + { + cp_parser_skip_to_closing_parenthesis (parser, true, false, + /*consume_paren=*/true); + return error_mark_node; + } + + return finish_decltype_type (expr, id_expression_or_member_access_p); +} + /* Special member functions [gram.special] */ /* Parse a conversion-function-id. @@ -8387,7 +8922,7 @@ cp_parser_conversion_function_id (cp_parser* parser) tree pushed_scope = NULL_TREE; /* Look for the `operator' token. */ - if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'")) + if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%")) return error_mark_node; /* When we parse the conversion-type-id, the current scope will be reset. However, we need that information in able to look up the @@ -8455,6 +8990,16 @@ cp_parser_conversion_type_id (cp_parser* parser) /*initialized=*/0, &attributes); if (attributes) cplus_decl_attributes (&type_specified, attributes, /*flags=*/0); + + /* Don't give this error when parsing tentatively. This happens to + work because we always parse this definitively once. */ + if (! cp_parser_uncommitted_to_tentative_parse_p (parser) + && type_uses_auto (type_specified)) + { + error ("invalid use of % in conversion operator"); + return error_mark_node; + } + return type_specified; } @@ -8530,17 +9075,20 @@ static void cp_parser_mem_initializer_list (cp_parser* parser) { tree mem_initializer_list = NULL_TREE; + cp_token *token = cp_lexer_peek_token (parser->lexer); /* Let the semantic analysis code know that we are starting the mem-initializer-list. */ if (!DECL_CONSTRUCTOR_P (current_function_decl)) - error ("only constructors take base initializers"); + error ("%Honly constructors take base initializers", + &token->location); /* Loop through the list. */ while (true) { tree mem_initializer; + token = cp_lexer_peek_token (parser->lexer); /* Parse the mem-initializer. */ mem_initializer = cp_parser_mem_initializer (parser); /* If the next token is a `...', we're expanding member initializers. */ @@ -8554,8 +9102,8 @@ cp_parser_mem_initializer_list (cp_parser* parser) if (mem_initializer != error_mark_node && !TYPE_P (TREE_PURPOSE (mem_initializer))) { - error ("cannot expand initializer for member %<%D%>", - TREE_PURPOSE (mem_initializer)); + error ("%Hcannot expand initializer for member %<%D%>", + &token->location, TREE_PURPOSE (mem_initializer)); mem_initializer = error_mark_node; } @@ -8585,6 +9133,7 @@ cp_parser_mem_initializer_list (cp_parser* parser) mem-initializer: mem-initializer-id ( expression-list [opt] ) + mem-initializer-id braced-init-list GNU extension: @@ -8602,11 +9151,13 @@ cp_parser_mem_initializer (cp_parser* parser) tree mem_initializer_id; tree expression_list; tree member; + cp_token *token = cp_lexer_peek_token (parser->lexer); /* Find out what is being initialized. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - pedwarn ("anachronistic old-style base class initializer"); + permerror (token->location, + "anachronistic old-style base class initializer"); mem_initializer_id = NULL_TREE; } else @@ -8615,11 +9166,20 @@ cp_parser_mem_initializer (cp_parser* parser) if (member && !DECL_P (member)) in_base_initializer = 1; - expression_list - = cp_parser_parenthesized_expression_list (parser, false, - /*cast_p=*/false, - /*allow_expansion_p=*/true, - /*non_constant_p=*/NULL); + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + bool expr_non_constant_p; + maybe_warn_cpp0x ("extended initializer lists"); + expression_list = cp_parser_braced_list (parser, &expr_non_constant_p); + CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; + expression_list = build_tree_list (NULL_TREE, expression_list); + } + else + expression_list + = cp_parser_parenthesized_expression_list (parser, false, + /*cast_p=*/false, + /*allow_expansion_p=*/true, + /*non_constant_p=*/NULL); if (expression_list == error_mark_node) return error_mark_node; if (!expression_list) @@ -8648,11 +9208,14 @@ cp_parser_mem_initializer_id (cp_parser* parser) bool template_p = false; tree id; + cp_token *token = cp_lexer_peek_token (parser->lexer); + /* `typename' is not allowed in this context ([temp.res]). */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME)) { - error ("keyword % not allowed in this context (a qualified " - "member initializer is implicitly a type)"); + error ("%Hkeyword % not allowed in this context (a qualified " + "member initializer is implicitly a type)", + &token->location); cp_lexer_consume_token (parser->lexer); } /* Look for the optional `::' operator. */ @@ -8722,7 +9285,7 @@ static tree cp_parser_operator_function_id (cp_parser* parser) { /* Look for the `operator' keyword. */ - if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'")) + if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%")) return error_mark_node; /* And then the name of the operator itself. */ return cp_parser_operator (parser); @@ -8778,7 +9341,7 @@ cp_parser_operator (cp_parser* parser) /* Consume the `[' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the `]' token. */ - cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); + cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>"); id = ansi_opname (op == NEW_EXPR ? VEC_NEW_EXPR : VEC_DELETE_EXPR); } @@ -8937,14 +9500,14 @@ cp_parser_operator (cp_parser* parser) /* Consume the `('. */ cp_lexer_consume_token (parser->lexer); /* Look for the matching `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); return ansi_opname (CALL_EXPR); case CPP_OPEN_SQUARE: /* Consume the `['. */ cp_lexer_consume_token (parser->lexer); /* Look for the matching `]'. */ - cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); + cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>"); return ansi_opname (ARRAY_REF); default: @@ -9020,7 +9583,6 @@ cp_parser_template_parameter_list (cp_parser* parser) while (true) { tree parameter; - cp_token *token; bool is_non_type; bool is_parameter_pack; @@ -9041,10 +9603,8 @@ cp_parser_template_parameter_list (cp_parser* parser) parameter_list = chainon (parameter_list, err_parm); } - /* Peek at the next token. */ - token = cp_lexer_peek_token (parser->lexer); - /* If it's not a `,', we're done. */ - if (token->type != CPP_COMMA) + /* If the next token is not a `,', we're done. */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) break; /* Otherwise, consume the `,' token. */ cp_lexer_consume_token (parser->lexer); @@ -9071,6 +9631,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, { cp_token *token; cp_parameter_declarator *parameter_declarator; + cp_declarator *id_declarator; tree parm; /* Assume it is a type parameter or a template parameter. */ @@ -9141,17 +9702,54 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, /* If the next token is an ellipsis, and we don't already have it marked as a parameter pack, then we have a parameter pack (that - has no declarator); */ + has no declarator). */ if (!*is_parameter_pack && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS) && declarator_can_be_parameter_pack (parameter_declarator->declarator)) { - /* Consume the `...'. */ + /* Consume the `...'. */ cp_lexer_consume_token (parser->lexer); maybe_warn_variadic_templates (); *is_parameter_pack = true; } + /* We might end up with a pack expansion as the type of the non-type + template parameter, in which case this is a non-type template + parameter pack. */ + else if (parameter_declarator + && parameter_declarator->decl_specifiers.type + && PACK_EXPANSION_P (parameter_declarator->decl_specifiers.type)) + { + *is_parameter_pack = true; + parameter_declarator->decl_specifiers.type = + PACK_EXPANSION_PATTERN (parameter_declarator->decl_specifiers.type); + } + + if (*is_parameter_pack && cp_lexer_next_token_is (parser->lexer, CPP_EQ)) + { + /* Parameter packs cannot have default arguments. However, a + user may try to do so, so we'll parse them and give an + appropriate diagnostic here. */ + + /* Consume the `='. */ + cp_token *start_token = cp_lexer_peek_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + + /* Find the name of the parameter pack. */ + id_declarator = parameter_declarator->declarator; + while (id_declarator && id_declarator->kind != cdk_id) + id_declarator = id_declarator->declarator; + + if (id_declarator && id_declarator->kind == cdk_id) + error ("%Htemplate parameter pack %qD cannot have a default argument", + &start_token->location, id_declarator->u.id.unqualified_name); + else + error ("%Htemplate parameter pack cannot have a default argument", + &start_token->location); + + /* Parse the default argument, but throw away the result. */ + cp_parser_default_argument (parser, /*template_parm_p=*/true); + } parm = grokdeclarator (parameter_declarator->declarator, ¶meter_declarator->decl_specifiers, @@ -9194,7 +9792,7 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack) /* Look for a keyword to tell us what kind of parameter this is. */ token = cp_parser_require (parser, CPP_KEYWORD, - "`class', `typename', or `template'"); + "%, %, or %"); if (!token) return error_mark_node; @@ -9241,10 +9839,11 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack) if (*is_parameter_pack) { if (identifier) - error ("template parameter pack %qD cannot have a default argument", - identifier); + error ("%Htemplate parameter pack %qD cannot have a " + "default argument", &token->location, identifier); else - error ("template parameter packs cannot have default arguments"); + error ("%Htemplate parameter packs cannot have " + "default arguments", &token->location); default_argument = NULL_TREE; } pop_deferring_access_checks (); @@ -9265,13 +9864,13 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack) tree default_argument; /* Look for the `<'. */ - cp_parser_require (parser, CPP_LESS, "`<'"); + cp_parser_require (parser, CPP_LESS, "%<<%>"); /* Parse the template-parameter-list. */ parameter_list = cp_parser_template_parameter_list (parser); /* Look for the `>'. */ - cp_parser_require (parser, CPP_GREATER, "`>'"); + cp_parser_require (parser, CPP_GREATER, "%<>%>"); /* Look for the `class' keyword. */ - cp_parser_require_keyword (parser, RID_CLASS, "`class'"); + cp_parser_require_keyword (parser, RID_CLASS, "%"); /* If the next token is an ellipsis, we have a template argument pack. */ if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) @@ -9312,6 +9911,9 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack) cp_lexer_consume_token (parser->lexer); /* Parse the id-expression. */ push_deferring_access_checks (dk_no_deferred); + /* save token before parsing the id-expression, for error + reporting */ + token = cp_lexer_peek_token (parser->lexer); default_argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, @@ -9332,7 +9934,8 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack) /*is_template=*/is_template, /*is_namespace=*/false, /*check_dependency=*/true, - /*ambiguous_decls=*/NULL); + /*ambiguous_decls=*/NULL, + token->location); /* See if the default argument is valid. */ default_argument = check_template_template_default_arg (default_argument); @@ -9342,10 +9945,13 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack) if (*is_parameter_pack) { if (identifier) - error ("template parameter pack %qD cannot have a default argument", - identifier); + error ("%Htemplate parameter pack %qD cannot " + "have a default argument", + &token->location, identifier); else - error ("template parameter packs cannot have default arguments"); + error ("%Htemplate parameter packs cannot " + "have default arguments", + &token->location); default_argument = NULL_TREE; } pop_deferring_access_checks (); @@ -9388,13 +9994,13 @@ cp_parser_template_id (cp_parser *parser, bool is_declaration) { int i; - tree template; + tree templ; tree arguments; tree template_id; cp_token_position start_of_id = 0; deferred_access_check *chk; VEC (deferred_access_check,gc) *access_check; - cp_token *next_token, *next_token_2; + cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL; bool is_identifier; /* If the next token corresponds to a template-id, there is no need @@ -9442,14 +10048,15 @@ cp_parser_template_id (cp_parser *parser, /* Parse the template-name. */ is_identifier = false; - template = cp_parser_template_name (parser, template_keyword_p, - check_dependency_p, - is_declaration, - &is_identifier); - if (template == error_mark_node || is_identifier) + token = cp_lexer_peek_token (parser->lexer); + templ = cp_parser_template_name (parser, template_keyword_p, + check_dependency_p, + is_declaration, + &is_identifier); + if (templ == error_mark_node || is_identifier) { pop_deferring_access_checks (); - return template; + return templ; } /* If we find the sequence `[:' after a template-name, it's probably @@ -9468,6 +10075,7 @@ cp_parser_template_id (cp_parser *parser, /* 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)) @@ -9482,15 +10090,17 @@ cp_parser_template_id (cp_parser *parser, } /* 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) + if (permerror (next_token->location, + "%<<::%> cannot begin a template-argument list")) { - static bool hint; - if (!hint) + static bool hint = false; + inform (next_token->location, + "%<<:%> is an alternate spelling for %<[%>." + " Insert whitespace between %<<%> and %<::%>"); + if (!hint && !flag_permissive) { - inform ("(if you use -fpermissive G++ will accept your code)"); + inform (next_token->location, "(if you use %<-fpermissive%>" + " G++ will accept your code)"); hint = true; } } @@ -9498,7 +10108,7 @@ cp_parser_template_id (cp_parser *parser, else { /* Look for the `<' that starts the template-argument-list. */ - if (!cp_parser_require (parser, CPP_LESS, "`<'")) + if (!cp_parser_require (parser, CPP_LESS, "%<<%>")) { pop_deferring_access_checks (); return error_mark_node; @@ -9508,10 +10118,10 @@ cp_parser_template_id (cp_parser *parser, } /* Build a representation of the specialization. */ - if (TREE_CODE (template) == IDENTIFIER_NODE) - template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments); - else if (DECL_CLASS_TEMPLATE_P (template) - || DECL_TEMPLATE_TEMPLATE_PARM_P (template)) + if (TREE_CODE (templ) == IDENTIFIER_NODE) + template_id = build_min_nt (TEMPLATE_ID_EXPR, templ, arguments); + else if (DECL_CLASS_TEMPLATE_P (templ) + || DECL_TEMPLATE_TEMPLATE_PARM_P (templ)) { bool entering_scope; /* In "template ... A::", A is the abstract A @@ -9523,17 +10133,17 @@ cp_parser_template_id (cp_parser *parser, && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)); template_id - = finish_template_type (template, arguments, entering_scope); + = finish_template_type (templ, arguments, entering_scope); } else { /* If it's not a class-template or a template-template, it should be a function-template. */ - gcc_assert ((DECL_FUNCTION_TEMPLATE_P (template) - || TREE_CODE (template) == OVERLOAD - || BASELINK_P (template))); + gcc_assert ((DECL_FUNCTION_TEMPLATE_P (templ) + || TREE_CODE (templ) == OVERLOAD + || BASELINK_P (templ))); - template_id = lookup_template_function (template, arguments); + template_id = lookup_template_function (templ, arguments); } /* If parsing tentatively, replace the sequence of tokens that makes @@ -9563,7 +10173,8 @@ cp_parser_template_id (cp_parser *parser, 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"); + error ("%Hparse error in template argument list", + &token->location); } pop_deferring_access_checks (); @@ -9617,6 +10228,7 @@ cp_parser_template_name (cp_parser* parser, tree identifier; tree decl; tree fns; + cp_token *token = cp_lexer_peek_token (parser->lexer); /* If the next token is `operator', then we have either an operator-function-id or a conversion-function-id. */ @@ -9676,8 +10288,9 @@ cp_parser_template_name (cp_parser* parser, cp_token_position start = 0; /* Explain what went wrong. */ - error ("non-template %qD used as template", identifier); - inform ("use %<%T::template %D%> to indicate that it is a template", + error ("%Hnon-template %qD used as template", + &token->location, identifier); + inform (input_location, "use %<%T::template %D%> to indicate that it is a template", parser->scope, identifier); /* If parsing tentatively, find the location of the "<" token. */ if (cp_parser_simulate_error (parser)) @@ -9720,7 +10333,8 @@ cp_parser_template_name (cp_parser* parser, /*is_template=*/false, /*is_namespace=*/false, check_dependency_p, - /*ambiguous_decls=*/NULL); + /*ambiguous_decls=*/NULL, + token->location); decl = maybe_get_template_decl_from_type_decl (decl); /* If DECL is a template, then the name was a template-name. */ @@ -9866,7 +10480,7 @@ cp_parser_template_argument (cp_parser* parser) bool template_p; bool address_p; bool maybe_type_id = false; - cp_token *token; + cp_token *token = NULL, *argument_start_token = NULL; cp_id_kind idk; /* There's really no way to know what we're looking at, so we just @@ -9881,9 +10495,10 @@ cp_parser_template_argument (cp_parser* parser) Therefore, we try a type-id first. */ cp_parser_parse_tentatively (parser); argument = cp_parser_type_id (parser); - /* If there was no error parsing the type-id but the next token is a '>>', - we probably found a typo for '> >'. But there are type-id which are - also valid expressions. For instance: + /* If there was no error parsing the type-id but the next token is a + '>>', our behavior depends on which dialect of C++ we're + parsing. In C++98, we probably found a typo for '> >'. But there + are type-id which are also valid expressions. For instance: struct X { int operator >> (int); }; template struct Foo {}; @@ -9892,8 +10507,12 @@ cp_parser_template_argument (cp_parser* parser) Here 'X()' is a valid type-id of a function type, but the user just wanted to write the expression "X() >> 5". Thus, we remember that we found a valid type-id, but we still try to parse the argument as an - expression to see what happens. */ + expression to see what happens. + + In C++0x, the '>>' will be considered two separate '>' + tokens. */ if (!cp_parser_error_occurred (parser) + && cxx_dialect == cxx98 && cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT)) { maybe_type_id = true; @@ -9913,6 +10532,7 @@ cp_parser_template_argument (cp_parser* parser) /* We're still not sure what the argument will be. */ cp_parser_parse_tentatively (parser); /* Try a template. */ + argument_start_token = cp_lexer_peek_token (parser->lexer); argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, @@ -9935,7 +10555,8 @@ cp_parser_template_argument (cp_parser* parser) /*is_template=*/template_p, /*is_namespace=*/false, /*check_dependency=*/true, - /*ambiguous_decls=*/NULL); + /*ambiguous_decls=*/NULL, + argument_start_token->location); if (TREE_CODE (argument) != TEMPLATE_DECL && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) cp_parser_error (parser, "expected template-name"); @@ -9960,7 +10581,7 @@ cp_parser_template_argument (cp_parser* parser) { cp_parser_parse_tentatively (parser); argument = cp_parser_primary_expression (parser, - /*adress_p=*/false, + /*address_p=*/false, /*cast_p=*/false, /*template_arg_p=*/true, &idk); @@ -10027,7 +10648,8 @@ cp_parser_template_argument (cp_parser* parser) if (cp_parser_parse_definitely (parser)) { if (address_p) - argument = build_x_unary_op (ADDR_EXPR, argument); + argument = build_x_unary_op (ADDR_EXPR, argument, + tf_warning_or_error); return argument; } } @@ -10091,6 +10713,7 @@ cp_parser_explicit_instantiation (cp_parser* parser) int declares_class_or_enum; cp_decl_specifier_seq decl_specifiers; tree extension_specifier = NULL_TREE; + cp_token *token; /* Look for an (optional) storage-class-specifier or function-specifier. */ @@ -10105,7 +10728,7 @@ cp_parser_explicit_instantiation (cp_parser* parser) } /* Look for the `template' keyword. */ - cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"); + cp_parser_require_keyword (parser, RID_TEMPLATE, "%"); /* Let the front end know that we are processing an explicit instantiation. */ begin_explicit_instantiation (); @@ -10113,6 +10736,7 @@ cp_parser_explicit_instantiation (cp_parser* parser) control while processing explicit instantiation directives. */ push_deferring_access_checks (dk_no_check); /* Parse a decl-specifier-seq. */ + token = cp_lexer_peek_token (parser->lexer); cp_parser_decl_specifier_seq (parser, CP_PARSER_FLAGS_OPTIONAL, &decl_specifiers, @@ -10145,7 +10769,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) /*member_p=*/false); if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_type (declarator, - decl_specifiers.type); + decl_specifiers.type, + decl_specifiers.type_location); if (declarator != cp_error_declarator) { decl = grokdeclarator (declarator, &decl_specifiers, @@ -10186,12 +10811,14 @@ static void cp_parser_explicit_specialization (cp_parser* parser) { bool need_lang_pop; + cp_token *token = cp_lexer_peek_token (parser->lexer); + /* Look for the `template' keyword. */ - cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"); + cp_parser_require_keyword (parser, RID_TEMPLATE, "%"); /* Look for the `<'. */ - cp_parser_require (parser, CPP_LESS, "`<'"); + cp_parser_require (parser, CPP_LESS, "%<<%>"); /* Look for the `>'. */ - cp_parser_require (parser, CPP_GREATER, "`>'"); + cp_parser_require (parser, CPP_GREATER, "%<>%>"); /* We have processed another parameter list. */ ++parser->num_template_parameter_lists; /* [temp] @@ -10200,7 +10827,7 @@ cp_parser_explicit_specialization (cp_parser* parser) linkage. */ if (current_lang_name == lang_name_c) { - error ("template specialization with C linkage"); + error ("%Htemplate specialization with C linkage", &token->location); /* Give it C++ linkage to avoid confusing other parts of the front end. */ push_lang_context (lang_name_cplusplus); @@ -10315,6 +10942,7 @@ cp_parser_type_specifier (cp_parser* parser, if (decl_specs) cp_parser_set_decl_spec_type (decl_specs, type_spec, + token->location, /*user_defined_p=*/true); return type_spec; } @@ -10339,6 +10967,7 @@ cp_parser_type_specifier (cp_parser* parser, if (decl_specs) cp_parser_set_decl_spec_type (decl_specs, type_spec, + token->location, /*user_defined_p=*/true); return type_spec; } @@ -10360,6 +10989,7 @@ cp_parser_type_specifier (cp_parser* parser, if (decl_specs) cp_parser_set_decl_spec_type (decl_specs, type_spec, + token->location, /*user_defined_p=*/true); return type_spec; @@ -10435,6 +11065,14 @@ cp_parser_type_specifier (cp_parser* parser, double void + C++0x Extension: + + simple-type-specifier: + auto + decltype ( expression ) + char16_t + char32_t + GNU Extension: simple-type-specifier: @@ -10463,6 +11101,12 @@ cp_parser_simple_type_specifier (cp_parser* parser, decl_specs->explicit_char_p = true; type = char_type_node; break; + case RID_CHAR16: + type = char16_type_node; + break; + case RID_CHAR32: + type = char32_type_node; + break; case RID_WCHAR: type = wchar_type_node; break; @@ -10503,6 +11147,22 @@ cp_parser_simple_type_specifier (cp_parser* parser, case RID_VOID: type = void_type_node; break; + + case RID_AUTO: + maybe_warn_cpp0x ("C++0x auto"); + type = make_auto (); + break; + + case RID_DECLTYPE: + /* Parse the `decltype' type. */ + type = cp_parser_decltype (parser); + + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, type, + token->location, + /*user_defined_p=*/true); + + return type; case RID_TYPEOF: /* Consume the `typeof' token. */ @@ -10515,6 +11175,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, if (decl_specs) cp_parser_set_decl_spec_type (decl_specs, type, + token->location, /*user_defined_p=*/true); return type; @@ -10536,6 +11197,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, && token->keyword != RID_LONG)) cp_parser_set_decl_spec_type (decl_specs, type, + token->location, /*user_defined=*/false); if (decl_specs) decl_specs->any_specifiers_p = true; @@ -10546,7 +11208,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, /* There is no valid C++ program where a non-template type is followed by a "<". That usually indicates that the user thought that the type was a template. */ - cp_parser_check_for_invalid_template_id (parser, type); + cp_parser_check_for_invalid_template_id (parser, type, token->location); return TYPE_NAME (type); } @@ -10575,6 +11237,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, /*type_p=*/false, /*is_declaration=*/false) != NULL_TREE); + token = cp_lexer_peek_token (parser->lexer); /* If we have seen a nested-name-specifier, and the next token is `template', then we are using the template-id production. */ if (parser->scope @@ -10609,6 +11272,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, type = NULL_TREE; if (type && decl_specs) cp_parser_set_decl_spec_type (decl_specs, type, + token->location, /*user_defined=*/true); } @@ -10641,7 +11305,8 @@ cp_parser_simple_type_specifier (cp_parser* parser, return qual_type; } - cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type)); + cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type), + token->location); } return type; @@ -10666,7 +11331,6 @@ static tree cp_parser_type_name (cp_parser* parser) { tree type_decl; - tree identifier; /* We can't know yet whether it is a class-name or not. */ cp_parser_parse_tentatively (parser); @@ -10682,51 +11346,72 @@ cp_parser_type_name (cp_parser* parser) if (!cp_parser_parse_definitely (parser)) { /* It must be a typedef-name or an enum-name. */ - identifier = cp_parser_identifier (parser); - if (identifier == error_mark_node) - return error_mark_node; + return cp_parser_nonclass_name (parser); + } - /* Look up the type-name. */ - type_decl = cp_parser_lookup_name_simple (parser, identifier); + return type_decl; +} - if (TREE_CODE (type_decl) != TYPE_DECL - && (objc_is_id (identifier) || objc_is_class_name (identifier))) - { - /* See if this is an Objective-C type. */ - tree protos = cp_parser_objc_protocol_refs_opt (parser); - tree type = objc_get_protocol_qualified_type (identifier, protos); - if (type) - type_decl = TYPE_NAME (type); - } +/* Parse a non-class type-name, that is, either an enum-name or a typedef-name. - /* Issue an error if we did not find a type-name. */ - if (TREE_CODE (type_decl) != TYPE_DECL) - { - if (!cp_parser_simulate_error (parser)) - cp_parser_name_lookup_error (parser, identifier, type_decl, - "is not a type"); - type_decl = error_mark_node; - } - /* Remember that the name was used in the definition of the - current class so that we can check later to see if the - meaning would have been different after the class was - entirely defined. */ - else if (type_decl != error_mark_node - && !parser->scope) - maybe_note_name_used_in_class (identifier, type_decl); - } + enum-name: + identifier + + typedef-name: + identifier + + Returns a TYPE_DECL for the type. */ +static tree +cp_parser_nonclass_name (cp_parser* parser) +{ + tree type_decl; + tree identifier; + + cp_token *token = cp_lexer_peek_token (parser->lexer); + identifier = cp_parser_identifier (parser); + if (identifier == error_mark_node) + return error_mark_node; + + /* Look up the type-name. */ + type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location); + + if (TREE_CODE (type_decl) != TYPE_DECL + && (objc_is_id (identifier) || objc_is_class_name (identifier))) + { + /* See if this is an Objective-C type. */ + tree protos = cp_parser_objc_protocol_refs_opt (parser); + tree type = objc_get_protocol_qualified_type (identifier, protos); + if (type) + type_decl = TYPE_NAME (type); + } + + /* Issue an error if we did not find a type-name. */ + if (TREE_CODE (type_decl) != TYPE_DECL) + { + if (!cp_parser_simulate_error (parser)) + cp_parser_name_lookup_error (parser, identifier, type_decl, + "is not a type", token->location); + return error_mark_node; + } + /* Remember that the name was used in the definition of the + current class so that we can check later to see if the + meaning would have been different after the class was + entirely defined. */ + else if (type_decl != error_mark_node + && !parser->scope) + maybe_note_name_used_in_class (identifier, type_decl); + return type_decl; } - /* Parse an elaborated-type-specifier. Note that the grammar given here incorporates the resolution to DR68. elaborated-type-specifier: class-key :: [opt] nested-name-specifier [opt] identifier class-key :: [opt] nested-name-specifier [opt] template [opt] template-id - enum :: [opt] nested-name-specifier [opt] identifier + enum-key :: [opt] nested-name-specifier [opt] identifier typename :: [opt] nested-name-specifier identifier typename :: [opt] nested-name-specifier template [opt] template-id @@ -10755,6 +11440,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, tree identifier; tree type = NULL_TREE; tree attributes = NULL_TREE; + cp_token *token = NULL; /* See if we're looking at the `enum' keyword. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM)) @@ -10763,6 +11449,17 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, cp_lexer_consume_token (parser->lexer); /* Remember that it's an enumeration type. */ tag_type = enum_type; + /* Parse the optional `struct' or `class' key (for C++0x scoped + enums). */ + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CLASS) + || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT)) + { + if (cxx_dialect == cxx98) + maybe_warn_cpp0x ("scoped enums"); + + /* Consume the `struct' or `class'. */ + cp_lexer_consume_token (parser->lexer); + } /* Parse the attributes. */ attributes = cp_parser_attributes_opt (parser); } @@ -10776,7 +11473,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, tag_type = typename_type; /* The `typename' keyword is only allowed in templates. */ if (!processing_template_decl) - pedwarn ("using % outside of template"); + permerror (input_location, "using % outside of template"); } /* Otherwise it must be a class-key. */ else @@ -10824,6 +11521,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, if (!template_p) cp_parser_parse_tentatively (parser); /* Parse the template-id. */ + token = cp_lexer_peek_token (parser->lexer); decl = cp_parser_template_id (parser, template_p, /*check_dependency_p=*/true, is_declaration); @@ -10845,6 +11543,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, if (!type) { + token = cp_lexer_peek_token (parser->lexer); identifier = cp_parser_identifier (parser); if (identifier == error_mark_node) @@ -10857,7 +11556,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, if (tag_type == typename_type && TREE_CODE (parser->scope) != NAMESPACE_DECL) return cp_parser_make_typename_type (parser, parser->scope, - identifier); + identifier, + token->location); /* Look up a qualified name in the usual way. */ if (parser->scope) { @@ -10869,7 +11569,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, /*is_template=*/false, /*is_namespace=*/false, /*check_dependency=*/true, - &ambiguous_decls); + &ambiguous_decls, + token->location); /* If the lookup was ambiguous, an error will already have been issued. */ @@ -10905,7 +11606,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, { cp_parser_diagnose_invalid_type_name (parser, parser->scope, - identifier); + identifier, + token->location); return error_mark_node; } @@ -10933,7 +11635,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, caught elsewhere in parsing. Those that are pointless arrive here. */ - if (cp_parser_declares_only_class_p (parser) + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON) && !is_friend && !processing_explicit_instantiation) warning (0, "declaration %qD does not declare anything", decl); @@ -11005,7 +11707,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, /* An unqualified name was used to reference this type, so there were no qualifying templates. */ if (!cp_parser_check_template_parameters (parser, - /*num_templates=*/0)) + /*num_templates=*/0, + token->location)) return error_mark_node; type = xref_tag (tag_type, identifier, ts, template_p); } @@ -11036,7 +11739,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, /* A "<" cannot follow an elaborated type specifier. If that happens, the user was probably trying to form a template-id. */ - cp_parser_check_for_invalid_template_id (parser, type); + cp_parser_check_for_invalid_template_id (parser, type, token->location); return type; } @@ -11044,11 +11747,19 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, /* Parse an enum-specifier. enum-specifier: - enum identifier [opt] { enumerator-list [opt] } + enum-key identifier [opt] enum-base [opt] { enumerator-list [opt] } + + enum-key: + enum + enum class [C++0x] + enum struct [C++0x] + + enum-base: [C++0x] + : type-specifier-seq GNU Extensions: - enum attributes[opt] identifier [opt] { enumerator-list [opt] } - attributes[opt] + enum-key attributes[opt] identifier [opt] enum-base [opt] + { enumerator-list [opt] }attributes[opt] Returns an ENUM_TYPE representing the enumeration, or NULL_TREE if the token stream isn't an enum-specifier after all. */ @@ -11059,6 +11770,9 @@ cp_parser_enum_specifier (cp_parser* parser) tree identifier; tree type; tree attributes; + bool scoped_enum_p = false; + bool has_underlying_type = false; + tree underlying_type = NULL_TREE; /* Parse tentatively so that we can back up if we don't find a enum-specifier. */ @@ -11070,6 +11784,20 @@ cp_parser_enum_specifier (cp_parser* parser) the enumeration being defined. */ cp_lexer_consume_token (parser->lexer); + /* Parse the "class" or "struct", which indicates a scoped + enumeration type in C++0x. */ + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CLASS) + || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT)) + { + if (cxx_dialect == cxx98) + maybe_warn_cpp0x ("scoped enums"); + + /* Consume the `struct' or `class' token. */ + cp_lexer_consume_token (parser->lexer); + + scoped_enum_p = true; + } + attributes = cp_parser_attributes_opt (parser); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) @@ -11077,11 +11805,46 @@ cp_parser_enum_specifier (cp_parser* parser) else identifier = make_anon_name (); + /* Check for the `:' that denotes a specified underlying type in C++0x. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + { + cp_decl_specifier_seq type_specifiers; + + /* At this point this is surely not elaborated type specifier. */ + if (!cp_parser_parse_definitely (parser)) + return NULL_TREE; + + if (cxx_dialect == cxx98) + maybe_warn_cpp0x ("scoped enums"); + + /* Consume the `:'. */ + cp_lexer_consume_token (parser->lexer); + + has_underlying_type = true; + + /* Parse the type-specifier-seq. */ + cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + &type_specifiers); + + /* If that didn't work, stop. */ + if (type_specifiers.type != error_mark_node) + { + underlying_type = grokdeclarator (NULL, &type_specifiers, TYPENAME, + /*initialized=*/0, NULL); + if (underlying_type == error_mark_node) + underlying_type = NULL_TREE; + } + } + /* Look for the `{' but don't consume it yet. */ if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) - cp_parser_simulate_error (parser); + { + cp_parser_error (parser, "expected %<{%>"); + if (has_underlying_type) + return NULL_TREE; + } - if (!cp_parser_parse_definitely (parser)) + if (!has_underlying_type && !cp_parser_parse_definitely (parser)) return NULL_TREE; /* Issue an error message if type-definitions are forbidden here. */ @@ -11091,7 +11854,7 @@ cp_parser_enum_specifier (cp_parser* parser) /* Create the new type. We do this before consuming the opening brace so the enum will be recorded as being on the line of its tag (or the 'enum' keyword, if there is no tag). */ - type = start_enum (identifier); + type = start_enum (identifier, underlying_type, scoped_enum_p); /* Consume the opening brace. */ cp_lexer_consume_token (parser->lexer); @@ -11107,7 +11870,7 @@ cp_parser_enum_specifier (cp_parser* parser) cp_parser_enumerator_list (parser, type); /* Consume the final '}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); /* Look for trailing attributes to apply to this enumeration, and apply them if appropriate. */ @@ -11149,8 +11912,8 @@ cp_parser_enumerator_list (cp_parser* parser, tree type) /* If the next token is a `}', there is a trailing comma. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) { - if (pedantic && !in_system_header) - pedwarn ("comma at end of enumerator list"); + if (!in_system_header) + pedwarn (input_location, OPT_pedantic, "comma at end of enumerator list"); break; } } @@ -11208,6 +11971,8 @@ cp_parser_namespace_name (cp_parser* parser) tree identifier; tree namespace_decl; + cp_token *token = cp_lexer_peek_token (parser->lexer); + /* Get the name of the namespace. */ identifier = cp_parser_identifier (parser); if (identifier == error_mark_node) @@ -11228,7 +11993,7 @@ cp_parser_namespace_name (cp_parser* parser) During the lookup of a name preceding the :: scope resolution operator, object, function, and enumerator names are ignored. - (Note that cp_parser_class_or_namespace_name only calls this + (Note that cp_parser_qualifying_entity only calls this function if the token after the name is the scope resolution operator.) */ namespace_decl = cp_parser_lookup_name (parser, identifier, @@ -11236,13 +12001,14 @@ cp_parser_namespace_name (cp_parser* parser) /*is_template=*/false, /*is_namespace=*/true, /*check_dependency=*/true, - /*ambiguous_decls=*/NULL); + /*ambiguous_decls=*/NULL, + token->location); /* If it's not a namespace, issue an error. */ if (namespace_decl == error_mark_node || TREE_CODE (namespace_decl) != NAMESPACE_DECL) { if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) - error ("%qD is not a namespace-name", identifier); + error ("%H%qD is not a namespace-name", &token->location, identifier); cp_parser_error (parser, "expected namespace-name"); namespace_decl = error_mark_node; } @@ -11273,9 +12039,19 @@ static void cp_parser_namespace_definition (cp_parser* parser) { tree identifier, attribs; + bool has_visibility; + bool is_inline; + + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE)) + { + is_inline = true; + cp_lexer_consume_token (parser->lexer); + } + else + is_inline = false; /* Look for the `namespace' keyword. */ - cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'"); + cp_parser_require_keyword (parser, RID_NAMESPACE, "%"); /* Get the name of the namespace. We do not attempt to distinguish between an original-namespace-definition and an @@ -11290,15 +12066,39 @@ cp_parser_namespace_definition (cp_parser* parser) attribs = cp_parser_attributes_opt (parser); /* Look for the `{' to start the namespace. */ - cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); + cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"); /* Start the namespace. */ - push_namespace_with_attribs (identifier, attribs); + push_namespace (identifier); + + /* "inline namespace" is equivalent to a stub namespace definition + followed by a strong using directive. */ + if (is_inline) + { + tree name_space = current_namespace; + /* Set up namespace association. */ + DECL_NAMESPACE_ASSOCIATIONS (name_space) + = tree_cons (CP_DECL_CONTEXT (name_space), NULL_TREE, + DECL_NAMESPACE_ASSOCIATIONS (name_space)); + /* Import the contents of the inline namespace. */ + pop_namespace (); + do_using_directive (name_space); + push_namespace (identifier); + } + + has_visibility = handle_namespace_attrs (current_namespace, attribs); + /* Parse the body of the namespace. */ cp_parser_namespace_body (parser); + +#ifdef HANDLE_PRAGMA_VISIBILITY + if (has_visibility) + pop_visibility (); +#endif + /* Finish the namespace. */ pop_namespace (); /* Look for the final `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); } /* Parse a namespace-body. @@ -11323,8 +12123,10 @@ cp_parser_namespace_alias_definition (cp_parser* parser) tree identifier; tree namespace_specifier; + cp_token *token = cp_lexer_peek_token (parser->lexer); + /* Look for the `namespace' keyword. */ - cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'"); + cp_parser_require_keyword (parser, RID_NAMESPACE, "%"); /* Look for the identifier. */ identifier = cp_parser_identifier (parser); if (identifier == error_mark_node) @@ -11333,19 +12135,19 @@ cp_parser_namespace_alias_definition (cp_parser* parser) if (!cp_parser_uncommitted_to_tentative_parse_p (parser) && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { - error ("% definition is not allowed here"); + error ("%H% definition is not allowed here", &token->location); /* Skip the definition. */ cp_lexer_consume_token (parser->lexer); if (cp_parser_skip_to_closing_brace (parser)) cp_lexer_consume_token (parser->lexer); return; } - cp_parser_require (parser, CPP_EQ, "`='"); + cp_parser_require (parser, CPP_EQ, "%<=%>"); /* Look for the qualified-namespace-specifier. */ namespace_specifier = cp_parser_qualified_namespace_specifier (parser); /* Look for the `;' token. */ - cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); /* Register the alias in the symbol table. */ do_namespace_alias (identifier, namespace_specifier); @@ -11404,7 +12206,7 @@ cp_parser_using_declaration (cp_parser* parser, else { /* Look for the `using' keyword. */ - cp_parser_require_keyword (parser, RID_USING, "`using'"); + cp_parser_require_keyword (parser, RID_USING, "%"); /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -11448,6 +12250,7 @@ cp_parser_using_declaration (cp_parser* parser, cp_parser_parse_definitely will be false, as required. */ return cp_parser_parse_definitely (parser); + token = cp_lexer_peek_token (parser->lexer); /* Parse the unqualified-id. */ identifier = cp_parser_unqualified_id (parser, /*template_keyword_p=*/false, @@ -11472,21 +12275,32 @@ cp_parser_using_declaration (cp_parser* parser, /* [namespace.udecl] A using declaration shall not name a template-id. */ - error ("a template-id may not appear in a using-declaration"); + error ("%Ha template-id may not appear in a using-declaration", + &token->location); else { if (at_class_scope_p ()) { /* Create the USING_DECL. */ decl = do_class_using_decl (parser->scope, identifier); - /* Add it to the list of members in this class. */ - finish_member_declaration (decl); + + if (check_for_bare_parameter_packs (decl)) + return false; + else + /* Add it to the list of members in this class. */ + finish_member_declaration (decl); } else { - decl = cp_parser_lookup_name_simple (parser, identifier); + decl = cp_parser_lookup_name_simple (parser, + identifier, + token->location); if (decl == error_mark_node) - cp_parser_name_lookup_error (parser, identifier, decl, NULL); + cp_parser_name_lookup_error (parser, identifier, + decl, NULL, + token->location); + else if (check_for_bare_parameter_packs (decl)) + return false; else if (!at_namespace_scope_p ()) do_local_using_decl (decl, qscope, identifier); else @@ -11495,7 +12309,7 @@ cp_parser_using_declaration (cp_parser* parser, } /* Look for the final `;'. */ - cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); return true; } @@ -11513,9 +12327,9 @@ cp_parser_using_directive (cp_parser* parser) tree attribs; /* Look for the `using' keyword. */ - cp_parser_require_keyword (parser, RID_USING, "`using'"); + cp_parser_require_keyword (parser, RID_USING, "%"); /* And the `namespace' keyword. */ - cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'"); + cp_parser_require_keyword (parser, RID_NAMESPACE, "%"); /* Look for the optional `::' operator. */ cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); /* And the optional nested-name-specifier. */ @@ -11531,7 +12345,7 @@ cp_parser_using_directive (cp_parser* parser) /* Update the symbol table. */ parse_using_directive (namespace_decl, attribs); /* Look for the final `;'. */ - cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); } /* Parse an asm-definition. @@ -11560,9 +12374,11 @@ cp_parser_asm_definition (cp_parser* parser) tree asm_stmt; bool volatile_p = false; bool extended_p = false; + bool invalid_inputs_p = false; + bool invalid_outputs_p = false; /* Look for the `asm' keyword. */ - cp_parser_require_keyword (parser, RID_ASM, "`asm'"); + cp_parser_require_keyword (parser, RID_ASM, "%"); /* See if the next token is `volatile'. */ if (cp_parser_allow_gnu_extensions_p (parser) && cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE)) @@ -11573,7 +12389,7 @@ cp_parser_asm_definition (cp_parser* parser) cp_lexer_consume_token (parser->lexer); } /* Look for the opening `('. */ - if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>")) return; /* Look for the string. */ string = cp_parser_string_literal (parser, false, false); @@ -11613,6 +12429,9 @@ cp_parser_asm_definition (cp_parser* parser) && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) outputs = cp_parser_asm_operand_list (parser); + + if (outputs == error_mark_node) + invalid_outputs_p = true; } /* If the next token is `::', there are no outputs, and the next token is the beginning of the inputs. */ @@ -11632,6 +12451,9 @@ cp_parser_asm_definition (cp_parser* parser) && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) inputs = cp_parser_asm_operand_list (parser); + + if (inputs == error_mark_node) + invalid_inputs_p = true; } else if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) /* The clobbers are coming next. */ @@ -11650,28 +12472,31 @@ cp_parser_asm_definition (cp_parser* parser) } } /* Look for the closing `)'. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>")) cp_parser_skip_to_closing_parenthesis (parser, true, false, /*consume_paren=*/true); - cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); - /* Create the ASM_EXPR. */ - if (parser->in_function_body) + if (!invalid_inputs_p && !invalid_outputs_p) { - asm_stmt = finish_asm_stmt (volatile_p, string, outputs, - inputs, clobbers); - /* If the extended syntax was not used, mark the ASM_EXPR. */ - if (!extended_p) + /* Create the ASM_EXPR. */ + if (parser->in_function_body) { - tree temp = asm_stmt; - if (TREE_CODE (temp) == CLEANUP_POINT_EXPR) - temp = TREE_OPERAND (temp, 0); + asm_stmt = finish_asm_stmt (volatile_p, string, outputs, + inputs, clobbers); + /* If the extended syntax was not used, mark the ASM_EXPR. */ + if (!extended_p) + { + tree temp = asm_stmt; + if (TREE_CODE (temp) == CLEANUP_POINT_EXPR) + temp = TREE_OPERAND (temp, 0); - ASM_INPUT_P (temp) = 1; + ASM_INPUT_P (temp) = 1; + } } + else + cgraph_add_asm_node (string); } - else - cgraph_add_asm_node (string); } /* Declarators [gram.dcl.decl] */ @@ -11723,7 +12548,8 @@ cp_parser_init_declarator (cp_parser* parser, int declares_class_or_enum, bool* function_definition_p) { - cp_token *token; + cp_token *token = NULL, *asm_spec_start_token = NULL, + *attributes_start_token = NULL; cp_declarator *declarator; tree prefix_attributes; tree attributes; @@ -11731,12 +12557,12 @@ cp_parser_init_declarator (cp_parser* parser, tree initializer; tree decl = NULL_TREE; tree scope; - bool is_initialized; + int is_initialized; /* Only valid if IS_INITIALIZED is true. In that case, CPP_EQ if initialized with "= ..", CPP_OPEN_PAREN if initialized with "(...)". */ enum cpp_ttype initialization_kind; - bool is_parenthesized_init = false; + bool is_direct_init = false; bool is_non_constant_init; int ctor_dtor_or_conv_p; bool friend_p; @@ -11757,6 +12583,7 @@ cp_parser_init_declarator (cp_parser* parser, resume_deferring_access_checks (); /* Parse the declarator. */ + token = cp_lexer_peek_token (parser->lexer); declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, &ctor_dtor_or_conv_p, @@ -11771,12 +12598,14 @@ cp_parser_init_declarator (cp_parser* parser, return error_mark_node; /* Check that the number of template-parameter-lists is OK. */ - if (!cp_parser_check_declarator_template_parameters (parser, declarator)) + if (!cp_parser_check_declarator_template_parameters (parser, declarator, + token->location)) return error_mark_node; if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_type (declarator, - decl_specifiers->type); + decl_specifiers->type, + decl_specifiers->type_location); /* Figure out what scope the entity declared by the DECLARATOR is located in. `grokdeclarator' sometimes changes the scope, so @@ -11788,8 +12617,10 @@ cp_parser_init_declarator (cp_parser* parser, if (cp_parser_allow_gnu_extensions_p (parser)) { /* Look for an asm-specification. */ + asm_spec_start_token = cp_lexer_peek_token (parser->lexer); asm_specification = cp_parser_asm_specification_opt (parser); /* And attributes. */ + attributes_start_token = cp_lexer_peek_token (parser->lexer); attributes = cp_parser_attributes_opt (parser); } else @@ -11802,7 +12633,8 @@ cp_parser_init_declarator (cp_parser* parser, token = cp_lexer_peek_token (parser->lexer); /* Check to see if the token indicates the start of a function-definition. */ - if (cp_parser_token_starts_function_definition_p (token)) + if (function_declarator_p (declarator) + && cp_parser_token_starts_function_definition_p (token)) { if (!function_definition_allowed_p) { @@ -11814,12 +12646,18 @@ cp_parser_init_declarator (cp_parser* parser, } else { + location_t func_brace_location + = cp_lexer_peek_token (parser->lexer)->location; + /* Neither attributes nor an asm-specification are allowed on a function-definition. */ if (asm_specification) - error ("an asm-specification is not allowed on a function-definition"); + error ("%Han asm-specification is not allowed " + "on a function-definition", + &asm_spec_start_token->location); if (attributes) - error ("attributes are not allowed on a function-definition"); + error ("%Hattributes are not allowed on a function-definition", + &attributes_start_token->location); /* This is a function-definition. */ *function_definition_p = true; @@ -11834,6 +12672,13 @@ cp_parser_init_declarator (cp_parser* parser, = (cp_parser_function_definition_from_specifiers_and_declarator (parser, decl_specifiers, prefix_attributes, declarator)); + if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl)) + { + /* This is where the prologue starts... */ + DECL_STRUCT_FUNCTION (decl)->function_start_locus + = func_brace_location; + } + return decl; } } @@ -11853,12 +12698,23 @@ cp_parser_init_declarator (cp_parser* parser, return error_mark_node; } - /* An `=' or an `(' indicates an initializer. */ + /* An `=' or an `(', or an '{' in C++0x, indicates an initializer. */ if (token->type == CPP_EQ - || token->type == CPP_OPEN_PAREN) + || token->type == CPP_OPEN_PAREN + || token->type == CPP_OPEN_BRACE) { - is_initialized = true; + is_initialized = SD_INITIALIZED; initialization_kind = token->type; + + if (token->type == CPP_EQ + && function_declarator_p (declarator)) + { + cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2); + if (t2->keyword == RID_DEFAULT) + is_initialized = SD_DEFAULTED; + else if (t2->keyword == RID_DELETE) + is_initialized = SD_DELETED; + } } else { @@ -11870,7 +12726,7 @@ cp_parser_init_declarator (cp_parser* parser, cp_parser_error (parser, "expected initializer"); return error_mark_node; } - is_initialized = false; + is_initialized = SD_UNINITIALIZED; initialization_kind = CPP_EOF; } @@ -11928,7 +12784,7 @@ cp_parser_init_declarator (cp_parser* parser, cp_parser_perform_template_parameter_access_checks (checks); /* Perform the access control checks for the declarator and the - the decl-specifiers. */ + decl-specifiers. */ perform_deferred_access_checks (); /* Restore the saved value. */ @@ -11938,12 +12794,13 @@ cp_parser_init_declarator (cp_parser* parser, /* Parse the initializer. */ initializer = NULL_TREE; - is_parenthesized_init = false; + is_direct_init = false; is_non_constant_init = true; if (is_initialized) { if (function_declarator_p (declarator)) { + cp_token *initializer_start_token = cp_lexer_peek_token (parser->lexer); if (initialization_kind == CPP_EQ) initializer = cp_parser_pure_specifier (parser); else @@ -11952,7 +12809,8 @@ cp_parser_init_declarator (cp_parser* parser, know what the user intended, so just silently consume the initializer. */ if (decl != error_mark_node) - error ("initializer provided for function"); + error ("%Hinitializer provided for function", + &initializer_start_token->location); cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, @@ -11961,7 +12819,7 @@ cp_parser_init_declarator (cp_parser* parser, } else initializer = cp_parser_initializer (parser, - &is_parenthesized_init, + &is_direct_init, &is_non_constant_init); } @@ -11969,7 +12827,8 @@ cp_parser_init_declarator (cp_parser* parser, initializer. Mark Mitchell proposed removing this functionality on the GCC mailing lists on 2002-08-13. This parser accepts the attributes -- but ignores them. */ - if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init) + if (cp_parser_allow_gnu_extensions_p (parser) + && initialization_kind == CPP_OPEN_PAREN) if (cp_parser_attributes_opt (parser)) warning (OPT_Wattributes, "attributes after parenthesized initializer ignored"); @@ -12002,8 +12861,8 @@ cp_parser_init_declarator (cp_parser* parser, a direct-initialization, which means that an `explicit' constructor is OK. Otherwise, an `explicit' constructor cannot be used. */ - ((is_parenthesized_init || !is_initialized) - ? 0 : LOOKUP_ONLYCONVERTING)); + ((is_direct_init || !is_initialized) + ? 0 : LOOKUP_ONLYCONVERTING)); } else if ((cxx_dialect != cxx98) && friend_p && decl && TREE_CODE (decl) == FUNCTION_DECL) @@ -12202,7 +13061,7 @@ cp_parser_direct_declarator (cp_parser* parser, int i (3); The first is the declaration of a function while the - second is a the definition of a variable, including its + second is the definition of a variable, including its initializer. Having seen only the parenthesis, we cannot know which of @@ -12220,8 +13079,10 @@ cp_parser_direct_declarator (cp_parser* parser, if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) { - cp_parameter_declarator *params; + tree params; unsigned saved_num_template_parameter_lists; + bool is_declarator = false; + tree t; /* In a member-declarator, the only valid interpretation of a parenthesis is the start of a @@ -12248,6 +13109,8 @@ cp_parser_direct_declarator (cp_parser* parser, = parser->num_template_parameter_lists; parser->num_template_parameter_lists = 0; + begin_scope (sk_function_parms, NULL_TREE); + /* Parse the parameter-declaration-clause. */ params = cp_parser_parameter_declaration_clause (parser); @@ -12260,12 +13123,15 @@ cp_parser_direct_declarator (cp_parser* parser, { cp_cv_quals cv_quals; tree exception_specification; + tree late_return; + + is_declarator = true; if (ctor_dtor_or_conv_p) *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0; first = false; /* Consume the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"); /* Parse the cv-qualifier-seq. */ cv_quals = cp_parser_cv_qualifier_seq_opt (parser); @@ -12273,19 +13139,29 @@ cp_parser_direct_declarator (cp_parser* parser, exception_specification = cp_parser_exception_specification_opt (parser); + late_return + = cp_parser_late_return_type_opt (parser); + /* Create the function-declarator. */ declarator = make_call_declarator (declarator, params, cv_quals, - exception_specification); + exception_specification, + late_return); /* Any subsequent parameter lists are to do with return type, so are not those of the declared function. */ parser->default_arg_ok_p = false; - - /* Repeat the main loop. */ - continue; } + + /* Remove the function parms from scope. */ + for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) + pop_binding (DECL_NAME (t), t); + leave_scope(); + + if (is_declarator) + /* Repeat the main loop. */ + continue; } /* If this is the first, we can try a parenthesized @@ -12309,7 +13185,7 @@ cp_parser_direct_declarator (cp_parser* parser, parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; first = false; /* Expect a `)'. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>")) declarator = cp_error_declarator; if (declarator == cp_error_declarator) break; @@ -12353,14 +13229,15 @@ cp_parser_direct_declarator (cp_parser* parser, in function scopes. */ else if (!parser->in_function_body) { - error ("array bound is not an integer constant"); + error ("%Harray bound is not an integer constant", + &token->location); bounds = error_mark_node; } } else bounds = NULL_TREE; /* Look for the closing `]'. */ - if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'")) + if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>")) { declarator = cp_error_declarator; break; @@ -12375,6 +13252,7 @@ cp_parser_direct_declarator (cp_parser* parser, special_function_kind sfk; bool abstract_ok; bool pack_expansion_p = false; + cp_token *declarator_id_start_token; /* Parse a declarator-id */ abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER); @@ -12393,6 +13271,7 @@ cp_parser_direct_declarator (cp_parser* parser, } } + declarator_id_start_token = cp_lexer_peek_token (parser->lexer); unqualified_name = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok); qualifying_scope = parser->scope; @@ -12461,8 +13340,9 @@ cp_parser_direct_declarator (cp_parser* parser, type = resolve_typename_type (qualifying_scope, /*only_current_p=*/false); /* If that failed, the declarator is invalid. */ - if (type == error_mark_node) - error ("%<%T::%E%> is not a type", + if (TREE_CODE (type) == TYPENAME_TYPE) + error ("%H%<%T::%E%> is not a type", + &declarator_id_start_token->location, TYPE_CONTEXT (qualifying_scope), TYPE_IDENTIFIER (qualifying_scope)); qualifying_scope = type; @@ -12488,8 +13368,9 @@ cp_parser_direct_declarator (cp_parser* parser, if (qualifying_scope && CLASSTYPE_USE_TEMPLATE (name_type)) { - error ("invalid use of constructor as a template"); - inform ("use %<%T::%D%> instead of %<%T::%D%> to " + error ("%Hinvalid use of constructor as a template", + &declarator_id_start_token->location); + inform (input_location, "use %<%T::%D%> instead of %<%T::%D%> to " "name the constructor in a qualified name", class_type, DECL_NAME (TYPE_TI_TEMPLATE (class_type)), @@ -12647,6 +13528,7 @@ cp_parser_ptr_operator (cp_parser* parser, cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false); /* Look for the nested-name specifier. */ + token = cp_lexer_peek_token (parser->lexer); cp_parser_nested_name_specifier (parser, /*typename_keyword_p=*/false, /*check_dependency_p=*/true, @@ -12655,13 +13537,13 @@ cp_parser_ptr_operator (cp_parser* parser, /* If we found it, and the next token is a `*', then we are indeed looking at a pointer-to-member operator. */ if (!cp_parser_error_occurred (parser) - && cp_parser_require (parser, CPP_MULT, "`*'")) + && cp_parser_require (parser, CPP_MULT, "%<*%>")) { /* Indicate that the `*' operator was used. */ code = INDIRECT_REF; if (TREE_CODE (parser->scope) == NAMESPACE_DECL) - error ("%qD is a namespace", parser->scope); + error ("%H%qD is a namespace", &token->location, parser->scope); else { /* The type of which the member is a member is given by the @@ -12736,7 +13618,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser) if (cv_quals & cv_qualifier) { - error ("duplicate cv-qualifier"); + error ("%Hduplicate cv-qualifier", &token->location); cp_lexer_purge_token (parser->lexer); } else @@ -12749,6 +13631,30 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser) return cv_quals; } +/* Parse a late-specified return type, if any. This is not a separate + non-terminal, but part of a function declarator, which looks like + + -> type-id + + Returns the type indicated by the type-id. */ + +static tree +cp_parser_late_return_type_opt (cp_parser* parser) +{ + cp_token *token; + + /* Peek at the next token. */ + token = cp_lexer_peek_token (parser->lexer); + /* A late-specified return type is indicated by an initial '->'. */ + if (token->type != CPP_DEREF) + return NULL_TREE; + + /* Consume the ->. */ + cp_lexer_consume_token (parser->lexer); + + return cp_parser_type_id (parser); +} + /* Parse a declarator-id. declarator-id: @@ -12821,6 +13727,13 @@ cp_parser_type_id (cp_parser* parser) if (!cp_parser_parse_definitely (parser)) abstract_declarator = NULL; + if (type_specifier_seq.type + && type_uses_auto (type_specifier_seq.type)) + { + error ("invalid use of %"); + return error_mark_node; + } + return groktypename (&type_specifier_seq, abstract_declarator); } @@ -12846,6 +13759,7 @@ cp_parser_type_specifier_seq (cp_parser* parser, { bool seen_type_specifier = false; cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL; + cp_token *start_token = NULL; /* Clear the TYPE_SPECIFIER_SEQ. */ clear_decl_specs (type_specifier_seq); @@ -12865,6 +13779,11 @@ cp_parser_type_specifier_seq (cp_parser* parser, continue; } + /* record the token of the beginning of the type specifier seq, + for error reporting purposes*/ + if (!start_token) + start_token = cp_lexer_peek_token (parser->lexer); + /* Look for the type-specifier. */ type_specifier = cp_parser_type_specifier (parser, flags, @@ -12908,7 +13827,7 @@ cp_parser_type_specifier_seq (cp_parser* parser, flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; } - cp_parser_check_decl_spec (type_specifier_seq); + cp_parser_check_decl_spec (type_specifier_seq, start_token->location); } /* Parse a parameter-declaration-clause. @@ -12921,10 +13840,10 @@ cp_parser_type_specifier_seq (cp_parser* parser, value of NULL indicates a parameter-declaration-clause consisting only of an ellipsis. */ -static cp_parameter_declarator * +static tree cp_parser_parameter_declaration_clause (cp_parser* parser) { - cp_parameter_declarator *parameters; + tree parameters; cp_token *token; bool ellipsis_p; bool is_error; @@ -12936,7 +13855,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) { /* Consume the `...' token. */ cp_lexer_consume_token (parser->lexer); - return NULL; + return NULL_TREE; } else if (token->type == CPP_CLOSE_PAREN) /* There are no parameters. */ @@ -12944,10 +13863,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) #ifndef NO_IMPLICIT_EXTERN_C if (in_system_header && current_class_type == NULL && current_lang_name == lang_name_c) - return NULL; + return NULL_TREE; else #endif - return no_parameters; + return void_list_node; } /* Check for `(void)', too, which is a special case. */ else if (token->keyword == RID_VOID @@ -12957,7 +13876,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) /* Consume the `void' token. */ cp_lexer_consume_token (parser->lexer); /* There are no parameters. */ - return no_parameters; + return void_list_node; } /* Parse the parameter-declaration-list. */ @@ -12977,7 +13896,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) cp_lexer_consume_token (parser->lexer); /* Expect an ellipsis. */ ellipsis_p - = (cp_parser_require (parser, CPP_ELLIPSIS, "`...'") != NULL); + = (cp_parser_require (parser, CPP_ELLIPSIS, "%<...%>") != NULL); } /* It might also be `...' if the optional trailing `,' was omitted. */ @@ -12992,8 +13911,8 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) ellipsis_p = false; /* Finish the parameter list. */ - if (parameters && ellipsis_p) - parameters->ellipsis_p = true; + if (!ellipsis_p) + parameters = chainon (parameters, void_list_node); return parameters; } @@ -13009,11 +13928,11 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) `void_list_node' is never appended to the list. Upon return, *IS_ERROR will be true iff an error occurred. */ -static cp_parameter_declarator * +static tree cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) { - cp_parameter_declarator *parameters = NULL; - cp_parameter_declarator **tail = ¶meters; + tree parameters = NULL_TREE; + tree *tail = ¶meters; bool saved_in_unbraced_linkage_specification_p; /* Assume all will go well. */ @@ -13029,6 +13948,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) while (true) { cp_parameter_declarator *parameter; + tree decl = error_mark_node; bool parenthesized_p; /* Parse the parameter. */ parameter @@ -13036,17 +13956,38 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) /*template_parm_p=*/false, &parenthesized_p); + /* We don't know yet if the enclosing context is deprecated, so wait + and warn in grokparms if appropriate. */ + deprecated_state = DEPRECATED_SUPPRESS; + + if (parameter) + decl = grokdeclarator (parameter->declarator, + ¶meter->decl_specifiers, + PARM, + parameter->default_argument != NULL_TREE, + ¶meter->decl_specifiers.attributes); + + deprecated_state = DEPRECATED_NORMAL; + /* If a parse error occurred parsing the parameter declaration, then the entire parameter-declaration-list is erroneous. */ - if (!parameter) + if (decl == error_mark_node) { *is_error = true; - parameters = NULL; + parameters = error_mark_node; break; } + + if (parameter->decl_specifiers.attributes) + cplus_decl_attributes (&decl, + parameter->decl_specifiers.attributes, + 0); + if (DECL_NAME (decl)) + decl = pushdecl (decl); + /* Add the new parameter to the list. */ - *tail = parameter; - tail = ¶meter->next; + *tail = build_tree_list (parameter->default_argument, decl); + tail = &TREE_CHAIN (*tail); /* Peek at the next token. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN) @@ -13135,7 +14076,7 @@ cp_parser_parameter_declaration (cp_parser *parser, cp_decl_specifier_seq decl_specifiers; cp_declarator *declarator; tree default_argument; - cp_token *token; + cp_token *token = NULL, *declarator_token_start = NULL; const char *saved_message; /* In a template parameter, `>' is not an operator. @@ -13204,6 +14145,7 @@ cp_parser_parameter_declaration (cp_parser *parser, && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) cp_parser_commit_to_tentative_parse (parser); /* Parse the declarator. */ + declarator_token_start = token; declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER, /*ctor_dtor_or_conv_p=*/NULL, @@ -13254,7 +14196,6 @@ cp_parser_parameter_declaration (cp_parser *parser, /* If the next token is `=', then process a default argument. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) { - bool saved_greater_than_is_operator_p; /* Consume the `='. */ cp_lexer_consume_token (parser->lexer); @@ -13264,6 +14205,7 @@ cp_parser_parameter_declaration (cp_parser *parser, && TYPE_BEING_DEFINED (current_class_type)) { unsigned depth = 0; + int maybe_template_id = 0; cp_token *first_token; cp_token *token; @@ -13282,6 +14224,33 @@ cp_parser_parameter_declaration (cp_parser *parser, /* In valid code, a default argument must be immediately followed by a `,' `)', or `...'. */ case CPP_COMMA: + if (depth == 0 && maybe_template_id) + { + /* If we've seen a '<', we might be in a + template-argument-list. Until Core issue 325 is + resolved, we don't know how this situation ought + to be handled, so try to DTRT. We check whether + what comes after the comma is a valid parameter + declaration list. If it is, then the comma ends + the default argument; otherwise the default + argument continues. */ + bool error = false; + + /* Set ITALP so cp_parser_parameter_declaration_list + doesn't decide to commit to this parse. */ + bool saved_italp = parser->in_template_argument_list_p; + parser->in_template_argument_list_p = true; + + cp_parser_parse_tentatively (parser); + cp_lexer_consume_token (parser->lexer); + cp_parser_parameter_declaration_list (parser, &error); + if (!cp_parser_error_occurred (parser) && !error) + done = true; + cp_parser_abort_tentative_parse (parser); + + parser->in_template_argument_list_p = saved_italp; + break; + } case CPP_CLOSE_PAREN: case CPP_ELLIPSIS: /* If we run into a non-nested `;', `}', or `]', @@ -13305,6 +14274,13 @@ cp_parser_parameter_declaration (cp_parser *parser, ++depth; break; + case CPP_LESS: + if (depth == 0) + /* This might be the comparison operator, or it might + start a template argument list. */ + ++maybe_template_id; + break; + case CPP_RSHIFT: if (cxx_dialect == cxx98) break; @@ -13313,17 +14289,22 @@ cp_parser_parameter_declaration (cp_parser *parser, cases. */ case CPP_GREATER: - /* If we see a non-nested `>', and `>' is not an - operator, then it marks the end of the default - argument. */ - if (!depth && !greater_than_is_operator_p) - done = true; + if (depth == 0) + { + /* This might be an operator, or it might close a + template argument list. But if a previous '<' + started a template argument list, this will have + closed it, so we can't be in one anymore. */ + maybe_template_id -= 1 + (token->type == CPP_RSHIFT); + if (maybe_template_id < 0) + maybe_template_id = 0; + } break; /* If we run out of tokens, issue an error message. */ case CPP_EOF: case CPP_PRAGMA_EOL: - error ("file ends in default argument"); + error ("%Hfile ends in default argument", &token->location); done = true; break; @@ -13350,7 +14331,7 @@ cp_parser_parameter_declaration (cp_parser *parser, token = cp_lexer_consume_token (parser->lexer); } - /* Create a DEFAULT_ARG to represented the unparsed default + /* Create a DEFAULT_ARG to represent the unparsed default argument. */ default_argument = make_node (DEFAULT_ARG); DEFARG_TOKENS (default_argument) @@ -13361,48 +14342,44 @@ cp_parser_parameter_declaration (cp_parser *parser, assignment-expression. */ else { - bool saved_local_variables_forbidden_p; - - /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is - set correctly. */ - saved_greater_than_is_operator_p - = parser->greater_than_is_operator_p; - parser->greater_than_is_operator_p = greater_than_is_operator_p; - /* 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; - /* The default argument expression may cause implicitly - defined member functions to be synthesized, which will - result in garbage collection. We must treat this - situation as if we were within the body of function so as - to avoid collecting live data on the stack. */ - ++function_depth; - /* Parse the assignment-expression. */ - if (template_parm_p) - push_deferring_access_checks (dk_no_deferred); - default_argument - = cp_parser_assignment_expression (parser, /*cast_p=*/false); - if (template_parm_p) - pop_deferring_access_checks (); - /* Restore saved state. */ - --function_depth; - parser->greater_than_is_operator_p - = saved_greater_than_is_operator_p; - parser->local_variables_forbidden_p - = saved_local_variables_forbidden_p; + token = cp_lexer_peek_token (parser->lexer); + default_argument + = cp_parser_default_argument (parser, template_parm_p); } + if (!parser->default_arg_ok_p) { - if (!flag_pedantic_errors) + if (flag_permissive) warning (0, "deprecated use of default argument for parameter of non-function"); else { - error ("default arguments are only permitted for function parameters"); + error ("%Hdefault arguments are only " + "permitted for function parameters", + &token->location); default_argument = NULL_TREE; } } + else if ((declarator && declarator->parameter_pack_p) + || (decl_specifiers.type + && PACK_EXPANSION_P (decl_specifiers.type))) + { + const char* kind = template_parm_p? "template " : ""; + + /* Find the name of the parameter pack. */ + cp_declarator *id_declarator = declarator; + while (id_declarator && id_declarator->kind != cdk_id) + id_declarator = id_declarator->declarator; + + if (id_declarator && id_declarator->kind == cdk_id) + error ("%H%sparameter pack %qD cannot have a default argument", + &declarator_token_start->location, + kind, id_declarator->u.id.unqualified_name); + else + error ("%H%sparameter pack cannot have a default argument", + &declarator_token_start->location, kind); + + default_argument = NULL_TREE; + } } else default_argument = NULL_TREE; @@ -13412,6 +14389,46 @@ cp_parser_parameter_declaration (cp_parser *parser, default_argument); } +/* Parse a default argument and return it. + + TEMPLATE_PARM_P is true if this is a default argument for a + non-type template parameter. */ +static tree +cp_parser_default_argument (cp_parser *parser, bool template_parm_p) +{ + tree default_argument = NULL_TREE; + bool saved_greater_than_is_operator_p; + bool saved_local_variables_forbidden_p; + + /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is + set correctly. */ + saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; + parser->greater_than_is_operator_p = !template_parm_p; + /* 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; + /* The default argument expression may cause implicitly + defined member functions to be synthesized, which will + result in garbage collection. We must treat this + situation as if we were within the body of function so as + to avoid collecting live data on the stack. */ + ++function_depth; + /* Parse the assignment-expression. */ + if (template_parm_p) + push_deferring_access_checks (dk_no_deferred); + default_argument + = cp_parser_assignment_expression (parser, /*cast_p=*/false); + if (template_parm_p) + pop_deferring_access_checks (); + /* Restore saved state. */ + --function_depth; + parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; + parser->local_variables_forbidden_p = saved_local_variables_forbidden_p; + + return default_argument; +} + /* Parse a function-body. function-body: @@ -13453,14 +14470,14 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser) Returns an expression representing the initializer. If no initializer is present, NULL_TREE is returned. - *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )' - production is used, and zero otherwise. *IS_PARENTHESIZED_INIT is - set to FALSE if there is no initializer present. If there is an + *IS_DIRECT_INIT is set to FALSE if the `= initializer-clause' + production is used, and TRUE otherwise. *IS_DIRECT_INIT is + set to TRUE if there is no initializer present. If there is an initializer, and it is not a constant-expression, *NON_CONSTANT_P is set to true; otherwise it is set to false. */ static tree -cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, +cp_parser_initializer (cp_parser* parser, bool* is_direct_init, bool* non_constant_p) { cp_token *token; @@ -13471,7 +14488,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, /* Let our caller know whether or not this initializer was parenthesized. */ - *is_parenthesized_init = (token->type == CPP_OPEN_PAREN); + *is_direct_init = (token->type != CPP_EQ); /* Assume that the initializer is constant. */ *non_constant_p = false; @@ -13487,6 +14504,12 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, /*cast_p=*/false, /*allow_expansion_p=*/true, non_constant_p); + else if (token->type == CPP_OPEN_BRACE) + { + maybe_warn_cpp0x ("extended initializer lists"); + init = cp_parser_braced_list (parser, non_constant_p); + CONSTRUCTOR_IS_DIRECT_INIT (init) = 1; + } else { /* Anything else is an error. */ @@ -13501,20 +14524,14 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, initializer-clause: assignment-expression - { initializer-list , [opt] } - { } + braced-init-list Returns an expression representing the initializer. If the `assignment-expression' production is used the value returned is simply a representation for the expression. - Otherwise, a CONSTRUCTOR is returned. The CONSTRUCTOR_ELTS will be - the elements of the initializer-list (or NULL, if the last - production is used). The TREE_TYPE for the CONSTRUCTOR will be - NULL_TREE. There is no way to detect whether or not the optional - trailing `,' was provided. NON_CONSTANT_P is as for - cp_parser_initializer. */ + Otherwise, calls cp_parser_braced_list. */ static tree cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) @@ -13536,25 +14553,46 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) initializer = fold_non_dependent_expr (initializer); } else + initializer = cp_parser_braced_list (parser, non_constant_p); + + return initializer; +} + +/* Parse a brace-enclosed initializer list. + + braced-init-list: + { initializer-list , [opt] } + { } + + Returns a CONSTRUCTOR. The CONSTRUCTOR_ELTS will be + the elements of the initializer-list (or NULL, if the last + production is used). The TREE_TYPE for the CONSTRUCTOR will be + NULL_TREE. There is no way to detect whether or not the optional + trailing `,' was provided. NON_CONSTANT_P is as for + cp_parser_initializer. */ + +static tree +cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) +{ + tree initializer; + + /* Consume the `{' token. */ + cp_lexer_consume_token (parser->lexer); + /* Create a CONSTRUCTOR to represent the braced-initializer. */ + initializer = make_node (CONSTRUCTOR); + /* If it's not a `}', then there is a non-trivial initializer. */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE)) { - /* Consume the `{' token. */ - cp_lexer_consume_token (parser->lexer); - /* Create a CONSTRUCTOR to represent the braced-initializer. */ - initializer = make_node (CONSTRUCTOR); - /* If it's not a `}', then there is a non-trivial initializer. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE)) - { - /* Parse the initializer list. */ - CONSTRUCTOR_ELTS (initializer) - = cp_parser_initializer_list (parser, non_constant_p); - /* A trailing `,' token is allowed. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) - cp_lexer_consume_token (parser->lexer); - } - /* Now, there should be a trailing `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + /* Parse the initializer list. */ + CONSTRUCTOR_ELTS (initializer) + = cp_parser_initializer_list (parser, non_constant_p); + /* A trailing `,' token is allowed. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); } - + /* Now, there should be a trailing `}'. */ + cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); + TREE_TYPE (initializer) = init_list_type_node; return initializer; } @@ -13599,8 +14637,8 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON) { /* Warn the user that they are using an extension. */ - if (pedantic) - pedwarn ("ISO C++ does not allow designated initializers"); + pedwarn (input_location, OPT_pedantic, + "ISO C++ does not allow designated initializers"); /* Consume the identifier. */ identifier = cp_lexer_consume_token (parser->lexer)->u.value; /* Consume the `:'. */ @@ -13682,6 +14720,7 @@ cp_parser_class_name (cp_parser *parser, tree scope; bool typename_p; cp_token *token; + tree identifier = NULL_TREE; /* All class-names start with an identifier. */ token = cp_lexer_peek_token (parser->lexer); @@ -13707,7 +14746,6 @@ cp_parser_class_name (cp_parser *parser, && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) { cp_token *identifier_token; - tree identifier; bool ambiguous_p; /* Look for the identifier. */ @@ -13749,10 +14787,12 @@ cp_parser_class_name (cp_parser *parser, /*is_template=*/false, /*is_namespace=*/false, check_dependency_p, - &ambiguous_decls); + &ambiguous_decls, + identifier_token->location); if (ambiguous_decls) { - error ("reference to %qD is ambiguous", identifier); + error ("%Hreference to %qD is ambiguous", + &identifier_token->location, identifier); print_candidates (ambiguous_decls); if (cp_parser_parsing_tentatively (parser)) { @@ -13805,11 +14845,13 @@ cp_parser_class_name (cp_parser *parser, } else if (TREE_CODE (decl) != TYPE_DECL || TREE_TYPE (decl) == error_mark_node - || !IS_AGGR_TYPE (TREE_TYPE (decl))) + || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))) decl = error_mark_node; if (decl == error_mark_node) cp_parser_error (parser, "expected class-name"); + else if (identifier && !parser->scope) + maybe_note_name_used_in_class (identifier, decl); return decl; } @@ -13831,6 +14873,7 @@ cp_parser_class_specifier (cp_parser* parser) bool nested_name_specifier_p; unsigned saved_num_template_parameter_lists; bool saved_in_function_body; + bool saved_in_unbraced_linkage_specification_p; tree old_scope = NULL_TREE; tree scope = NULL_TREE; tree bases; @@ -13852,7 +14895,7 @@ cp_parser_class_specifier (cp_parser* parser) } /* Look for the `{'. */ - if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'")) + if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>")) { pop_deferring_access_checks (); return error_mark_node; @@ -13882,6 +14925,10 @@ cp_parser_class_specifier (cp_parser* parser) /* We are not in a function body. */ saved_in_function_body = parser->in_function_body; parser->in_function_body = false; + /* We are not immediately inside an extern "lang" block. */ + saved_in_unbraced_linkage_specification_p + = parser->in_unbraced_linkage_specification_p; + parser->in_unbraced_linkage_specification_p = false; /* Start the class. */ if (nested_name_specifier_p) @@ -13899,7 +14946,7 @@ cp_parser_class_specifier (cp_parser* parser) cp_parser_member_specification_opt (parser); /* Look for the trailing `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); /* We get better error messages by noticing a common problem: a missing trailing `;'. */ token = cp_lexer_peek_token (parser->lexer); @@ -13994,6 +15041,8 @@ cp_parser_class_specifier (cp_parser* parser) parser->in_function_body = saved_in_function_body; parser->num_template_parameter_lists = saved_num_template_parameter_lists; + parser->in_unbraced_linkage_specification_p + = saved_in_unbraced_linkage_specification_p; return type; } @@ -14043,7 +15092,7 @@ cp_parser_class_head (cp_parser* parser, bool invalid_explicit_specialization_p = false; tree pushed_scope = NULL_TREE; unsigned num_templates; - + cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL; /* Assume no nested-name-specifier will be present. */ *nested_name_specifier_p = false; /* Assume no template parameter lists will be used in defining the @@ -14076,6 +15125,7 @@ cp_parser_class_head (cp_parser* parser, /* Determine the name of the class. Begin by looking for an optional nested-name-specifier. */ + nested_name_specifier_token_start = cp_lexer_peek_token (parser->lexer); nested_name_specifier = cp_parser_nested_name_specifier_opt (parser, /*typename_keyword_p=*/false, @@ -14086,6 +15136,7 @@ cp_parser_class_head (cp_parser* parser, identifier. */ if (nested_name_specifier) { + type_start_token = cp_lexer_peek_token (parser->lexer); /* Although the grammar says `identifier', it really means `class-name' or `template-name'. You are only allowed to define a class that has already been declared with this @@ -14115,6 +15166,7 @@ cp_parser_class_head (cp_parser* parser, if (!cp_parser_parse_definitely (parser)) { invalid_nested_name_p = true; + type_start_token = cp_lexer_peek_token (parser->lexer); id = cp_parser_identifier (parser); if (id == error_mark_node) id = NULL_TREE; @@ -14149,6 +15201,7 @@ cp_parser_class_head (cp_parser* parser, an identifier, or nothing at all. */ cp_parser_parse_tentatively (parser); /* Check for a template-id. */ + type_start_token = cp_lexer_peek_token (parser->lexer); id = cp_parser_template_id (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, @@ -14157,7 +15210,10 @@ cp_parser_class_head (cp_parser* parser, if (!cp_parser_parse_definitely (parser)) { if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) - id = cp_parser_identifier (parser); + { + type_start_token = cp_lexer_peek_token (parser->lexer); + id = cp_parser_identifier (parser); + } else id = NULL_TREE; } @@ -14171,7 +15227,8 @@ cp_parser_class_head (cp_parser* parser, pop_deferring_access_checks (); if (id) - cp_parser_check_for_invalid_template_id (parser, id); + cp_parser_check_for_invalid_template_id (parser, id, + type_start_token->location); /* If it's not a `:' or a `{' then we can't really be looking at a class-head, since a class-head only appears as part of a @@ -14188,11 +15245,17 @@ cp_parser_class_head (cp_parser* parser, cp_parser_commit_to_tentative_parse (parser); /* Issue the error about the overly-qualified name now. */ if (qualified_p) - cp_parser_error (parser, - "global qualification of class name is invalid"); + { + cp_parser_error (parser, + "global qualification of class name is invalid"); + return error_mark_node; + } else if (invalid_nested_name_p) - cp_parser_error (parser, - "qualified name does not name a class"); + { + cp_parser_error (parser, + "qualified name does not name a class"); + return error_mark_node; + } else if (nested_name_specifier) { tree scope; @@ -14200,7 +15263,8 @@ cp_parser_class_head (cp_parser* parser, /* Reject typedef-names in class heads. */ if (!DECL_IMPLICIT_TYPEDEF_P (type)) { - error ("invalid class name in declaration of %qD", type); + error ("%Hinvalid class name in declaration of %qD", + &type_start_token->location, type); type = NULL_TREE; goto done; } @@ -14211,20 +15275,28 @@ cp_parser_class_head (cp_parser* parser, class was originally declared, the program is invalid. */ if (scope && !is_ancestor (scope, nested_name_specifier)) { - error ("declaration of %qD in %qD which does not enclose %qD", - type, scope, nested_name_specifier); + if (at_namespace_scope_p ()) + error ("%Hdeclaration of %qD in namespace %qD which does not " + "enclose %qD", + &type_start_token->location, + type, scope, nested_name_specifier); + else + error ("%Hdeclaration of %qD in %qD which does not enclose %qD", + &type_start_token->location, + type, scope, nested_name_specifier); type = NULL_TREE; goto done; } /* [dcl.meaning] - A declarator-id shall not be qualified exception of the + A declarator-id shall not be qualified except for the definition of a ... nested class outside of its class - ... [or] a the definition or explicit instantiation of a + ... [or] the definition or explicit instantiation of a class member of a namespace outside of its namespace. */ if (scope == nested_name_specifier) { - pedwarn ("extra qualification ignored"); + permerror (input_location, "%Hextra qualification not allowed", + &nested_name_specifier_token_start->location); nested_name_specifier = NULL_TREE; num_templates = 0; } @@ -14235,7 +15307,8 @@ cp_parser_class_head (cp_parser* parser, && parser->num_template_parameter_lists == 0 && template_id_p) { - error ("an explicit specialization must be preceded by %