Bug 90735 - missing location in -Wreturn-local-addr on a function with two return statements
Summary: missing location in -Wreturn-local-addr on a function with two return statements
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 9.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wreturn-local-addr
  Show dependency treegraph
 
Reported: 2019-06-03 17:08 UTC by Martin Sebor
Modified: 2020-02-09 23:05 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2019-06-03 17:08:13 UTC
The -Wreturn-local-addr warning is often missing location information when issued for one of two (or more) return statements in a function involving conditionals.  For example:

$ cat a.c && gcc -O2 -S -Wall -Wextra a.c
extern int a[], b[];

int* f (int i, int j)
{
  int c;
  int *p = i < 0 ? a : b;
  if (*p)
    return p;
  if (j < 0)
    p = &c;

  return p;
}
a.c: In function ‘f’:
cc1: warning: function may return address of local variable [-Wreturn-local-addr]
a.c:5:7: note: declared here
    5 |   int c;
      |       ^
Comment 1 Martin Sebor 2019-06-03 18:00:21 UTC
The output of the -fdump-tree-all-lineno option shows the correct location information in the a.c.007t.omplower dump:

;; Function f (f, funcdef_no=0, decl_uid=1909, cgraph_uid=1, symbol_order=0)

f (int i, int j)
[../a.c:4:1] {
  int * iftmp.0;
  int * D.1920;
  int c;
  int * p;

  try
    {
      [../a.c:6:22] if (i < 0) goto <D.1915>; else goto <D.1916>;
      <D.1915>:
      [../a.c:6:22] iftmp.0 = [../a.c:6:20] &a;
      goto <D.1917>;
      <D.1916>:
      [../a.c:6:22] iftmp.0 = [../a.c:6:24] &b;
      <D.1917>:
      [../a.c:6:8] p = iftmp.0;
      [../a.c:7:7] _1 = [../a.c:7:7] *p;
      [../a.c:7:6] if (_1 != 0) goto <D.1918>; else goto <D.1919>;
      <D.1918>:
      [../a.c:8:12] D.1920 = p;
      [../a.c:8:12] // predicted unlikely by early return (on trees) predictor.
      [../a.c:8:12] return D.1920;
      <D.1919>:
      [../a.c:9:6] if (j < 0) goto <D.1921>; else goto <D.1922>;
      <D.1921>:
      [../a.c:10:7] p = [../a.c:10:9] &c;
      <D.1922>:
      [../a.c:12:10] D.1920 = p;
      [../a.c:12:10] return D.1920;
    }
  finally
    {
      c = {CLOBBER};
    }
}

but the a.c.008t.lower dump below does not.  The two return statements (one on line 8 and the other on line 12) are merged into one at the end of the function.  I'm not sure what would be a good solution here.  Keeping the location of either one of the statement would still lead to inaccurate results in some cases.  But maybe that's better than no location at all.

;; Function f (f, funcdef_no=0, decl_uid=1909, cgraph_uid=1, symbol_order=0)

f (int i, int j)
{
  int * p;
  int c;
  int * D.1920;
  int * iftmp.0;

  try
    {
      [../a.c:6:22] if (i < 0) goto <D.1915>; else goto <D.1916>;
      <D.1915>:
      [../a.c:6:22] iftmp.0 = [../a.c:6:20] &a;
      goto <D.1917>;
      <D.1916>:
      [../a.c:6:22] iftmp.0 = [../a.c:6:24] &b;
      <D.1917>:
      [../a.c:6:8] p = iftmp.0;
      [../a.c:7:7] _1 = [../a.c:7:7] *p;
      [../a.c:7:6] if (_1 != 0) goto <D.1918>; else goto <D.1919>;
      <D.1918>:
      [../a.c:8:12] D.1920 = p;
      [../a.c:8:12] // predicted unlikely by early return (on trees) predictor.
      [../a.c:8:12] goto <D.1923>;
      <D.1919>:
      [../a.c:9:6] if (j < 0) goto <D.1921>; else goto <D.1922>;
      <D.1921>:
      [../a.c:10:7] p = [../a.c:10:9] &c;
      <D.1922>:
      [../a.c:12:10] D.1920 = p;
      [../a.c:12:10] goto <D.1923>;
    }
  finally
    {
      c = {CLOBBER};
    }
  <D.1923>:
  return D.1920;
}
Comment 2 Martin Sebor 2019-06-03 18:19:21 UTC
The problem is in this function in gimple-low.c:

    /* Lower a GIMPLE_RETURN GSI.  DATA is passed through the recursion.  */

    static void
    lower_gimple_return (gimple_stmt_iterator *gsi, struct lower_data *data)
    {
      ...

      if (gimple_return_retval (stmt) == gimple_return_retval (tmp_rs.stmt))
	{
	  /* Remove the line number from the representative return statement.
	     It now fills in for many such returns.  Failure to remove this
	     will result in incorrect results for coverage analysis.  */
	  gimple_set_location (tmp_rs.stmt, UNKNOWN_LOCATION);

	  goto found;
	}
      ...

I wonder if setting the location to the closing curly brace of the function definition would not cause these failures.  At least the warning would point into the right function if not the right statement.