Commit 9003adc7 by David Malcolm Committed by David Malcolm

C++: underline parameters in mismatching function calls

gcc/cp/ChangeLog:
	* call.c (get_fndecl_argument_location): New function.
	(convert_like_real): Use it  when complaining about argument type
	mismatches.
	* cp-tree.h (struct cp_parameter_declarator): Add "loc" field.
	* parser.c (make_parameter_declarator): Add "loc" param and use
	it to initialize the new field.
	(cp_parser_translation_unit): Add UNKNOWN_LOCATION for "loc" of
	the "no_parameters" parameter.
	(cp_parser_parameter_declaration_list): Set the location of the
	result of grokdeclarator to be the parameter's loc, assuming no
	errors.
	(cp_parser_parameter_declaration): Generate a location for the
	parameter and pass to make_parameter_declarator.

gcc/testsuite/ChangeLog:
	* g++.dg/diagnostic/param-type-mismatch.C: Update expected results
	to reflect highlighting of parameters; add test coverage for
	callback parameters.

From-SVN: r253096
parent 8c2ea6b2
2017-09-22 David Malcolm <dmalcolm@redhat.com>
* call.c (get_fndecl_argument_location): New function.
(convert_like_real): Use it when complaining about argument type
mismatches.
* cp-tree.h (struct cp_parameter_declarator): Add "loc" field.
* parser.c (make_parameter_declarator): Add "loc" param and use
it to initialize the new field.
(cp_parser_translation_unit): Add UNKNOWN_LOCATION for "loc" of
the "no_parameters" parameter.
(cp_parser_parameter_declaration_list): Set the location of the
result of grokdeclarator to be the parameter's loc, assuming no
errors.
(cp_parser_parameter_declaration): Generate a location for the
parameter and pass to make_parameter_declarator.
2017-09-20 Nathan Sidwell <nathan@acm.org> 2017-09-20 Nathan Sidwell <nathan@acm.org>
* name-lookup.c (member_name_cmp): Use DECL_UID for final * name-lookup.c (member_name_cmp): Use DECL_UID for final
......
...@@ -6579,6 +6579,30 @@ maybe_print_user_conv_context (conversion *convs) ...@@ -6579,6 +6579,30 @@ maybe_print_user_conv_context (conversion *convs)
} }
} }
/* Locate the parameter with the given index within FNDECL.
ARGNUM is zero based, -1 indicates the `this' argument of a method.
Return the location of the FNDECL itself if there are problems. */
static location_t
get_fndecl_argument_location (tree fndecl, int argnum)
{
int i;
tree param;
/* Locate param by index within DECL_ARGUMENTS (fndecl). */
for (i = 0, param = FUNCTION_FIRST_USER_PARM (fndecl);
i < argnum && param;
i++, param = TREE_CHAIN (param))
;
/* If something went wrong (e.g. if we have a builtin and thus no arguments),
return the location of FNDECL. */
if (param == NULL)
return DECL_SOURCE_LOCATION (fndecl);
return DECL_SOURCE_LOCATION (param);
}
/* Perform the conversions in CONVS on the expression EXPR. FN and /* Perform the conversions in CONVS on the expression EXPR. FN and
ARGNUM are used for diagnostics. ARGNUM is zero based, -1 ARGNUM are used for diagnostics. ARGNUM is zero based, -1
indicates the `this' argument of a method. INNER is nonzero when indicates the `this' argument of a method. INNER is nonzero when
...@@ -6680,7 +6704,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, ...@@ -6680,7 +6704,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
complained = permerror (loc, "invalid conversion from %qH to %qI", complained = permerror (loc, "invalid conversion from %qH to %qI",
TREE_TYPE (expr), totype); TREE_TYPE (expr), totype);
if (complained && fn) if (complained && fn)
inform (DECL_SOURCE_LOCATION (fn), inform (get_fndecl_argument_location (fn, argnum),
" initializing argument %P of %qD", argnum, fn); " initializing argument %P of %qD", argnum, fn);
return cp_convert (totype, expr, complain); return cp_convert (totype, expr, complain);
......
...@@ -5659,6 +5659,8 @@ struct cp_parameter_declarator { ...@@ -5659,6 +5659,8 @@ struct cp_parameter_declarator {
tree default_argument; tree default_argument;
/* True iff this is a template parameter pack. */ /* True iff this is a template parameter pack. */
bool template_parameter_pack_p; bool template_parameter_pack_p;
/* Location within source. */
location_t loc;
}; };
/* A declarator. */ /* A declarator. */
......
...@@ -1691,6 +1691,7 @@ cp_parameter_declarator * ...@@ -1691,6 +1691,7 @@ cp_parameter_declarator *
make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers, make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
cp_declarator *declarator, cp_declarator *declarator,
tree default_argument, tree default_argument,
location_t loc,
bool template_parameter_pack_p = false) bool template_parameter_pack_p = false)
{ {
cp_parameter_declarator *parameter; cp_parameter_declarator *parameter;
...@@ -1705,6 +1706,7 @@ make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers, ...@@ -1705,6 +1706,7 @@ make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
parameter->declarator = declarator; parameter->declarator = declarator;
parameter->default_argument = default_argument; parameter->default_argument = default_argument;
parameter->template_parameter_pack_p = template_parameter_pack_p; parameter->template_parameter_pack_p = template_parameter_pack_p;
parameter->loc = loc;
return parameter; return parameter;
} }
...@@ -4379,7 +4381,8 @@ cp_parser_translation_unit (cp_parser* parser) ...@@ -4379,7 +4381,8 @@ cp_parser_translation_unit (cp_parser* parser)
/* Create the error declarator. */ /* Create the error declarator. */
cp_error_declarator = make_declarator (cdk_error); cp_error_declarator = make_declarator (cdk_error);
/* Create the empty parameter list. */ /* Create the empty parameter list. */
no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE); no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE,
UNKNOWN_LOCATION);
/* Remember where the base of the declarator obstack lies. */ /* Remember where the base of the declarator obstack lies. */
declarator_obstack_base = obstack_next_free (&declarator_obstack); declarator_obstack_base = obstack_next_free (&declarator_obstack);
} }
...@@ -21218,6 +21221,8 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) ...@@ -21218,6 +21221,8 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
PARM, PARM,
parameter->default_argument != NULL_TREE, parameter->default_argument != NULL_TREE,
&parameter->decl_specifiers.attributes); &parameter->decl_specifiers.attributes);
if (decl != error_mark_node && parameter->loc != UNKNOWN_LOCATION)
DECL_SOURCE_LOCATION (decl) = parameter->loc;
} }
deprecated_state = DEPRECATED_NORMAL; deprecated_state = DEPRECATED_NORMAL;
...@@ -21371,6 +21376,7 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -21371,6 +21376,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
= G_("types may not be defined in parameter types"); = G_("types may not be defined in parameter types");
/* Parse the declaration-specifiers. */ /* Parse the declaration-specifiers. */
cp_token *decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
cp_parser_decl_specifier_seq (parser, cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_NONE, CP_PARSER_FLAGS_NONE,
&decl_specifiers, &decl_specifiers,
...@@ -21555,9 +21561,33 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -21555,9 +21561,33 @@ cp_parser_parameter_declaration (cp_parser *parser,
else else
default_argument = NULL_TREE; default_argument = NULL_TREE;
/* Generate a location for the parameter, ranging from the start of the
initial token to the end of the final token (using input_location for
the latter, set up by cp_lexer_set_source_position_from_token when
consuming tokens).
If we have a identifier, then use it for the caret location, e.g.
extern int callee (int one, int (*two)(int, int), float three);
~~~~~~^~~~~~~~~~~~~~
otherwise, reuse the start location for the caret location e.g.:
extern int callee (int one, int (*)(int, int), float three);
^~~~~~~~~~~~~~~~~
*/
location_t caret_loc = (declarator && declarator->id_loc != UNKNOWN_LOCATION
? declarator->id_loc
: decl_spec_token_start->location);
location_t param_loc = make_location (caret_loc,
decl_spec_token_start->location,
input_location);
return make_parameter_declarator (&decl_specifiers, return make_parameter_declarator (&decl_specifiers,
declarator, declarator,
default_argument, default_argument,
param_loc,
template_parameter_pack_p); template_parameter_pack_p);
} }
2017-09-22 David Malcolm <dmalcolm@redhat.com>
* g++.dg/diagnostic/param-type-mismatch.C: Update expected results
to reflect highlighting of parameters; add test coverage for
callback parameters.
2017-09-22 Richard Biener <rguenther@suse.de> 2017-09-22 Richard Biener <rguenther@suse.de>
* gcc.dg/graphite/scop-24.c: New testcase. * gcc.dg/graphite/scop-24.c: New testcase.
......
...@@ -3,10 +3,7 @@ ...@@ -3,10 +3,7 @@
/* A collection of calls where argument 2 is of the wrong type. /* A collection of calls where argument 2 is of the wrong type.
TODO: we should put the caret and underline for the diagnostic TODO: we should put the caret and underline for the diagnostic
at the second argument, rather than the close paren. at the second argument, rather than the close paren. */
TODO: we should highlight the second parameter of the callee, rather
than its name. */
/* decl, with argname. */ /* decl, with argname. */
...@@ -22,7 +19,7 @@ int test_1 (int first, int second, float third) ...@@ -22,7 +19,7 @@ int test_1 (int first, int second, float third)
// { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_1 } // { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_1 }
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
extern int callee_1 (int one, const char *two, float three); extern int callee_1 (int one, const char *two, float three);
^~~~~~~~ ~~~~~~~~~~~~^~~
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -40,7 +37,7 @@ int test_2 (int first, int second, float third) ...@@ -40,7 +37,7 @@ int test_2 (int first, int second, float third)
// { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_2 } // { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_2 }
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
extern int callee_2 (int, const char *, float); extern int callee_2 (int, const char *, float);
^~~~~~~~ ^~~~~~~~~~~~
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -61,7 +58,7 @@ int test_3 (int first, int second, float third) ...@@ -61,7 +58,7 @@ int test_3 (int first, int second, float third)
// { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_3 } // { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*, float\\)'" "" { target *-*-* } callee_3 }
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
static int callee_3 (int one, const char *two, float three) static int callee_3 (int one, const char *two, float three)
^~~~~~~~ ~~~~~~~~~~~~^~~
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -78,7 +75,7 @@ int test_4 (int first, int second, float third) ...@@ -78,7 +75,7 @@ int test_4 (int first, int second, float third)
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
struct s4 { static int member_1 (int one, const char *two, float three); }; struct s4 { static int member_1 (int one, const char *two, float three); };
^~~~~~~~ ~~~~~~~~~~~~^~~
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -96,7 +93,7 @@ int test_5 (int first, int second, float third) ...@@ -96,7 +93,7 @@ int test_5 (int first, int second, float third)
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
struct s5 { int member_1 (int one, const char *two, float three); }; struct s5 { int member_1 (int one, const char *two, float three); };
^~~~~~~~ ~~~~~~~~~~~~^~~
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -113,7 +110,7 @@ int test_6 (int first, int second, float third, s6 *ptr) ...@@ -113,7 +110,7 @@ int test_6 (int first, int second, float third, s6 *ptr)
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
struct s6 { int member_1 (int one, const char *two, float three); }; struct s6 { int member_1 (int one, const char *two, float three); };
^~~~~~~~ ~~~~~~~~~~~~^~~
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -153,7 +150,7 @@ int test_8 (int first, int second, float third) ...@@ -153,7 +150,7 @@ int test_8 (int first, int second, float third)
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
struct s8 { static int member_1 (int one, T two, float three); }; struct s8 { static int member_1 (int one, T two, float three); };
^~~~~~~~ ~~^~~
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
...@@ -172,7 +169,43 @@ int test_9 (int first, int second, float third) ...@@ -172,7 +169,43 @@ int test_9 (int first, int second, float third)
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" } /* { dg-begin-multiline-output "" }
struct s9 { int member_1 (int one, T two, float three); }; struct s9 { int member_1 (int one, T two, float three); };
^~~~~~~~ ~~^~~
{ dg-end-multiline-output "" } */
}
/* Callback with name. */
extern int callee_10 (int one, int (*two)(int, int), float three); // { dg-line callee_10 }
int test_10 (int first, int second, float third)
{
return callee_10 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
/* { dg-begin-multiline-output "" }
return callee_10 (first, second, third);
^
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_10\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_10 }
/* { dg-begin-multiline-output "" }
extern int callee_10 (int one, int (*two)(int, int), float three);
~~~~~~^~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
/* Callback without name. */
extern int callee_11 (int one, int (*)(int, int), float three); // { dg-line callee_11 }
int test_11 (int first, int second, float third)
{
return callee_11 (first, second, third); // { dg-error "invalid conversion from 'int' to 'int \\(\\*\\)\\(int, int\\)'" }
/* { dg-begin-multiline-output "" }
return callee_11 (first, second, third);
^
{ dg-end-multiline-output "" } */
// { dg-message "initializing argument 2 of 'int callee_11\\(int, int \\(\\*\\)\\(int, int\\), float\\)'" "" { target *-*-* } callee_11 }
/* { dg-begin-multiline-output "" }
extern int callee_11 (int one, int (*)(int, int), float three);
^~~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */ { dg-end-multiline-output "" } */
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment