public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* C++: missing result_decl loc of (member) functions
@ 2022-04-20 17:20 Bernhard Reutner-Fischer
  2022-04-24 14:09 ` Bernhard Reutner-Fischer
  0 siblings, 1 reply; 3+ messages in thread
From: Bernhard Reutner-Fischer @ 2022-04-20 17:20 UTC (permalink / raw)
  To: gcc-help; +Cc: Bernhard Reutner-Fischer, jason

[-- Attachment #1: Type: text/plain, Size: 5152 bytes --]

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


[-- Attachment #2: result_decl_loc.00.patch --]
[-- Type: text/x-patch, Size: 3692 bytes --]

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;
 }
 \f
 /* 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);
 }
 
 


[-- Attachment #3: return-narrow.cc --]
[-- Type: text/x-c++src, Size: 1058 bytes --]

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);
}


[-- Attachment #4: return-narrow-2.cc --]
[-- Type: text/x-c++src, Size: 287 bytes --]

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 >;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: C++: missing result_decl loc of (member) functions
  2022-04-20 17:20 C++: missing result_decl loc of (member) functions Bernhard Reutner-Fischer
@ 2022-04-24 14:09 ` Bernhard Reutner-Fischer
  2022-04-25 15:22   ` Jason Merrill
  0 siblings, 1 reply; 3+ messages in thread
From: Bernhard Reutner-Fischer @ 2022-04-24 14:09 UTC (permalink / raw)
  To: gcc-help; +Cc: rep.dot.nop, jason

On Wed, 20 Apr 2022 19:20:24 +0200
Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> wrote:

> 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:

> ¹) 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:

This is due to decl1 having been ggc_freed here:

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
@@ -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;
+

which is why i previously had to use current_function_decl here.
> 
> 
> $ XXX=1 ../gcc/xg++ -B../gcc -c -o return-narrow.o return-narrow.cc -fdiagnostics-color=always 

> 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


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: C++: missing result_decl loc of (member) functions
  2022-04-24 14:09 ` Bernhard Reutner-Fischer
@ 2022-04-25 15:22   ` Jason Merrill
  0 siblings, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2022-04-25 15:22 UTC (permalink / raw)
  To: Bernhard Reutner-Fischer, gcc-help

On 4/24/22 10:09, Bernhard Reutner-Fischer wrote:
> On Wed, 20 Apr 2022 19:20:24 +0200
> Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> wrote:
> 
>> 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:
> 
>> ¹) 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:
> 
> This is due to decl1 having been ggc_freed here:

We might move building the RESULT_DECL from start_preparsed_function to 
grokfndecl, at which point we can set the location directly.  Maybe only 
build it if funcdef_flag is true.

> 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
> @@ -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;
> +
> 
> which is why i previously had to use current_function_decl here.
>>
>>
>> $ XXX=1 ../gcc/xg++ -B../gcc -c -o return-narrow.o return-narrow.cc -fdiagnostics-color=always
> 
>> 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
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-04-25 15:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-20 17:20 C++: missing result_decl loc of (member) functions Bernhard Reutner-Fischer
2022-04-24 14:09 ` Bernhard Reutner-Fischer
2022-04-25 15:22   ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).