diff options
author | Dodji Seketeli <dseketel@redhat.com> | 2008-07-11 16:32:29 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2008-07-11 18:32:29 +0200 |
commit | 760b18ad400092ea513d159b825b3617247dce8c (patch) | |
tree | 1fe565658b383beee4cfa352a8dd8f952dd7c8ec /gcc/cp | |
parent | ab2203551a5de8b2ce820426293bafde14330a69 (diff) | |
download | gcc-760b18ad400092ea513d159b825b3617247dce8c.zip gcc-760b18ad400092ea513d159b825b3617247dce8c.tar.gz gcc-760b18ad400092ea513d159b825b3617247dce8c.tar.bz2 |
re PR c++/31754 (Improve column number accuracy in error messages)
2008-07-11 Dodji Seketeli <dseketel@redhat.com>
PR c++/31754
* cp-tree.h (struct cp_decl_specifier_seq): add a location field. It
carries the location of the primary type.
* parser.c (cp_parser_check_type_definition): update documentation.
(cp_parser_check_for_definition_in_return_type,
cp_parser_check_for_invalid_template_id,
cp_parser_set_decl_spec_type,
cp_parser_check_for_definition_in_return_type,
cp_parser_diagnose_invalid_type_name,
cp_parser_new_expression, cp_parser_explicit_instantiation,
cp_parser_type_specifier, cp_parser_simple_type_specifier,
cp_parser_omp_for_loop, cp_parser_pragma): use location in error messages.
From-SVN: r137721
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/parser.c | 106 |
3 files changed, 88 insertions, 38 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0161f2e..c48fe96 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,4 +1,19 @@ -2008-07-11 Dodji Seketeli <dseketel@redhat.com> +2008-07-11 Dodji Seketeli <dseketel@redhat.com> + + PR c++/31754 + * cp-tree.h (struct cp_decl_specifier_seq): add a location field. It + carries the location of the primary type. + * parser.c (cp_parser_check_type_definition): update documentation. + (cp_parser_check_for_definition_in_return_type, + cp_parser_check_for_invalid_template_id, + cp_parser_set_decl_spec_type, + cp_parser_check_for_definition_in_return_type, + cp_parser_diagnose_invalid_type_name, + cp_parser_new_expression, cp_parser_explicit_instantiation, + cp_parser_type_specifier, cp_parser_simple_type_specifier, + cp_parser_omp_for_loop, cp_parser_pragma): use location in error messages. + +2008-06-30 Dodji Seketeli <dseketel@redhat.com> PR c++/31754 * pt.c, semantic.c: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 10eba33..b07effe 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3927,6 +3927,9 @@ typedef struct cp_decl_specifier_seq { reflected here. This field will be a TYPE, unless a typedef-name was used, in which case it will be a TYPE_DECL. */ tree type; + /* The location of the primary type. Mainly used for error + reporting. */ + location_t type_location; /* The attributes, if any, provided with the specifier sequence. */ tree attributes; /* If non-NULL, a built-in type that the user attempted to redefine diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 2429bfc..567f04e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1950,7 +1950,7 @@ static bool cp_parser_declares_only_class_p static void cp_parser_set_storage_class (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 @@ -1998,9 +1998,9 @@ static bool cp_parser_simulate_error 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 @@ -2214,11 +2214,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 @@ -2231,31 +2232,32 @@ 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)", - type); + error ("%Hnew types may not be defined in a return type", &type_location); + inform ("%H(perhaps a semicolon is missing after the definition of %qT)", + &type_location, type); } } /* 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); @@ -2301,32 +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, - location_t id_location) + 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, id_location); + 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: @@ -2358,8 +2362,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, if (TREE_CODE (field) == TYPE_DECL && DECL_NAME (field) == id) { - inform ("(perhaps %<typename %T::%E%> was intended)", - BINFO_TYPE (b), id); + inform ("%H(perhaps %<typename %T::%E%> was intended)", + &location, BINFO_TYPE (b), id); break; } if (field) @@ -2373,10 +2377,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, 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 (); } @@ -5576,7 +5581,8 @@ cp_parser_new_expression (cp_parser* parser) { error ("%Harray bound forbidden after parenthesized type-id", &token->location); - inform ("try removing the parentheses around the type-id"); + inform ("%Htry removing the parentheses around the type-id", + &token->location); cp_parser_direct_new_declarator (parser); } nelts = NULL_TREE; @@ -10599,6 +10605,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. */ @@ -10621,6 +10628,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, @@ -10653,7 +10661,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, @@ -10825,6 +10834,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; } @@ -10849,6 +10859,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; } @@ -10870,6 +10881,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; @@ -11045,6 +11057,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; @@ -11060,6 +11073,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; @@ -11081,6 +11095,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; @@ -11091,7 +11106,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); } @@ -11120,6 +11135,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 @@ -11154,6 +11170,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); } @@ -11186,7 +11203,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; @@ -11608,7 +11626,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; } @@ -12413,7 +12431,8 @@ cp_parser_init_declarator (cp_parser* parser, 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 @@ -14875,6 +14894,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; @@ -14918,7 +14938,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; } @@ -14932,7 +14955,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 @@ -15521,7 +15545,8 @@ cp_parser_member_declaration (cp_parser* parser) if (declares_class_or_enum & 2) cp_parser_check_for_definition_in_return_type - (declarator, decl_specifiers.type); + (declarator, decl_specifiers.type, + decl_specifiers.type_location); /* Look for an asm-specification. */ asm_specification = cp_parser_asm_specification_opt (parser); @@ -18141,6 +18166,7 @@ cp_parser_set_storage_class (cp_parser *parser, static void cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, tree type_spec, + location_t location, bool user_defined_p) { decl_specs->any_specifiers_p = true; @@ -18167,6 +18193,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, { decl_specs->type = type_spec; decl_specs->user_defined_type_p = false; + decl_specs->type_location = location; } } else if (decl_specs->type) @@ -18176,6 +18203,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, decl_specs->type = type_spec; decl_specs->user_defined_type_p = user_defined_p; decl_specs->redefined_builtin_type = NULL_TREE; + decl_specs->type_location = location; } } @@ -21105,7 +21133,10 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses) else { if (!collapse_err) - error ("collapsed loops not perfectly nested"); + { + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + error ("%Hcollapsed loops not perfectly nested", &loc); + } collapse_err = true; cp_parser_statement_seq_opt (parser, NULL); cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); @@ -21593,8 +21624,9 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context) cp_parser_omp_taskwait (parser, pragma_tok); return false; case pragma_stmt: - error ("%<#pragma omp taskwait%> may only be " - "used in compound statements"); + error ("%H%<#pragma omp taskwait%> may only be " + "used in compound statements", + &pragma_tok->location); break; default: goto bad_stmt; |