On Wed, 2024-08-21 at 16:05 -0400, Jason Merrill wrote:
> On 8/21/24 3:34 PM, Arsen Arsenović wrote:
> > Jason Merrill <ja...@redhat.com> writes:
> > 
> > > On 8/21/24 1:52 PM, Arsen Arsenović wrote:
> > > > For clarity, here's the entire split-up patch I intend to push,
> > > > if it
> > > > looks OK.  Tested on x86_64-pc-linux-gnu.
> > > > I've renamed the field we've discussed and also a few
> > > > parameters that
> > > > refer to 'kw' to be less specific.  The code is functionally
> > > > identical.
> > > > OK for trunk?
> > > > TIA, have a lovely day.
> > > > ---------- >8 ----------
> > > > This patch improves the EXPR_LOCATION associated with parsed
> > > > RETURN_EXPRs so that they can be used in diagnostics later. 
> > > > This change
> > > > also happened to un-suppress an analyzer false-negative that
> > > > was
> > > > happening because the location of RETURN_EXPR was entirely
> > > > within the
> > > > NULL macro, which was defined in a system header.  PR
> > > > analyzer/116304.
> > > 
> > > The PR number should be on its own line, and in the subject line.
> > 
> > It isn't a total fix for that PR, that's why I didn't name it as
> > part of
> > the changelog and subject line, but to be fair it would not be
> > wrong to
> > put it there anyway, as it is related.  Will reword.
> > 
> > > > gcc/cp/ChangeLog:
> > > >         * cp-tree.h (finish_return_stmt): Add optional
> > > > location_t
> > > >         parameter, defaulting to input_location.
> > > >         * parser.cc (cp_parser_jump_statement): Improve return
> > > > and
> > > >         co_return locations so that they span their entire
> > > > statements.
> > > >         * semantics.cc (finish_return_stmt): Use the new
> > > > stmt_loc
> > > >         parameter in place of input_location.
> > > > gcc/testsuite/ChangeLog:
> > > >         * c-c++-common/analyzer/inlining-4-multiline.c: Adjust
> > > > locations
> > > >         in diagnostics.
> > > 
> > > This doesn't look like a location adjustment, but removing
> > > testing of expected
> > > output.  If the output changed, please change the test to check
> > > the new output
> > > rather than not at all.
> > 
> > This is the new output - the diagnostics no longer expand that
> > macro,
> > since the location is not wholly contained within it.  The relevant
> > part
> > of the diagnostics after the change is:
> > 
> > --8<---------------cut here---------------start------------->8---
> >                    |
> >                  'const char* inner(int)': event 5 (depth 3)
> >                    |
> >                    |     return NULL;
> >                    |
> > --8<---------------cut here---------------end--------------->8---
> > 
> > ... as opposed to (excuse the quote difference - the former was
> > pulled
> > from g++.log and the latter from a manual invocation):
> > 
> > --8<---------------cut here---------------start------------->8---
> >                    |
> >                  ‘const char* inner(int)’: event 5 (depth 3)
> >                    |
> >                    |/home/arsen/gcc-mine/gcc/testsuite/c-c++-
> > common/analyzer/../../gcc.dg/analyzer/analyzer-decls.h:7:14:
> >                    | #define NULL nullptr
> >                    |              ^~~~~~~
> >                    |              |
> >                    |              (5) ...to here
> > /home/arsen/gcc-mine/gcc/testsuite/c-c++-common/analyzer/inlining-
> > 4-multiline.c:14:12: note: in expansion of macro ‘NULL’
> >                    |     return NULL;
> >                    |            ^~~~
> >                    |
> > --8<---------------cut here---------------end--------------->8---
> > 
> > ... presumably, the diagnostics chose to elide those bits of output
> > due
> > to the new location covering the entire line (and hence not being
> > too
> > informative) - but I haven't debugged that (as I assumed the
> > diagnostic
> > code is DTRT now).
> 
> It seems weird to lose the "...to here" marking on the return.  Any 
> thoughts, David?

Sorry for missing this earlier.

With the patch applied, I see:

