C++: missing result_decl loc of (member) functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux