lto, testsuite: Fix ICE in -Wodr (PR lto/83121)
commit0a425a4ac0c3c2ad22086c490efccbd9a0849df3
authordmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 17 Jan 2018 16:56:56 +0000 (17 16:56 +0000)
committerdmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 17 Jan 2018 16:56:56 +0000 (17 16:56 +0000)
tree7b14acd4aab7681b7028d9c600cad008ca4ddba5
parent2c1c4ac97e211a4ed566460c6f10ffcc815f5215
lto, testsuite: Fix ICE in -Wodr (PR lto/83121)

PR lto/83121 reports an ICE deep inside the linemap code when -Wodr
reports on a type mismatch.

The root cause is that the warning can access the DECL_SOURCE_LOCATION
of a streamed-in decl before the lto_location_cache has been applied.

lto_location_cache::input_location stores RESERVED_LOCATION_COUNT (==2)
as a poison value until the cache is applied:
250   /* Keep value RESERVED_LOCATION_COUNT in *loc as linemap lookups will
251      ICE on it.  */

The fix is relatively simple: apply the cache before reading the
DECL_SOURCE_LOCATION.

Triggering the ICE was fiddly: it seems to be affected by many things,
including the order of files, and (I think) by filenames.  My theory is
that it's affected by the ordering of the tree nodes in the LTO stream:
for the ICE to occur, the types in question need to be compared before
some other operation flushes the lto_location_cache.  This ordering
is affected by the hash-based ordering in DFS in lto-streamer-out.c, which
might explain why r255066 seemed to trigger the bug; the only relevant
change to LTO there seemed to be:
  * lto-streamer-out.c (hash_tree): Hash TYPE_EMPTY_P and DECL_PADDING_P.
If so, then the bug was presumably already present, but hidden.

The patch also adds regression test coverage for the ICE, which is more
involved - as far as I can tell, we don't have an existing way to verify
diagnostics emitted during link-time optimization.

Hence the patch adds some machinery to lib/lto.exp to support two new
directives: dg-lto-warning and dg-lto-message, corresponding to
dg-warning and dg-message respectively, where the diagnostics are
expected to be emitted at link-time.

The test case includes examples of LTO warnings and notes in both the
primary and secondary source files

Doing so required reusing the logic from DejaGnu for handling diagnostics.
Unfortunately the pertinent code is a 50 line loop within a ~200 line Tcl
function in dg.exp (dg-test), so I had to copy it from DejaGnu, making
various changes as necessary (see lto_handle_diagnostics_for_file in the
patch; for example the LTO version supports multiple source files,
identifying which source file emitted a diagnostic).

For non-LTO diagnostics we currently ignore surplus "note" diagnostics.
This patch updates lto_prune_warns to follow this behavior (since
otherwise we'd need numerous dg-lto-message directives for the motivating
test case).

The patch adds these PASS results to g++.sum:

PASS: g++.dg/lto/pr83121 cp_lto_pr83121_0.o assemble, -O0 -flto
PASS: g++.dg/lto/pr83121 cp_lto_pr83121_1.o assemble, -O0 -flto
PASS: g++.dg/lto/pr83121  (test for LTO warnings, pr83121_0.C line 6)
PASS: g++.dg/lto/pr83121  (test for LTO warnings, pr83121_0.C line 8)
PASS: g++.dg/lto/pr83121  (test for LTO warnings, pr83121_1.C line 2)
PASS: g++.dg/lto/pr83121  (test for LTO warnings, pr83121_1.C line 3)
PASS: g++.dg/lto/pr83121 cp_lto_pr83121_0.o-cp_lto_pr83121_1.o link, -O0 -flto

The output for dg-lto-message above refers to "warnings", rather than
"messages" but that's the same as for the non-LTO case, where dg-message
also refers to "warnings".

gcc/ChangeLog:
PR lto/83121
* ipa-devirt.c (add_type_duplicate): When comparing memory layout,
call the lto_location_cache before reading the
DECL_SOURCE_LOCATION of the types.

gcc/testsuite/ChangeLog:
PR lto/83121
* g++.dg/lto/pr83121_0.C: New test case.
* g++.dg/lto/pr83121_1.C: New test case.
* lib/lto.exp (lto_handle_diagnostics_for_file): New procedure,
adapted from DejaGnu's dg-test.
(lto_handle_diagnostics): New procedure.
(lto_prune_warns): Ignore informational notes.
(lto-link-and-maybe-run): Add "messages_by_file" param.
Call lto_handle_diagnostics.  Avoid issuing "unresolved" for
"execute" when "link" fails if "execute" was not specified.
(lto-can-handle-directive): New procedure.
(lto-get-options-main): Call lto-can-handle-directive.  Add a
dg-messages local, using it to set the caller's
dg-messages-by-file for the given source file.
(lto-get-options): Likewise.
(lto-execute): Add dg-messages-by-file local, and pass it to
lto-link-and-maybe-run.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@256801 138bc75d-0d04-0410-961f-82ee72b054a4
gcc/ChangeLog
gcc/ipa-devirt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lto/pr83121_0.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lto/pr83121_1.C [new file with mode: 0644]
gcc/testsuite/lib/lto.exp