diff options
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/c/c-decl.c | 6 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 38 | ||||
-rw-r--r-- | gcc/c/c-tree.h | 4 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 78 |
5 files changed, 115 insertions, 30 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 " |