aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c/ChangeLog19
-rw-r--r--gcc/c/c-decl.c6
-rw-r--r--gcc/c/c-parser.c38
-rw-r--r--gcc/c/c-tree.h4
-rw-r--r--gcc/c/c-typeck.c78
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.dg/diagnostic-range-bad-called-object.c2
-rw-r--r--gcc/testsuite/gcc.dg/param-type-mismatch.c83
-rw-r--r--gcc/testsuite/gcc.dg/pr68533.c8
9 files changed, 206 insertions, 42 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 87d6c0a..ae9d639 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,22 @@
+2017-10-04 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.c (push_parm_decl): Store c_parm's location into the
+ PARAM_DECL.
+ (build_c_parm): Add "loc" param and store it within the c_parm.
+ * c-parser.c (struct c_parser): Add "last_token_location" field.
+ (c_parser_consume_token): Store location of the token into the
+ new field.
+ (c_parser_declaration_or_fndef): Store params into DECL_ARGUMENTS
+ when handling a FUNCTION_DECL, if it doesn't already have them.
+ (c_parser_parameter_declaration): Generate a location for the
+ parameter, and pass it to the call to build_c_parm.
+ * c-tree.h (struct c_parm): Add field "loc".
+ (build_c_parm): Add location_t param.
+ * c-typeck.c (get_fndecl_argument_location): New function.
+ (inform_for_arg): New function.
+ (convert_for_assignment): Use inform_for_arg when dealing with
+ ic_argpass.
+
2017-09-29 Jakub Jelinek <jakub@redhat.com>
* c-decl.c (grokfield): Use SET_DECL_C_BIT_FIELD here if
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index a6b7c20..724d193 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -5190,6 +5190,8 @@ push_parm_decl (const struct c_parm *parm, tree *expr)
decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
&attrs, expr, NULL, DEPRECATED_NORMAL);
+ if (decl && DECL_P (decl))
+ DECL_SOURCE_LOCATION (decl) = parm->loc;
decl_attributes (&decl, attrs, 0);
decl = pushdecl (decl);
@@ -9700,12 +9702,14 @@ build_void_list_node (void)
struct c_parm *
build_c_parm (struct c_declspecs *specs, tree attrs,
- struct c_declarator *declarator)
+ struct c_declarator *declarator,
+ location_t loc)
{
struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
ret->specs = specs;
ret->attrs = attrs;
ret->declarator = declarator;
+ ret->loc = loc;
return ret;
}
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index a36397b..1a5e39e 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -206,6 +206,9 @@ struct GTY(()) c_parser {
/* Buffer to hold all the tokens from parsing the vector attribute for the
SIMD-enabled functions (formerly known as elemental functions). */
vec <c_token, va_gc> *cilk_simd_fn_tokens;
+
+ /* Location of the last consumed token. */
+ location_t last_token_location;
};
/* Return a pointer to the Nth token in PARSERs tokens_buf. */
@@ -770,6 +773,7 @@ c_parser_consume_token (c_parser *parser)
gcc_assert (parser->tokens[0].type != CPP_EOF);
gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
+ parser->last_token_location = parser->tokens[0].location;
if (parser->tokens != &parser->tokens_buf[0])
parser->tokens++;
else if (parser->tokens_avail == 2)
@@ -2120,6 +2124,10 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
tree d = start_decl (declarator, specs, false,
chainon (postfix_attrs,
all_prefix_attrs));
+ if (d && TREE_CODE (d) == FUNCTION_DECL)
+ if (declarator->kind == cdk_function)
+ if (DECL_ARGUMENTS (d) == NULL_TREE)
+ DECL_ARGUMENTS (d) = declarator->u.arg_info->parms;
if (omp_declare_simd_clauses.exists ()
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
{
@@ -4039,6 +4047,9 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
c_parser_skip_to_end_of_parameter (parser);
return NULL;
}
+
+ location_t start_loc = c_parser_peek_token (parser)->location;
+
specs = build_null_declspecs ();
if (attrs)
{
@@ -4061,8 +4072,33 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
}
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
postfix_attrs = c_parser_attributes (parser);
+
+ /* Generate a location for the parameter, ranging from the start of the
+ initial token to the end of the final token.
+
+ 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 end_loc = parser->last_token_location;
+
+ /* Find any cdk_id declarator; determine if we have an identifier. */
+ c_declarator *id_declarator = declarator;
+ while (id_declarator && id_declarator->kind != cdk_id)
+ id_declarator = id_declarator->declarator;
+ location_t caret_loc = (id_declarator->u.id
+ ? id_declarator->id_loc
+ : start_loc);
+ location_t param_loc = make_location (caret_loc, start_loc, end_loc);
+
return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
- declarator);
+ declarator, param_loc);
}
/* Parse a string literal in an asm expression. It should not be
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 96c7ae7..1135647 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -477,6 +477,8 @@ struct c_parm {
tree attrs;
/* The declarator. */
struct c_declarator *declarator;
+ /* The location of the parameter. */
+ location_t loc;
};
/* Used when parsing an enum. Initialized by start_enum. */
@@ -581,7 +583,7 @@ extern void temp_pop_parm_decls (void);
extern tree xref_tag (enum tree_code, tree);
extern struct c_typespec parser_xref_tag (location_t, enum tree_code, tree);
extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
- struct c_declarator *);
+ struct c_declarator *, location_t);
extern struct c_declarator *build_attrs_declarator (tree,
struct c_declarator *);
extern struct c_declarator *build_function_declarator (struct c_arg_info *,
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 73e7460..2a10813 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6180,6 +6180,50 @@ maybe_warn_string_init (location_t loc, tree type, struct c_expr expr)
"array initialized from parenthesized string constant");
}
+/* Attempt to locate the parameter with the given index within FNDECL,
+ returning DECL_SOURCE_LOCATION (FNDECL) if it can't be found. */
+
+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 = DECL_ARGUMENTS (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 DECL_SOURCE_LOCATION (FNDECL). */
+ if (param == NULL)
+ return DECL_SOURCE_LOCATION (fndecl);
+
+ return DECL_SOURCE_LOCATION (param);
+}
+
+/* Issue a note about a mismatching argument for parameter PARMNUM
+ to FUNDECL, for types EXPECTED_TYPE and ACTUAL_TYPE.
+ Attempt to issue the note at the pertinent parameter of the decl;
+ failing that issue it at the location of FUNDECL; failing that
+ issue it at PLOC. */
+
+static void
+inform_for_arg (tree fundecl, location_t ploc, int parmnum,
+ tree expected_type, tree actual_type)
+{
+ location_t loc;
+ if (fundecl && !DECL_IS_BUILTIN (fundecl))
+ loc = get_fndecl_argument_location (fundecl, parmnum - 1);
+ else
+ loc = ploc;
+
+ inform (loc,
+ "expected %qT but argument is of type %qT",
+ expected_type, actual_type);
+}
+
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the
original type of RHS; this differs from TREE_TYPE (RHS) for enum
@@ -6251,10 +6295,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
{ \
case ic_argpass: \
if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
- "expected %qT but argument is of type %qT", \
- type, rhstype); \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
break; \
case ic_assign: \
pedwarn (LOCATION, OPT, AS); \
@@ -6280,10 +6321,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
{ \
case ic_argpass: \
if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
- "expected %qT but argument is of type %qT", \
- type, rhstype); \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
break; \
case ic_assign: \
pedwarn (LOCATION, OPT, AS, QUALS); \
@@ -6309,10 +6347,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
{ \
case ic_argpass: \
if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
- "expected %qT but argument is of type %qT", \
- type, rhstype); \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
break; \
case ic_assign: \
warning_at (LOCATION, OPT, AS, QUALS); \
@@ -6864,10 +6899,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (pedwarn (expr_loc, OPT_Wincompatible_pointer_types,
"passing argument %d of %qE from incompatible "
"pointer type", parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT",
- type, rhstype);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
break;
case ic_assign:
pedwarn (location, OPT_Wincompatible_pointer_types,
@@ -6910,10 +6942,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (pedwarn (expr_loc, OPT_Wint_conversion,
"passing argument %d of %qE makes pointer from "
"integer without a cast", parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT",
- type, rhstype);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
break;
case ic_assign:
pedwarn (location, OPT_Wint_conversion,
@@ -6944,10 +6973,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (pedwarn (expr_loc, OPT_Wint_conversion,
"passing argument %d of %qE makes integer from "
"pointer without a cast", parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT",
- type, rhstype);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
break;
case ic_assign:
pedwarn (location, OPT_Wint_conversion,
@@ -6985,9 +7011,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
case ic_argpass:
error_at (expr_loc, "incompatible type for argument %d of %qE", parmnum,
rname);
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT", type, rhstype);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
break;
case ic_assign:
error_at (location, "incompatible types when assigning to type %qT from "
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 61357e8..eb9f5b8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,15 @@
2017-10-04 David Malcolm <dmalcolm@redhat.com>
+ * gcc.dg/diagnostic-range-bad-called-object.c: Update expected
+ underlining for param.
+ * gcc.dg/param-type-mismatch.c: Update expected results to reflect
+ highlighting of parameters; add test coverage for trivial
+ parameter decls, and for callback parameters.
+ * gcc.dg/pr68533.c: Update location of two errors to reflect
+ location of params.
+
+2017-10-04 David Malcolm <dmalcolm@redhat.com>
+
* jit.dg/test-expressions.c (make_test_of_vectors): New function.
(create_code): Call it.
* jit.dg/test-vector-rvalues.cc: New test case.
diff --git a/gcc/testsuite/gcc.dg/diagnostic-range-bad-called-object.c b/gcc/testsuite/gcc.dg/diagnostic-range-bad-called-object.c
index 95fb3e9..0f7fd2a 100644
--- a/gcc/testsuite/gcc.dg/diagnostic-range-bad-called-object.c
+++ b/gcc/testsuite/gcc.dg/diagnostic-range-bad-called-object.c
@@ -19,6 +19,6 @@ void call_of_non_function_ptr (char **argP, char **argQ)
{ dg-end-multiline-output "" }
{ dg-begin-multiline-output "" }
void call_of_non_function_ptr (char **argP, char **argQ)
- ^~~~
+ ~~~~~~~^~~~
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/param-type-mismatch.c b/gcc/testsuite/gcc.dg/param-type-mismatch.c
index 70ea0bc..9498a74 100644
--- a/gcc/testsuite/gcc.dg/param-type-mismatch.c
+++ b/gcc/testsuite/gcc.dg/param-type-mismatch.c
@@ -1,9 +1,6 @@
/* { dg-options "-fdiagnostics-show-caret" } */
-/* A collection of calls where argument 2 is of the wrong type.
-
- TODO: we should highlight the second parameter of the callee, rather
- than its name. */
+/* A collection of calls where argument 2 is of the wrong type. */
/* decl, with argname. */
@@ -19,7 +16,7 @@ int test_1 (int first, int second, float third)
/* { dg-message "expected 'const char \\*' but argument is of type 'int'" "" { target *-*-* } callee_1 } */
/* { dg-begin-multiline-output "" }
extern int callee_1 (int one, const char *two, float three);
- ^~~~~~~~
+ ~~~~~~~~~~~~^~~
{ dg-end-multiline-output "" } */
}
@@ -37,7 +34,7 @@ int test_2 (int first, int second, float third)
/* { dg-message "expected 'const char \\*' but argument is of type 'int'" "" { target *-*-* } callee_2 } */
/* { dg-begin-multiline-output "" }
extern int callee_2 (int, const char *, float);
- ^~~~~~~~
+ ^~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
@@ -58,6 +55,78 @@ int test_3 (int first, int second, float third)
/* { dg-message "expected 'const char \\*' but argument is of type 'int'" "" { target *-*-* } callee_3 } */
/* { dg-begin-multiline-output "" }
static int callee_3 (int one, const char *two, float three)
- ^~~~~~~~
+ ~~~~~~~~~~~~^~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Trivial decl, with argname. */
+
+extern int callee_4 (int one, float two, float three); /* { dg-line callee_4 } */
+
+int test_4 (int first, const char *second, float third)
+{
+ return callee_4 (first, second, third); /* { dg-error "incompatible type for argument 2 of 'callee_4'" } */
+ /* { dg-begin-multiline-output "" }
+ return callee_4 (first, second, third);
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+ /* { dg-message "expected 'float' but argument is of type 'const char \\*'" "" { target *-*-* } callee_4 } */
+ /* { dg-begin-multiline-output "" }
+ extern int callee_4 (int one, float two, float three);
+ ~~~~~~^~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Trivial decl, without argname. */
+
+extern int callee_5 (int, float, float); /* { dg-line callee_5 } */
+
+int test_5 (int first, const char *second, float third)
+{
+ return callee_5 (first, second, third); /* { dg-error "incompatible type for argument 2 of 'callee_5'" } */
+ /* { dg-begin-multiline-output "" }
+ return callee_5 (first, second, third);
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+ /* { dg-message "expected 'float' but argument is of type 'const char \\*'" "" { target *-*-* } callee_5 } */
+ /* { dg-begin-multiline-output "" }
+ extern int callee_5 (int, float, float);
+ ^~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Callback with name. */
+
+extern int callee_6 (int one, int (*two)(int, int), float three); /* { dg-line callee_6 } */
+
+int test_6 (int first, int second, float third)
+{
+ return callee_6 (first, second, third); /* { dg-warning "passing argument 2 of 'callee_6' makes pointer from integer without a cast" } */
+ /* { dg-begin-multiline-output "" }
+ return callee_6 (first, second, third);
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+ /* { dg-message " expected 'int \\(\\*\\)\\(int, int\\)' but argument is of type 'int'" "" { target *-*-* } callee_6 } */
+ /* { dg-begin-multiline-output "" }
+ extern int callee_6 (int one, int (*two)(int, int), float three);
+ ~~~~~~^~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Callback without name. */
+
+extern int callee_7 (int one, int (*)(int, int), float three); /* { dg-line callee_7 } */
+
+int test_7 (int first, int second, float third)
+{
+ return callee_7 (first, second, third); /* { dg-warning "passing argument 2 of 'callee_7' makes pointer from integer without a cast" } */
+ /* { dg-begin-multiline-output "" }
+ return callee_7 (first, second, third);
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+ /* { dg-message " expected 'int \\(\\*\\)\\(int, int\\)' but argument is of type 'int'" "" { target *-*-* } callee_7 } */
+ /* { dg-begin-multiline-output "" }
+ extern int callee_7 (int one, int (*)(int, int), float three);
+ ^~~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr68533.c b/gcc/testsuite/gcc.dg/pr68533.c
index e1a1f31..49e67a9 100644
--- a/gcc/testsuite/gcc.dg/pr68533.c
+++ b/gcc/testsuite/gcc.dg/pr68533.c
@@ -28,8 +28,8 @@ f2 (
void
f3 (
- const void
- ) /* { dg-error "'void' as only parameter may not be qualified" } */
+ const void /* { dg-error "'void' as only parameter may not be qualified" } */
+ )
{
}
@@ -54,8 +54,8 @@ void
f6 (
int
x,
- void
- ) /* { dg-error "'void' must be the only parameter" } */
+ void /* { dg-error "'void' must be the only parameter" } */
+ )
{
}