Bug 106274 - Loss of macro tracking information with -flto
Summary: Loss of macro tracking information with -flto
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: lto (show other bugs)
Version: 12.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic, lto
Depends on:
Blocks:
 
Reported: 2022-07-12 19:51 UTC by Lewis Hyatt
Modified: 2024-11-06 16:43 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-07-13 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Lewis Hyatt 2022-07-12 19:51:32 UTC
This is related to PR101551 but easier to demonstrate a testcase for:

=======
#define X(p) p == 0
int f(void *) __attribute__((nonnull));
int f(void *p) {
    return X(p);
}
========

When compiled without -flto, there is information on the macro expansion in the diagnostics:

$ gcc -c t5.c -Wnonnull-compare
/home/lewis/t5.c: In function ‘f’:
/home/lewis/t5.c:1:16: warning: nonnull argument ‘p’ compared to NULL [-Wnonnull-compare]
    1 | #define X(p) p == 0
      |                ^
/home/lewis/t5.c:4:12: note: in expansion of macro ‘X’
    4 |     return X(p);
      |            ^

However, if you add -flto, you don't get the extra information:

$ gcc -c t5.c -Wnonnull-compare -flto
/home/lewis/t5.c: In function ‘f’:
/home/lewis/t5.c:1:16: warning: nonnull argument ‘p’ compared to NULL [-Wnonnull-compare]
    1 | #define X(p) p == 0
      |                ^

The reason is that this warning is generated after the ipa_free_lang_data pass, and that does this:

========
/* If we are the LTO frontend we have freed lang-specific data already.  */
  if (in_lto_p
      || (!flag_generate_lto && !flag_generate_offload))
    {
      /* Rebuild type inheritance graph even when not doing LTO to get
         consistent profile data.  */
      rebuild_type_inheritance_graph ();
      return 0;
    }

...

    /* Reset diagnostic machinery.  */
    tree_diagnostics_defaults (global_dc);

========

With -flto, flag_generate_lto is true, so it doesn't return early, and proceeds to the last line, which resets the diagnostic finalizer to default_diagnostic_finalizer, which is not aware of virtual locations.

PR101551 is about more or less the same thing except it's the other case that prevents this function from returning early (flag_generate_offload == true). I am not sure to what extent they are otherwise related.

Is it possible to avoid resetting the diagnostics machinery in either of these cases? Thanks...
Comment 1 Richard Biener 2022-07-13 06:38:07 UTC
I think the point is that in free-lang-data we are bulldozering over data structures that the frontend might not be happy about (in the attempt to make
the streamed IL small), so we try to reset all callbacks into frontend code
that might crash.

I'm not sure to what extent this is still required with respect to the
diagnostic context though - you'd have to try.

There's also the old long-standing TODO to perform this "frontend scrapping"
also when not using -flto just to save on memory for the followup optimization
(but this runs into the same issue that late diagnostics then appear
"mangled").
Comment 2 Martin Liška 2022-07-13 07:15:45 UTC
I think it's a dup of PR80922.
Comment 3 Lewis Hyatt 2022-07-13 12:13:38 UTC
(In reply to Martin Liška from comment #2)
> I think it's a dup of PR80922.

I think it's a bit different, if I understand correctly, PR80922 is asking for something much more difficult, it wants the LTO streaming process to be able to remember that it saw a diagnostic pragma, so that the LTO frontend can know about it when reading the data back in, and so suppress new warnings it is able to generate due to the power of the interprocedural analysis it has access to. That seems pretty challenging, given we still have a lot of bugs with just handling diagnostic pragmas properly in the non-LTO case.

In my testcase here, the diagnostic is emitted by cc1/cc1plus while producing the data for LTO, not by the LTO frontend, and everything is fine with it except that it gets printed with a barebones printer, rather than a virtual location aware printer.
Comment 4 Lewis Hyatt 2022-07-13 17:48:51 UTC
(In reply to Richard Biener from comment #1)
> I'm not sure to what extent this is still required with respect to the
> diagnostic context though - you'd have to try.

Thanks for the explanation, the general nature of it makes sense to me now. There is one current testcase (g++.dg/20090121-1.C) which demonstrates that it's not OK to simply skip calling tree_diagnostics_defaults () entirely for -flto... For that testcase, the -Wuninitialized diagnostic calling back into the C+ frontend (cp_printer) would ICE after ipa-free-lang-data pass if so.

It seems like it should be doable to address this, maybe frontends could specify how they want ipa-free-lang-data to adjust their diagnostic context, so it wouldn't have to be all or nothing. I can look into that sometime, perhaps it would help with enabling this pass to run during non-LTO compilation as well.