Hi! I'm having a hard time to set the correct location of the result decl of member functions in C++. Any hint on where to best fix the missing locus? TIA for any hint (or a fix :). Long version: Neither the C nor the C++ frontend seem to have a working/proper location for the RESULT_DECL of functions. This makes it impossible to have diagnostics point at the return type of a function and hence it is impossible to have fixit-replace hints for the return types. [There is a gfortran bug that asks to use narrower return types for functions in the FE and i meant to get me a C++ warning that would point out all affected spots in the fortran FE..] Adding the correct location to the result decl of a function in the C frontend was easy, see attached. Same for the C++ FE for normal functions. These are covered in the attached sample-testcase return-narrow.cc ¹) and work well. I'm attaching a single patch for the C and C++ FE, knowing that they are to be sent separately upon real submission and probably only once stage1 reopens. But i cannot seem to find a proper spot to handle member functions (if that's the correct term for them). These are preparsed functions AFAICS and i'd need a place where i can get at the declspecs[ds_type_spec] and the function is parsed "enough" that the return type is determined, i think. I'm attaching the sample-testcase return-narrow-2.cc which, with a pristine compiler, gives no location for the result decl at all: ---8<--- $ XXX=1 ../gcc/xg++ -B../gcc -c -o return-narrow.o return-narrow-2.cc -fdiagnostics-color=always return-narrow-2.cc: In member function ‘long unsigned int __mini_vector< <template-parameter-1-1> >::_M_space_left()’: return-narrow-2.cc:7:3: warning: result decl locus sample 7 | { return _M_finish != 0; } | ^ | the return type return-narrow-2.cc: In instantiation of ‘long unsigned int __mini_vector< <template-parameter-1-1> >::_M_space_left() [with <template-parameter-1-1> = std::pair<long int, long int>]’: return-narrow-2.cc:9:17: required from here return-narrow-2.cc:6:3: warning: result decl locus sample 6 | _M_space_left() | ^~~~~~~~~~~~~ | the return type return-narrow-2.cc: In instantiation of ‘long unsigned int __mini_vector< <template-parameter-1-1> >::_M_space_left() [with <template-parameter-1-1> = int]’: return-narrow-2.cc:10:17: required from here return-narrow-2.cc:6:3: warning: result decl locus sample 6 | _M_space_left() | ^~~~~~~~~~~~~ | the return type ---8<--- I'd like to have the result_decl of _M_space_left point to the type unsigned long on line 5, which i think would be the correct type of that memberfn: 1 namespace std { template < typename, typename > struct pair; } 2 template < typename > struct __mini_vector 3 { 4 int _M_finish; 5 unsigned long 6 _M_space_left() 7 { return _M_finish != 0; } 8 }; 9 template class __mini_vector< std::pair< long, long > >; 10 template class __mini_vector< int >; help? :) TIA! ¹) C functions work out fine once fixed to have the correct loc. C++ functions worked fine once, but i now see that apparently "int my_main" on line 42 regressed again in the meantime: $ XXX=1 ../gcc/xg++ -B../gcc -c -o return-narrow.o return-narrow.cc -fdiagnostics-color=always return-narrow.cc: In function ‘int xyz(int, int, int)’: return-narrow.cc:1:1: warning: result decl locus sample 1 | int xyz (int param1, int param2, int param3) | ^~~ | the return type return-narrow.cc: In function ‘int abc(int, int, int)’: return-narrow.cc:11:1: warning: result decl locus sample 11 | int abc (int param1, int param2, int param3) | ^~~ | the return type return-narrow.cc: In function ‘const void* const* pointer_thingie(void*)’: return-narrow.cc:21:7: warning: result decl locus sample 21 | const void *const * pointer_thingie (void *i) | ^~~~ | the return type return-narrow.cc: In function ‘int comparer(int, int, int)’: return-narrow.cc:25:1: warning: result decl locus sample 25 | int comparer (int param1, int param2, int param3) | ^~~ | the return type return-narrow.cc: In function ‘int main()’: return-narrow.cc:35:1: warning: result decl locus sample 35 | int main (void) // dg-bogus "Function .main. could return .bool." | ^~~ | the return type return-narrow.cc: In function ‘int my_main(int, char**)’: return-narrow.cc:42:25: warning: result decl locus sample 42 | int my_main (int, char**) { return 0; } | ^ | the return type return-narrow.cc: In function ‘int hidden_main(int, char**)’: return-narrow.cc:43:1: warning: result decl locus sample 43 | int hidden_main (int, char**) { return 1; } | ^~~ | the return type return-narrow.cc: In function ‘int i64c(int)’: return-narrow.cc:46:1: warning: result decl locus sample 46 | int i64c(int i) | ^~~ | the return type
gcc/c/ChangeLog: * c-decl.cc (start_function): Set the result decl location. gcc/cp/ChangeLog: * decl.cc (start_function): Set the result decl location. (finish_function): XXX locus sample gcc/ChangeLog: * tree-pretty-print.cc (dump_location): Use pp_colon and pp_right_bracket where applicable. diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index c701f07befe..a441d187c1b 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -9487,6 +9487,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, tree decl1, old_decl; tree restype, resdecl; location_t loc; + location_t result_loc; current_function_returns_value = 0; /* Assume, until we see it does. */ current_function_returns_null = 0; @@ -9712,8 +9713,11 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator, push_scope (); declare_parm_level (); + /* Set the result decl source location to the location of the typespec. */ + result_loc = (declspecs->locations[cdw_typespec] == UNKNOWN_LOCATION + ? loc : declspecs->locations[cdw_typespec]); restype = TREE_TYPE (TREE_TYPE (current_function_decl)); - resdecl = build_decl (loc, RESULT_DECL, NULL_TREE, restype); + resdecl = build_decl (result_loc, RESULT_DECL, NULL_TREE, restype); DECL_ARTIFICIAL (resdecl) = 1; DECL_IGNORED_P (resdecl) = 1; DECL_RESULT (current_function_decl) = resdecl; diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index c136dbbba1a..38874bf1558 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -17361,6 +17361,8 @@ start_function (cp_decl_specifier_seq *declspecs, tree attrs) { tree decl1; + tree result; + bool ret; decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs); invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1); @@ -17373,7 +17375,18 @@ start_function (cp_decl_specifier_seq *declspecs, gcc_assert (same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node)); - return start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT); + ret = start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT); + + /* decl1 might be ggc_freed here. */ + //decl1 = current_function_decl; + + /* Set the result decl source location to the location of the typespec. */ + if (TREE_CODE (decl1) == FUNCTION_DECL + && declspecs->locations[ds_type_spec] != UNKNOWN_LOCATION + && (result = DECL_RESULT (decl1)) != NULL_TREE + && DECL_SOURCE_LOCATION (result) == input_location) + DECL_SOURCE_LOCATION (result) = declspecs->locations[ds_type_spec]; + return ret; } /* Returns true iff an EH_SPEC_BLOCK should be created in the body of @@ -17942,6 +17955,13 @@ finish_function (bool inline_p) "non-void")) suppress_warning (fndecl, OPT_Wreturn_type); } + if (getenv("XXX") != NULL) + { + location_t result_loc = DECL_SOURCE_LOCATION (DECL_RESULT (fndecl)); + gcc_rich_location richloc (result_loc); + richloc.add_fixit_replace (result_loc, "the return type"); + warning_at (&richloc, 0, "result dec%c locus sample", 'l'); + } /* Lambda closure members are implicitly constexpr if possible. */ if (cxx_dialect >= cxx17 diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index 99af977979d..591883c4063 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -1412,12 +1412,12 @@ dump_location (pretty_printer *pp, location_t loc) if (xloc.file) { pp_string (pp, xloc.file); - pp_string (pp, ":"); + pp_colon (pp); } pp_decimal_int (pp, xloc.line); pp_colon (pp); pp_decimal_int (pp, xloc.column); - pp_string (pp, "] "); + pp_right_bracket (pp); }
int xyz (int param1, int param2, int param3) { if (param1 == 42) return 1; if (param2 == 17) return 1; if (param3 == 99) return 1; return 0; } int abc (int param1, int param2, int param3) { if (param1 == 42) return 0; if (param2 == 17) return 0; if (param3 == 99) return 0; return 0; } const void *const * pointer_thingie (void *i) { return (const void *const *)((long)i & 1); } int comparer (int param1, int param2, int param3) { if (param1 >= 42) return 1; if (param2 == 17) return 1; if (param3 <= 99) return -1; return 0; } int main (void) // dg-bogus "Function .main. could return .bool." { return 0; } _Pragma("GCC visibility push(hidden)") int my_main (int argc, char**argv) __attribute__(( visibility("default") )); int my_main (int, char**) { return 0; } int hidden_main (int, char**) { return 1; } _Pragma("GCC visibility pop") int i64c(int i) { i &= 0x3f; if (i == 0) return '.'; if (i == 1) return '/'; if (i < 12) return ('0' - 2 + i); if (i < 38) return ('A' - 12 + i); return ('a' - 38 + i); }
namespace std { template < typename, typename > struct pair; } template < typename > struct __mini_vector { int _M_finish; unsigned long _M_space_left() { return _M_finish != 0; } }; template class __mini_vector< std::pair< long, long > >; template class __mini_vector< int >;