$ ./xg++ -B. -S -fanalyzer -O2 
../../src/gcc/testsuite/c-c++-common/analyzer/inlining-4-multiline.c
../../src/gcc/testsuite/c-c++-common/analyzer/inlining-4-multiline.c: In 
function ‘char outer(int)’:
../../src/gcc/testsuite/c-c++-common/analyzer/inlining-4-multiline.c:27:23: 
warning: dereference of NULL ‘0’ [CWE-476] [-Wanalyzer-null-dereference]
   27 |   return *middle (flag); /* { dg-warning "dereference of NULL" 
"warning" } */
      |                       ^
  ‘char outer(int)’: events 1-2
    │
    │   25 | outer (int flag)
    │      | ^~~~~
    │      | |
    │      | (1) entry to ‘outer’
    │   26 | {
    │   27 |   return *middle (flag); /* { dg-warning "dereference of NULL" 
"warning" } */
    │      |                  ~
    │      |                  |
    │      |                  (2) inlined call to ‘middle’ from ‘outer’
    │
    └──> ‘const char* middle(int)’: event 3
           │
           │   21 |   return inner (flag);
           │      |                ^
           │      |                |
           │      |                (3) inlined call to ‘inner’ from ‘middle’
           │
           └──> ‘const char* inner(int)’: event 4
                  │
                  │   13 |   if (flag)
                  │      |   ^~
                  │      |   |
                  │      |   (4) following ‘true’ branch (when ‘flag != 0’)... 
─>─┐
                  │      |                                                      
  │
                  │
                ‘const char* inner(int)’: event 5
                  │
                  │      |                                                      
  │
                  │      
|┌───────────────────────────────────────────────────────┘
                  │   14 |│    return NULL;
                  │
    <─────────────┘
    │
  ‘char outer(int)’: event 6
    │
    │   27 |   return *middle (flag); /* { dg-warning "dereference of NULL" 
"warning" } */
    │      |                       ^
    │      |                       |
    │      |                       (6) ⚠️  dereference of NULL ‘<unknown>’
    │

and in particular this weird output for event 5:

                ‘const char* inner(int)’: event 5
                  │
                  │      |                                                      
  │
                  │      
|┌───────────────────────────────────────────────────────┘
                  │   14 |│    return NULL;
                  │
    <─────────────┘


I did some poking at this in the debugger (via a breakpoint on
path_summary::path_summary).

Looking at event (5) (with idx == 4)'s location_t:

(gdb) p cur_event_range->m_richloc.m_ranges.m_embedded[0]
$13 = {m_loc = 4611686018427387937, m_range_display_kind =
SHOW_RANGE_WITH_CARET, 
  m_label = 0x526e358, m_highlight_color = 0x0}
(gdb) p /x cur_event_range->m_richloc.m_ranges.m_embedded[0]
$14 = {m_loc = 0x4000000000000021, m_range_display_kind = 0x0, m_label
= 0x526e358, 
  m_highlight_color = 0x0}

Looks like this is an ad-hoc location (64-bit):

(gdb) call inform (0x4000000000000021, "")
In function ‘const char* inner(int)’,
    inlined from ‘const char* middle(int)’ at
../../src/gcc/testsuite/c-c++-common/analyzer/inlining-4-
multiline.c:21:16,
    inlined from ‘char outer(int)’ at ../../src/gcc/testsuite/c-c++-
common/analyzer/inlining-4-multiline.c:27:18:

   14 |     return NULL;

Looking up the ad-hoc data for 0x4000000000000021:

(gdb) p line_table->m_location_adhoc_data_map.data[0x21]
$16 = {locus = 2368512, src_range = {m_start = 2368512, m_finish =
4611686018427387897}, 
  data = 0x7fffea650958, discriminator = 0}

The inlining info is in "data"; looking at the caret/start/finish
locations:

(gdb) call inform (2368512, "")
../../src/gcc/testsuite/c-c++-common/analyzer/inlining-4-multiline.c:
In function ‘char outer(int)’:

   14 |     return NULL;
      |     ^
(gdb) call inform (4611686018427387897, "")
In file included from ../../src/gcc/testsuite/c-c++-
common/analyzer/inlining-4-multiline.c:7:

    7 | #define NULL nullptr
      |              ^~~~~~~
../../src/gcc/testsuite/c-c++-common/analyzer/inlining-4-
multiline.c:14:12: note: in expansion of macro ‘NULL’
   14 |     return NULL;
      |            ^~~~

So the issue is that the "start" and "caret" parts of the location_t
are at the "r" of "return" in inlining-4-multiline.c line 14, but the
"end" part of the location_t is on the NULL token expanded as part of a
macro expansion, presumably created by this part of the patch:

+       /* A location spanning the whole statement (up to ';').  */
+       auto stmt_loc = make_location (token->location,
+                                      token->location,
+                                      input_location);
+

Hence the location_t spans two different source files, and diagnostic-
show-locus.cc rejects attempting to draw an underline for such a
location_t, and hence the text label for the underline ("...to here")
doesn't get printed either.

I'm not sure if the location_t value being created by the patch is
"wrong" or whether diagnostic-show-locus.cc could/should have a
workaround for such cases.

Dave

> 
> > > >         * c-c++-common/analyzer/malloc-paths-9-noexcept.c:
> > > > Ditto.
> > > 
> > > ...like you do properly in this test.
> > > 
> > > >         * c-c++-common/analyzer/malloc-CWE-401-example.c:
> > > > Accept the
> > > >         new warning on line 34 (fixed false negative).
> > > 
> > > I'd think the new dg-warning could replace the obsolete TODO?
> > 
> > I left it because the TODO still exists for C (which wasn't fixed
> > in
> > this patch - hence the { target c++ }).  I can clarify it like:
> > 
> >    /* TODO: should complain that "buf" is leaked on this path in C
> >       also.  */
> > 
> > ... which should be more informative.
> 
> Sounds good.
> 
> Jason
> 

Reply via email to