diff -Nrcpad gcc-16-20250720/ChangeLog gcc-16-20250727/ChangeLog
*** gcc-16-20250720/ChangeLog	Sun Jul 20 22:32:07 2025
--- gcc-16-20250727/ChangeLog	Sun Jul 27 22:32:07 2025
***************
*** 1,3 ****
--- 1,7 ----
+ 2025-07-22  Patrick Palka  <ppalka@redhat.com>
+ 
+ 	* MAINTAINERS: Add myself as C++ front end reviewer.
+ 
  2025-07-07  Tamar Christina  <tamar.christina@arm.com>
  
  	* MAINTAINERS: Add myself to AArch64 pot.
diff -Nrcpad gcc-16-20250720/LAST_UPDATED gcc-16-20250727/LAST_UPDATED
*** gcc-16-20250720/LAST_UPDATED	Sun Jul 20 22:33:13 2025
--- gcc-16-20250727/LAST_UPDATED	Sun Jul 27 22:32:22 2025
***************
*** 1 ****
! Obtained from git: master revision 7083aeaef5b6d8be1ae419b834e8e56d90026ace
--- 1 ----
! Obtained from git: master revision 0f61284eae6365e77b28af8fa4bc3dc7e5e0fac9
diff -Nrcpad gcc-16-20250720/MAINTAINERS gcc-16-20250727/MAINTAINERS
*** gcc-16-20250720/MAINTAINERS	Sun Jul 20 22:32:07 2025
--- gcc-16-20250727/MAINTAINERS	Sun Jul 27 22:32:07 2025
*************** callgraph               Martin Jambor
*** 282,287 ****
--- 282,288 ----
  C front end             Marek Polacek           <polacek@redhat.com>
  CTF, BTF                Indu Bhagat             <indu.bhagat@oracle.com>
  CTF, BTF, bpf port      David Faust             <david.faust@oracle.com>
+ c++                     Patrick Palka           <ppalka@gcc.gnu.org>
  dataflow                Paolo Bonzini           <bonzini@gnu.org>
  dataflow                Seongbae Park           <seongbae.park@gmail.com>
  dataflow                Kenneth Zadeck          <zadeck@naturalbridge.com>
diff -Nrcpad gcc-16-20250720/MD5SUMS gcc-16-20250727/MD5SUMS
*** gcc-16-20250720/MD5SUMS	Sun Jul 20 22:33:23 2025
--- gcc-16-20250727/MD5SUMS	Sun Jul 27 22:32:26 2025
***************
*** 1,5 ****
  # This file contains the MD5 checksums of the files in the
! # gcc-16-20250720.tar.xz tarball.
  #
  # Besides verifying that all files in the tarball were correctly expanded,
  # it also can be used to determine if any files have changed since the
--- 1,5 ----
  # This file contains the MD5 checksums of the files in the
! # gcc-16-20250727.tar.xz tarball.
  #
  # Besides verifying that all files in the tarball were correctly expanded,
  # it also can be used to determine if any files have changed since the
*************** b8acb527560fc760209d200fcfab8ff4  .githu
*** 21,32 ****
  fe60d87048567d4fe8c8a0ed2448bcc8  COPYING.RUNTIME
  d32239bcb673463ab874e80d47fae504  COPYING3
  6a6a8e020838b23406c81b19c1d46df6  COPYING3.LIB
! e8dc5897a89c1245862d41d180276bed  ChangeLog
  fd4ecdf5d672efe2b0e409aca9cf9446  ChangeLog.jit
  09538b708302f1735f6fa05b622ecf5e  ChangeLog.tree-ssa
  24ab760126489e69436a43185dc3d202  INSTALL/README
! 3cad30e66df508f884631ac40dacc241  LAST_UPDATED
! df653c6054ec83e9f6460a9da96b41a1  MAINTAINERS
  95166ed050922b15d201d1fa647b5872  Makefile.def
  7dcc983bfbcda6838b504185562b60a3  Makefile.in
  2c81c9de7da119a00341d5e9529e629f  Makefile.tpl
--- 21,32 ----
  fe60d87048567d4fe8c8a0ed2448bcc8  COPYING.RUNTIME
  d32239bcb673463ab874e80d47fae504  COPYING3
  6a6a8e020838b23406c81b19c1d46df6  COPYING3.LIB
! 7dd4cae811193b1c264b4e7b9f36a827  ChangeLog
  fd4ecdf5d672efe2b0e409aca9cf9446  ChangeLog.jit
  09538b708302f1735f6fa05b622ecf5e  ChangeLog.tree-ssa
  24ab760126489e69436a43185dc3d202  INSTALL/README
! 1e7b979896f7102f536dfde7515848de  LAST_UPDATED
! 02b52535f10dbe4f1c32efd8d33ac655  MAINTAINERS
  95166ed050922b15d201d1fa647b5872  Makefile.def
  7dcc983bfbcda6838b504185562b60a3  Makefile.in
  2c81c9de7da119a00341d5e9529e629f  Makefile.tpl
*************** e2dc6b4fd62b77bff96b7951ef74f78f  config
*** 154,160 ****
  db74a73c3c9c3cc71edec37c2436e082  config/zstd.m4
  9d9c5508a65175be5f9e10721e55ebbc  configure
  82e46c5338f6449fa0a149b6adf12797  configure.ac
! 4fefbefd6a3ecacecf1015f446c93bbd  contrib/ChangeLog
  5fc435c7928f858246df931ea3f3ece7  contrib/ChangeLog.jit
  7af8d2979bf1a7cfa88e30d05fa22be2  contrib/ChangeLog.tree-ssa
  13605e5ba7b533ecbe3a902b8ebe4079  contrib/analyze_brprob.py
--- 154,160 ----
  db74a73c3c9c3cc71edec37c2436e082  config/zstd.m4
  9d9c5508a65175be5f9e10721e55ebbc  configure
  82e46c5338f6449fa0a149b6adf12797  configure.ac
! bfd48bad16e79c188d1637d6aed484c4  contrib/ChangeLog
  5fc435c7928f858246df931ea3f3ece7  contrib/ChangeLog.jit
  7af8d2979bf1a7cfa88e30d05fa22be2  contrib/ChangeLog.tree-ssa
  13605e5ba7b533ecbe3a902b8ebe4079  contrib/analyze_brprob.py
*************** c3217001bd26d7357f97d76467773e6d  contri
*** 187,198 ****
  8d11d67047d66e5a932dfc9ff91893fa  contrib/dglib.pm
  1a43c19edffafd7cca44c23265ada323  contrib/diffsummary.py
  5bda781277a8bf1ae8288d346a92cece  contrib/download_prerequisites
! 41527218c525aae1eca3267f19f2bc97  contrib/filter-clang-warnings.py
  332fd0835826d637b5b6cf8db14358a5  contrib/filter_gcc_for_doxygen
  db03e57377f9eb202b7b783eb81fe40d  contrib/filter_knr2ansi.pl
  d577ea19d05f19a8364f73c9901223b7  contrib/filter_params.py
  1f09615feb91c049cbf46b27ea159c58  contrib/gcc-changelog/git_check_commit.py
! 1c82c39ec07b95e02c998d4285dac60c  contrib/gcc-changelog/git_commit.py
  6a772ce384751a560f60790681e6fc41  contrib/gcc-changelog/git_email.py
  039963086e96c2e9fdf8ae5643394a9c  contrib/gcc-changelog/git_repository.py
  0c7ef238161fe16d8678afe62d331579  contrib/gcc-changelog/git_update_version.py
--- 187,198 ----
  8d11d67047d66e5a932dfc9ff91893fa  contrib/dglib.pm
  1a43c19edffafd7cca44c23265ada323  contrib/diffsummary.py
  5bda781277a8bf1ae8288d346a92cece  contrib/download_prerequisites
! c031cdd918e93a5780aab350a42591d8  contrib/filter-clang-warnings.py
  332fd0835826d637b5b6cf8db14358a5  contrib/filter_gcc_for_doxygen
  db03e57377f9eb202b7b783eb81fe40d  contrib/filter_knr2ansi.pl
  d577ea19d05f19a8364f73c9901223b7  contrib/filter_params.py
  1f09615feb91c049cbf46b27ea159c58  contrib/gcc-changelog/git_check_commit.py
! abf46076097d755f3e1908cbe8eb7eb0  contrib/gcc-changelog/git_commit.py
  6a772ce384751a560f60790681e6fc41  contrib/gcc-changelog/git_email.py
  039963086e96c2e9fdf8ae5643394a9c  contrib/gcc-changelog/git_repository.py
  0c7ef238161fe16d8678afe62d331579  contrib/gcc-changelog/git_update_version.py
*************** d577ea19d05f19a8364f73c9901223b7  contri
*** 200,206 ****
  0b845b0a18e1acc7cc4d441b4f0cb449  contrib/gcc-changelog/test_email.py
  6662a65218b0a11d673a65656b98d821  contrib/gcc-changelog/test_patches.txt
  983cf4f7b54ddd2b8962dda15b74d10a  contrib/gcc-git-customization.sh
! d0b0f3c6beb762cbd110e36c97a75ad7  contrib/gcc.doxy
  e1a3ba387b3d9bff3516856146cea62d  contrib/gcc_build
  a80a0165b2b8f366a31514e30720bd21  contrib/gcc_update
  f1df2625cad7941fd494fda00a9ad5f1  contrib/gen_autofdo_event.py
--- 200,206 ----
  0b845b0a18e1acc7cc4d441b4f0cb449  contrib/gcc-changelog/test_email.py
  6662a65218b0a11d673a65656b98d821  contrib/gcc-changelog/test_patches.txt
  983cf4f7b54ddd2b8962dda15b74d10a  contrib/gcc-git-customization.sh
! da34c6613c21220f18626495bd667d9b  contrib/gcc.doxy
  e1a3ba387b3d9bff3516856146cea62d  contrib/gcc_build
  a80a0165b2b8f366a31514e30720bd21  contrib/gcc_update
  f1df2625cad7941fd494fda00a9ad5f1  contrib/gen_autofdo_event.py
*************** a22e70b3f29292d0e628450f4bb11e62  fixinc
*** 516,522 ****
  a916467b91076e631dd8edb7424769c7  gcc/COPYING.LIB
  d32239bcb673463ab874e80d47fae504  gcc/COPYING3
  6a6a8e020838b23406c81b19c1d46df6  gcc/COPYING3.LIB
! 4d192ecda348f324849334ef17c66998  gcc/ChangeLog
  51281e73aa07fb62394bd72f3c9299ba  gcc/ChangeLog-1997
  f77af8c9ac412064886b00c5506123b5  gcc/ChangeLog-1998
  00a2e4ead1b289bf69bca0196fed6f9f  gcc/ChangeLog-1999
--- 516,522 ----
  a916467b91076e631dd8edb7424769c7  gcc/COPYING.LIB
  d32239bcb673463ab874e80d47fae504  gcc/COPYING3
  6a6a8e020838b23406c81b19c1d46df6  gcc/COPYING3.LIB
! 090d20958b1e34f517d3bba8f4302e3c  gcc/ChangeLog
  51281e73aa07fb62394bd72f3c9299ba  gcc/ChangeLog-1997
  f77af8c9ac412064886b00c5506123b5  gcc/ChangeLog-1998
  00a2e4ead1b289bf69bca0196fed6f9f  gcc/ChangeLog-1999
*************** fb3fadb88e1d2b3b640cfaaa5ff11780  gcc/Ch
*** 553,571 ****
  3eb07e0b2e542409bf73d359f7f65609  gcc/ChangeLog.ptr
  e13638e26743ba41e6011b76cc00d9a9  gcc/ChangeLog.tree-ssa
  739ab47f6425bcea1d05e4fc0542de54  gcc/ChangeLog.tuples
! 85db5c642505f625114629577b73daef  gcc/DATESTAMP
  deb513e591f23901188e22323bd3b1d4  gcc/DEV-PHASE
  eb92e1ff5e982ca07e173e0eb286d243  gcc/FSFChangeLog
  30e1e33411566388b3164558482dc5e6  gcc/FSFChangeLog.10
  36698274bb69e2ada20f5cc434f3caa5  gcc/FSFChangeLog.11
  4dc2573d948287a3722ce977490b026c  gcc/LANGUAGES
! 5bba15cf4c6ebd67fb7a98f13898867a  gcc/Makefile.in
  ec6799501b2eb2923d5de6a66169dbd2  gcc/ONEWS
  15d6908b4409b0925d9f1c72b56b5cb7  gcc/README.Portability
  cd96bf34cb76c97f86704a59b9ddb18a  gcc/acinclude.m4
  18db4664d7e31002aac43ebcf20e075f  gcc/aclocal.m4
  16a499934b71eb6cf7c0d6899cd6006a  gcc/ada/.gitignore
! 994f00acd36b1cebdfa30aefb58e9b76  gcc/ada/ChangeLog
  c2094c0d3135f9ac89917f162046ee04  gcc/ada/ChangeLog-2001
  fa410b57f5d814d5d3ac3b45f486cdcf  gcc/ada/ChangeLog-2002
  2dbefa7bdc8dc28ec746002028861278  gcc/ada/ChangeLog-2003
--- 553,571 ----
  3eb07e0b2e542409bf73d359f7f65609  gcc/ChangeLog.ptr
  e13638e26743ba41e6011b76cc00d9a9  gcc/ChangeLog.tree-ssa
  739ab47f6425bcea1d05e4fc0542de54  gcc/ChangeLog.tuples
! 15a48d7558f1d4fffc9ffa5281df85e6  gcc/DATESTAMP
  deb513e591f23901188e22323bd3b1d4  gcc/DEV-PHASE
  eb92e1ff5e982ca07e173e0eb286d243  gcc/FSFChangeLog
  30e1e33411566388b3164558482dc5e6  gcc/FSFChangeLog.10
  36698274bb69e2ada20f5cc434f3caa5  gcc/FSFChangeLog.11
  4dc2573d948287a3722ce977490b026c  gcc/LANGUAGES
! 85c179a7584cfd47e180ef1c14839a60  gcc/Makefile.in
  ec6799501b2eb2923d5de6a66169dbd2  gcc/ONEWS
  15d6908b4409b0925d9f1c72b56b5cb7  gcc/README.Portability
  cd96bf34cb76c97f86704a59b9ddb18a  gcc/acinclude.m4
  18db4664d7e31002aac43ebcf20e075f  gcc/aclocal.m4
  16a499934b71eb6cf7c0d6899cd6006a  gcc/ada/.gitignore
! e31c17cac7de631ad15ad59a55b128e5  gcc/ada/ChangeLog
  c2094c0d3135f9ac89917f162046ee04  gcc/ada/ChangeLog-2001
  fa410b57f5d814d5d3ac3b45f486cdcf  gcc/ada/ChangeLog-2002
  2dbefa7bdc8dc28ec746002028861278  gcc/ada/ChangeLog-2003
*************** eea9961506181531b5f7f1a7f62fe428  gcc/ad
*** 595,601 ****
  1ddbf3755fbef2d964b15c7104b9937d  gcc/ada/Make-generated.in
  6c9c3b4249e781ed48c7ae55e8ef9999  gcc/ada/Makefile.in
  3ade0c7d664404c6006c38dccaa83475  gcc/ada/Makefile.rtl
! db7e461b5b214c390e35d18397979f74  gcc/ada/accessibility.adb
  fbd3226b85f1e1cc6eb250fa51de4be1  gcc/ada/accessibility.ads
  80867b66cbed2dba054564ea216b3c66  gcc/ada/ada_get_targ.adb
  a07518144c5203a421dbc45a7b16e04f  gcc/ada/adabkend.adb
--- 595,601 ----
  1ddbf3755fbef2d964b15c7104b9937d  gcc/ada/Make-generated.in
  6c9c3b4249e781ed48c7ae55e8ef9999  gcc/ada/Makefile.in
  3ade0c7d664404c6006c38dccaa83475  gcc/ada/Makefile.rtl
! 38343dc270740eef23a38cd3c750dde1  gcc/ada/accessibility.adb
  fbd3226b85f1e1cc6eb250fa51de4be1  gcc/ada/accessibility.ads
  80867b66cbed2dba054564ea216b3c66  gcc/ada/ada_get_targ.adb
  a07518144c5203a421dbc45a7b16e04f  gcc/ada/adabkend.adb
*************** f8207765beac36c54d43698a11140afa  gcc/ad
*** 613,619 ****
  3150d7e2a4f0018bb92d065ed3aedcc0  gcc/ada/argv-lynxos178-raven-cert.c
  5470386a6301c0323b6ee66cf06c1e42  gcc/ada/argv.c
  f2493dd09ce42a8a76ba82606b9e20e3  gcc/ada/aspects.adb
! cbdd556ce9a061827b67dcab28d48962  gcc/ada/aspects.ads
  96017e82d14823563a6f140bb84ab657  gcc/ada/atree.adb
  14d6b3ce6a60df74711e12144f5f85a2  gcc/ada/atree.ads
  1a5f952bcb9d3c3529147729f3c4ef61  gcc/ada/atree.h
--- 613,619 ----
  3150d7e2a4f0018bb92d065ed3aedcc0  gcc/ada/argv-lynxos178-raven-cert.c
  5470386a6301c0323b6ee66cf06c1e42  gcc/ada/argv.c
  f2493dd09ce42a8a76ba82606b9e20e3  gcc/ada/aspects.adb
! e2eaeeeffdac88a55132441a8de89c4a  gcc/ada/aspects.ads
  96017e82d14823563a6f140bb84ab657  gcc/ada/atree.adb
  14d6b3ce6a60df74711e12144f5f85a2  gcc/ada/atree.ads
  1a5f952bcb9d3c3529147729f3c4ef61  gcc/ada/atree.h
*************** a012e0cb5df366014b5a4988036a509a  gcc/ad
*** 680,686 ****
  7559c05099cde820bf8bebbceabccc04  gcc/ada/doc/gnat_rm.rst
  5bf95a83da0a709f6bdf91751e65e01f  gcc/ada/doc/gnat_rm/about_this_guide.rst
  95f36013115a0d2964f52a340712b135  gcc/ada/doc/gnat_rm/compatibility_and_porting_guide.rst
! f88b707c2abbc5d9cd90127a84ed6fd7  gcc/ada/doc/gnat_rm/gnat_language_extensions.rst
  ae3d832d67eb0561de58deff709050db  gcc/ada/doc/gnat_rm/implementation_advice.rst
  4ef0af28325df2c1534cc73b9f4ed108  gcc/ada/doc/gnat_rm/implementation_defined_aspects.rst
  687e948eae92592a9bb4b738fd473d80  gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst
--- 680,686 ----
  7559c05099cde820bf8bebbceabccc04  gcc/ada/doc/gnat_rm.rst
  5bf95a83da0a709f6bdf91751e65e01f  gcc/ada/doc/gnat_rm/about_this_guide.rst
  95f36013115a0d2964f52a340712b135  gcc/ada/doc/gnat_rm/compatibility_and_porting_guide.rst
! 80abf921d2520d1f9c1d9675040d6c6f  gcc/ada/doc/gnat_rm/gnat_language_extensions.rst
  ae3d832d67eb0561de58deff709050db  gcc/ada/doc/gnat_rm/implementation_advice.rst
  4ef0af28325df2c1534cc73b9f4ed108  gcc/ada/doc/gnat_rm/implementation_defined_aspects.rst
  687e948eae92592a9bb4b738fd473d80  gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst
*************** bb3c8ae8aaf1cbd06bc44135da97d801  gcc/ad
*** 694,700 ****
  952177853de529b7a2f483f0d195d2b4  gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst
  1fb33f7304c23a143fa3a6313055f70b  gcc/ada/doc/gnat_rm/security_hardening_features.rst
  2fcc4a1e79f8bad335a4fa544f39c374  gcc/ada/doc/gnat_rm/specialized_needs_annexes.rst
! 3280f0cd5068d9afb4b30c72e74bd637  gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
  a8608ebf71444d2564728c8a41283e03  gcc/ada/doc/gnat_rm/standard_library_routines.rst
  56f7744dd862728c63870212761faa26  gcc/ada/doc/gnat_rm/the_gnat_library.rst
  391d17bf855af400348685ff678c6a6a  gcc/ada/doc/gnat_rm/the_implementation_of_standard_i_o.rst
--- 694,700 ----
  952177853de529b7a2f483f0d195d2b4  gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst
  1fb33f7304c23a143fa3a6313055f70b  gcc/ada/doc/gnat_rm/security_hardening_features.rst
  2fcc4a1e79f8bad335a4fa544f39c374  gcc/ada/doc/gnat_rm/specialized_needs_annexes.rst
! 31e0ba409ca563e1717444ab64e1e253  gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
  a8608ebf71444d2564728c8a41283e03  gcc/ada/doc/gnat_rm/standard_library_routines.rst
  56f7744dd862728c63870212761faa26  gcc/ada/doc/gnat_rm/the_gnat_library.rst
  391d17bf855af400348685ff678c6a6a  gcc/ada/doc/gnat_rm/the_implementation_of_standard_i_o.rst
*************** f1c71b64e1c84e240c7b5aea7331a32a  gcc/ad
*** 720,726 ****
  22b295629c6dacd0ec2e5475a6c7b4e6  gcc/ada/einfo-utils.adb
  fdeb0b11ed378cc91d79b0c88e2d35a0  gcc/ada/einfo-utils.ads
  4f882a8b5e78253d5838b1a83e4af5bb  gcc/ada/einfo.adb
! 25080b42fae8a4be76b3e639ac9182f5  gcc/ada/einfo.ads
  9fb4fb23a55081d07dc554eeb3253f91  gcc/ada/elists.adb
  1d7f8772477453dee268f8697433a589  gcc/ada/elists.ads
  2d6cb36d45dda0bf32d01725709f0007  gcc/ada/elists.h
--- 720,726 ----
  22b295629c6dacd0ec2e5475a6c7b4e6  gcc/ada/einfo-utils.adb
  fdeb0b11ed378cc91d79b0c88e2d35a0  gcc/ada/einfo-utils.ads
  4f882a8b5e78253d5838b1a83e4af5bb  gcc/ada/einfo.adb
! c4d6a308f607de241f2d4298028642e1  gcc/ada/einfo.ads
  9fb4fb23a55081d07dc554eeb3253f91  gcc/ada/elists.adb
  1d7f8772477453dee268f8697433a589  gcc/ada/elists.ads
  2d6cb36d45dda0bf32d01725709f0007  gcc/ada/elists.h
*************** e51a9a19184b2a73f27bb944998177e6  gcc/ad
*** 745,755 ****
  8745064abd42114e7f2f12824abd58f8  gcc/ada/eval_fat.adb
  04c8399e5b8f5b974be325af4fc5793b  gcc/ada/eval_fat.ads
  5062429d8789169d01db0423985a5e99  gcc/ada/exit.c
! 184f7baa67cb2c59df10301a49ccb424  gcc/ada/exp_aggr.adb
  738bfb6669a1b696ef62dbecd858300a  gcc/ada/exp_aggr.ads
  f5cfbe3c80cc2c7ded2440a52b2b9cf0  gcc/ada/exp_atag.adb
  17872534d797a09463e33092ff3c4b9c  gcc/ada/exp_atag.ads
! ba27b26a494e7c39898301b6f2552d84  gcc/ada/exp_attr.adb
  16622dd90fd58bfbfa68224d0bfaf8b2  gcc/ada/exp_attr.ads
  4cb08de59df5f8d0a124038dcbb392f0  gcc/ada/exp_cg.adb
  b18d9873e8e43583acd0e69ba6635023  gcc/ada/exp_cg.ads
--- 745,755 ----
  8745064abd42114e7f2f12824abd58f8  gcc/ada/eval_fat.adb
  04c8399e5b8f5b974be325af4fc5793b  gcc/ada/eval_fat.ads
  5062429d8789169d01db0423985a5e99  gcc/ada/exit.c
! 591f2188cdbdb7a1f30c3cf79954d5a7  gcc/ada/exp_aggr.adb
  738bfb6669a1b696ef62dbecd858300a  gcc/ada/exp_aggr.ads
  f5cfbe3c80cc2c7ded2440a52b2b9cf0  gcc/ada/exp_atag.adb
  17872534d797a09463e33092ff3c4b9c  gcc/ada/exp_atag.ads
! f92320098f3bfbdb28074146d81a0f7e  gcc/ada/exp_attr.adb
  16622dd90fd58bfbfa68224d0bfaf8b2  gcc/ada/exp_attr.ads
  4cb08de59df5f8d0a124038dcbb392f0  gcc/ada/exp_cg.adb
  b18d9873e8e43583acd0e69ba6635023  gcc/ada/exp_cg.ads
*************** fce186389d317dec9c580f569a2a845a  gcc/ad
*** 762,787 ****
  c6728830f0888dc3385e474b5925c01f  gcc/ada/exp_ch13.ads
  d037443d1b61c02110e124f3c701b449  gcc/ada/exp_ch2.adb
  476e299ea88b583859604d0071046143  gcc/ada/exp_ch2.ads
! 39748ac93cc49c3617b3fe16d780a30b  gcc/ada/exp_ch3.adb
  53e0d855cd76aedff48a9e6266db49e8  gcc/ada/exp_ch3.ads
! cd451a03d3f6e30e0aed13ae4ca5d48f  gcc/ada/exp_ch4.adb
  ef982b9647c35560ae7ff386e547bd16  gcc/ada/exp_ch4.ads
  d8ee1a2097135d84f7788fd2ece2f305  gcc/ada/exp_ch5.adb
  f0c7dc0ade3f9639e946e709a9288f31  gcc/ada/exp_ch5.ads
! a52340b3cccc05ad9853052b91719ae3  gcc/ada/exp_ch6.adb
! c22c79787fe7516adb5a4c55613fb6ab  gcc/ada/exp_ch6.ads
! 323962e06b80a131d23f743cae560e49  gcc/ada/exp_ch7.adb
  31ee5e50c565d4788d9b794acb5bfebb  gcc/ada/exp_ch7.ads
  ff5f2710ba824ff8ef979c388663bac2  gcc/ada/exp_ch8.adb
  c1f464d28d24669bfe156f13cabe5fca  gcc/ada/exp_ch8.ads
! 2a95204a60ff3eba6c8d60f584833827  gcc/ada/exp_ch9.adb
! 9ab762fdf6b68687829c67eae82562e8  gcc/ada/exp_ch9.ads
  f47ce79d25dbb4d2f5cc6c375ee8c103  gcc/ada/exp_code.adb
  983664237ff0b38442a164f60d531514  gcc/ada/exp_code.ads
  c5f46927bfde5cfdba7070186c0a3890  gcc/ada/exp_dbug.adb
  7d55b512bc6b963b537cd44b692b8a54  gcc/ada/exp_dbug.ads
! 4d1c737cea17039b99b988cf0cea6cd4  gcc/ada/exp_disp.adb
! 00b2b98f2a8868fd7a89f79c72a645ac  gcc/ada/exp_disp.ads
  f8d7c73c2eb136405382e9f889d15683  gcc/ada/exp_dist.adb
  116919038aa6e7d0ec9ce9ab609f0bc2  gcc/ada/exp_dist.ads
  623e2e99136d92d39e5b0f3277759f6a  gcc/ada/exp_fixd.adb
--- 762,787 ----
  c6728830f0888dc3385e474b5925c01f  gcc/ada/exp_ch13.ads
  d037443d1b61c02110e124f3c701b449  gcc/ada/exp_ch2.adb
  476e299ea88b583859604d0071046143  gcc/ada/exp_ch2.ads
! f21e17620da6dec2cf524ed22e35caa7  gcc/ada/exp_ch3.adb
  53e0d855cd76aedff48a9e6266db49e8  gcc/ada/exp_ch3.ads
! 5ed207f23c17d3b5d6d3569d9a37e46c  gcc/ada/exp_ch4.adb
  ef982b9647c35560ae7ff386e547bd16  gcc/ada/exp_ch4.ads
  d8ee1a2097135d84f7788fd2ece2f305  gcc/ada/exp_ch5.adb
  f0c7dc0ade3f9639e946e709a9288f31  gcc/ada/exp_ch5.ads
! 9cddce09930e7179c134da0bdddbe8d0  gcc/ada/exp_ch6.adb
! 54a1ff576d38d91bbd44c24ee1a6a5ff  gcc/ada/exp_ch6.ads
! 74b1c0c8de6d21525f546baf9d52d9c3  gcc/ada/exp_ch7.adb
  31ee5e50c565d4788d9b794acb5bfebb  gcc/ada/exp_ch7.ads
  ff5f2710ba824ff8ef979c388663bac2  gcc/ada/exp_ch8.adb
  c1f464d28d24669bfe156f13cabe5fca  gcc/ada/exp_ch8.ads
! 2b1d2d9d9511bebd24062412e9cf01c3  gcc/ada/exp_ch9.adb
! e26475f86b42d59910afddd6b59f6f2f  gcc/ada/exp_ch9.ads
  f47ce79d25dbb4d2f5cc6c375ee8c103  gcc/ada/exp_code.adb
  983664237ff0b38442a164f60d531514  gcc/ada/exp_code.ads
  c5f46927bfde5cfdba7070186c0a3890  gcc/ada/exp_dbug.adb
  7d55b512bc6b963b537cd44b692b8a54  gcc/ada/exp_dbug.ads
! 822f3c96f37d1727a89b5db88b16f1e2  gcc/ada/exp_disp.adb
! 7151f16c23b394a2f2eef990ebee4e20  gcc/ada/exp_disp.ads
  f8d7c73c2eb136405382e9f889d15683  gcc/ada/exp_dist.adb
  116919038aa6e7d0ec9ce9ab609f0bc2  gcc/ada/exp_dist.ads
  623e2e99136d92d39e5b0f3277759f6a  gcc/ada/exp_fixd.adb
*************** c48a8396237679c48ceef2c507661e1a  gcc/ad
*** 794,815 ****
  0e4de6363c3876604fc8fa97e180ddcf  gcc/ada/exp_pakd.ads
  be32a682413bacdc827334ec3f62973a  gcc/ada/exp_prag.adb
  b971e56ee00efc31bd07e4f49eb4e97e  gcc/ada/exp_prag.ads
! 5c439124d2bab6aebfa6ddc31b112752  gcc/ada/exp_put_image.adb
  c0f39ee1d515a13193e5726a49291c99  gcc/ada/exp_put_image.ads
  e224b65ac653dc73160c1665f825b557  gcc/ada/exp_sel.adb
  adda0da8d4f449351c0486c3277f39bd  gcc/ada/exp_sel.ads
  624e684a9e8c068e4ad7dc5d3a3eb244  gcc/ada/exp_smem.adb
  5eb50023abeda9a76f66518671ad1d05  gcc/ada/exp_smem.ads
! 63204e999b8ecaf7a7ac1365749a855e  gcc/ada/exp_spark.adb
  0365865a8be979f0a1db6a61cadbe940  gcc/ada/exp_spark.ads
! b042ff9582cb94caab7f476203ea6809  gcc/ada/exp_strm.adb
  772292d8d5c1417fcb3279f7ac312e3a  gcc/ada/exp_strm.ads
  59000e9704cdc65241a4bceab3308eb3  gcc/ada/exp_tss.adb
  52a5741c37559d0398594d7baa1c99ac  gcc/ada/exp_tss.ads
  a55ae41c0e68be209828e4229c2bbae3  gcc/ada/exp_unst.adb
  d2f34876e61000e49299ef9b2569cbbf  gcc/ada/exp_unst.ads
! 387abff87b8e41be728e42dda647aba1  gcc/ada/exp_util.adb
! cae531f0465d59eedf5daf97690f2e50  gcc/ada/exp_util.ads
  d12050aeac4d9f87dd69e7ae55d6dfce  gcc/ada/expander.adb
  53bb0eb5c4feebf8b5fbef639f5827bd  gcc/ada/expander.ads
  b38851c9b7a0167a71b96e69b7c86fb1  gcc/ada/expect.c
--- 794,815 ----
  0e4de6363c3876604fc8fa97e180ddcf  gcc/ada/exp_pakd.ads
  be32a682413bacdc827334ec3f62973a  gcc/ada/exp_prag.adb
  b971e56ee00efc31bd07e4f49eb4e97e  gcc/ada/exp_prag.ads
! 6983963a291a366b979e48c5a8edaf02  gcc/ada/exp_put_image.adb
  c0f39ee1d515a13193e5726a49291c99  gcc/ada/exp_put_image.ads
  e224b65ac653dc73160c1665f825b557  gcc/ada/exp_sel.adb
  adda0da8d4f449351c0486c3277f39bd  gcc/ada/exp_sel.ads
  624e684a9e8c068e4ad7dc5d3a3eb244  gcc/ada/exp_smem.adb
  5eb50023abeda9a76f66518671ad1d05  gcc/ada/exp_smem.ads
! e0237c4fffac107d40eb312c5be606db  gcc/ada/exp_spark.adb
  0365865a8be979f0a1db6a61cadbe940  gcc/ada/exp_spark.ads
! c545b78124b9df301cdeef2979c79209  gcc/ada/exp_strm.adb
  772292d8d5c1417fcb3279f7ac312e3a  gcc/ada/exp_strm.ads
  59000e9704cdc65241a4bceab3308eb3  gcc/ada/exp_tss.adb
  52a5741c37559d0398594d7baa1c99ac  gcc/ada/exp_tss.ads
  a55ae41c0e68be209828e4229c2bbae3  gcc/ada/exp_unst.adb
  d2f34876e61000e49299ef9b2569cbbf  gcc/ada/exp_unst.ads
! 620fcc032d227b06cedd5ace6d46dc37  gcc/ada/exp_util.adb
! f38c33811ff4495921f4fab803f1b045  gcc/ada/exp_util.ads
  d12050aeac4d9f87dd69e7ae55d6dfce  gcc/ada/expander.adb
  53bb0eb5c4feebf8b5fbef639f5827bd  gcc/ada/expander.ads
  b38851c9b7a0167a71b96e69b7c86fb1  gcc/ada/expect.c
*************** fdb9382a8288a3a5b805910a0a3615e8  gcc/ad
*** 823,829 ****
  576d7463667fc4c859a05f9e19146427  gcc/ada/fname-uf.ads
  ec7cf235c00294fe67198b9bf264f3d9  gcc/ada/fname.adb
  5ef403dc7e6540ad58ec4ccec10de65c  gcc/ada/fname.ads
! 32f9c4a5754646fe4a2f6b4b7e49e5f1  gcc/ada/freeze.adb
  0cfb73b82bc6277eb801329c392229d2  gcc/ada/freeze.ads
  498bb16c341cb753da6cbb10f928fb0f  gcc/ada/frontend.adb
  6f776be1d84e9d8c996b576c19a4349f  gcc/ada/frontend.ads
--- 823,829 ----
  576d7463667fc4c859a05f9e19146427  gcc/ada/fname-uf.ads
  ec7cf235c00294fe67198b9bf264f3d9  gcc/ada/fname.adb
  5ef403dc7e6540ad58ec4ccec10de65c  gcc/ada/fname.ads
! 545e902233226ec4090c2c6ac65dd8b1  gcc/ada/freeze.adb
  0cfb73b82bc6277eb801329c392229d2  gcc/ada/freeze.ads
  498bb16c341cb753da6cbb10f928fb0f  gcc/ada/frontend.adb
  6f776be1d84e9d8c996b576c19a4349f  gcc/ada/frontend.ads
*************** fa1feb51010fc73b933487acbdcf85e8  gcc/ad
*** 842,859 ****
  8c3391ec25d2f8a3e26b0553d537d3e2  gcc/ada/gcc-interface/lang-specs.h
  43e609e56eeb0ff4e57be465cd17ddbc  gcc/ada/gcc-interface/lang.opt
  9b5bb16ec797188515b64efd5c00378a  gcc/ada/gcc-interface/lang.opt.urls
! 1403993cbf8ac5d3b60092dd85c26fa6  gcc/ada/gcc-interface/misc.cc
  a74b4504c5ad4ed4e963f0691c289b40  gcc/ada/gcc-interface/system.ads
  b350a6fd65cafe8bd47dc42192437310  gcc/ada/gcc-interface/targtyps.cc
! 34dc74bdcfc4940dc904bd9a4aae2535  gcc/ada/gcc-interface/trans.cc
! 80875110ccbd5107800053583558ac3a  gcc/ada/gcc-interface/utils.cc
  7b0d708fd189018a87468ef844fc3811  gcc/ada/gcc-interface/utils2.cc
! e76ed7d8c0660e26f7c07afe04f09ed9  gcc/ada/gen_il-fields.ads
! ae086e9a20282e38e6223b0ef67776f3  gcc/ada/gen_il-gen-gen_entities.adb
! 117d059d852b91f0ca5bd704d53e66da  gcc/ada/gen_il-gen-gen_nodes.adb
  fa07e4c6240b8cfff6d7d98112fee236  gcc/ada/gen_il-gen.adb
  c979a98c6b57608c79d578871fa0c58a  gcc/ada/gen_il-gen.ads
! 76bbf6f38878113d65648e887fc2fd72  gcc/ada/gen_il-internals.adb
  df0beb95a99f054fd498bb3fc0b8fccc  gcc/ada/gen_il-internals.ads
  6f79de1a05bf91310c857e93030b71e6  gcc/ada/gen_il-main.adb
  8e01eef966574a548d971c02ad5b66be  gcc/ada/gen_il-types.ads
--- 842,859 ----
  8c3391ec25d2f8a3e26b0553d537d3e2  gcc/ada/gcc-interface/lang-specs.h
  43e609e56eeb0ff4e57be465cd17ddbc  gcc/ada/gcc-interface/lang.opt
  9b5bb16ec797188515b64efd5c00378a  gcc/ada/gcc-interface/lang.opt.urls
! 267766beb94b2d6cae2c0fd0cec080c4  gcc/ada/gcc-interface/misc.cc
  a74b4504c5ad4ed4e963f0691c289b40  gcc/ada/gcc-interface/system.ads
  b350a6fd65cafe8bd47dc42192437310  gcc/ada/gcc-interface/targtyps.cc
! c7340ba0f3353b13106405b6414dfaf0  gcc/ada/gcc-interface/trans.cc
! 00d80a399c475dcde9c4b8291d7cc480  gcc/ada/gcc-interface/utils.cc
  7b0d708fd189018a87468ef844fc3811  gcc/ada/gcc-interface/utils2.cc
! e7b7cbfb520ac605f983bf6b77e26f50  gcc/ada/gen_il-fields.ads
! c4674dab93a542b7b760fd90931d7d88  gcc/ada/gen_il-gen-gen_entities.adb
! 28a01a5fa281c27bced23a05b683c39d  gcc/ada/gen_il-gen-gen_nodes.adb
  fa07e4c6240b8cfff6d7d98112fee236  gcc/ada/gen_il-gen.adb
  c979a98c6b57608c79d578871fa0c58a  gcc/ada/gen_il-gen.ads
! a4ef8df72ec73a9d208be64172da03c2  gcc/ada/gen_il-internals.adb
  df0beb95a99f054fd498bb3fc0b8fccc  gcc/ada/gen_il-internals.ads
  6f79de1a05bf91310c857e93030b71e6  gcc/ada/gen_il-main.adb
  8e01eef966574a548d971c02ad5b66be  gcc/ada/gen_il-types.ads
*************** c30d04e8e72b6ecb391a5f74ed43baa6  gcc/ad
*** 872,878 ****
  917ea7311a30ec4c5cec3e610ca640c2  gcc/ada/gnat2.gpr
  49c5329fd360e2bf4e549bc7de93aab7  gcc/ada/gnat_cuda.adb
  de69fc271ce889490809004600fcac0f  gcc/ada/gnat_cuda.ads
! 70b985cafe9f30c90e988835a65133e0  gcc/ada/gnat_rm.texi
  81f45e97d2c16fe64085b67469c03a94  gcc/ada/gnat_ugn.texi
  957e02fdb4684d592d9172cea8dfb4cb  gcc/ada/gnatbind.adb
  fff8dfca966e9d6f779ce90e57344a0f  gcc/ada/gnatbind.ads
--- 872,878 ----
  917ea7311a30ec4c5cec3e610ca640c2  gcc/ada/gnat2.gpr
  49c5329fd360e2bf4e549bc7de93aab7  gcc/ada/gnat_cuda.adb
  de69fc271ce889490809004600fcac0f  gcc/ada/gnat_cuda.ads
! 09338805f4f4eeb77c19b6db7211c2ca  gcc/ada/gnat_rm.texi
  81f45e97d2c16fe64085b67469c03a94  gcc/ada/gnat_ugn.texi
  957e02fdb4684d592d9172cea8dfb4cb  gcc/ada/gnatbind.adb
  fff8dfca966e9d6f779ce90e57344a0f  gcc/ada/gnatbind.ads
*************** d84f29439bcbc88c275e531630e2e14e  gcc/ad
*** 898,904 ****
  78c482a261b45ba578d801b564bc7d38  gcc/ada/gnatvsn.ads
  b06692d44846cc28fe529c1ea2f3ded6  gcc/ada/gprep.adb
  56f06790ba3f6dfe539fa7f244e80e53  gcc/ada/gprep.ads
! 5092f371a9240b2413cc69a5274d3b71  gcc/ada/gsocket.h
  e4efe68d0e25214fe54b93342a51d8bd  gcc/ada/hostparm.ads
  b18590491ceee0c729cf111d19381239  gcc/ada/impunit.adb
  7407048c8e72f7cc4527e91ef1efd1c8  gcc/ada/impunit.ads
--- 898,904 ----
  78c482a261b45ba578d801b564bc7d38  gcc/ada/gnatvsn.ads
  b06692d44846cc28fe529c1ea2f3ded6  gcc/ada/gprep.adb
  56f06790ba3f6dfe539fa7f244e80e53  gcc/ada/gprep.ads
! c5800bf428d690955e4f8f9f3efd4017  gcc/ada/gsocket.h
  e4efe68d0e25214fe54b93342a51d8bd  gcc/ada/hostparm.ads
  b18590491ceee0c729cf111d19381239  gcc/ada/impunit.adb
  7407048c8e72f7cc4527e91ef1efd1c8  gcc/ada/impunit.ads
*************** b1588f448e1bfcadc0ef11876d9a4198  gcc/ad
*** 1173,1179 ****
  100dc0e25b19b06e674b97a54983a819  gcc/ada/libgnat/a-calcon.ads
  2548ef7af48aac0031d579e8e93198e4  gcc/ada/libgnat/a-caldel.adb
  f231833a1ff7a48232b1159c51481f11  gcc/ada/libgnat/a-caldel.ads
! 2b2058290cadb2bf1d58e993ef65378f  gcc/ada/libgnat/a-calend.adb
  58891b8f4212994cc869226814cd8c3f  gcc/ada/libgnat/a-calend.ads
  255ab4aa146bfc13c622bc430f4cd06d  gcc/ada/libgnat/a-calfor.adb
  42e2eb28d020217b4a0627bc1cc321ea  gcc/ada/libgnat/a-calfor.ads
--- 1173,1179 ----
  100dc0e25b19b06e674b97a54983a819  gcc/ada/libgnat/a-calcon.ads
  2548ef7af48aac0031d579e8e93198e4  gcc/ada/libgnat/a-caldel.adb
  f231833a1ff7a48232b1159c51481f11  gcc/ada/libgnat/a-caldel.ads
! 616e20b7bbf6c91ccf8c97e5fcf0213e  gcc/ada/libgnat/a-calend.adb
  58891b8f4212994cc869226814cd8c3f  gcc/ada/libgnat/a-calend.ads
  255ab4aa146bfc13c622bc430f4cd06d  gcc/ada/libgnat/a-calfor.adb
  42e2eb28d020217b4a0627bc1cc321ea  gcc/ada/libgnat/a-calfor.ads
*************** f231833a1ff7a48232b1159c51481f11  gcc/ad
*** 1181,1188 ****
  d731f2a00c2328507e1708628b8f8534  gcc/ada/libgnat/a-catizo.ads
  152d7a7e6487f59656c18275fb1019b7  gcc/ada/libgnat/a-cbdlli.adb
  7e71a77b7ce68633d73f5e8553a7e95b  gcc/ada/libgnat/a-cbdlli.ads
! 95e5eb7a6da0c84ffcf80fd16bec8909  gcc/ada/libgnat/a-cbhama.adb
! 597a8cb501b0d5e9195f714d6f240fc5  gcc/ada/libgnat/a-cbhama.ads
  9223e8d2808faab558fea487a6f7533a  gcc/ada/libgnat/a-cbhase.adb
  2618731613309e98934dd5386b4dc20c  gcc/ada/libgnat/a-cbhase.ads
  47d4b5a405ecab1cb8ba5d73e8fd812f  gcc/ada/libgnat/a-cbmutr.adb
--- 1181,1188 ----
  d731f2a00c2328507e1708628b8f8534  gcc/ada/libgnat/a-catizo.ads
  152d7a7e6487f59656c18275fb1019b7  gcc/ada/libgnat/a-cbdlli.adb
  7e71a77b7ce68633d73f5e8553a7e95b  gcc/ada/libgnat/a-cbdlli.ads
! 1cb9e0a1e9900c6d3d931b524cd6091a  gcc/ada/libgnat/a-cbhama.adb
! ae4142c1ed4537f1eb124c9eac394129  gcc/ada/libgnat/a-cbhama.ads
  9223e8d2808faab558fea487a6f7533a  gcc/ada/libgnat/a-cbhase.adb
  2618731613309e98934dd5386b4dc20c  gcc/ada/libgnat/a-cbhase.ads
  47d4b5a405ecab1cb8ba5d73e8fd812f  gcc/ada/libgnat/a-cbmutr.adb
*************** ba42f57979e85f9332b1abfaaaa87acc  gcc/ad
*** 1763,1769 ****
  88c79d357cdbd1228d991c58d3abb14b  gcc/ada/libgnat/g-byorma.ads
  6b4c08a28de128992419116223b49748  gcc/ada/libgnat/g-bytswa.adb
  cfca851f558eff2691d8c4725422f34d  gcc/ada/libgnat/g-bytswa.ads
! e4413ca3f51093a6080d135df52d06a0  gcc/ada/libgnat/g-calend.adb
  54d472cb4a530e1a3d8f57c5a71eaf9c  gcc/ada/libgnat/g-calend.ads
  172cbdecdc80b79191b03d1e99bebb5b  gcc/ada/libgnat/g-casuti.adb
  1bf6a034e019c41d01d146693f15f4da  gcc/ada/libgnat/g-casuti.ads
--- 1763,1769 ----
  88c79d357cdbd1228d991c58d3abb14b  gcc/ada/libgnat/g-byorma.ads
  6b4c08a28de128992419116223b49748  gcc/ada/libgnat/g-bytswa.adb
  cfca851f558eff2691d8c4725422f34d  gcc/ada/libgnat/g-bytswa.ads
! dc802d699a838901af55fbf5d0043d59  gcc/ada/libgnat/g-calend.adb
  54d472cb4a530e1a3d8f57c5a71eaf9c  gcc/ada/libgnat/g-calend.ads
  172cbdecdc80b79191b03d1e99bebb5b  gcc/ada/libgnat/g-casuti.adb
  1bf6a034e019c41d01d146693f15f4da  gcc/ada/libgnat/g-casuti.ads
*************** e1d19b45765179c36403496818173fe1  gcc/ad
*** 1892,1898 ****
  8eafdb255d0eafa3f943efc1feff0e4e  gcc/ada/libgnat/g-shshco.adb
  afddbc4dfe9848ead2602333a601e647  gcc/ada/libgnat/g-shshco.ads
  906d456a919e6eb5a8c2607d82654e13  gcc/ada/libgnat/g-soccon.ads
! 52e2640d46a43ca1f6b97d82de8fba3d  gcc/ada/libgnat/g-socket.adb
  380817e1240d7c23ab2c9fc61e0b0a34  gcc/ada/libgnat/g-socket.ads
  fa45db9b2f71318e55323cbb90bf74e8  gcc/ada/libgnat/g-socket__dummy.adb
  a1efda814643c7a15fe7c0b0aa7a1b9e  gcc/ada/libgnat/g-socket__dummy.ads
--- 1892,1898 ----
  8eafdb255d0eafa3f943efc1feff0e4e  gcc/ada/libgnat/g-shshco.adb
  afddbc4dfe9848ead2602333a601e647  gcc/ada/libgnat/g-shshco.ads
  906d456a919e6eb5a8c2607d82654e13  gcc/ada/libgnat/g-soccon.ads
! 7c7130575dfc4d69264cec1d23f5065a  gcc/ada/libgnat/g-socket.adb
  380817e1240d7c23ab2c9fc61e0b0a34  gcc/ada/libgnat/g-socket.ads
  fa45db9b2f71318e55323cbb90bf74e8  gcc/ada/libgnat/g-socket__dummy.adb
  a1efda814643c7a15fe7c0b0aa7a1b9e  gcc/ada/libgnat/g-socket__dummy.ads
*************** ee42403c9984dd389a6e7c3046178b10  gcc/ad
*** 2870,2876 ****
  dbaacbc6137249e74a2f6564812aebf9  gcc/ada/rtsfind.adb
  e4e5cf29682458c5890157bcbd67e0c1  gcc/ada/rtsfind.ads
  66e987f268458746a6afb190c151af7a  gcc/ada/runtime.h
! b6100bf6eaab78f9424e994302129621  gcc/ada/s-oscons-tmplt.c
  a34bfe2b691bf488816cc77770321ff3  gcc/ada/s-pack.adb.tmpl
  769f019e3de5c30e3ae7534efbba17df  gcc/ada/s-pack.ads.tmpl
  f2b44210590da3ce7d60699034656b7f  gcc/ada/scans.adb
--- 2870,2876 ----
  dbaacbc6137249e74a2f6564812aebf9  gcc/ada/rtsfind.adb
  e4e5cf29682458c5890157bcbd67e0c1  gcc/ada/rtsfind.ads
  66e987f268458746a6afb190c151af7a  gcc/ada/runtime.h
! 3ba3797c77ab11da135266710dd26c4a  gcc/ada/s-oscons-tmplt.c
  a34bfe2b691bf488816cc77770321ff3  gcc/ada/s-pack.adb.tmpl
  769f019e3de5c30e3ae7534efbba17df  gcc/ada/s-pack.ads.tmpl
  f2b44210590da3ce7d60699034656b7f  gcc/ada/scans.adb
*************** b58c1b9f5b963c617e489cf6a637242a  gcc/ad
*** 2889,2898 ****
  852fbcc89a3ed10b6c00d4f9686d1405  gcc/ada/sem.ads
  56077675be6cdea397a7c913a87672b6  gcc/ada/sem_aggr.adb
  d9e9e67a1e6554ab3bc7e11269dd3763  gcc/ada/sem_aggr.ads
! 4a4bed3e8155177fe516773f0103a256  gcc/ada/sem_attr.adb
  825e191d7eee72ea4718b1fc2ba02824  gcc/ada/sem_attr.ads
! 4a02c8331cea42852aa409345905ab04  gcc/ada/sem_aux.adb
! 53f33d18e4572e77b490e9320f5c2aa4  gcc/ada/sem_aux.ads
  1b4e45ef8df3f33dae9b6710ce3bbf7a  gcc/ada/sem_case.adb
  88daa5c9b6e135316b52695cae25a496  gcc/ada/sem_case.ads
  84667b3de209c0b04f82a349c6125ab0  gcc/ada/sem_cat.adb
--- 2889,2898 ----
  852fbcc89a3ed10b6c00d4f9686d1405  gcc/ada/sem.ads
  56077675be6cdea397a7c913a87672b6  gcc/ada/sem_aggr.adb
  d9e9e67a1e6554ab3bc7e11269dd3763  gcc/ada/sem_aggr.ads
! 3b4c4d9018fc314a05c87deb2e5f04c3  gcc/ada/sem_attr.adb
  825e191d7eee72ea4718b1fc2ba02824  gcc/ada/sem_attr.ads
! cac7c47e492012f0e61000bebe5ae037  gcc/ada/sem_aux.adb
! e15b069fa2ff472febda85c8b9cacb81  gcc/ada/sem_aux.ads
  1b4e45ef8df3f33dae9b6710ce3bbf7a  gcc/ada/sem_case.adb
  88daa5c9b6e135316b52695cae25a496  gcc/ada/sem_case.ads
  84667b3de209c0b04f82a349c6125ab0  gcc/ada/sem_cat.adb
*************** e364f4e3ae92066699cc93a8f7b828c1  gcc/ad
*** 2901,2929 ****
  6e34ce648cfc10b24c12b68e0e59dcb8  gcc/ada/sem_ch10.ads
  5980a02146588bf0e31ced2382290670  gcc/ada/sem_ch11.adb
  1b6f89866a5d427002df059be3847d62  gcc/ada/sem_ch11.ads
! e30a1ad4da7b8d2395043452e6ed5ec0  gcc/ada/sem_ch12.adb
  b0a3315dce9de8e3bbbb3682c8b0e2ff  gcc/ada/sem_ch12.ads
! 0eef1fb5bf49a8878f6e3e24d19ba3f1  gcc/ada/sem_ch13.adb
  42a7b1073e168e8be85f2203fbddd148  gcc/ada/sem_ch13.ads
  14326c522718c8cb8415b13a79c07972  gcc/ada/sem_ch2.adb
  2471d629be4739ff5135aa87a2ec9166  gcc/ada/sem_ch2.ads
! 9f4770487c9a532babeaf5e8fd3730d6  gcc/ada/sem_ch3.adb
  a9694f8bc09b47075cae226e570e02f0  gcc/ada/sem_ch3.ads
! e1f6f3ce38bcab22f09e5181b8a18af2  gcc/ada/sem_ch4.adb
  adba03aae1f439b9e9db8cea05d8e03f  gcc/ada/sem_ch4.ads
! 0135ad6cef623899ddfc58bedb11e1bb  gcc/ada/sem_ch5.adb
  ec8d5a42c27c46e4969c16d6e18ed276  gcc/ada/sem_ch5.ads
! 40cb10bb8fee99563f3a61286ef27f63  gcc/ada/sem_ch6.adb
! 51bdafe51a1cae21d9fba800fcd7a572  gcc/ada/sem_ch6.ads
  3c7c6e6b95a9cddb1d6f1a42a5962379  gcc/ada/sem_ch7.adb
  24a1265e6a25756265643858abcf7ded  gcc/ada/sem_ch7.ads
! 9fb98cdca68de7159f88210dc7bfb2a6  gcc/ada/sem_ch8.adb
  f0b4e317e5d5515a6ec337bc5acf5fe0  gcc/ada/sem_ch8.ads
! 7fdc25b17002200422b401c1df8f051c  gcc/ada/sem_ch9.adb
  7b283bd6453de444c7075a8c6f215dda  gcc/ada/sem_ch9.ads
  dea2a3321bde0d3ed6be665ade24a2c6  gcc/ada/sem_dim.adb
  d0ed9c569455451ee26c8e2565b7125b  gcc/ada/sem_dim.ads
! dc4aae103bf28240aeca01e27e881dbe  gcc/ada/sem_disp.adb
  40937cb7584e45e4c545aa3e4c20fbb2  gcc/ada/sem_disp.ads
  8f677120e0bcecbdcfa5b9c4f44cb282  gcc/ada/sem_dist.adb
  a38c4ce4bc2936bd0a73c28ff1b0df61  gcc/ada/sem_dist.ads
--- 2901,2929 ----
  6e34ce648cfc10b24c12b68e0e59dcb8  gcc/ada/sem_ch10.ads
  5980a02146588bf0e31ced2382290670  gcc/ada/sem_ch11.adb
  1b6f89866a5d427002df059be3847d62  gcc/ada/sem_ch11.ads
! 48c5facaaa28a3043abd59c4f9122f9b  gcc/ada/sem_ch12.adb
  b0a3315dce9de8e3bbbb3682c8b0e2ff  gcc/ada/sem_ch12.ads
! 088ce0a61eea7a82bf9c5fd0f5ebc51c  gcc/ada/sem_ch13.adb
  42a7b1073e168e8be85f2203fbddd148  gcc/ada/sem_ch13.ads
  14326c522718c8cb8415b13a79c07972  gcc/ada/sem_ch2.adb
  2471d629be4739ff5135aa87a2ec9166  gcc/ada/sem_ch2.ads
! 524f99aea0ed3f321230fdcaa1d6c5d2  gcc/ada/sem_ch3.adb
  a9694f8bc09b47075cae226e570e02f0  gcc/ada/sem_ch3.ads
! 904f36c9a9bf09c65759cab2728c22c7  gcc/ada/sem_ch4.adb
  adba03aae1f439b9e9db8cea05d8e03f  gcc/ada/sem_ch4.ads
! f5c661468bc72925e2297ff32e812702  gcc/ada/sem_ch5.adb
  ec8d5a42c27c46e4969c16d6e18ed276  gcc/ada/sem_ch5.ads
! 2e84010f6396d898ab407bd3a3ae5435  gcc/ada/sem_ch6.adb
! e243030a8b8486f145f0544a7e0d6f47  gcc/ada/sem_ch6.ads
  3c7c6e6b95a9cddb1d6f1a42a5962379  gcc/ada/sem_ch7.adb
  24a1265e6a25756265643858abcf7ded  gcc/ada/sem_ch7.ads
! 7aca9207bf76039a345f39c73664adf9  gcc/ada/sem_ch8.adb
  f0b4e317e5d5515a6ec337bc5acf5fe0  gcc/ada/sem_ch8.ads
! 546c616e1a0e3e76b6220644a605da51  gcc/ada/sem_ch9.adb
  7b283bd6453de444c7075a8c6f215dda  gcc/ada/sem_ch9.ads
  dea2a3321bde0d3ed6be665ade24a2c6  gcc/ada/sem_dim.adb
  d0ed9c569455451ee26c8e2565b7125b  gcc/ada/sem_dim.ads
! afc0c6c63f3b4af535cbedd72c00385e  gcc/ada/sem_disp.adb
  40937cb7584e45e4c545aa3e4c20fbb2  gcc/ada/sem_disp.ads
  8f677120e0bcecbdcfa5b9c4f44cb282  gcc/ada/sem_dist.adb
  a38c4ce4bc2936bd0a73c28ff1b0df61  gcc/ada/sem_dist.ads
*************** e8e79e2a818321d7816e27eed8d17404  gcc/ad
*** 2939,2945 ****
  bcb22deebc83b966e7be367087d9fd7b  gcc/ada/sem_mech.ads
  e2f3633d170142979d7ed46d67a83b5b  gcc/ada/sem_prag.adb
  77d07a6ae20be77457587ee20ba32423  gcc/ada/sem_prag.ads
! 0de51ef4cc99905ee063ed424da8ef09  gcc/ada/sem_res.adb
  bb01f11ceaa352a8b99f95fcbcfe97d9  gcc/ada/sem_res.ads
  28d33ede4288814374d1909847798c7d  gcc/ada/sem_scil.adb
  db6f5a37bd59fd83ff3286e71ab985fe  gcc/ada/sem_scil.ads
--- 2939,2945 ----
  bcb22deebc83b966e7be367087d9fd7b  gcc/ada/sem_mech.ads
  e2f3633d170142979d7ed46d67a83b5b  gcc/ada/sem_prag.adb
  77d07a6ae20be77457587ee20ba32423  gcc/ada/sem_prag.ads
! a79509888717bcca5b84e0ba62619eb6  gcc/ada/sem_res.adb
  bb01f11ceaa352a8b99f95fcbcfe97d9  gcc/ada/sem_res.ads
  28d33ede4288814374d1909847798c7d  gcc/ada/sem_scil.adb
  db6f5a37bd59fd83ff3286e71ab985fe  gcc/ada/sem_scil.ads
*************** db6f5a37bd59fd83ff3286e71ab985fe  gcc/ad
*** 2947,2954 ****
  89d73c108bd8921f6d6cd84d98726ea5  gcc/ada/sem_smem.ads
  d0a2f5b2f65a874363f7fbe2b9a79f8b  gcc/ada/sem_type.adb
  dee50852181adfada17fb5b7423ed973  gcc/ada/sem_type.ads
! 6724923013ceca6c44a581f614941665  gcc/ada/sem_util.adb
! 5c2fd7785d1403e27f5bc0ed4d3b8235  gcc/ada/sem_util.ads
  9668d6a37fe84f41a81a7ffcb66d5ecc  gcc/ada/sem_warn.adb
  441e0f80657ef72324e40dd20cebfc82  gcc/ada/sem_warn.ads
  239ca67ac9aa430abfe5120a8d4302d9  gcc/ada/set_targ.adb
--- 2947,2954 ----
  89d73c108bd8921f6d6cd84d98726ea5  gcc/ada/sem_smem.ads
  d0a2f5b2f65a874363f7fbe2b9a79f8b  gcc/ada/sem_type.adb
  dee50852181adfada17fb5b7423ed973  gcc/ada/sem_type.ads
! 555923a1d35ea906b85837d23fcfbf0e  gcc/ada/sem_util.adb
! a5c6b19173c26bbe5e7fd3d54ee4895e  gcc/ada/sem_util.ads
  9668d6a37fe84f41a81a7ffcb66d5ecc  gcc/ada/sem_warn.adb
  441e0f80657ef72324e40dd20cebfc82  gcc/ada/sem_warn.ads
  239ca67ac9aa430abfe5120a8d4302d9  gcc/ada/set_targ.adb
*************** f32c4d3d5df9ad9663b4978f7f8a2573  gcc/ad
*** 2968,2974 ****
  5508690394c02353c472f15fdd05b280  gcc/ada/sinfo-utils.adb
  df1aa3814d8c5281deb3b526c99368fc  gcc/ada/sinfo-utils.ads
  e6d5c3ccb5893bb3943fbdf529b298d6  gcc/ada/sinfo.adb
! afba074844e27f973c77dcb0988bac5c  gcc/ada/sinfo.ads
  ebb37a07fb72782f86b0c141d3f6077c  gcc/ada/sinput-c.adb
  ec9033e4caebeb446063de16e18918f4  gcc/ada/sinput-c.ads
  2fec6a5fbe7c9e765ea70c82814b0fd3  gcc/ada/sinput-d.adb
--- 2968,2974 ----
  5508690394c02353c472f15fdd05b280  gcc/ada/sinfo-utils.adb
  df1aa3814d8c5281deb3b526c99368fc  gcc/ada/sinfo-utils.ads
  e6d5c3ccb5893bb3943fbdf529b298d6  gcc/ada/sinfo.adb
! 7bb0ec1948d808ea803d59fd500b8ea9  gcc/ada/sinfo.ads
  ebb37a07fb72782f86b0c141d3f6077c  gcc/ada/sinput-c.adb
  ec9033e4caebeb446063de16e18918f4  gcc/ada/sinput-c.ads
  2fec6a5fbe7c9e765ea70c82814b0fd3  gcc/ada/sinput-d.adb
*************** f6ff4b8bae7d2f10bf04f58ae4efb096  gcc/ad
*** 2978,2984 ****
  bb43802a54a3cfd9cb953188a875da3d  gcc/ada/sinput.adb
  ba7717c1c0a8bd7b1c3feee6580246e6  gcc/ada/sinput.ads
  66e1d7dbeefd14b51758e17a022c2929  gcc/ada/snames.adb-tmpl
! 6d49541c40b4d9103a24e289caf7ccdd  gcc/ada/snames.ads-tmpl
  b5bad059d1da34b0f6f1f8e3b605f212  gcc/ada/snames.h-tmpl
  efc103042b1bc17447f48a276dc860ab  gcc/ada/socket.c
  8bdf1e57c628c071b503b49f5c5078f6  gcc/ada/spark_xrefs.adb
--- 2978,2984 ----
  bb43802a54a3cfd9cb953188a875da3d  gcc/ada/sinput.adb
  ba7717c1c0a8bd7b1c3feee6580246e6  gcc/ada/sinput.ads
  66e1d7dbeefd14b51758e17a022c2929  gcc/ada/snames.adb-tmpl
! f16f762fd285bf52b6d610189da527b6  gcc/ada/snames.ads-tmpl
  b5bad059d1da34b0f6f1f8e3b605f212  gcc/ada/snames.h-tmpl
  efc103042b1bc17447f48a276dc860ab  gcc/ada/socket.c
  8bdf1e57c628c071b503b49f5c5078f6  gcc/ada/spark_xrefs.adb
*************** ceaa52edf6355622601cd30f7c096b06  gcc/ad
*** 2994,3000 ****
  426fe1648aa969a711bc91b140c31950  gcc/ada/strub.ads
  8afc1c7d58bdd832cfc07e0b7f154b20  gcc/ada/style.adb
  47034d64868bf09604f7cf41bfa8f20b  gcc/ada/style.ads
! 13b060cdc887d7f83a4b48f3851e2121  gcc/ada/styleg.adb
  93df3efe29025f787333e334faf17c55  gcc/ada/styleg.ads
  2e977ce8e3a4cc0d1344850f639eea97  gcc/ada/stylesw.adb
  072e20e96999b6e3137326e76e71b03d  gcc/ada/stylesw.ads
--- 2994,3000 ----
  426fe1648aa969a711bc91b140c31950  gcc/ada/strub.ads
  8afc1c7d58bdd832cfc07e0b7f154b20  gcc/ada/style.adb
  47034d64868bf09604f7cf41bfa8f20b  gcc/ada/style.ads
! 602e5a3e4582230b3df902db3781e848  gcc/ada/styleg.adb
  93df3efe29025f787333e334faf17c55  gcc/ada/styleg.ads
  2e977ce8e3a4cc0d1344850f639eea97  gcc/ada/stylesw.adb
  072e20e96999b6e3137326e76e71b03d  gcc/ada/stylesw.ads
*************** ceaa52edf6355622601cd30f7c096b06  gcc/ad
*** 3006,3012 ****
  2ee5998b92d56bf9c5cc341e1f1ad78e  gcc/ada/switch-m.ads
  7e7afcf1b2687d2270ec21617a7bb854  gcc/ada/switch.adb
  3ce7cd08e301dd2487e065308c9e9fe9  gcc/ada/switch.ads
! 6726d67dd3bb2abdda020dd462bc80ee  gcc/ada/sysdep.c
  bef209f16c0106f0a9c5255fb6bf96bb  gcc/ada/table.adb
  b1eaff871eb559b799ef7fe2960e86f9  gcc/ada/table.ads
  9f45bf3ee4cf0a6b06c0b5cc6a4830a7  gcc/ada/targext.c
--- 3006,3012 ----
  2ee5998b92d56bf9c5cc341e1f1ad78e  gcc/ada/switch-m.ads
  7e7afcf1b2687d2270ec21617a7bb854  gcc/ada/switch.adb
  3ce7cd08e301dd2487e065308c9e9fe9  gcc/ada/switch.ads
! 1c5f4065ed9bfb55ca7167c50baf2159  gcc/ada/sysdep.c
  bef209f16c0106f0a9c5255fb6bf96bb  gcc/ada/table.adb
  b1eaff871eb559b799ef7fe2960e86f9  gcc/ada/table.ads
  9f45bf3ee4cf0a6b06c0b5cc6a4830a7  gcc/ada/targext.c
*************** df3f6c6882fc8f715d4cc537af0f6442  gcc/ad
*** 3058,3068 ****
  a13250e9011949e791f210139f4c4323  gcc/align.h
  192d075c6984da6ef1e282fd63829079  gcc/alloc-pool.cc
  b2194a7136db5f26272ca6162d858997  gcc/alloc-pool.h
! 905711b0e3b46373d582a48e64e48c23  gcc/analyzer/ChangeLog
! aaa842009d67015d581300713c2b0686  gcc/analyzer/access-diagram.cc
! 9de61ebb9551c4e4ef3bfa77f503bfa0  gcc/analyzer/access-diagram.h
! 0ec14334bc6385cf08ed3a2de610ef9c  gcc/analyzer/ana-state-to-diagnostic-state.cc
! 68c8f1e0100d1c3e1943c147b8d2e747  gcc/analyzer/ana-state-to-diagnostic-state.h
  0fbda9dacfcf6f4071f7bee8c6b7dbe9  gcc/analyzer/analysis-plan.cc
  b5f1385e0b051936dcf6b44d2802237b  gcc/analyzer/analysis-plan.h
  5e7a1356f3a013d95df4966c3b0184db  gcc/analyzer/analyzer-language.cc
--- 3058,3068 ----
  a13250e9011949e791f210139f4c4323  gcc/align.h
  192d075c6984da6ef1e282fd63829079  gcc/alloc-pool.cc
  b2194a7136db5f26272ca6162d858997  gcc/alloc-pool.h
! e23274eaa578ff852752fed565ad2ef2  gcc/analyzer/ChangeLog
! 51f6840360573e2c2c0b157723b94c0b  gcc/analyzer/access-diagram.cc
! 58f352acafda673d24da4113c4f80b8d  gcc/analyzer/access-diagram.h
! 9b9effe796cc5df0612c35031d57d8bb  gcc/analyzer/ana-state-to-diagnostic-state.cc
! acecd42f928b39f9f6857f55e7a67153  gcc/analyzer/ana-state-to-diagnostic-state.h
  0fbda9dacfcf6f4071f7bee8c6b7dbe9  gcc/analyzer/analysis-plan.cc
  b5f1385e0b051936dcf6b44d2802237b  gcc/analyzer/analysis-plan.h
  5e7a1356f3a013d95df4966c3b0184db  gcc/analyzer/analyzer-language.cc
*************** b40988a4cf1f11f85dc4b7182a0253fd  gcc/an
*** 3072,3102 ****
  bfd6293a1330b0a0026fdc80c0c23351  gcc/analyzer/analyzer-pass.cc
  313f066c1695c476ca0de7d8f98cc4db  gcc/analyzer/analyzer-selftests.cc
  a2da2c4ef5a4fe3acbece54115b2fcd5  gcc/analyzer/analyzer-selftests.h
! d4ff950465f696f54908b12a402c4570  gcc/analyzer/analyzer.cc
  7728dfb3aa000e39dae978127135b53e  gcc/analyzer/analyzer.opt
  7c4b3ff66e19fadda3d2ea672e55bd5b  gcc/analyzer/analyzer.opt.urls
  36bb44ed21a23a1a8cfb1813e07e2618  gcc/analyzer/bar-chart.cc
  632007f36f35e261443f6de2baf0656a  gcc/analyzer/bar-chart.h
! 856d703000578b2f75953114b5cbdea2  gcc/analyzer/bounds-checking.cc
! b3b4ea3c5d2bbdc7f1dbb54cf7c50562  gcc/analyzer/call-details.cc
  34784d3ca75f5fd6835d234890d819ef  gcc/analyzer/call-details.h
! ab7785be9752af3c41527ce7aa08e5f9  gcc/analyzer/call-info.cc
  80e57512f90deb1472ad7ad386c76c6b  gcc/analyzer/call-info.h
  83a7dc74d76e0f16a332e5c8a5435092  gcc/analyzer/call-string.cc
  850dcfdb7202d7b55db64d1dbe5cf586  gcc/analyzer/call-string.h
  5ee965667b05f3d325ad2eea5190fa2f  gcc/analyzer/call-summary.cc
  bc77cd1e5aec40e5623c49cb8974b3d4  gcc/analyzer/call-summary.h
! 80389ec568719f79240d502bf7f769f8  gcc/analyzer/checker-event.cc
! 0aa38d5db3e7001e116eb3d95f93fe7c  gcc/analyzer/checker-event.h
! c4687f7aa3cb8374e9f9a685ba14ee0e  gcc/analyzer/checker-path.cc
! bbcfe5f4c035b0e04c335bc110c841c0  gcc/analyzer/checker-path.h
! 6b6291eb4a03bf034e574c4f02dbe8d8  gcc/analyzer/common.h
  60fa08b701b562f0dde13dd1877ddcd1  gcc/analyzer/complexity.cc
  9113c9c3a7167f3119fc0552883611b5  gcc/analyzer/complexity.h
  74ace4f7805c8393c9c164dacc3c8322  gcc/analyzer/constraint-manager.cc
  78d08c7af5c5ace7e984a3062c8053a5  gcc/analyzer/constraint-manager.h
! dba762ca3a9701b0861140d5a243492e  gcc/analyzer/diagnostic-manager.cc
! f44cc8516da447fede0702befbb862f6  gcc/analyzer/diagnostic-manager.h
  dd456f59ea47fe70beffe68e760b8bf2  gcc/analyzer/engine.cc
  acc1f4f20384df654fa365f64ad6a6f9  gcc/analyzer/engine.h
  c31696d47421f74a13cc907d022b3935  gcc/analyzer/event-loc-info.h
--- 3072,3102 ----
  bfd6293a1330b0a0026fdc80c0c23351  gcc/analyzer/analyzer-pass.cc
  313f066c1695c476ca0de7d8f98cc4db  gcc/analyzer/analyzer-selftests.cc
  a2da2c4ef5a4fe3acbece54115b2fcd5  gcc/analyzer/analyzer-selftests.h
! ae42d1af6f0865a580be5b5785f09543  gcc/analyzer/analyzer.cc
  7728dfb3aa000e39dae978127135b53e  gcc/analyzer/analyzer.opt
  7c4b3ff66e19fadda3d2ea672e55bd5b  gcc/analyzer/analyzer.opt.urls
  36bb44ed21a23a1a8cfb1813e07e2618  gcc/analyzer/bar-chart.cc
  632007f36f35e261443f6de2baf0656a  gcc/analyzer/bar-chart.h
! 5d87c207a6d8c669b3ff743d748bb938  gcc/analyzer/bounds-checking.cc
! a82a71ab7f96ca02b70fd75fd951ea5f  gcc/analyzer/call-details.cc
  34784d3ca75f5fd6835d234890d819ef  gcc/analyzer/call-details.h
! 203c27c81792a274c12b0b1f0e7658e7  gcc/analyzer/call-info.cc
  80e57512f90deb1472ad7ad386c76c6b  gcc/analyzer/call-info.h
  83a7dc74d76e0f16a332e5c8a5435092  gcc/analyzer/call-string.cc
  850dcfdb7202d7b55db64d1dbe5cf586  gcc/analyzer/call-string.h
  5ee965667b05f3d325ad2eea5190fa2f  gcc/analyzer/call-summary.cc
  bc77cd1e5aec40e5623c49cb8974b3d4  gcc/analyzer/call-summary.h
! 399cfb6eb3baf3ee49a4c867aa03f715  gcc/analyzer/checker-event.cc
! 55206f539e6dc12c4379dd09712a1f0f  gcc/analyzer/checker-event.h
! 3ab3510c119841ad20bbfcab82653f7c  gcc/analyzer/checker-path.cc
! 717c8ea5a0fcd626c448dd37a593cfda  gcc/analyzer/checker-path.h
! 458fdaf5604da3f5885623bb7f034d40  gcc/analyzer/common.h
  60fa08b701b562f0dde13dd1877ddcd1  gcc/analyzer/complexity.cc
  9113c9c3a7167f3119fc0552883611b5  gcc/analyzer/complexity.h
  74ace4f7805c8393c9c164dacc3c8322  gcc/analyzer/constraint-manager.cc
  78d08c7af5c5ace7e984a3062c8053a5  gcc/analyzer/constraint-manager.h
! ccd553f0d2a96c74a34cc0bebc63ebd3  gcc/analyzer/diagnostic-manager.cc
! 3f393f4ab5ba02ae9be5a89e15cbf389  gcc/analyzer/diagnostic-manager.h
  dd456f59ea47fe70beffe68e760b8bf2  gcc/analyzer/engine.cc
  acc1f4f20384df654fa365f64ad6a6f9  gcc/analyzer/engine.h
  c31696d47421f74a13cc907d022b3935  gcc/analyzer/event-loc-info.h
*************** bd0aa8aba8793b6e03f6cddffd57b301  gcc/an
*** 3105,3148 ****
  af675735c50099e3d3123b9ef8d97dad  gcc/analyzer/feasible-graph.h
  75fa61994e084f2c6f9d6ccff6da1c5b  gcc/analyzer/function-set.cc
  73d77bbed77b45ed4b05881eeccbc992  gcc/analyzer/function-set.h
! eac039e9d9e8b9cb384a8ba136fdbf78  gcc/analyzer/infinite-loop.cc
! 88e901e53566d286a6529d3ab31c3611  gcc/analyzer/infinite-recursion.cc
  7ee54f0568377ab1b37ccdc7bb949387  gcc/analyzer/inlining-iterator.h
  9289c540d66da127e56aa983ca018af6  gcc/analyzer/kf-analyzer.cc
  f939ceabcab4e031bd8a0960eaa768dc  gcc/analyzer/kf-lang-cp.cc
! 9a9fe11eb047335b0c6e9f9995e6fca8  gcc/analyzer/kf.cc
  87c0ace2795d7de6063a286af6c85d5b  gcc/analyzer/known-function-manager.cc
  03a32d089b911aa5389a2b9006795f83  gcc/analyzer/known-function-manager.h
! c1a5cbf927517772015d9be0349c4415  gcc/analyzer/pending-diagnostic.cc
! 801dd659a2e39b1419f0cf63f793e632  gcc/analyzer/pending-diagnostic.h
! b0a3db683bfca881a5f79aab8edc412a  gcc/analyzer/program-point.cc
  c1fbd7a3b6a1c66e2dbbc2e6725bab7b  gcc/analyzer/program-point.h
! cbf03051ed9c00a2121e5acc5775cd2c  gcc/analyzer/program-state.cc
  88b5f5d134b7604026c38d9f5b2cbb29  gcc/analyzer/program-state.h
  fe06c3c30ebc980430c4383a990fb092  gcc/analyzer/ranges.cc
  f0acfecca8767075f2b2e9bc04089741  gcc/analyzer/ranges.h
  58fb7d339e1159812f9592e6de91dfa3  gcc/analyzer/reachability.h
  59f0552f76cf621495df906f2db01f93  gcc/analyzer/record-layout.cc
  57354826ca1c448180149706333f891f  gcc/analyzer/record-layout.h
! c3940a144186acca651ddcdbc67ed8c2  gcc/analyzer/region-model-asm.cc
  3bb1776cb845ffbe486880216ac3f330  gcc/analyzer/region-model-manager.cc
  d63277a107754fc16d0f14e27723be50  gcc/analyzer/region-model-manager.h
  fd4829788ccc0c5b24898e946b18894e  gcc/analyzer/region-model-reachability.cc
  34ab719ce08057bb88f8bf20e7c3c959  gcc/analyzer/region-model-reachability.h
! 1d500f788729d66520449e3844eddb93  gcc/analyzer/region-model.cc
  12dbb4c144503439cf120f53cc69ce8e  gcc/analyzer/region-model.h
  26879bd907a888e30cb97cc1b3957778  gcc/analyzer/region.cc
  1ea9c46e24a4c830bab76a9ddf0ffa3f  gcc/analyzer/region.h
! 4356a32305c610c1d964e4d9ac9e9887  gcc/analyzer/sm-fd.cc
  7a28d77074f7b1b5ea7b79aa82f21698  gcc/analyzer/sm-fd.dot
! 103402a324c9fe6e7152fd7eea542a3f  gcc/analyzer/sm-file.cc
  38e55000eed6a24e2db959ceb1b99c4f  gcc/analyzer/sm-file.dot
! 3e2d7100a8fb63ac8925a26d5ffd9da3  gcc/analyzer/sm-malloc.cc
  e0c92f0f51c6cc6d8c51b020ac66c866  gcc/analyzer/sm-malloc.dot
! 329c3fd7929ce7a7c5137d3a3a6e12fb  gcc/analyzer/sm-pattern-test.cc
! 3a4a4355dda682acff21bd54d4fa0aec  gcc/analyzer/sm-sensitive.cc
! 6ec21218f67516b79559c765cd3b438c  gcc/analyzer/sm-signal.cc
! b069f65a3ee66f0abe951eda3cc5b50b  gcc/analyzer/sm-taint.cc
  80b4a3586caa92819fb59f51689cb53d  gcc/analyzer/sm.cc
  8591769ffb0e0287072889a6706d28cd  gcc/analyzer/sm.h
  0b805ff6293fa32e40ae2b5b76f12432  gcc/analyzer/state-purge.cc
--- 3105,3148 ----
  af675735c50099e3d3123b9ef8d97dad  gcc/analyzer/feasible-graph.h
  75fa61994e084f2c6f9d6ccff6da1c5b  gcc/analyzer/function-set.cc
  73d77bbed77b45ed4b05881eeccbc992  gcc/analyzer/function-set.h
! e8fdf8aae887a06668b928191ec6da7a  gcc/analyzer/infinite-loop.cc
! 7f7c333f7b16b355475364b28ab1e37a  gcc/analyzer/infinite-recursion.cc
  7ee54f0568377ab1b37ccdc7bb949387  gcc/analyzer/inlining-iterator.h
  9289c540d66da127e56aa983ca018af6  gcc/analyzer/kf-analyzer.cc
  f939ceabcab4e031bd8a0960eaa768dc  gcc/analyzer/kf-lang-cp.cc
! f32274ec03562757a6e4486d10c7d720  gcc/analyzer/kf.cc
  87c0ace2795d7de6063a286af6c85d5b  gcc/analyzer/known-function-manager.cc
  03a32d089b911aa5389a2b9006795f83  gcc/analyzer/known-function-manager.h
! a3d0c02b50cbbcec43b3e11b7f924601  gcc/analyzer/pending-diagnostic.cc
! d5314202d047f9c9dadbafd255300e4a  gcc/analyzer/pending-diagnostic.h
! 2b832b9c504b35df0b392144a6e972a2  gcc/analyzer/program-point.cc
  c1fbd7a3b6a1c66e2dbbc2e6725bab7b  gcc/analyzer/program-point.h
! acfab5c6c210453c5c3ea11ee178a69f  gcc/analyzer/program-state.cc
  88b5f5d134b7604026c38d9f5b2cbb29  gcc/analyzer/program-state.h
  fe06c3c30ebc980430c4383a990fb092  gcc/analyzer/ranges.cc
  f0acfecca8767075f2b2e9bc04089741  gcc/analyzer/ranges.h
  58fb7d339e1159812f9592e6de91dfa3  gcc/analyzer/reachability.h
  59f0552f76cf621495df906f2db01f93  gcc/analyzer/record-layout.cc
  57354826ca1c448180149706333f891f  gcc/analyzer/record-layout.h
! c9c8852b4b59b06ab29b2a557fffed4c  gcc/analyzer/region-model-asm.cc
  3bb1776cb845ffbe486880216ac3f330  gcc/analyzer/region-model-manager.cc
  d63277a107754fc16d0f14e27723be50  gcc/analyzer/region-model-manager.h
  fd4829788ccc0c5b24898e946b18894e  gcc/analyzer/region-model-reachability.cc
  34ab719ce08057bb88f8bf20e7c3c959  gcc/analyzer/region-model-reachability.h
! e2a02c253827acc1a12543c90d32c2a5  gcc/analyzer/region-model.cc
  12dbb4c144503439cf120f53cc69ce8e  gcc/analyzer/region-model.h
  26879bd907a888e30cb97cc1b3957778  gcc/analyzer/region.cc
  1ea9c46e24a4c830bab76a9ddf0ffa3f  gcc/analyzer/region.h
! 2d30a76b5e3759b2f248f26f3deb7e6e  gcc/analyzer/sm-fd.cc
  7a28d77074f7b1b5ea7b79aa82f21698  gcc/analyzer/sm-fd.dot
! c4143ba7f15b2ebb99f1baf69977d2a4  gcc/analyzer/sm-file.cc
  38e55000eed6a24e2db959ceb1b99c4f  gcc/analyzer/sm-file.dot
! 4ce5b45bae6a512dccf777dfe7419c46  gcc/analyzer/sm-malloc.cc
  e0c92f0f51c6cc6d8c51b020ac66c866  gcc/analyzer/sm-malloc.dot
! 2ba73b1a94b1ba447cf0faecae53806f  gcc/analyzer/sm-pattern-test.cc
! 3161ab2d3840caee34e00c9b0e28ff03  gcc/analyzer/sm-sensitive.cc
! 9bc9a3fc593ca7c6bf214544b2477cd5  gcc/analyzer/sm-signal.cc
! dce678df78f1adacad05565863b07fe6  gcc/analyzer/sm-taint.cc
  80b4a3586caa92819fb59f51689cb53d  gcc/analyzer/sm.cc
  8591769ffb0e0287072889a6706d28cd  gcc/analyzer/sm.h
  0b805ff6293fa32e40ae2b5b76f12432  gcc/analyzer/state-purge.cc
*************** fd6d3aab6e3dc2f26680b6d3ee68a8fe  gcc/an
*** 3157,3163 ****
  336e5422328aefad109c05dff847934f  gcc/analyzer/symbol.h
  c60f1ef3d02e040c88d9e217de84ee81  gcc/analyzer/trimmed-graph.cc
  2d528f5f807adc6941ed2a20cc193c7f  gcc/analyzer/trimmed-graph.h
! 459d86c51b22afac472cf796833ac553  gcc/analyzer/varargs.cc
  cc81acb908eb9d6b13038a95c3a10a9c  gcc/analyzer/varargs.dot
  eeb42b412edc2884a4c60d6f38f7473b  gcc/array-traits.h
  6abcb9777280c69da14835a391a5c347  gcc/asan.cc
--- 3157,3163 ----
  336e5422328aefad109c05dff847934f  gcc/analyzer/symbol.h
  c60f1ef3d02e040c88d9e217de84ee81  gcc/analyzer/trimmed-graph.cc
  2d528f5f807adc6941ed2a20cc193c7f  gcc/analyzer/trimmed-graph.h
! 4f474853939ba265b67e975cdb22c9ed  gcc/analyzer/varargs.cc
  cc81acb908eb9d6b13038a95c3a10a9c  gcc/analyzer/varargs.dot
  eeb42b412edc2884a4c60d6f38f7473b  gcc/array-traits.h
  6abcb9777280c69da14835a391a5c347  gcc/asan.cc
*************** fe292df4b7f3e3ef7c0b8305084b6844  gcc/bi
*** 3185,3212 ****
  9519cf786b112194737e7d0c3534a854  gcc/builtins.cc
  4928906d86168cbc863e309bdb3ec391  gcc/builtins.def
  bd61b50b47560dc1324bf507bea5d87e  gcc/builtins.h
! 6f14f645c47f7a702bc545c422ff11ec  gcc/c-family/ChangeLog
  ea3fa1f4d7390a105fa3caab4f79aaf7  gcc/c-family/ChangeLog.gimple-classes
  823fe168bb0f63a39de62d9f0251a1b5  gcc/c-family/c-ada-spec.cc
  4e83011bee68d9607834ed5335191d65  gcc/c-family/c-ada-spec.h
  7080332af7f52639bff3e04c1c8dfee5  gcc/c-family/c-attribs.cc
! 7c7087d355210f92a3e615ce76d0675f  gcc/c-family/c-common.cc
  c273c4ad95ccdbfe677146505900c62e  gcc/c-family/c-common.def
! 19fb19e4311805f52f48f30e7873ad2e  gcc/c-family/c-common.h
! c1aa039e875437c70f79787c2752305d  gcc/c-family/c-cppbuiltin.cc
  01db2d5cca29943c49bb372f2137d874  gcc/c-family/c-dump.cc
! b74c57df986113249610e15abda6d38b  gcc/c-family/c-format.cc
  c8d86c12bc259d3a335f338ce3a10304  gcc/c-family/c-format.h
  33e75548501d8294a77fd654bc8d4d39  gcc/c-family/c-gimplify.cc
! 4d15aede5a4841d6489aa40ad1304c00  gcc/c-family/c-indentation.cc
  a4b7179d2e948bb7586a9143fbe05593  gcc/c-family/c-indentation.h
! 4c01c042c599ee5c7b21aeb2c0cccbe8  gcc/c-family/c-lex.cc
  c880dc584a0fd4908e5df33dd81137b8  gcc/c-family/c-objc.h
  ff101b60d9a9ba25502bca2f5713b2a3  gcc/c-family/c-omp.cc
! 4edcbf51287f45cd2508ff5250ae0efd  gcc/c-family/c-opts.cc
  2f1a14531d3a436ca9f4aad2812c3898  gcc/c-family/c-pch.cc
  6e53d008a0c4738339154c353a50ff0a  gcc/c-family/c-ppoutput.cc
! 9fc831d62cb02feeec158e948abc2b6b  gcc/c-family/c-pragma.cc
  10932d88b49c31cc0912970b8f153a0f  gcc/c-family/c-pragma.h
  6b06dfa990e7bab82095a54e9f6b9aee  gcc/c-family/c-pretty-print.cc
  65ddbb97d9d65906a812f9c61b9ca1d1  gcc/c-family/c-pretty-print.h
--- 3185,3212 ----
  9519cf786b112194737e7d0c3534a854  gcc/builtins.cc
  4928906d86168cbc863e309bdb3ec391  gcc/builtins.def
  bd61b50b47560dc1324bf507bea5d87e  gcc/builtins.h
! 2db6ba72a7f90c2ca1ad3226d6766783  gcc/c-family/ChangeLog
  ea3fa1f4d7390a105fa3caab4f79aaf7  gcc/c-family/ChangeLog.gimple-classes
  823fe168bb0f63a39de62d9f0251a1b5  gcc/c-family/c-ada-spec.cc
  4e83011bee68d9607834ed5335191d65  gcc/c-family/c-ada-spec.h
  7080332af7f52639bff3e04c1c8dfee5  gcc/c-family/c-attribs.cc
! 78c56cfdab4bb19086143ab771281aa3  gcc/c-family/c-common.cc
  c273c4ad95ccdbfe677146505900c62e  gcc/c-family/c-common.def
! e26b8d36ab6e21fadddb5a570de25ee4  gcc/c-family/c-common.h
! d1a713f57fff4077ba78dc3e61668454  gcc/c-family/c-cppbuiltin.cc
  01db2d5cca29943c49bb372f2137d874  gcc/c-family/c-dump.cc
! 19059a85545bb95b391e68da0cbc670c  gcc/c-family/c-format.cc
  c8d86c12bc259d3a335f338ce3a10304  gcc/c-family/c-format.h
  33e75548501d8294a77fd654bc8d4d39  gcc/c-family/c-gimplify.cc
! 15ee0a70aef7b52e6e17c009e2b8ccfa  gcc/c-family/c-indentation.cc
  a4b7179d2e948bb7586a9143fbe05593  gcc/c-family/c-indentation.h
! c80c4d6e16ab46358143d22a8a146725  gcc/c-family/c-lex.cc
  c880dc584a0fd4908e5df33dd81137b8  gcc/c-family/c-objc.h
  ff101b60d9a9ba25502bca2f5713b2a3  gcc/c-family/c-omp.cc
! 6bf83c8332e0c624cc1aa91ac3a1e3f5  gcc/c-family/c-opts.cc
  2f1a14531d3a436ca9f4aad2812c3898  gcc/c-family/c-pch.cc
  6e53d008a0c4738339154c353a50ff0a  gcc/c-family/c-ppoutput.cc
! cfc760e3be8b3db6dfc8fef49282c0aa  gcc/c-family/c-pragma.cc
  10932d88b49c31cc0912970b8f153a0f  gcc/c-family/c-pragma.h
  6b06dfa990e7bab82095a54e9f6b9aee  gcc/c-family/c-pretty-print.cc
  65ddbb97d9d65906a812f9c61b9ca1d1  gcc/c-family/c-pretty-print.h
*************** fc808567009babd00ebcf49b5b985691  gcc/c-
*** 3220,3249 ****
  2716f2dd9d461ac6da32e9185698bbb2  gcc/c-family/c-type-mismatch.h
  2012b44c59e574c36b82149a7d19a455  gcc/c-family/c-ubsan.cc
  a28f2477c85a17e42026521322b3649a  gcc/c-family/c-ubsan.h
! ed4e4a12acd44dcb58dd646d038bc97a  gcc/c-family/c-warn.cc
  17455f6a048d561960ad726b2c9c8104  gcc/c-family/c.opt
  3de9bdf85b7d9f6b213e8dbcb9672fa5  gcc/c-family/c.opt.urls
  22bd7478421befafcfbd805e3ca373ac  gcc/c-family/cppspec.cc
! aaf683e3b02704cfbfab0627d82edf85  gcc/c-family/known-headers.cc
! ce9d2259a1edb5d4b1f728988bd9ef6a  gcc/c-family/known-headers.h
  f09c431056b5138e7cfe8376e05de9a6  gcc/c-family/name-hint.h
  d71f74b5b48d9ec5e4e6463e7330121d  gcc/c-family/stub-objc.cc
! 578318d43be9e30bece1ea5f0e0e4eca  gcc/c/ChangeLog
  b1fc09d2244c8e8a72b4df9bc9af30d7  gcc/c/Make-lang.in
  f1e5593aebd5cffb4b3cbffe6bd0860a  gcc/c/c-aux-info.cc
  178d24653bb20936d73bad078e70763c  gcc/c/c-convert.cc
! 0bf23268b3f76981a0355a46bd071a63  gcc/c/c-decl.cc
! 3601ac6299bb2579fedc2dcf2aba7773  gcc/c/c-errors.cc
  d9b5dea1631cefab5fe5ca3602db30f0  gcc/c/c-fold.cc
  d9c0725d061adffdf400457d91be3aed  gcc/c/c-lang.cc
  4be9de2ca25340adb8f350478db6a3d8  gcc/c/c-lang.h
! 29c0a26baf73e55c081ac675fa7f87f8  gcc/c/c-objc-common.cc
  757f583d06a3ec98336adbfc92b4e6a8  gcc/c/c-objc-common.h
! cfc55d61879f20e03f49bcf026ecbc0d  gcc/c/c-parser.cc
  9c122bd6feb8ae4a94420c890e654801  gcc/c/c-parser.h
  9179f46b6a06c7d734278f5ce2c55883  gcc/c/c-tree.def
! 9cef7f8aed78affc01930dfcb3d3185c  gcc/c/c-tree.h
! acb871cf80c7127745acc972ac76e6c6  gcc/c/c-typeck.cc
  cd371895d730dd64e947066b2e4378f8  gcc/c/config-lang.in
  1bd76a24d1322659f048abe2272a6f34  gcc/c/gccspec.cc
  c169f2d94910060e76c333db12b960b9  gcc/c/gimple-parser.cc
--- 3220,3249 ----
  2716f2dd9d461ac6da32e9185698bbb2  gcc/c-family/c-type-mismatch.h
  2012b44c59e574c36b82149a7d19a455  gcc/c-family/c-ubsan.cc
  a28f2477c85a17e42026521322b3649a  gcc/c-family/c-ubsan.h
! 47faafdef0d76034184e171880096959  gcc/c-family/c-warn.cc
  17455f6a048d561960ad726b2c9c8104  gcc/c-family/c.opt
  3de9bdf85b7d9f6b213e8dbcb9672fa5  gcc/c-family/c.opt.urls
  22bd7478421befafcfbd805e3ca373ac  gcc/c-family/cppspec.cc
! 801075b0f2da341a38f761b3b7ffd7cd  gcc/c-family/known-headers.cc
! ac5daa4f7d7788a3f68dde7fe7a25316  gcc/c-family/known-headers.h
  f09c431056b5138e7cfe8376e05de9a6  gcc/c-family/name-hint.h
  d71f74b5b48d9ec5e4e6463e7330121d  gcc/c-family/stub-objc.cc
! 1d17f56a1fefc6234d95209996bfbd9f  gcc/c/ChangeLog
  b1fc09d2244c8e8a72b4df9bc9af30d7  gcc/c/Make-lang.in
  f1e5593aebd5cffb4b3cbffe6bd0860a  gcc/c/c-aux-info.cc
  178d24653bb20936d73bad078e70763c  gcc/c/c-convert.cc
! 1ac127190e7abf13e7858f1032308b25  gcc/c/c-decl.cc
! 10e620f790089957c832097206d0d6d6  gcc/c/c-errors.cc
  d9b5dea1631cefab5fe5ca3602db30f0  gcc/c/c-fold.cc
  d9c0725d061adffdf400457d91be3aed  gcc/c/c-lang.cc
  4be9de2ca25340adb8f350478db6a3d8  gcc/c/c-lang.h
! e0b7650de772103a6ae330552c1960bc  gcc/c/c-objc-common.cc
  757f583d06a3ec98336adbfc92b4e6a8  gcc/c/c-objc-common.h
! 2421baf964ca38c8c75f0382ee9b600a  gcc/c/c-parser.cc
  9c122bd6feb8ae4a94420c890e654801  gcc/c/c-parser.h
  9179f46b6a06c7d734278f5ce2c55883  gcc/c/c-tree.def
! bba523ee762447fbd666f594326b08e2  gcc/c/c-tree.h
! 8a451e6a63d92d9cecbd3f097bc3a9d2  gcc/c/c-typeck.cc
  cd371895d730dd64e947066b2e4378f8  gcc/c/config-lang.in
  1bd76a24d1322659f048abe2272a6f34  gcc/c/gccspec.cc
  c169f2d94910060e76c333db12b960b9  gcc/c/gimple-parser.cc
*************** dce5f9aa135bb3752695f3103daa686a  gcc/cf
*** 3262,3268 ****
  0d52ee7360736bb3d0306e66c1f3a9ce  gcc/cfgbuild.h
  39bbd18fab17b2880094aa317111df50  gcc/cfgcleanup.cc
  0761d2fe0a8e51aa7ed662e27b66747a  gcc/cfgcleanup.h
! 3049ee5f8436759ed3046e6ab57658d0  gcc/cfgexpand.cc
  1ec4e9a88b7aff0e8dc3577ab103b559  gcc/cfgexpand.h
  748c8fca5e6dfe774ff333205ea9f9be  gcc/cfghooks.cc
  bbad65845fcf9cdbc5137d96f92eacab  gcc/cfghooks.h
--- 3262,3268 ----
  0d52ee7360736bb3d0306e66c1f3a9ce  gcc/cfgbuild.h
  39bbd18fab17b2880094aa317111df50  gcc/cfgcleanup.cc
  0761d2fe0a8e51aa7ed662e27b66747a  gcc/cfgcleanup.h
! 2f34675fb48ec944588297d36eafe342  gcc/cfgexpand.cc
  1ec4e9a88b7aff0e8dc3577ab103b559  gcc/cfgexpand.h
  748c8fca5e6dfe774ff333205ea9f9be  gcc/cfghooks.cc
  bbad65845fcf9cdbc5137d96f92eacab  gcc/cfghooks.h
*************** e8aea35c3537127601ec95f65a09591c  gcc/cg
*** 3277,3290 ****
  6efd2066f705098914ba5a90b8214010  gcc/cgraph.h
  5fa2e94f261a8a6fc0d80b1c4b227d25  gcc/cgraphbuild.cc
  b87eab2b04054f0d3cd20768be99c655  gcc/cgraphclones.cc
! c6827069836464ba4b82602e2718a45b  gcc/cgraphunit.cc
  70fa61377ff65ad3f25778a40159f510  gcc/cif-code.def
! d6cfe22cb56fc18c20d59fd71ab7bcd6  gcc/cobol/ChangeLog
! 783fc8af6b9427ff266b9f49d0ff66f2  gcc/cobol/Make-lang.in
  0a84e784d2bc4066654d2377fc6a2930  gcc/cobol/TODO
! 4db79ca2e7cdc9dd9f433e97a9dd07e8  gcc/cobol/cbldiag.h
  030342886cc720f11f17d7691f6f24ae  gcc/cobol/cdf-copy.cc
! 863070b9be19b82eb398f76a723103f8  gcc/cobol/cdf.y
  b916ef498fa1cc9821e56ab612f00f3a  gcc/cobol/cdfval.h
  fb65c7259141f1223fa29175a2e441ed  gcc/cobol/cobol-system.h
  700d96c955db2d85a4da3d00138a4e5a  gcc/cobol/cobol1.cc
--- 3277,3290 ----
  6efd2066f705098914ba5a90b8214010  gcc/cgraph.h
  5fa2e94f261a8a6fc0d80b1c4b227d25  gcc/cgraphbuild.cc
  b87eab2b04054f0d3cd20768be99c655  gcc/cgraphclones.cc
! 0f66c996f10f0bf02ea42e4e3088d9e7  gcc/cgraphunit.cc
  70fa61377ff65ad3f25778a40159f510  gcc/cif-code.def
! 4bed41bb1517ef8d59a93d3ebe85304d  gcc/cobol/ChangeLog
! 38de2f3ba3eff58bbacc8dcdbdcd5be7  gcc/cobol/Make-lang.in
  0a84e784d2bc4066654d2377fc6a2930  gcc/cobol/TODO
! ff81b8f0fee01c60af0d84e2b6e6c7e3  gcc/cobol/cbldiag.h
  030342886cc720f11f17d7691f6f24ae  gcc/cobol/cdf-copy.cc
! b7033ccad4ae579d60141168fb904aa8  gcc/cobol/cdf.y
  b916ef498fa1cc9821e56ab612f00f3a  gcc/cobol/cdfval.h
  fb65c7259141f1223fa29175a2e441ed  gcc/cobol/cobol-system.h
  700d96c955db2d85a4da3d00138a4e5a  gcc/cobol/cobol1.cc
*************** bdd6fbf13776c7983a16ac857615424c  gcc/co
*** 3297,3311 ****
  4e726128e0c090e4f3a71efddf5ffa8c  gcc/cobol/gcobc
  14b121f37018fb2571c4e1ac8f69d0a1  gcc/cobol/gcobol.1
  527925049a81a36c06220d368570f55a  gcc/cobol/gcobol.3
! f07bec493c758b66ae1e8dd2f1726d52  gcc/cobol/gcobolspec.cc
! b05af49df5a0a7a81b855db31b1b6f09  gcc/cobol/genapi.cc
! 2c87a9f67df8ea6146bc45d1a2ea1592  gcc/cobol/genapi.h
! f9992ed246b9ae1c88d284364ca41762  gcc/cobol/gengen.cc
! c6848847819715f0eeb0c129a43131a4  gcc/cobol/gengen.h
! 8c3f4ec22da170f9dda554b5838bef78  gcc/cobol/genmath.cc
  d44e8c86d57fb704b6c1fbab3464fb9a  gcc/cobol/genmath.h
! 24a944b1cb9e11a7948a481c0a44e22c  gcc/cobol/genutil.cc
! b1416fc94d0a8a3423d9f2c2ef64f366  gcc/cobol/genutil.h
  7b9c1ead6f9d3661133f7f732811719c  gcc/cobol/help.gen
  0fa33dbe050697f40b5e8df91896da9a  gcc/cobol/inspect.h
  2c85ade938027e95c4c411b384f6ad11  gcc/cobol/lang-specs.h
--- 3297,3311 ----
  4e726128e0c090e4f3a71efddf5ffa8c  gcc/cobol/gcobc
  14b121f37018fb2571c4e1ac8f69d0a1  gcc/cobol/gcobol.1
  527925049a81a36c06220d368570f55a  gcc/cobol/gcobol.3
! d7c8a533dca0074af1f74be3f2ef9dce  gcc/cobol/gcobolspec.cc
! b12bab0fac0bbfdd1adf898b5db34869  gcc/cobol/genapi.cc
! 797fd59c29555ae478d4d0c1d889e9a7  gcc/cobol/genapi.h
! 711ffde98c30b53bd78b59663250da5e  gcc/cobol/gengen.cc
! e9232e498b04c68faa18eb31fabd8177  gcc/cobol/gengen.h
! c1182aa9280b379f0ba83879a6008ef7  gcc/cobol/genmath.cc
  d44e8c86d57fb704b6c1fbab3464fb9a  gcc/cobol/genmath.h
! 8f32919e6f61718b1db29fb4b9ae2ea1  gcc/cobol/genutil.cc
! 0bf535aa2c65d8348460ace042ee6b79  gcc/cobol/genutil.h
  7b9c1ead6f9d3661133f7f732811719c  gcc/cobol/help.gen
  0fa33dbe050697f40b5e8df91896da9a  gcc/cobol/inspect.h
  2c85ade938027e95c4c411b384f6ad11  gcc/cobol/lang-specs.h
*************** b1416fc94d0a8a3423d9f2c2ef64f366  gcc/co
*** 3313,3334 ****
  746a2d46b3bc2a5f5663a9d64a78a674  gcc/cobol/lang.opt.urls
  7bab28df69a22be2ad0a8d95ec263e2d  gcc/cobol/lexio.cc
  5953c820cdc03feb815bfbf28c10730c  gcc/cobol/lexio.h
! a59fcda8b722bd427628bb728599ed0f  gcc/cobol/parse.y
! 8e70fb10f2723dca6d4fbc88c59c17e6  gcc/cobol/parse_ante.h
  e141e23293fb343e7ccbaa2fe6bcef33  gcc/cobol/parse_util.h
! 5eeacc8bd158cdcb196ef381d1d86228  gcc/cobol/scan.l
! 0ec2003e2d4f21885e4189f9176aedb5  gcc/cobol/scan_ante.h
  20dead6c32b0fb6b826220e76ae691a8  gcc/cobol/scan_post.h
  b1fcf3cab39d3874200f92620f2a54e9  gcc/cobol/show_parse.h
  d75653f25ec3b747265e4ab78aa71521  gcc/cobol/structs.cc
  be06e098e0c2eb8f8ac2f0094bf53181  gcc/cobol/structs.h
! 5562009fa72d960219878c747d360310  gcc/cobol/symbols.cc
! 78c5bb132627990b25338c0fbfd1c3cb  gcc/cobol/symbols.h
  de4928630bb37aa4064841c89cdf22a2  gcc/cobol/symfind.cc
  27218e3639557e7e74246aa4982f089c  gcc/cobol/token_names.h
  434f4899280e27d0717b2e56d5bf12f2  gcc/cobol/udf/stored-char-length.cbl
! cb6f25df1e41a29b4e4391bd6e78f796  gcc/cobol/util.cc
! 650b1815d38e4fe88ba521c41d6e7d8b  gcc/cobol/util.h
  0f3dba102a04da8ca1e45b9b16741bde  gcc/collect-utils.cc
  6e6685d60444844fecf36350b5956f77  gcc/collect-utils.h
  30202062ccc5696f6203f07ab6965763  gcc/collect2-aix.cc
--- 3313,3334 ----
  746a2d46b3bc2a5f5663a9d64a78a674  gcc/cobol/lang.opt.urls
  7bab28df69a22be2ad0a8d95ec263e2d  gcc/cobol/lexio.cc
  5953c820cdc03feb815bfbf28c10730c  gcc/cobol/lexio.h
! 474efac0104ac60ca10e8144f1dec9f5  gcc/cobol/parse.y
! 86fab272aa025f60db4c44ca52316ffe  gcc/cobol/parse_ante.h
  e141e23293fb343e7ccbaa2fe6bcef33  gcc/cobol/parse_util.h
! 5867381ff3c4a77f01b91b925f3e9ce4  gcc/cobol/scan.l
! de93b808ce631b9d18f96b69bcbe4ac8  gcc/cobol/scan_ante.h
  20dead6c32b0fb6b826220e76ae691a8  gcc/cobol/scan_post.h
  b1fcf3cab39d3874200f92620f2a54e9  gcc/cobol/show_parse.h
  d75653f25ec3b747265e4ab78aa71521  gcc/cobol/structs.cc
  be06e098e0c2eb8f8ac2f0094bf53181  gcc/cobol/structs.h
! e5ff9d25c23e0c5fd9a7d82589c83f27  gcc/cobol/symbols.cc
! 7fe837511da66531d20c3897e34bfa13  gcc/cobol/symbols.h
  de4928630bb37aa4064841c89cdf22a2  gcc/cobol/symfind.cc
  27218e3639557e7e74246aa4982f089c  gcc/cobol/token_names.h
  434f4899280e27d0717b2e56d5bf12f2  gcc/cobol/udf/stored-char-length.cbl
! ce38963e7ad5e58b892c971cab3d2628  gcc/cobol/util.cc
! ed3f467605b997678af9e5189497d41b  gcc/cobol/util.h
  0f3dba102a04da8ca1e45b9b16741bde  gcc/collect-utils.cc
  6e6685d60444844fecf36350b5956f77  gcc/collect-utils.h
  30202062ccc5696f6203f07ab6965763  gcc/collect2-aix.cc
*************** f55010fab8b9aabea82c3ac50d031028  gcc/co
*** 3339,3345 ****
  7041e62f0f582b09331732fef4bb9545  gcc/combine-stack-adj.cc
  5d00831740184b5f4f8f133a3a1ffc16  gcc/combine.cc
  2b9ccf7fc2473ef7e36aee9bcf170843  gcc/common.md
! 5edfe7132d50fbb47984aa62ed547535  gcc/common.opt
  0c7e2b88581be53c82638531823fff61  gcc/common.opt.urls
  26050db921f73fd87b026dc950bde97b  gcc/common/common-target-def.h
  dae02ebe59cdaaf21611ad354e939ca5  gcc/common/common-target.def
--- 3339,3345 ----
  7041e62f0f582b09331732fef4bb9545  gcc/combine-stack-adj.cc
  5d00831740184b5f4f8f133a3a1ffc16  gcc/combine.cc
  2b9ccf7fc2473ef7e36aee9bcf170843  gcc/common.md
! f7321dff057cc0da7292ef7eaecbab11  gcc/common.opt
  0c7e2b88581be53c82638531823fff61  gcc/common.opt.urls
  26050db921f73fd87b026dc950bde97b  gcc/common/common-target-def.h
  dae02ebe59cdaaf21611ad354e939ca5  gcc/common/common-target.def
*************** b5a916bb9dd788754ac9e4ad7174ee74  gcc/co
*** 3400,3406 ****
  b209201703dd766f76ff5e16b99191e5  gcc/compare-elim.cc
  618780fbce0ce0cb6f9b86e079ce4e54  gcc/conditions.h
  1b4bc58c657bf910929d06d51bc8fa6c  gcc/config.build
! e4f1e66aa9ced489419e6b820b44b62d  gcc/config.gcc
  053bb14b428d0f073932e88b9a29a8bd  gcc/config.host
  3dc731165a45d3ea42a6ea23586442eb  gcc/config.in
  8e697813dc96ca90f5d0f4c196efe2cc  gcc/config/README
--- 3400,3406 ----
  b209201703dd766f76ff5e16b99191e5  gcc/compare-elim.cc
  618780fbce0ce0cb6f9b86e079ce4e54  gcc/conditions.h
  1b4bc58c657bf910929d06d51bc8fa6c  gcc/config.build
! 2c153077a63a333c3c28eb48406d6e4d  gcc/config.gcc
  053bb14b428d0f073932e88b9a29a8bd  gcc/config.host
  3dc731165a45d3ea42a6ea23586442eb  gcc/config.in
  8e697813dc96ca90f5d0f4c196efe2cc  gcc/config/README
*************** d1e3bcda28d89d23e45fed74c629752a  gcc/co
*** 3413,3419 ****
  ba4e797220b33827e769b09447623896  gcc/config/aarch64/aarch64-cc-fusion.cc
  133f61af7e288fe91ca31c659939c551  gcc/config/aarch64/aarch64-coff.h
  61a6ea51f727c8e7a93590b1a91c29fa  gcc/config/aarch64/aarch64-cores.def
! f0a8397b1e293e23f65674cd004845ae  gcc/config/aarch64/aarch64-cost-tables.h
  bef2a61270424fd606c71d78d20ad675  gcc/config/aarch64/aarch64-d.cc
  36405b6300d5ec6ca8faf17212ad1bc9  gcc/config/aarch64/aarch64-d.h
  d75100bc2f054afcf41a992cdaa5f793  gcc/config/aarch64/aarch64-early-ra.cc
--- 3413,3419 ----
  ba4e797220b33827e769b09447623896  gcc/config/aarch64/aarch64-cc-fusion.cc
  133f61af7e288fe91ca31c659939c551  gcc/config/aarch64/aarch64-coff.h
  61a6ea51f727c8e7a93590b1a91c29fa  gcc/config/aarch64/aarch64-cores.def
! 85b8b0267c641b7fb638fffcb3016739  gcc/config/aarch64/aarch64-cost-tables.h
  bef2a61270424fd606c71d78d20ad675  gcc/config/aarch64/aarch64-d.cc
  36405b6300d5ec6ca8faf17212ad1bc9  gcc/config/aarch64/aarch64-d.h
  d75100bc2f054afcf41a992cdaa5f793  gcc/config/aarch64/aarch64-early-ra.cc
*************** b9530750d10c463842868c73aee2e94e  gcc/co
*** 3440,3446 ****
  7cfa3d0cdd28cdcd73a29c2c8a925548  gcc/config/aarch64/aarch64-simd-builtin-types.def
  8f28d55d0c7fc64387352822e99a37ff  gcc/config/aarch64/aarch64-simd-builtins.def
  33ce4a896b77324d9be6448637daf9ca  gcc/config/aarch64/aarch64-simd-pragma-builtins.def
! d6df560098f137d6be5bc95202b64cab  gcc/config/aarch64/aarch64-simd.md
  fc7e762346daa959b84d01220d563f16  gcc/config/aarch64/aarch64-sme.md
  fa6672290fdf9366d9919defcb7e41d7  gcc/config/aarch64/aarch64-speculation.cc
  9ab182bab4cc10bb9676b1309abb562f  gcc/config/aarch64/aarch64-sve-builtins-base.cc
--- 3440,3446 ----
  7cfa3d0cdd28cdcd73a29c2c8a925548  gcc/config/aarch64/aarch64-simd-builtin-types.def
  8f28d55d0c7fc64387352822e99a37ff  gcc/config/aarch64/aarch64-simd-builtins.def
  33ce4a896b77324d9be6448637daf9ca  gcc/config/aarch64/aarch64-simd-pragma-builtins.def
! 7548b5fd45bc2e7a87bf4a23ca02ab1f  gcc/config/aarch64/aarch64-simd.md
  fc7e762346daa959b84d01220d563f16  gcc/config/aarch64/aarch64-sme.md
  fa6672290fdf9366d9919defcb7e41d7  gcc/config/aarch64/aarch64-speculation.cc
  9ab182bab4cc10bb9676b1309abb562f  gcc/config/aarch64/aarch64-sve-builtins-base.cc
*************** e2d80b89552da0c6b4cb6bede3b2e573  gcc/co
*** 3458,3470 ****
  354a32b5af602553358eb32a9ac919a5  gcc/config/aarch64/aarch64-sve-builtins.cc
  30d08305d5bc784af521254aea449949  gcc/config/aarch64/aarch64-sve-builtins.def
  5ef25fd86c1c16a4a6fb3f74e12802b4  gcc/config/aarch64/aarch64-sve-builtins.h
! 143e32a20616a6134f9c7235d570aca8  gcc/config/aarch64/aarch64-sve.md
! e7bba7b6ccb3d6036da76c51d54fc69d  gcc/config/aarch64/aarch64-sve2.md
  85eca95263cb099f09b18daca655f091  gcc/config/aarch64/aarch64-sys-regs.def
  b301dc231a69a28202d2b7d79ea75f5d  gcc/config/aarch64/aarch64-tune.md
  d10a350a80f8f12ee435c64d236e2767  gcc/config/aarch64/aarch64-tuning-flags.def
  a5cfcce7c9dd86a597161f8bde3497bc  gcc/config/aarch64/aarch64-vxworks.h
! 2b2e49b31680777e0918acad4f97d36b  gcc/config/aarch64/aarch64.cc
  97fd54a20ac88d76171e744940efd8ba  gcc/config/aarch64/aarch64.h
  58defab70a0bc4fb2f3fb6d61eee40d7  gcc/config/aarch64/aarch64.md
  ae13780a8296e9c52f9e9b8cd95dc312  gcc/config/aarch64/aarch64.opt
--- 3458,3470 ----
  354a32b5af602553358eb32a9ac919a5  gcc/config/aarch64/aarch64-sve-builtins.cc
  30d08305d5bc784af521254aea449949  gcc/config/aarch64/aarch64-sve-builtins.def
  5ef25fd86c1c16a4a6fb3f74e12802b4  gcc/config/aarch64/aarch64-sve-builtins.h
! ae297e5417604b5dc9f6cc89eeaf66ab  gcc/config/aarch64/aarch64-sve.md
! f2b95a40ce1d1fd85b5a5d0b5dfad86e  gcc/config/aarch64/aarch64-sve2.md
  85eca95263cb099f09b18daca655f091  gcc/config/aarch64/aarch64-sys-regs.def
  b301dc231a69a28202d2b7d79ea75f5d  gcc/config/aarch64/aarch64-tune.md
  d10a350a80f8f12ee435c64d236e2767  gcc/config/aarch64/aarch64-tuning-flags.def
  a5cfcce7c9dd86a597161f8bde3497bc  gcc/config/aarch64/aarch64-vxworks.h
! 6260273b976d97406be6b81e8e2cfd36  gcc/config/aarch64/aarch64.cc
  97fd54a20ac88d76171e744940efd8ba  gcc/config/aarch64/aarch64.h
  58defab70a0bc4fb2f3fb6d61eee40d7  gcc/config/aarch64/aarch64.md
  ae13780a8296e9c52f9e9b8cd95dc312  gcc/config/aarch64/aarch64.opt
*************** c61b39c4504a36e5c45cd1e3b64723d7  gcc/co
*** 3483,3489 ****
  ae88170d2d567105865813bb4b77d91f  gcc/config/aarch64/biarchlp64.h
  124d7f2adedfdccecd86bb0274dfc7aa  gcc/config/aarch64/check-sve-md.awk
  3268556a1b779072abfdf2537453d7ac  gcc/config/aarch64/constraints.md
! d98f001d9d7b4c0bc18d715b4d512ab9  gcc/config/aarch64/cortex-a57-fma-steering.cc
  034ef57fb17f601ded123d7a43b51d02  gcc/config/aarch64/cygming.h
  13b725f057e939c7ebe5bd19da1df7ee  gcc/config/aarch64/driver-aarch64.cc
  f713d33fdaee532813b56547dd070c8c  gcc/config/aarch64/fractional-cost.h
--- 3483,3489 ----
  ae88170d2d567105865813bb4b77d91f  gcc/config/aarch64/biarchlp64.h
  124d7f2adedfdccecd86bb0274dfc7aa  gcc/config/aarch64/check-sve-md.awk
  3268556a1b779072abfdf2537453d7ac  gcc/config/aarch64/constraints.md
! dd76583202434d2161c8668396b95079  gcc/config/aarch64/cortex-a57-fma-steering.cc
  034ef57fb17f601ded123d7a43b51d02  gcc/config/aarch64/cygming.h
  13b725f057e939c7ebe5bd19da1df7ee  gcc/config/aarch64/driver-aarch64.cc
  f713d33fdaee532813b56547dd070c8c  gcc/config/aarch64/fractional-cost.h
*************** f7165d62ef852e1929a8fc9a85c01ab2  gcc/co
*** 3491,3497 ****
  dfcdbda4a3bb64a86fdf64ce6fce0ae3  gcc/config/aarch64/geniterators.sh
  bc3b4ebfac8bfd42d3e9098f33585afd  gcc/config/aarch64/gentune.sh
  86eaf33edeb885c2c9ae2a9825879e59  gcc/config/aarch64/host-aarch64-darwin.cc
! bb7dbe9f4cd4dd2740fc9ba67fc369d7  gcc/config/aarch64/iterators.md
  a1fcb0b7e687756c781537faf6a229b9  gcc/config/aarch64/predicates.md
  a4e902ee1494ba5eee811ea46ecdf995  gcc/config/aarch64/rtems.h
  311b65ba9e415ee9bec122a44389ec72  gcc/config/aarch64/t-aarch64
--- 3491,3497 ----
  dfcdbda4a3bb64a86fdf64ce6fce0ae3  gcc/config/aarch64/geniterators.sh
  bc3b4ebfac8bfd42d3e9098f33585afd  gcc/config/aarch64/gentune.sh
  86eaf33edeb885c2c9ae2a9825879e59  gcc/config/aarch64/host-aarch64-darwin.cc
! a305511a7acc73201c8c7ce521e52136  gcc/config/aarch64/iterators.md
  a1fcb0b7e687756c781537faf6a229b9  gcc/config/aarch64/predicates.md
  a4e902ee1494ba5eee811ea46ecdf995  gcc/config/aarch64/rtems.h
  311b65ba9e415ee9bec122a44389ec72  gcc/config/aarch64/t-aarch64
*************** c6495aa81de32f973141a776003c7fec  gcc/co
*** 3609,3615 ****
  2a910650029579bceccf08fc2394245b  gcc/config/arm/aarch-common-protos.h
  4642b68ce62d734c7e0791f174de8467  gcc/config/arm/aarch-common.cc
  f9afd2ef855bfd549493f6da71fd93b7  gcc/config/arm/aarch-common.h
! 0fcc6a97fcf14fe1517964a09016261f  gcc/config/arm/aarch-cost-tables.h
  cbe08e188cf39566da9323f36b3f6171  gcc/config/arm/aout.h
  21ce8fc8466aee09b6bf705a93ef374a  gcc/config/arm/arm-builtins.cc
  9dd7793ad1cabff379e14aed638e7920  gcc/config/arm/arm-builtins.h
--- 3609,3615 ----
  2a910650029579bceccf08fc2394245b  gcc/config/arm/aarch-common-protos.h
  4642b68ce62d734c7e0791f174de8467  gcc/config/arm/aarch-common.cc
  f9afd2ef855bfd549493f6da71fd93b7  gcc/config/arm/aarch-common.h
! 7fce9ff8e59611a1c7f9d0b0855271c1  gcc/config/arm/aarch-cost-tables.h
  cbe08e188cf39566da9323f36b3f6171  gcc/config/arm/aout.h
  21ce8fc8466aee09b6bf705a93ef374a  gcc/config/arm/arm-builtins.cc
  9dd7793ad1cabff379e14aed638e7920  gcc/config/arm/arm-builtins.h
*************** eafc8a2abc331243ea846fab22b8aec4  gcc/co
*** 3639,3645 ****
  5d895a88bb2048a83e3ccc08d50f3151  gcc/config/arm/arm-tables.opt
  f805d118929dd79f6bd4dc75c77c968b  gcc/config/arm/arm-tables.opt.urls
  1f1a55560eb97e283125003609418bce  gcc/config/arm/arm-tune.md
! 4f974ae26108aba9f8f5367a47c54969  gcc/config/arm/arm.cc
  4b4c240869c2413c542f051e20fc26d1  gcc/config/arm/arm.h
  5f7e052e197e5f93418cf111af042afe  gcc/config/arm/arm.md
  6438602120f5212434b003b5018064ec  gcc/config/arm/arm.opt
--- 3639,3645 ----
  5d895a88bb2048a83e3ccc08d50f3151  gcc/config/arm/arm-tables.opt
  f805d118929dd79f6bd4dc75c77c968b  gcc/config/arm/arm-tables.opt.urls
  1f1a55560eb97e283125003609418bce  gcc/config/arm/arm-tune.md
! c1881e55e466689b125a3029d6086ba0  gcc/config/arm/arm.cc
  4b4c240869c2413c542f051e20fc26d1  gcc/config/arm/arm.h
  5f7e052e197e5f93418cf111af042afe  gcc/config/arm/arm.md
  6438602120f5212434b003b5018064ec  gcc/config/arm/arm.opt
*************** aa43c35c0ae5db419161044c2dd507a8  gcc/co
*** 3840,3846 ****
  c8b88ac6c665fd095189745df437cf09  gcc/config/cris/cris-modes.def
  9e4259629bc50331463e6d4b3dd2abcd  gcc/config/cris/cris-passes.def
  8df4296499456e2e0541e3686a4574e2  gcc/config/cris/cris-protos.h
! 8f05959de1ffa7f1fc927c231870ba88  gcc/config/cris/cris.cc
  6e63163a3a0583da3f0cde44fbd537c1  gcc/config/cris/cris.h
  51de895e261d869e46e1c2e2179f2294  gcc/config/cris/cris.md
  0dc2ffb20f6fe00475b86380239022e5  gcc/config/cris/cris.opt
--- 3840,3846 ----
  c8b88ac6c665fd095189745df437cf09  gcc/config/cris/cris-modes.def
  9e4259629bc50331463e6d4b3dd2abcd  gcc/config/cris/cris-passes.def
  8df4296499456e2e0541e3686a4574e2  gcc/config/cris/cris-protos.h
! 98c06ee9fc7b0554c6a37fba5252298d  gcc/config/cris/cris.cc
  6e63163a3a0583da3f0cde44fbd537c1  gcc/config/cris/cris.h
  51de895e261d869e46e1c2e2179f2294  gcc/config/cris/cris.md
  0dc2ffb20f6fe00475b86380239022e5  gcc/config/cris/cris.opt
*************** f01fb2b02fd44587cfacf67b0f42dcd0  gcc/co
*** 3906,3912 ****
  e45ad8462e6bd37fd5391b27ae4a226f  gcc/config/epiphany/epiphany-modes.def
  a68316e51382508b2d562a6afe5cb729  gcc/config/epiphany/epiphany-protos.h
  3b8b97ef25d50a778883ba2a5364c4eb  gcc/config/epiphany/epiphany-sched.md
! f63bc078b4d43bf4838b3a7eb5bac4a8  gcc/config/epiphany/epiphany.cc
  7dfe2cb93a23891c028a120b29585014  gcc/config/epiphany/epiphany.h
  ad8db21c57cea738b7569b3a397f7034  gcc/config/epiphany/epiphany.md
  0593a72b45a7325ddee9ca1e5a6887ac  gcc/config/epiphany/epiphany.opt
--- 3906,3912 ----
  e45ad8462e6bd37fd5391b27ae4a226f  gcc/config/epiphany/epiphany-modes.def
  a68316e51382508b2d562a6afe5cb729  gcc/config/epiphany/epiphany-protos.h
  3b8b97ef25d50a778883ba2a5364c4eb  gcc/config/epiphany/epiphany-sched.md
! 68dc94055ccfb70c7b1cbdc0b4718cf1  gcc/config/epiphany/epiphany.cc
  7dfe2cb93a23891c028a120b29585014  gcc/config/epiphany/epiphany.h
  ad8db21c57cea738b7569b3a397f7034  gcc/config/epiphany/epiphany.md
  0593a72b45a7325ddee9ca1e5a6887ac  gcc/config/epiphany/epiphany.opt
*************** e89c0c1a7b28f107b53b364765ee06a9  gcc/co
*** 3968,3983 ****
  f562bceab670643f983022c708caa29c  gcc/config/gcn/gcn-devices.def
  ff3ae1701a0dc72a48dd18a907796d2e  gcc/config/gcn/gcn-hsa.h
  491ab7557adb9ed61fba81e4f5b96dc2  gcc/config/gcn/gcn-modes.def
! 6dc006161b26192d57c73a8d136a24a2  gcc/config/gcn/gcn-opts.h
  b395ed990d9e6d7c2698fdd602685d3f  gcc/config/gcn/gcn-protos.h
  96a52bdb8005bdd8f36552a27a7234d2  gcc/config/gcn/gcn-run.cc
  1dbed4e12cf62ae67464d874f1e2e9e8  gcc/config/gcn/gcn-tables.opt
  ca8c1935ac88d760dc3a5b7e97558f28  gcc/config/gcn/gcn-tables.opt.urls
  23106fa0b82354400a9c82b82a9af33a  gcc/config/gcn/gcn-tree.cc
! 8526d591a0b868940b1ab7518d7b9b0a  gcc/config/gcn/gcn-valu.md
! 26fdf7c4c4217a569734143da4dd7b9c  gcc/config/gcn/gcn.cc
  686d66a24f66638a6a8dc76ddae3acb6  gcc/config/gcn/gcn.h
! b096110f77173b29d83d00101d0c18c0  gcc/config/gcn/gcn.md
  ea362cc71f1b9679e105d57822167b51  gcc/config/gcn/gcn.opt
  6c96a5ccd826ec5a9ddf7ffe7fda572d  gcc/config/gcn/gcn.opt.urls
  6d70e3b6694d21aaf0fc6f1764858c4e  gcc/config/gcn/gen-gcn-device-macros.awk
--- 3968,3983 ----
  f562bceab670643f983022c708caa29c  gcc/config/gcn/gcn-devices.def
  ff3ae1701a0dc72a48dd18a907796d2e  gcc/config/gcn/gcn-hsa.h
  491ab7557adb9ed61fba81e4f5b96dc2  gcc/config/gcn/gcn-modes.def
! d17ad063136b02710bbc816efc0af809  gcc/config/gcn/gcn-opts.h
  b395ed990d9e6d7c2698fdd602685d3f  gcc/config/gcn/gcn-protos.h
  96a52bdb8005bdd8f36552a27a7234d2  gcc/config/gcn/gcn-run.cc
  1dbed4e12cf62ae67464d874f1e2e9e8  gcc/config/gcn/gcn-tables.opt
  ca8c1935ac88d760dc3a5b7e97558f28  gcc/config/gcn/gcn-tables.opt.urls
  23106fa0b82354400a9c82b82a9af33a  gcc/config/gcn/gcn-tree.cc
! 4bb4aa145755d23d847645668f4e572f  gcc/config/gcn/gcn-valu.md
! 8be9db985566399a2891ebaa0f3d5d13  gcc/config/gcn/gcn.cc
  686d66a24f66638a6a8dc76ddae3acb6  gcc/config/gcn/gcn.h
! 2772825343eb51158c80a6aa553a710e  gcc/config/gcn/gcn.md
  ea362cc71f1b9679e105d57822167b51  gcc/config/gcn/gcn.opt
  6c96a5ccd826ec5a9ddf7ffe7fda572d  gcc/config/gcn/gcn.opt.urls
  6d70e3b6694d21aaf0fc6f1764858c4e  gcc/config/gcn/gen-gcn-device-macros.awk
*************** c9c3969c00808c9b6809fbeab3e4a1d2  gcc/co
*** 4168,4174 ****
  1ee34fa5f2ae92fd7d48419d8fc529f8  gcc/config/i386/i386-features.h
  66732512f01bad0bbb26cb3c09ec773e  gcc/config/i386/i386-isa.def
  795643c7d23acf02568d7fa7acad0138  gcc/config/i386/i386-modes.def
! f8083b4b3cf6d8f73bc085f936b3be32  gcc/config/i386/i386-options.cc
  08c877d750ab52ddb4fe7c99c90d62de  gcc/config/i386/i386-options.h
  02c486451c524cfc143358e07b88cd70  gcc/config/i386/i386-opts.h
  2b4efb0edf861dd06ddc1445aa9e4d05  gcc/config/i386/i386-passes.def
--- 4168,4174 ----
  1ee34fa5f2ae92fd7d48419d8fc529f8  gcc/config/i386/i386-features.h
  66732512f01bad0bbb26cb3c09ec773e  gcc/config/i386/i386-isa.def
  795643c7d23acf02568d7fa7acad0138  gcc/config/i386/i386-modes.def
! 4440623fe3ebd9fbb0e7293b77c09c08  gcc/config/i386/i386-options.cc
  08c877d750ab52ddb4fe7c99c90d62de  gcc/config/i386/i386-options.h
  02c486451c524cfc143358e07b88cd70  gcc/config/i386/i386-opts.h
  2b4efb0edf861dd06ddc1445aa9e4d05  gcc/config/i386/i386-passes.def
*************** f8083b4b3cf6d8f73bc085f936b3be32  gcc/co
*** 4176,4182 ****
  5b778b3296ea91dab0ca82338ca6828d  gcc/config/i386/i386-rust-and-jit.inc
  b19c27e8a900f9eeb7d73e2bb4b8d313  gcc/config/i386/i386-rust.cc
  24065393854cd1e08e3285bd707210fe  gcc/config/i386/i386-rust.h
! b2d7a660073ce41a81e57a76b110bb94  gcc/config/i386/i386.cc
  9b20906d8a7d93f706d1a2e855678ee6  gcc/config/i386/i386.h
  e9893adb04e24870dacd693fd5ceccd7  gcc/config/i386/i386.md
  23985b411cb15228b631691265bfefe9  gcc/config/i386/i386.opt
--- 4176,4182 ----
  5b778b3296ea91dab0ca82338ca6828d  gcc/config/i386/i386-rust-and-jit.inc
  b19c27e8a900f9eeb7d73e2bb4b8d313  gcc/config/i386/i386-rust.cc
  24065393854cd1e08e3285bd707210fe  gcc/config/i386/i386-rust.h
! f17d9539984d4f71551bc1d4a46c96da  gcc/config/i386/i386.cc
  9b20906d8a7d93f706d1a2e855678ee6  gcc/config/i386/i386.h
  e9893adb04e24870dacd693fd5ceccd7  gcc/config/i386/i386.md
  23985b411cb15228b631691265bfefe9  gcc/config/i386/i386.opt
*************** d3ad067b1fa15bbce42fd3cc4499966e  gcc/co
*** 4412,4418 ****
  688cd325dbeb853413435f029e712cb2  gcc/config/loongarch/loongarch-str.h
  a8cd9a4a3d712802475e91e0ec9a3274  gcc/config/loongarch/loongarch-target-attr.cc
  f539c2da7e8d7a3ef7c741bceee19eed  gcc/config/loongarch/loongarch-tune.h
! f2b6b17d293c2846dbd52d3f5bc183ad  gcc/config/loongarch/loongarch.cc
  cac7a4f19361731647870d2210078a9e  gcc/config/loongarch/loongarch.h
  9fd9109f20f7dfce6de910d45b5dbc85  gcc/config/loongarch/loongarch.md
  bcc951e237d5501fc2acd6ef3141724c  gcc/config/loongarch/loongarch.opt
--- 4412,4418 ----
  688cd325dbeb853413435f029e712cb2  gcc/config/loongarch/loongarch-str.h
  a8cd9a4a3d712802475e91e0ec9a3274  gcc/config/loongarch/loongarch-target-attr.cc
  f539c2da7e8d7a3ef7c741bceee19eed  gcc/config/loongarch/loongarch-tune.h
! 11b1dedb8e3d146dffb6d66df3b61d18  gcc/config/loongarch/loongarch.cc
  cac7a4f19361731647870d2210078a9e  gcc/config/loongarch/loongarch.h
  9fd9109f20f7dfce6de910d45b5dbc85  gcc/config/loongarch/loongarch.md
  bcc951e237d5501fc2acd6ef3141724c  gcc/config/loongarch/loongarch.opt
*************** d6da8f84e5835bd14f146fc765bcb39d  gcc/co
*** 4873,4880 ****
  cd13b51383c99c08d86250b61fed3805  gcc/config/pru/pru.opt.urls
  540013c309ceb3efb2b16d728b1fc726  gcc/config/pru/t-pru
  a5e691ce14017f2a89283ed510bb78fd  gcc/config/riscv/arch-canonicalize
! c03a1f1227d66da08f83d94c7f02c13b  gcc/config/riscv/autovec-opt.md
! 35b924fc992b99e8ad4ffbdac1e256a3  gcc/config/riscv/autovec.md
  40e0e0684e3c3a934587129211c4674c  gcc/config/riscv/bitmanip.md
  79131f969561dadd487936a1bffbb846  gcc/config/riscv/constraints.md
  4e0968dc35562b151fd162778542718f  gcc/config/riscv/corev.def
--- 4873,4880 ----
  cd13b51383c99c08d86250b61fed3805  gcc/config/pru/pru.opt.urls
  540013c309ceb3efb2b16d728b1fc726  gcc/config/pru/t-pru
  a5e691ce14017f2a89283ed510bb78fd  gcc/config/riscv/arch-canonicalize
! 0673612816114db21fa7d56be315a067  gcc/config/riscv/autovec-opt.md
! 0a8d3bb5c92b40519d869bae882cf263  gcc/config/riscv/autovec.md
  40e0e0684e3c3a934587129211c4674c  gcc/config/riscv/bitmanip.md
  79131f969561dadd487936a1bffbb846  gcc/config/riscv/constraints.md
  4e0968dc35562b151fd162778542718f  gcc/config/riscv/corev.def
*************** a8964e5c7fad78fa42fc5b8f0dc2e91b  gcc/co
*** 4885,4903 ****
  8b83b20385b0cc79dbd5378c1df1bb6a  gcc/config/riscv/gen-riscv-ext-opt.cc
  d88ea862a5be7784a17a698cc6a7c5e5  gcc/config/riscv/gen-riscv-ext-texi.cc
  fdf40414be0404faa2f689ccff02d68d  gcc/config/riscv/generic-ooo.md
! a124ceec225b4a292b25b31a9a635a5e  gcc/config/riscv/generic-vector-ooo.md
  b7e955ddfed9efbb0296ef639c095e2a  gcc/config/riscv/generic.md
  d8e970a7377ae8ee7892f014d5bbc979  gcc/config/riscv/genrvv-type-indexer.cc
  473ed80ccf8dc1ff43e427a45cca3a1e  gcc/config/riscv/gnu.h
  4e30eb4d51786f677ce1c181647193e1  gcc/config/riscv/iterators.md
  85139511ec0cad0144207dc8efc0ed90  gcc/config/riscv/linux.h
  648db331f8cdbd06edc3e19c6dd794b3  gcc/config/riscv/mips-insn.md
! 22c4239b709147e20546aaa492483d43  gcc/config/riscv/mips-p8700.md
  52728cfca05017f727570e4e983fc5fa  gcc/config/riscv/multilib-generator
  80e8994ee9e6abf380e68aca6443d157  gcc/config/riscv/peephole.md
  a3d3fa9142d4e2ed34ead146941c574a  gcc/config/riscv/pic.md
  674baa66306b2b08e1b80995759f5381  gcc/config/riscv/pipeline-checker
! f53e4614284e23bd7db6c2ad74b52c12  gcc/config/riscv/predicates.md
  c10bfd4598b8e2176b92031831f3b341  gcc/config/riscv/riscv-avlprop.cc
  3b5651b95f6a076ccd28e73bae600e52  gcc/config/riscv/riscv-builtins.cc
  717dabcf24d5f1356542a7716b96af87  gcc/config/riscv/riscv-c.cc
--- 4885,4903 ----
  8b83b20385b0cc79dbd5378c1df1bb6a  gcc/config/riscv/gen-riscv-ext-opt.cc
  d88ea862a5be7784a17a698cc6a7c5e5  gcc/config/riscv/gen-riscv-ext-texi.cc
  fdf40414be0404faa2f689ccff02d68d  gcc/config/riscv/generic-ooo.md
! 6870f06708152b8c85e3a3c045a0407a  gcc/config/riscv/generic-vector-ooo.md
  b7e955ddfed9efbb0296ef639c095e2a  gcc/config/riscv/generic.md
  d8e970a7377ae8ee7892f014d5bbc979  gcc/config/riscv/genrvv-type-indexer.cc
  473ed80ccf8dc1ff43e427a45cca3a1e  gcc/config/riscv/gnu.h
  4e30eb4d51786f677ce1c181647193e1  gcc/config/riscv/iterators.md
  85139511ec0cad0144207dc8efc0ed90  gcc/config/riscv/linux.h
  648db331f8cdbd06edc3e19c6dd794b3  gcc/config/riscv/mips-insn.md
! bffa0caedd7144aff55c80a16431d1a1  gcc/config/riscv/mips-p8700.md
  52728cfca05017f727570e4e983fc5fa  gcc/config/riscv/multilib-generator
  80e8994ee9e6abf380e68aca6443d157  gcc/config/riscv/peephole.md
  a3d3fa9142d4e2ed34ead146941c574a  gcc/config/riscv/pic.md
  674baa66306b2b08e1b80995759f5381  gcc/config/riscv/pipeline-checker
! 8aa1f691325236757736c781f4f49d8a  gcc/config/riscv/predicates.md
  c10bfd4598b8e2176b92031831f3b341  gcc/config/riscv/riscv-avlprop.cc
  3b5651b95f6a076ccd28e73bae600e52  gcc/config/riscv/riscv-builtins.cc
  717dabcf24d5f1356542a7716b96af87  gcc/config/riscv/riscv-c.cc
*************** c10bfd4598b8e2176b92031831f3b341  gcc/co
*** 4910,4916 ****
  a8a293d3f8f01367abc68e7556a51898  gcc/config/riscv/riscv-ext-sifive.def
  85fb34f0d0de09dc83b4df6f525d78f9  gcc/config/riscv/riscv-ext-thead.def
  5551f756c3aae6dce60511f7f52efa5c  gcc/config/riscv/riscv-ext-ventana.def
! ad20aa730e465a3cde222b04291e4e54  gcc/config/riscv/riscv-ext.def
  3adf32d34a1bba8b56650a8b8b73c28a  gcc/config/riscv/riscv-ext.opt
  8463b74f5d66e1a7f0d58a7ae087d8ad  gcc/config/riscv/riscv-ext.opt.urls
  1b0b6b632f747d9387ef25821e8673b4  gcc/config/riscv/riscv-feature-bits.h
--- 4910,4916 ----
  a8a293d3f8f01367abc68e7556a51898  gcc/config/riscv/riscv-ext-sifive.def
  85fb34f0d0de09dc83b4df6f525d78f9  gcc/config/riscv/riscv-ext-thead.def
  5551f756c3aae6dce60511f7f52efa5c  gcc/config/riscv/riscv-ext-ventana.def
! 7cdd94b1055d8a23c33054988d58c836  gcc/config/riscv/riscv-ext.def
  3adf32d34a1bba8b56650a8b8b73c28a  gcc/config/riscv/riscv-ext.opt
  8463b74f5d66e1a7f0d58a7ae087d8ad  gcc/config/riscv/riscv-ext.opt.urls
  1b0b6b632f747d9387ef25821e8673b4  gcc/config/riscv/riscv-feature-bits.h
*************** b467d35485b39b25863e918609a322d0  gcc/co
*** 4918,4952 ****
  b1bc6d82a24b7b0e658a43956a37419c  gcc/config/riscv/riscv-modes.def
  7631415b148bf332623531ebb3e0262b  gcc/config/riscv/riscv-opts.h
  2c59654f5f7fe2689efd370c0441b6bd  gcc/config/riscv/riscv-passes.def
! 2e6904a840f311ea0fa5c0b003d03e87  gcc/config/riscv/riscv-protos.h
  446f0f39c6f980e246ea56f1233e9271  gcc/config/riscv/riscv-scalar-crypto.def
  7a88fbbf6ce3f23037c77808a5e294f7  gcc/config/riscv/riscv-selftests.cc
  da4e034d23a8f2754b1dfce0122f286e  gcc/config/riscv/riscv-shorten-memrefs.cc
  62b31689063eeeca8f0e7ae25da92d0a  gcc/config/riscv/riscv-sr.cc
! 5934e743da72bdc74e1d53f049b127fc  gcc/config/riscv/riscv-string.cc
  b0db0a336461a6390b254a883b8b491a  gcc/config/riscv/riscv-subset.h
  be3e0da2403121c429e21501de9c9b5f  gcc/config/riscv/riscv-target-attr.cc
! 217cf67491666f02f7a66fb64206ceea  gcc/config/riscv/riscv-v.cc
  0d419e9df116fed7ce6e0ae15131417e  gcc/config/riscv/riscv-v.h
  c5f3161dedd668dfb126ffb191cfb236  gcc/config/riscv/riscv-vect-permconst.cc
! 8bb68ed754e01cc6cbd31b250968d7f6  gcc/config/riscv/riscv-vector-builtins-bases.cc
  689f453a4cdf7fa3e64a7f4bfba8f7dd  gcc/config/riscv/riscv-vector-builtins-bases.h
  bdc5f6caf56fd0411faf705e9c32ccd4  gcc/config/riscv/riscv-vector-builtins-functions.def
  1a84bfaa3f89d99edacd5d2eb1444186  gcc/config/riscv/riscv-vector-builtins-shapes.cc
  7e178dc137007d4ca1aaaaf29940c12f  gcc/config/riscv/riscv-vector-builtins-shapes.h
  83165bddb05b2721bc426bd1fe3ec4c0  gcc/config/riscv/riscv-vector-builtins-types.def
! c7f56884d80a411d921f1c7add273f23  gcc/config/riscv/riscv-vector-builtins.cc
  74c291180c302842c646af24c77d184c  gcc/config/riscv/riscv-vector-builtins.def
! 9b7d99df8e2f12e55ad2fce0020b462c  gcc/config/riscv/riscv-vector-builtins.h
! 147ceeb3518a43458ebef3a69344fc3f  gcc/config/riscv/riscv-vector-costs.cc
! bd7a0d0d03ad4788f6cf7579df11a66e  gcc/config/riscv/riscv-vector-costs.h
  f51037a9e437f8e9ce7215b2da5ad4e2  gcc/config/riscv/riscv-vector-switch.def
  5a1dc434073ed565843a91456f836a9a  gcc/config/riscv/riscv-vsetvl.cc
  d120ed6eb2847b636271b3a1ef82ecbf  gcc/config/riscv/riscv-vsetvl.def
  7082a18dbfc574d47bf71f4d50dd30f9  gcc/config/riscv/riscv-zicfilp.cc
! 3ffec5ec709f63f0cfccf3f2cc9f1fab  gcc/config/riscv/riscv.cc
  1e6d5c3cff4825c434ac203d43f0b5ab  gcc/config/riscv/riscv.h
! 9adedbc98e06d788506dd97118766bec  gcc/config/riscv/riscv.md
  fec1c87bba727131a45d4ec4a9ae5490  gcc/config/riscv/riscv.opt
  d1d34490d8b53ec20d70ed9e2e56e3ab  gcc/config/riscv/riscv.opt.urls
  374e3c204946cff8c4be2bcad6641830  gcc/config/riscv/riscv_bitmanip.h
--- 4918,4952 ----
  b1bc6d82a24b7b0e658a43956a37419c  gcc/config/riscv/riscv-modes.def
  7631415b148bf332623531ebb3e0262b  gcc/config/riscv/riscv-opts.h
  2c59654f5f7fe2689efd370c0441b6bd  gcc/config/riscv/riscv-passes.def
! 1cd12da5e0a57f1dd467452d0faa27e6  gcc/config/riscv/riscv-protos.h
  446f0f39c6f980e246ea56f1233e9271  gcc/config/riscv/riscv-scalar-crypto.def
  7a88fbbf6ce3f23037c77808a5e294f7  gcc/config/riscv/riscv-selftests.cc
  da4e034d23a8f2754b1dfce0122f286e  gcc/config/riscv/riscv-shorten-memrefs.cc
  62b31689063eeeca8f0e7ae25da92d0a  gcc/config/riscv/riscv-sr.cc
! f565a42da3474d73faf1ea727e2d7dcb  gcc/config/riscv/riscv-string.cc
  b0db0a336461a6390b254a883b8b491a  gcc/config/riscv/riscv-subset.h
  be3e0da2403121c429e21501de9c9b5f  gcc/config/riscv/riscv-target-attr.cc
! 5a45cb608fcdf80d04d79cfa3530f044  gcc/config/riscv/riscv-v.cc
  0d419e9df116fed7ce6e0ae15131417e  gcc/config/riscv/riscv-v.h
  c5f3161dedd668dfb126ffb191cfb236  gcc/config/riscv/riscv-vect-permconst.cc
! 1d781df8fdb7dc0f6e332b3fe767ad85  gcc/config/riscv/riscv-vector-builtins-bases.cc
  689f453a4cdf7fa3e64a7f4bfba8f7dd  gcc/config/riscv/riscv-vector-builtins-bases.h
  bdc5f6caf56fd0411faf705e9c32ccd4  gcc/config/riscv/riscv-vector-builtins-functions.def
  1a84bfaa3f89d99edacd5d2eb1444186  gcc/config/riscv/riscv-vector-builtins-shapes.cc
  7e178dc137007d4ca1aaaaf29940c12f  gcc/config/riscv/riscv-vector-builtins-shapes.h
  83165bddb05b2721bc426bd1fe3ec4c0  gcc/config/riscv/riscv-vector-builtins-types.def
! ff674aa0b74174665ea5acf67b875d64  gcc/config/riscv/riscv-vector-builtins.cc
  74c291180c302842c646af24c77d184c  gcc/config/riscv/riscv-vector-builtins.def
! ed801cb8cef5db332d83dd226bad1510  gcc/config/riscv/riscv-vector-builtins.h
! e55be9657c13d60ca65e90cc7bb82c5d  gcc/config/riscv/riscv-vector-costs.cc
! 2a441fb15ed4d774924fe163f29ccf7a  gcc/config/riscv/riscv-vector-costs.h
  f51037a9e437f8e9ce7215b2da5ad4e2  gcc/config/riscv/riscv-vector-switch.def
  5a1dc434073ed565843a91456f836a9a  gcc/config/riscv/riscv-vsetvl.cc
  d120ed6eb2847b636271b3a1ef82ecbf  gcc/config/riscv/riscv-vsetvl.def
  7082a18dbfc574d47bf71f4d50dd30f9  gcc/config/riscv/riscv-zicfilp.cc
! ceb0aaef76af1f27856694ab36bc93e2  gcc/config/riscv/riscv.cc
  1e6d5c3cff4825c434ac203d43f0b5ab  gcc/config/riscv/riscv.h
! e6c7d018aa0c0a73c813aae4ce9c6b50  gcc/config/riscv/riscv.md
  fec1c87bba727131a45d4ec4a9ae5490  gcc/config/riscv/riscv.opt
  d1d34490d8b53ec20d70ed9e2e56e3ab  gcc/config/riscv/riscv.opt.urls
  374e3c204946cff8c4be2bcad6641830  gcc/config/riscv/riscv_bitmanip.h
*************** bcf728ad2379630774fd5bb529d4ee86  gcc/co
*** 4980,4988 ****
  fd8e9517de64ab23821ea1284ea6d7f6  gcc/config/riscv/thead.md
  b5e46305db1116cc1758b504ea37fe74  gcc/config/riscv/vector-bfloat16.md
  88f7597398d0c8b8b87baba5fd207996  gcc/config/riscv/vector-crypto.md
! 1e72fd3b97655cba4fdef52c125ed35a  gcc/config/riscv/vector-iterators.md
! 9231da0a3760d35dafdec45d85a3e6a6  gcc/config/riscv/vector.md
! 4ffde0be9b9a0efe78c98b4407d00397  gcc/config/riscv/xiangshan.md
  0f64aaa114ab62a1a46f7ac422d6a129  gcc/config/riscv/zc.md
  36cba2444ae9c8f107fee34492bd0ed6  gcc/config/riscv/zicond.md
  484e293fd0201a6e967e08cfb88bfed2  gcc/config/rl78/constraints.md
--- 4980,4988 ----
  fd8e9517de64ab23821ea1284ea6d7f6  gcc/config/riscv/thead.md
  b5e46305db1116cc1758b504ea37fe74  gcc/config/riscv/vector-bfloat16.md
  88f7597398d0c8b8b87baba5fd207996  gcc/config/riscv/vector-crypto.md
! ebed0032394077f4410660bcb8b59f15  gcc/config/riscv/vector-iterators.md
! 32f27efd1435474199683e4d52770ee8  gcc/config/riscv/vector.md
! e31222c427cb48729f4c65dbd87b6b53  gcc/config/riscv/xiangshan.md
  0f64aaa114ab62a1a46f7ac422d6a129  gcc/config/riscv/zc.md
  36cba2444ae9c8f107fee34492bd0ed6  gcc/config/riscv/zicond.md
  484e293fd0201a6e967e08cfb88bfed2  gcc/config/rl78/constraints.md
*************** dce39de8bb20b88ffeb8b2073101dcfe  gcc/co
*** 5110,5116 ****
  5621b2aa0be1c71c3955c4e3bad6cf49  gcc/config/rs6000/rs6000-string.cc
  062e9e612338d86d0d47a3e1131384fa  gcc/config/rs6000/rs6000-tables.opt
  ce8de9a27f36b759a69194616c02eb38  gcc/config/rs6000/rs6000-tables.opt.urls
! 0c97c99093f9384ba11100fdc1973754  gcc/config/rs6000/rs6000.cc
  1d91827dae3ab7a332473805ac3cf40c  gcc/config/rs6000/rs6000.h
  ad1b62754d030b34f5ff67d2991b43b1  gcc/config/rs6000/rs6000.md
  77c1c38e6705e421b8838bf19f938cef  gcc/config/rs6000/rs6000.opt
--- 5110,5116 ----
  5621b2aa0be1c71c3955c4e3bad6cf49  gcc/config/rs6000/rs6000-string.cc
  062e9e612338d86d0d47a3e1131384fa  gcc/config/rs6000/rs6000-tables.opt
  ce8de9a27f36b759a69194616c02eb38  gcc/config/rs6000/rs6000-tables.opt.urls
! db6ba662442bf9f15f64daaf0e0d4b61  gcc/config/rs6000/rs6000.cc
  1d91827dae3ab7a332473805ac3cf40c  gcc/config/rs6000/rs6000.h
  ad1b62754d030b34f5ff67d2991b43b1  gcc/config/rs6000/rs6000.md
  77c1c38e6705e421b8838bf19f938cef  gcc/config/rs6000/rs6000.opt
*************** d7112093049d4abbc421609d032b7358  gcc/co
*** 5209,5215 ****
  6fdfe66fdde3f81b83dc16c27ac7df3f  gcc/config/s390/s390-opts.h
  87bca0c72260bdf7b32cbe797e607999  gcc/config/s390/s390-passes.def
  94c7aecc0d353c9aa984b4bcea01590b  gcc/config/s390/s390-protos.h
! 2bb5317880e3e10de0ab75de1cdafc59  gcc/config/s390/s390.cc
  f162b44703353c72956061efcbe580d7  gcc/config/s390/s390.h
  708ec951fb00aa87d495349008fad5f5  gcc/config/s390/s390.md
  fa4475320c7a3767bf9accfa736efcc6  gcc/config/s390/s390.opt
--- 5209,5215 ----
  6fdfe66fdde3f81b83dc16c27ac7df3f  gcc/config/s390/s390-opts.h
  87bca0c72260bdf7b32cbe797e607999  gcc/config/s390/s390-passes.def
  94c7aecc0d353c9aa984b4bcea01590b  gcc/config/s390/s390-protos.h
! f4a9294b49d226130e11ea79f8849656  gcc/config/s390/s390.cc
  f162b44703353c72956061efcbe580d7  gcc/config/s390/s390.h
  708ec951fb00aa87d495349008fad5f5  gcc/config/s390/s390.md
  fa4475320c7a3767bf9accfa736efcc6  gcc/config/s390/s390.opt
*************** f3a2992c8e85b13e50b261e26924d83f  gcc/co
*** 5473,5495 ****
  87fc5c87547999f715031b4ff99fb67b  gcc/config/xtensa/xtensa-dynconfig.cc
  c7be35a23fd70ac184dd9072319304c7  gcc/config/xtensa/xtensa-opts.h
  e59f31891252abdd41eedc784b25ed6b  gcc/config/xtensa/xtensa-protos.h
! 6c1ab2067ac398070806ea5b01728eb0  gcc/config/xtensa/xtensa.cc
  f378c965e5e289a389bbf48d20867d48  gcc/config/xtensa/xtensa.h
! b92f4879bce79aeae64e0091394f3cbe  gcc/config/xtensa/xtensa.md
  f0452ea712955ce21c9c149136850780  gcc/config/xtensa/xtensa.opt
  db57d7603312357e8c0cfb21c32353d1  gcc/config/xtensa/xtensa.opt.urls
! e0206d81539aa917fcef027728d6213f  gcc/configure
! 589dce473c65acfa5e07dd7a2784fcb6  gcc/configure.ac
  ec3aa966ca3fe9c6f84d4378160541b6  gcc/context.cc
  d1bde52b8dee0c0c5506d7e320b1bb61  gcc/context.h
  a9c3cddee4e237141062720b72fe38cd  gcc/convert.cc
  0bc6fd549059c635d460ac1b2be648d8  gcc/convert.h
! 9a52d4bcaec7df09971007540ad91f77  gcc/coretypes.h
  086834dbb33047e862ba6b6171eda392  gcc/coroutine-builtins.def
  5d31df44fc0a5b17beb74ce0ff38e214  gcc/coroutine-passes.cc
  02796caeaa2f14f72dc3c9c23cc97dfc  gcc/coverage.cc
  722fb5fda78e55c5af5da72cad78751f  gcc/coverage.h
! 24a2ed9ba8b28b2d509de7e31dd69208  gcc/cp/ChangeLog
  70c059f2b75a2fc1bb95a526b21b8cd7  gcc/cp/ChangeLog-1993
  7cbd106e10a0ba7c052bee3fe20671c2  gcc/cp/ChangeLog-1994
  3b1e3ed23ad4363f75e6fd2fbb583dee  gcc/cp/ChangeLog-1995
--- 5473,5495 ----
  87fc5c87547999f715031b4ff99fb67b  gcc/config/xtensa/xtensa-dynconfig.cc
  c7be35a23fd70ac184dd9072319304c7  gcc/config/xtensa/xtensa-opts.h
  e59f31891252abdd41eedc784b25ed6b  gcc/config/xtensa/xtensa-protos.h
! 988ffbef8c0f422b986dd7e920ca260f  gcc/config/xtensa/xtensa.cc
  f378c965e5e289a389bbf48d20867d48  gcc/config/xtensa/xtensa.h
! 79ea7a5d4eebe3e5ee624db15dfe6499  gcc/config/xtensa/xtensa.md
  f0452ea712955ce21c9c149136850780  gcc/config/xtensa/xtensa.opt
  db57d7603312357e8c0cfb21c32353d1  gcc/config/xtensa/xtensa.opt.urls
! f68072ed087e51553c85876765be1ebe  gcc/configure
! 25b00d6f2854fbefe0d865f7d6e9ab3a  gcc/configure.ac
  ec3aa966ca3fe9c6f84d4378160541b6  gcc/context.cc
  d1bde52b8dee0c0c5506d7e320b1bb61  gcc/context.h
  a9c3cddee4e237141062720b72fe38cd  gcc/convert.cc
  0bc6fd549059c635d460ac1b2be648d8  gcc/convert.h
! fa062fdcbed6412a676fa477d87ba334  gcc/coretypes.h
  086834dbb33047e862ba6b6171eda392  gcc/coroutine-builtins.def
  5d31df44fc0a5b17beb74ce0ff38e214  gcc/coroutine-passes.cc
  02796caeaa2f14f72dc3c9c23cc97dfc  gcc/coverage.cc
  722fb5fda78e55c5af5da72cad78751f  gcc/coverage.h
! 718de023f5a0c81248cff9cc37263979  gcc/cp/ChangeLog
  70c059f2b75a2fc1bb95a526b21b8cd7  gcc/cp/ChangeLog-1993
  7cbd106e10a0ba7c052bee3fe20671c2  gcc/cp/ChangeLog-1994
  3b1e3ed23ad4363f75e6fd2fbb583dee  gcc/cp/ChangeLog-1995
*************** bcf7c5d02934e40f17edeb18d58c4d4d  gcc/cp
*** 5525,5540 ****
  c1c7801b9b0f379e702a4f6cb83972e7  gcc/cp/ChangeLog.ptr
  9aa3cd9f75c785de9f51446e3f295515  gcc/cp/ChangeLog.tree-ssa
  2315f072c416e98144559bbdb5312c21  gcc/cp/Make-lang.in
! 4a9cab8ddf338dc396a175e877afe6d0  gcc/cp/call.cc
  fce8de27014c109814b3f69be6a5d4f6  gcc/cp/cfns.gperf
  68fc21d4889b1c70ccf89747b98b1fb4  gcc/cp/cfns.h
  7f0529acba840882ae2d5681da795c85  gcc/cp/class.cc
  ee3fb2cc9b9557d3895f527353160bd4  gcc/cp/config-lang.in
! d7a910d8076ff6f40b43f38af30e3d66  gcc/cp/constexpr.cc
! 6ffd8d77b853d22c2d560e54c9d68fb9  gcc/cp/constraint.cc
  613233facbf4b0f1cff770ed6c49c666  gcc/cp/contracts.cc
  1f1cd3a021a2cd25741e252145ee8282  gcc/cp/contracts.h
! 78ed5e7da2c45931ed1e44da5f9040c9  gcc/cp/coroutines.cc
  1817def94193f0cfabd4fa5b321af011  gcc/cp/coroutines.h
  0891b03593ba6bcdf48dfd997f3f34b6  gcc/cp/cp-gimplify.cc
  3bf6da2fd9bef7475fae5ee6d9cdcf15  gcc/cp/cp-lang.cc
--- 5525,5540 ----
  c1c7801b9b0f379e702a4f6cb83972e7  gcc/cp/ChangeLog.ptr
  9aa3cd9f75c785de9f51446e3f295515  gcc/cp/ChangeLog.tree-ssa
  2315f072c416e98144559bbdb5312c21  gcc/cp/Make-lang.in
! 4ffb9a058a3b363c2346f08341cb1333  gcc/cp/call.cc
  fce8de27014c109814b3f69be6a5d4f6  gcc/cp/cfns.gperf
  68fc21d4889b1c70ccf89747b98b1fb4  gcc/cp/cfns.h
  7f0529acba840882ae2d5681da795c85  gcc/cp/class.cc
  ee3fb2cc9b9557d3895f527353160bd4  gcc/cp/config-lang.in
! 2a450adaa7313491e186c43119d8eb16  gcc/cp/constexpr.cc
! 1625c2488730833231388a3dcdd5b8a8  gcc/cp/constraint.cc
  613233facbf4b0f1cff770ed6c49c666  gcc/cp/contracts.cc
  1f1cd3a021a2cd25741e252145ee8282  gcc/cp/contracts.h
! ebc33bcbb6e9f1bbaba630368e255575  gcc/cp/coroutines.cc
  1817def94193f0cfabd4fa5b321af011  gcc/cp/coroutines.h
  0891b03593ba6bcdf48dfd997f3f34b6  gcc/cp/cp-gimplify.cc
  3bf6da2fd9bef7475fae5ee6d9cdcf15  gcc/cp/cp-lang.cc
*************** d7a910d8076ff6f40b43f38af30e3d66  gcc/cp
*** 5543,5566 ****
  acb30767d403ad5a0d7ae97437159ebe  gcc/cp/cp-objcp-common.h
  da10ef04236f524fa56f82f602775a89  gcc/cp/cp-trait.def
  ce9f2ccac9e2657417018bc8f8064421  gcc/cp/cp-tree.def
! 79f4301815332bcffc93f9e7f8bcc955  gcc/cp/cp-tree.h
  e5ccdda9d62d96ac397910d0fa391b0a  gcc/cp/cp-ubsan.cc
  b7ae95468b0150bbe2b3cba351e96a2c  gcc/cp/cvt.cc
  28a2733b7abed60b2b102105bb7cebaf  gcc/cp/cxx-pretty-print.cc
  955ecfa636599a39229757737e271819  gcc/cp/cxx-pretty-print.h
  c1cc5dac36866c611933c037cc1d6f2f  gcc/cp/cxxapi-data.csv
! 3c32eb852766c731f6feab4e6d023496  gcc/cp/decl.cc
  7f116fdc50b24dcb13cdcf096636aef9  gcc/cp/decl.h
  a8747e45489cb64f2f4528a1973fcacf  gcc/cp/decl2.cc
  691a10b3246d19925433648ba9a4ea9a  gcc/cp/dump.cc
! a3df348ec76b7ef7cfe2877aec7fffcc  gcc/cp/error.cc
! 88b3c7658097d35045cd04dac2eb1d31  gcc/cp/except.cc
  73d53be529221aad38fb412e9e7d1ee3  gcc/cp/expr.cc
  3b7c086cfb4ed89e6ae40a09ca796704  gcc/cp/friend.cc
  3d079dd21f8a1ab95fb2d1f96d799283  gcc/cp/g++spec.cc
  30b9ed40d39cf78b95792ef5dca2aebb  gcc/cp/gen-cxxapi-file.py
! 6d44875db98234b640f99194d69cb96c  gcc/cp/init.cc
! 0c5bbd15c915ed041bda7cb401227a4b  gcc/cp/lambda.cc
  ac5d78393361c1bcb930119a896a14ca  gcc/cp/lang-specs.h
  1352d53c83446655a7fcab07fcdeddc1  gcc/cp/lex.cc
  aaf76a9b03fd0532d2904aef004fd66a  gcc/cp/logic.cc
--- 5543,5566 ----
  acb30767d403ad5a0d7ae97437159ebe  gcc/cp/cp-objcp-common.h
  da10ef04236f524fa56f82f602775a89  gcc/cp/cp-trait.def
  ce9f2ccac9e2657417018bc8f8064421  gcc/cp/cp-tree.def
! 30853f9719a8acc9a1f7d913ad89f9c0  gcc/cp/cp-tree.h
  e5ccdda9d62d96ac397910d0fa391b0a  gcc/cp/cp-ubsan.cc
  b7ae95468b0150bbe2b3cba351e96a2c  gcc/cp/cvt.cc
  28a2733b7abed60b2b102105bb7cebaf  gcc/cp/cxx-pretty-print.cc
  955ecfa636599a39229757737e271819  gcc/cp/cxx-pretty-print.h
  c1cc5dac36866c611933c037cc1d6f2f  gcc/cp/cxxapi-data.csv
! 490c082f15a6b8772dee5e04e8fa03bb  gcc/cp/decl.cc
  7f116fdc50b24dcb13cdcf096636aef9  gcc/cp/decl.h
  a8747e45489cb64f2f4528a1973fcacf  gcc/cp/decl2.cc
  691a10b3246d19925433648ba9a4ea9a  gcc/cp/dump.cc
! 69badb4c3f76c9dbd270a2c2d56ee401  gcc/cp/error.cc
! ad1ba8457732d4c15cf2c956bd7035d8  gcc/cp/except.cc
  73d53be529221aad38fb412e9e7d1ee3  gcc/cp/expr.cc
  3b7c086cfb4ed89e6ae40a09ca796704  gcc/cp/friend.cc
  3d079dd21f8a1ab95fb2d1f96d799283  gcc/cp/g++spec.cc
  30b9ed40d39cf78b95792ef5dca2aebb  gcc/cp/gen-cxxapi-file.py
! 142701672ecfe15addb5c0d02c027f7b  gcc/cp/init.cc
! 3c6caedf85a293177af7ba0b6a7353d4  gcc/cp/lambda.cc
  ac5d78393361c1bcb930119a896a14ca  gcc/cp/lang-specs.h
  1352d53c83446655a7fcab07fcdeddc1  gcc/cp/lex.cc
  aaf76a9b03fd0532d2904aef004fd66a  gcc/cp/logic.cc
*************** aaf76a9b03fd0532d2904aef004fd66a  gcc/cp
*** 5568,5592 ****
  936bd061907a7a899c3285cf17b17674  gcc/cp/mapper-client.cc
  6c77b1fab5f6d146677090285a202a50  gcc/cp/mapper-client.h
  44e22b51797f89c9da996523a6d97f1c  gcc/cp/mapper-resolver.cc
! 8bace54cefb0ac9061a21ae69213043d  gcc/cp/method.cc
! fa764aa6d94c6032a884155a3a442c62  gcc/cp/module.cc
! 06f95ada11e42d69946cf7b65d247c53  gcc/cp/name-lookup.cc
  6e376c0a7ec6c4a14de40885e3b1a0cb  gcc/cp/name-lookup.h
  e7fe06956aada61bcaae5168ad47a9c1  gcc/cp/operators.def
  813c253a000ee20d8d6598f56edc400e  gcc/cp/optimize.cc
! cb58b434119f74350f0353679cad0eb1  gcc/cp/parser.cc
  e8a3a03873c6294ff25a783941b8d8af  gcc/cp/parser.h
! 1dc403e27640c8f4cf3702e4c06ad69b  gcc/cp/pt.cc
  a121c0a45933b618832614be1fbfd5c7  gcc/cp/ptree.cc
  ee1ddf1e1b9554bb1a10109ce8c6dee5  gcc/cp/rtti.cc
  a4930c49ed8f9e6b019399bd1faf86d0  gcc/cp/search.cc
! ca008066743d497e321364e5d175c6de  gcc/cp/semantics.cc
  b58bf61fbfed45af179b7104e72a9486  gcc/cp/std-name-hint.gperf
  2425db76c32085977eff047c982cebab  gcc/cp/std-name-hint.h
! 360fbad46e0539fd434f268f76ae2d9d  gcc/cp/tree.cc
  bb1304379ac1bf9a568942bc7e976e8a  gcc/cp/type-utils.h
! 791bac04d6637f4df754c7f2c13154ec  gcc/cp/typeck.cc
! 1fea2b59dbf93b59626d7546b3c1f738  gcc/cp/typeck2.cc
  aa6906e22dc44502ca268580e5b8dfdd  gcc/cp/vtable-class-hierarchy.cc
  c74d2f6cc5dcb1bf1953c093eb903b37  gcc/cppbuiltin.cc
  05a136afb0839d5238cd1390602e748e  gcc/cppbuiltin.h
--- 5568,5592 ----
  936bd061907a7a899c3285cf17b17674  gcc/cp/mapper-client.cc
  6c77b1fab5f6d146677090285a202a50  gcc/cp/mapper-client.h
  44e22b51797f89c9da996523a6d97f1c  gcc/cp/mapper-resolver.cc
! bf85ce388aad5b027ff445c6813600b9  gcc/cp/method.cc
! 8dac8d4be1ce39ff8b44cfa27ad7c975  gcc/cp/module.cc
! eed0876afd8c67b71fbaa0f71b1ad615  gcc/cp/name-lookup.cc
  6e376c0a7ec6c4a14de40885e3b1a0cb  gcc/cp/name-lookup.h
  e7fe06956aada61bcaae5168ad47a9c1  gcc/cp/operators.def
  813c253a000ee20d8d6598f56edc400e  gcc/cp/optimize.cc
! 3b53d4b09a216a6a48b9e9988458fff2  gcc/cp/parser.cc
  e8a3a03873c6294ff25a783941b8d8af  gcc/cp/parser.h
! 1c00657d191b7450fa2fe8909a6fda8b  gcc/cp/pt.cc
  a121c0a45933b618832614be1fbfd5c7  gcc/cp/ptree.cc
  ee1ddf1e1b9554bb1a10109ce8c6dee5  gcc/cp/rtti.cc
  a4930c49ed8f9e6b019399bd1faf86d0  gcc/cp/search.cc
! cccc5c0bc73cfa410a0a11404fd64a8d  gcc/cp/semantics.cc
  b58bf61fbfed45af179b7104e72a9486  gcc/cp/std-name-hint.gperf
  2425db76c32085977eff047c982cebab  gcc/cp/std-name-hint.h
! bb59c5ae196f831747fd7fc38c0999cd  gcc/cp/tree.cc
  bb1304379ac1bf9a568942bc7e976e8a  gcc/cp/type-utils.h
! 0d1f4c9abc7ea4cb3682d067e9540fce  gcc/cp/typeck.cc
! 75ee85794a3c4856e3de8a2f45bfcc6f  gcc/cp/typeck2.cc
  aa6906e22dc44502ca268580e5b8dfdd  gcc/cp/vtable-class-hierarchy.cc
  c74d2f6cc5dcb1bf1953c093eb903b37  gcc/cppbuiltin.cc
  05a136afb0839d5238cd1390602e748e  gcc/cppbuiltin.h
*************** ec1e9c9456a8530e241079823e2fc126  gcc/cr
*** 5602,5608 ****
  15aef1bfc1d9935a8df200d3827b59c6  gcc/ctfc.cc
  3df123e84e7c118eb423425f2100e3b5  gcc/ctfc.h
  aec0cd5251de880945c96eb21e97eac9  gcc/ctfout.cc
! 599c6422152c2d898eb15dde1b1484e7  gcc/d/ChangeLog
  94dbce564aba342900829d11192f8905  gcc/d/ChangeLog-2006
  1a0536d6571bca334bb5c00dbdf257ab  gcc/d/ChangeLog-2007
  362a026d745031260b2e4dd8eba9becc  gcc/d/ChangeLog-2008
--- 5602,5608 ----
  15aef1bfc1d9935a8df200d3827b59c6  gcc/ctfc.cc
  3df123e84e7c118eb423425f2100e3b5  gcc/ctfc.h
  aec0cd5251de880945c96eb21e97eac9  gcc/ctfout.cc
! 1c32fb925d7f70209db05b72fad25716  gcc/d/ChangeLog
  94dbce564aba342900829d11192f8905  gcc/d/ChangeLog-2006
  1a0536d6571bca334bb5c00dbdf257ab  gcc/d/ChangeLog-2007
  362a026d745031260b2e4dd8eba9becc  gcc/d/ChangeLog-2008
*************** bea890f9a34a3828dac2371f1f1796bf  gcc/d/
*** 5631,5637 ****
  70ffb6bfceda6c8afd5611f3b4a675cd  gcc/d/d-compiler.cc
  186086ac63d9d73dbed30ccc75c3ae62  gcc/d/d-convert.cc
  973d6dc819b7a8aee527f89ad0f00e08  gcc/d/d-ctfloat.cc
! e4a31bc23588216ddf30ac8e625a173f  gcc/d/d-diagnostic.cc
  949e72b27b36c126d810adb5e31283bb  gcc/d/d-frontend.cc
  749304aa6de563eed68793be22f7cd6e  gcc/d/d-frontend.h
  b2113d2270102ca524bf783ba0720409  gcc/d/d-gimplify.cc
--- 5631,5637 ----
  70ffb6bfceda6c8afd5611f3b4a675cd  gcc/d/d-compiler.cc
  186086ac63d9d73dbed30ccc75c3ae62  gcc/d/d-convert.cc
  973d6dc819b7a8aee527f89ad0f00e08  gcc/d/d-ctfloat.cc
! 8fe3d79d465006544704fd486e3a9280  gcc/d/d-diagnostic.cc
  949e72b27b36c126d810adb5e31283bb  gcc/d/d-frontend.cc
  749304aa6de563eed68793be22f7cd6e  gcc/d/d-frontend.h
  b2113d2270102ca524bf783ba0720409  gcc/d/d-gimplify.cc
*************** a7bde590e8469b2ffb53fcd2a06033af  gcc/d/
*** 5847,5853 ****
  532169cc522c2173657371a604a5c583  gcc/d/modules.cc
  5be4062eb2b710347ff98e3d8c9cfdde  gcc/d/runtime.cc
  14ab71dfd3fc06afb477ec01aa077f09  gcc/d/runtime.def
! 57c9d4836a44d452b1ab333bf12b3a4b  gcc/d/toir.cc
  4af3aaebbbb939e7e67ed0f4349a4524  gcc/d/typeinfo.cc
  6cca916bc4f20b74318d58d6429ce267  gcc/d/types.cc
  257fb956c4a8d2279293b031e195fdaa  gcc/data-streamer-in.cc
--- 5847,5853 ----
  532169cc522c2173657371a604a5c583  gcc/d/modules.cc
  5be4062eb2b710347ff98e3d8c9cfdde  gcc/d/runtime.cc
  14ab71dfd3fc06afb477ec01aa077f09  gcc/d/runtime.def
! d84165be059ff7e94be688bf4fadefd8  gcc/d/toir.cc
  4af3aaebbbb939e7e67ed0f4349a4524  gcc/d/typeinfo.cc
  6cca916bc4f20b74318d58d6429ce267  gcc/d/types.cc
  257fb956c4a8d2279293b031e195fdaa  gcc/data-streamer-in.cc
*************** b9d078b88658c87d713e175705b687be  gcc/df
*** 5870,5916 ****
  243e0658083f87e4b05d8914b98053c2  gcc/df.h
  b24ae235869e8ddfde6c45d41923f7ef  gcc/dfp.cc
  3a50d04564ba93f9be134a744fdd40f1  gcc/dfp.h
! aa13c8ce0ee0d35ca8e78fef45b93463  gcc/diagnostic-buffer.h
! 4b477754fac3d1dfcc21f651d641ea08  gcc/diagnostic-client-data-hooks.h
! 5771d42150cd2d9eba59db1bfd12fee2  gcc/diagnostic-color.cc
! 65522110920a99041a18ed5b093986fd  gcc/diagnostic-color.h
! b14c12c33aee36a4d29601627a1a67da  gcc/diagnostic-core.h
! be405b20597be971120eee5709db8c4a  gcc/diagnostic-diagram.h
! 464f9293a5979b80b6bc2271616a7c79  gcc/diagnostic-digraphs.cc
! fcb6ed742d3249e66ed6302ccb9291a6  gcc/diagnostic-digraphs.h
! a24233a009f0c9d29e034e6ba63082de  gcc/diagnostic-event-id.h
! b2690a6e98ac797223d7202794c41601  gcc/diagnostic-format-html.cc
! ebcf925d650be4ee570760e6dc64702a  gcc/diagnostic-format-html.h
! 7c0d7bcb1dccf9bc12d00eda06f977f6  gcc/diagnostic-format-sarif.cc
! add72f82b14a63bb9615ebc8007065c5  gcc/diagnostic-format-sarif.h
! 374c1a4e48613be5c065401323abd464  gcc/diagnostic-format-text.cc
! 1d011aadc9c5b8b2321e93fc1b4f8f44  gcc/diagnostic-format-text.h
! 0401e62acc37419d938a447e13406b9a  gcc/diagnostic-format.h
! c57536f66ae2965d5f7308e1fe115f1e  gcc/diagnostic-global-context.cc
  ddb5e19e6f3ff8224aedd1a60eaad23e  gcc/diagnostic-highlight-colors.h
! dd85098d241db456b95090aed8ac8026  gcc/diagnostic-label-effects.h
! 0833c895a57471d96f0413545cdf8a65  gcc/diagnostic-macro-unwinding.cc
! 124a9446918f0c1e7a8586ac4aea6729  gcc/diagnostic-macro-unwinding.h
! 0fc9e67bd520ad3e420b3f5f1bffc09d  gcc/diagnostic-metadata.h
! e32f47c03714e4be891aef1903c8a04f  gcc/diagnostic-output-file.h
! da65429c71b4fa43fe8a32a4a073b4d7  gcc/diagnostic-output-spec.cc
! 44a6737f244d23915aa9f9eda34652da  gcc/diagnostic-output-spec.h
! 4769d8f66a021a927cabe0098108de1e  gcc/diagnostic-path-output.cc
! b3ce84de2a59b7673f4ed0887c4f34db  gcc/diagnostic-path.cc
! d368f70a65d9c4125f8440d91dded353  gcc/diagnostic-path.h
! cde9b376952f76ba61798ba6e4cb4f6b  gcc/diagnostic-show-locus.cc
! 6b93e61211f8001b7a53df197d64a3e4  gcc/diagnostic-spec.cc
! 375a39d1eff397ae7fcdce6e05c76d50  gcc/diagnostic-spec.h
! d2869ace5760e8df245accf7765dd13f  gcc/diagnostic-state-graphs.cc
! 0d39634f418b8220e258f405ac55f110  gcc/diagnostic-state-graphs.h
! 47c9fcb4830ef835cb2d6c8c288bd305  gcc/diagnostic-state-to-dot.cc
! dabd477d68c54372f8519e7c917d4a11  gcc/diagnostic-url.h
! 53ba40a82691983ff26a03a15d41c587  gcc/diagnostic.cc
! 03b04b0fb78353ca76570e5ef92cf756  gcc/diagnostic.def
! d5ff67c2f303f635694420af037dbc7a  gcc/diagnostic.h
  e2ff50cf5215e2299270f0da4d4d60d0  gcc/digraph.cc
  18e73120a6e21ceac1adce40777000cf  gcc/digraph.h
! d01e9b299edd1dbc5dea57dfd4ab85d3  gcc/doc/analyzer.texi
  7c6d6f8bba4a9890d950bdef623af96f  gcc/doc/avr-mmcu.texi
  628200aba31497f381052220465b8927  gcc/doc/bugreport.texi
  519dad6b92ca7405e11a87efd5ddd705  gcc/doc/cfg.texi
--- 5870,5938 ----
  243e0658083f87e4b05d8914b98053c2  gcc/df.h
  b24ae235869e8ddfde6c45d41923f7ef  gcc/dfp.cc
  3a50d04564ba93f9be134a744fdd40f1  gcc/dfp.h
! 93b73dbd9036edc5371e50289303ddde  gcc/diagnostic-core.h
! a94dd5f1cfd3551d976846dfd5627f4e  gcc/diagnostic-global-context.cc
  ddb5e19e6f3ff8224aedd1a60eaad23e  gcc/diagnostic-highlight-colors.h
! 77d6cba3ed8490570085b919ef8aeb2c  gcc/diagnostic.h
! 09716b3c4ca28b81c3b06a044696555a  gcc/diagnostics/buffering.cc
! aea647fc04e00e3ca00c0f4c70f50ae1  gcc/diagnostics/buffering.h
! 4cff1b2ec2d39f3930459438cb8e0863  gcc/diagnostics/changes.cc
! ff66e6baa4830cf18c7b97e2eb383ac5  gcc/diagnostics/changes.h
! edcbcad65269c8bfebcac2def7bc9cc1  gcc/diagnostics/client-data-hooks.h
! c9250b15349fce5a608b769043f111e5  gcc/diagnostics/color.cc
! d29ddcb032cf35e525663d8b857fe46b  gcc/diagnostics/color.h
! feea31e8e6eec9c1403f01df95d221d4  gcc/diagnostics/context-options.h
! 1e8552f89835f89c29bbef91a5abb881  gcc/diagnostics/context.cc
! b5bd8b05f581d65cf7f13eaef0721745  gcc/diagnostics/context.h
! 6eb2e40f405d950a9e9f3c089680a899  gcc/diagnostics/diagnostic-info.h
! fd87cae7d2e8cfdbfe401ce78e684593  gcc/diagnostics/diagnostics-selftests.cc
! 1ca1218e8ad79ba30925b61d63e7c5b0  gcc/diagnostics/diagnostics-selftests.h
! b1a342ed1575b6a45df5f31d699e73c8  gcc/diagnostics/diagram.h
! f2f7f2e44f68617193d688191fd08395  gcc/diagnostics/digraphs.cc
! 2b7bbaecee26ffad2cf1ec52058566bf  gcc/diagnostics/digraphs.h
! cff4c3f5d806ef5fa9ea2a9776fcc922  gcc/diagnostics/event-id.h
! 8664e7fd52051d76308c83d24d86c7b6  gcc/diagnostics/file-cache.cc
! 4e3d1fe87ad0979f552310facbc2e534  gcc/diagnostics/file-cache.h
! e4415a48bb1aac47a946214cf7335424  gcc/diagnostics/html-sink.cc
! 1fe5721d92cff8138e2730e9fd8839ae  gcc/diagnostics/html-sink.h
! e5801529f87f5812381a450d52efaebf  gcc/diagnostics/kinds.def
! 0e7b7ba2494e5650473c71225e47feb5  gcc/diagnostics/kinds.h
! 8fa4ac986e2a5fb33b9feaf7a3090bc8  gcc/diagnostics/lazy-paths.cc
! 4ed6c990f3102512e3c60c6c5069dd21  gcc/diagnostics/lazy-paths.h
! c131a194acbb9d5e4682e19f1a759181  gcc/diagnostics/logical-locations.h
! ed9e23a6a190e966a47730d652613dd2  gcc/diagnostics/macro-unwinding.cc
! 1a1b13e68ed47b8eb0342caa0caee17b  gcc/diagnostics/macro-unwinding.h
! f25b62af6fdde6c09fc4ebaa5ef69f94  gcc/diagnostics/metadata.h
! 625181add33d5bfe0e9fbec59bff16f5  gcc/diagnostics/option-classifier.cc
! 3df9c58d5592c4781758cda2f751adb8  gcc/diagnostics/option-classifier.h
! ee46d9f24ee418300e1cb8af08ce0e7c  gcc/diagnostics/option-id.h
! f5d7b6b5a0da4617c6298991d76432f3  gcc/diagnostics/output-file.h
! 3bd9050f9603573f32f48b3ce66a2f2d  gcc/diagnostics/output-spec.cc
! 3eec925c74669a3ab2099a0428b64b64  gcc/diagnostics/output-spec.h
! cefbba8b03685fbfd838e1f457bb843a  gcc/diagnostics/paths-output.cc
! e60ad2d99ee160a6acce95a85c4f5884  gcc/diagnostics/paths.cc
! ab20f8a7e64efd9ea6670e6447014d6f  gcc/diagnostics/paths.h
! de5f99f705454eb77bab66ff714737e6  gcc/diagnostics/sarif-sink.cc
! 9fda361308b90adaea42525d93f3772e  gcc/diagnostics/sarif-sink.h
! ee068b3f8fd2d449eee5a70ef6dad518  gcc/diagnostics/selftest-context.cc
! 0c9931582348dcf2e668dad28878e073  gcc/diagnostics/selftest-context.h
! 380b1d9e0cb480756d7490c2ff04e99b  gcc/diagnostics/selftest-logical-locations.cc
! 7073aeb2c7dc0e5c5ad6514f695f2317  gcc/diagnostics/selftest-logical-locations.h
! 112984df670b9db84c11f891b9d5b94b  gcc/diagnostics/selftest-paths.cc
! 24e9e37ce7832be5c6807735b79cb487  gcc/diagnostics/selftest-paths.h
! 7cdb74e1f66d5f344d0902bc7ca9c28d  gcc/diagnostics/selftest-source-printing.h
! 23b873a5a360cfeb44c280cac2b3e38f  gcc/diagnostics/sink.h
! 83cfb383914a3b5f56ce7cf9222d2389  gcc/diagnostics/source-printing-effects.h
! e0f36673d93e0bff33a430aef98b4884  gcc/diagnostics/source-printing.cc
! c7ddef71ac29eb2a389042f195e3b325  gcc/diagnostics/state-graphs-to-dot.cc
! 725af6438f327bd6aa23464c8fc3653a  gcc/diagnostics/state-graphs.cc
! fd0a458b50e99299115a0f8f2f59dd9d  gcc/diagnostics/state-graphs.h
! 04bb2de48a7ef980f68f889970311006  gcc/diagnostics/text-sink.cc
! e7cfa8c355bd53afc9f9504161d44986  gcc/diagnostics/text-sink.h
! b882c3ac372bd1a3c12cb702a5bdf197  gcc/diagnostics/url.h
  e2ff50cf5215e2299270f0da4d4d60d0  gcc/digraph.cc
  18e73120a6e21ceac1adce40777000cf  gcc/digraph.h
! 896dfab99ef4a3f697fdf60723346e28  gcc/doc/analyzer.texi
  7c6d6f8bba4a9890d950bdef623af96f  gcc/doc/avr-mmcu.texi
  628200aba31497f381052220465b8927  gcc/doc/bugreport.texi
  519dad6b92ca7405e11a87efd5ddd705  gcc/doc/cfg.texi
*************** d01e9b299edd1dbc5dea57dfd4ab85d3  gcc/do
*** 5920,5932 ****
  83d0f5c88fe90065e5c5538b9a3f123a  gcc/doc/configterms.texi
  b8ee6e280a9d71c11b682c6942c6bd21  gcc/doc/contrib.texi
  2bb27ef73a41b4f2fff3dd7b08febbfd  gcc/doc/contribute.texi
! dc09e43d1d1ebad6e6902b9c5b7aec73  gcc/doc/cpp.texi
  808d1c20ece40d5e2d9c8daa6cdaabf6  gcc/doc/cppdiropts.texi
  acdfc663791e4321372e79932070d05d  gcc/doc/cppenv.texi
  81ae745aed5479afae430c578fa29055  gcc/doc/cppinternals.texi
  1a2d44757bb0f40b09493ac3863eba93  gcc/doc/cppopts.texi
  14b0532614eb25d7d84e7efd6664ecf3  gcc/doc/cppwarnopts.texi
! 69cdbfa9bdc6f9bedc3c526f12a4a141  gcc/doc/extend.texi
  ddcdbcb699f5252a1c1219d92d87ed8b  gcc/doc/fragments.texi
  cd346f0c279f68138ef08c7addc796de  gcc/doc/frontends.texi
  a28615d9873d98f0d5f4ef8dd3e4c39d  gcc/doc/gcc.texi
--- 5942,5954 ----
  83d0f5c88fe90065e5c5538b9a3f123a  gcc/doc/configterms.texi
  b8ee6e280a9d71c11b682c6942c6bd21  gcc/doc/contrib.texi
  2bb27ef73a41b4f2fff3dd7b08febbfd  gcc/doc/contribute.texi
! 3923947091df4b8c54eae1595710a7d5  gcc/doc/cpp.texi
  808d1c20ece40d5e2d9c8daa6cdaabf6  gcc/doc/cppdiropts.texi
  acdfc663791e4321372e79932070d05d  gcc/doc/cppenv.texi
  81ae745aed5479afae430c578fa29055  gcc/doc/cppinternals.texi
  1a2d44757bb0f40b09493ac3863eba93  gcc/doc/cppopts.texi
  14b0532614eb25d7d84e7efd6664ecf3  gcc/doc/cppwarnopts.texi
! 5d5957d536be9758c0dc3f34f4254e76  gcc/doc/extend.texi
  ddcdbcb699f5252a1c1219d92d87ed8b  gcc/doc/fragments.texi
  cd346f0c279f68138ef08c7addc796de  gcc/doc/frontends.texi
  a28615d9873d98f0d5f4ef8dd3e4c39d  gcc/doc/gcc.texi
*************** a1f65f3aec3cc5d5b6505fb976d4c216  gcc/do
*** 5988,5994 ****
  c98feb0a43876ed3ef2fca3c8448e8f8  gcc/doc/lto.texi
  26f08ad01720c082109915a4ec33c80f  gcc/doc/makefile.texi
  2f8484fc473d3a7141e34a260b920ea3  gcc/doc/match-and-simplify.texi
! cc8e010fe28e3129f0f50cb24cfca188  gcc/doc/md.texi
  8836b7001f069e8dead6a4643108258b  gcc/doc/objc.texi
  9673b2a6dd62d5ac08afb00421e98cdb  gcc/doc/optinfo.texi
  0ae5c8ef7a8ce01c113543a03df7e0df  gcc/doc/options.texi
--- 6010,6016 ----
  c98feb0a43876ed3ef2fca3c8448e8f8  gcc/doc/lto.texi
  26f08ad01720c082109915a4ec33c80f  gcc/doc/makefile.texi
  2f8484fc473d3a7141e34a260b920ea3  gcc/doc/match-and-simplify.texi
! ce20ce13aa52471e6b264e2fd332d5a2  gcc/doc/md.texi
  8836b7001f069e8dead6a4643108258b  gcc/doc/objc.texi
  9673b2a6dd62d5ac08afb00421e98cdb  gcc/doc/optinfo.texi
  0ae5c8ef7a8ce01c113543a03df7e0df  gcc/doc/options.texi
*************** ee33d902cd60afae792843ff15ad6706  gcc/do
*** 6001,6007 ****
  bd20fd07c5ee8f444bf1d3f5e64e066a  gcc/doc/service.texi
  cdeab873fffaddbd520f6837429ae728  gcc/doc/sourcebuild.texi
  324bbfba4e1ce0b6019ce86e466edde0  gcc/doc/standards.texi
! fd3bf27e33907464460ab9208cdd2240  gcc/doc/tm.texi
  06d0869eb2bec892f989f31bcd7da233  gcc/doc/tm.texi.in
  c4168f9f01adf4dd8adc647c04107142  gcc/doc/tree-ssa.texi
  5f62752970e47d350c8cbce47123d1cf  gcc/doc/trouble.texi
--- 6023,6029 ----
  bd20fd07c5ee8f444bf1d3f5e64e066a  gcc/doc/service.texi
  cdeab873fffaddbd520f6837429ae728  gcc/doc/sourcebuild.texi
  324bbfba4e1ce0b6019ce86e466edde0  gcc/doc/standards.texi
! 0e789edda01500eababf582450c41865  gcc/doc/tm.texi
  06d0869eb2bec892f989f31bcd7da233  gcc/doc/tm.texi.in
  c4168f9f01adf4dd8adc647c04107142  gcc/doc/tree-ssa.texi
  5f62752970e47d350c8cbce47123d1cf  gcc/doc/trouble.texi
*************** baaae59ceda4df837a6f62ffb0f29ee7  gcc/dw
*** 6028,6038 ****
  47ff7f9e9ca081597e6dd9be5b4d091a  gcc/dwarf2out.cc
  7ff70632352b65c214e02360ed6d6aae  gcc/dwarf2out.h
  fdd976759ee89958c91a4010e53c0f02  gcc/early-remat.cc
- e0339faf7da1ffc9030bc3a53b41cc1c  gcc/edit-context.cc
- 237d0c79a98880d977007c3345019bf8  gcc/edit-context.h
  0fa3f12b9f441f701d99e167274a0961  gcc/emit-rtl.cc
  958b8dfdb92b879b9cbab057e540c587  gcc/emit-rtl.h
! 22fb4d062235835cdf34b4077884887d  gcc/errors.cc
  7109c06aed199f804c8906e6febd8c9f  gcc/errors.h
  e67bf1a2587fc7f7361e841145ff4cfb  gcc/escaped_string.h
  0f7edc740a7778567090fd93180c02f0  gcc/et-forest.cc
--- 6050,6058 ----
  47ff7f9e9ca081597e6dd9be5b4d091a  gcc/dwarf2out.cc
  7ff70632352b65c214e02360ed6d6aae  gcc/dwarf2out.h
  fdd976759ee89958c91a4010e53c0f02  gcc/early-remat.cc
  0fa3f12b9f441f701d99e167274a0961  gcc/emit-rtl.cc
  958b8dfdb92b879b9cbab057e540c587  gcc/emit-rtl.h
! 316746bb2e9bcd3e58de3aa2487f98a6  gcc/errors.cc
  7109c06aed199f804c8906e6febd8c9f  gcc/errors.h
  e67bf1a2587fc7f7361e841145ff4cfb  gcc/escaped_string.h
  0f7edc740a7778567090fd93180c02f0  gcc/et-forest.cc
*************** e67bf1a2587fc7f7361e841145ff4cfb  gcc/es
*** 6044,6050 ****
  b5fa845ff578d70e8ceae655d6affc51  gcc/explow.h
  a4ee0bae47797ce73f05daef7a07edd4  gcc/expmed.cc
  dee0d85cc89e81b4cc185f1c3102811e  gcc/expmed.h
! de0db91482e3d0889769a83bc7e854dc  gcc/expr.cc
  5480b0f834e382e22c92192d7f5a4744  gcc/expr.h
  7117d2d0dde87eaf1ab2853b5bfd62e2  gcc/ext-dce.cc
  2ecf474a8f5380e5027c5b7a745cd736  gcc/fibonacci_heap.cc
--- 6064,6070 ----
  b5fa845ff578d70e8ceae655d6affc51  gcc/explow.h
  a4ee0bae47797ce73f05daef7a07edd4  gcc/expmed.cc
  dee0d85cc89e81b4cc185f1c3102811e  gcc/expmed.h
! 64d2bae30b15234ee9552b30b5ff753f  gcc/expr.cc
  5480b0f834e382e22c92192d7f5a4744  gcc/expr.h
  7117d2d0dde87eaf1ab2853b5bfd62e2  gcc/ext-dce.cc
  2ecf474a8f5380e5027c5b7a745cd736  gcc/fibonacci_heap.cc
*************** ee644c05e4a3461a8c2f5a4a5ea285bd  gcc/fi
*** 6053,6059 ****
  0e60f266755de3aceb6aac0c955d9771  gcc/file-find.h
  776db52685d2e253eb6227b4cfac0b55  gcc/file-prefix-map.cc
  b0756a8dbbe0b39051dfda2c5e26663f  gcc/file-prefix-map.h
! a7bd1af0b1ebb1020c3f0c463acaaae9  gcc/final.cc
  28cc3b30502fab34fffa55fd82454e16  gcc/fixed-value.cc
  7852b04b41add4ad6cc7c7c86cb82658  gcc/fixed-value.h
  96975c8e38a86e287c8c387deeeda7f0  gcc/flag-types.h
--- 6073,6079 ----
  0e60f266755de3aceb6aac0c955d9771  gcc/file-find.h
  776db52685d2e253eb6227b4cfac0b55  gcc/file-prefix-map.cc
  b0756a8dbbe0b39051dfda2c5e26663f  gcc/file-prefix-map.h
! 77b50b9533828ae8b124e191cc55b74f  gcc/final.cc
  28cc3b30502fab34fffa55fd82454e16  gcc/fixed-value.cc
  7852b04b41add4ad6cc7c7c86cb82658  gcc/fixed-value.h
  96975c8e38a86e287c8c387deeeda7f0  gcc/flag-types.h
*************** ada0afb884a142f8214291990679be13  gcc/fo
*** 6063,6069 ****
  6dd1484a5224f1070c3b6065080cb93d  gcc/fold-const.cc
  f23dec03425a07611492fa2c061cd7d2  gcc/fold-const.h
  cd4e6baf5d162fbd41160606055f8297  gcc/fold-mem-offsets.cc
! dbc6c48baeb4a524d39961220006c227  gcc/fortran/ChangeLog
  083c53fadafdcf3be46713838a51e36c  gcc/fortran/ChangeLog-2002
  2a4ca18d211fb2603139354fd16398ed  gcc/fortran/ChangeLog-2003
  e7462609ebd0dd7c874e0fc00e2833aa  gcc/fortran/ChangeLog-2004
--- 6083,6089 ----
  6dd1484a5224f1070c3b6065080cb93d  gcc/fold-const.cc
  f23dec03425a07611492fa2c061cd7d2  gcc/fold-const.h
  cd4e6baf5d162fbd41160606055f8297  gcc/fold-mem-offsets.cc
! 90715dd12a1681c4d9a5e4ce139a8c25  gcc/fortran/ChangeLog
  083c53fadafdcf3be46713838a51e36c  gcc/fortran/ChangeLog-2002
  2a4ca18d211fb2603139354fd16398ed  gcc/fortran/ChangeLog-2003
  e7462609ebd0dd7c874e0fc00e2833aa  gcc/fortran/ChangeLog-2004
*************** aed3aedb6378a970055dff9e11eedc2d  gcc/fo
*** 6100,6106 ****
  16ea0e15947038265fbb5983b455b7bf  gcc/fortran/constructor.cc
  85285f438769e841d8dc39fedcd731d5  gcc/fortran/constructor.h
  8a26ac4e9bbfcee3a5911bf1864ee2e6  gcc/fortran/convert.cc
! e2cec99de05b647cb16807fa80637b97  gcc/fortran/cpp.cc
  b7e224f665bb5044ce35ed09435bd4fb  gcc/fortran/cpp.h
  a232f4d280ad08511e2718281b3d1ab6  gcc/fortran/data.cc
  d85e2f2fc3ee4721563bd47719063fb6  gcc/fortran/data.h
--- 6120,6126 ----
  16ea0e15947038265fbb5983b455b7bf  gcc/fortran/constructor.cc
  85285f438769e841d8dc39fedcd731d5  gcc/fortran/constructor.h
  8a26ac4e9bbfcee3a5911bf1864ee2e6  gcc/fortran/convert.cc
! 72a18e3cbbefa104cd97e707657e5848  gcc/fortran/cpp.cc
  b7e224f665bb5044ce35ed09435bd4fb  gcc/fortran/cpp.h
  a232f4d280ad08511e2718281b3d1ab6  gcc/fortran/data.cc
  d85e2f2fc3ee4721563bd47719063fb6  gcc/fortran/data.h
*************** d85e2f2fc3ee4721563bd47719063fb6  gcc/fo
*** 6108,6120 ****
  c33e2c4c7527bec8a125dd093dc59f2a  gcc/fortran/dependency.cc
  70111b1c7592e650c281b513c3cf2f47  gcc/fortran/dependency.h
  b6cce6988f87edda182aec1b6c3cd291  gcc/fortran/dump-parse-tree.cc
! c7e7056eadbc33e368018f5bd15ae27e  gcc/fortran/error.cc
! db184b6596cd9f39834087b0dc7d0ed8  gcc/fortran/expr.cc
  4951d066b4086c9dc1486fd5e2dbe2c2  gcc/fortran/f95-lang.cc
  e188a9b3cb73106cab46a15d36a12b66  gcc/fortran/frontend-passes.cc
  a39f360f255f1ef6dfd91ccefef63e05  gcc/fortran/gfc-diagnostic.def
  bd08c55098f00394b9922e6163c27b92  gcc/fortran/gfc-internals.texi
! 03fba586e92d2a8043690f35ab3a54fc  gcc/fortran/gfortran.h
  d29bb6813221f46b4cde9df77292c412  gcc/fortran/gfortran.texi
  af66ab40a5434219772b76ad10035e45  gcc/fortran/gfortranspec.cc
  9253f176e44c2708e2c503251b27d6b8  gcc/fortran/interface.cc
--- 6128,6140 ----
  c33e2c4c7527bec8a125dd093dc59f2a  gcc/fortran/dependency.cc
  70111b1c7592e650c281b513c3cf2f47  gcc/fortran/dependency.h
  b6cce6988f87edda182aec1b6c3cd291  gcc/fortran/dump-parse-tree.cc
! 0aa273bc8ec396d25bbd76d19dd7d226  gcc/fortran/error.cc
! 2cf4f6db79ab50724953f10bfdf32831  gcc/fortran/expr.cc
  4951d066b4086c9dc1486fd5e2dbe2c2  gcc/fortran/f95-lang.cc
  e188a9b3cb73106cab46a15d36a12b66  gcc/fortran/frontend-passes.cc
  a39f360f255f1ef6dfd91ccefef63e05  gcc/fortran/gfc-diagnostic.def
  bd08c55098f00394b9922e6163c27b92  gcc/fortran/gfc-internals.texi
! 91fc8222c33fea62e8a0be1fb38de974  gcc/fortran/gfortran.h
  d29bb6813221f46b4cde9df77292c412  gcc/fortran/gfortran.texi
  af66ab40a5434219772b76ad10035e45  gcc/fortran/gfortranspec.cc
  9253f176e44c2708e2c503251b27d6b8  gcc/fortran/interface.cc
*************** e0ae917f78fe49a1e67153dca52a68b2  gcc/fo
*** 6138,6144 ****
  6e89e2e347d7f6e1576cbda0e958b5bd  gcc/fortran/misc.cc
  3b3c13f513e2236a6456d1d3b112404c  gcc/fortran/module.cc
  055cdc9c702c67c02729328aedac6553  gcc/fortran/openmp.cc
! 5f5bb791665584c12e186daf259f7cdf  gcc/fortran/options.cc
  f9dfcfe624705f792e9784bfbd2020f8  gcc/fortran/parse.cc
  c1b40e866a8bbe611aa65278fe2508d3  gcc/fortran/parse.h
  8282ea5f4e00d5c64da552ea2f31dcc6  gcc/fortran/primary.cc
--- 6158,6164 ----
  6e89e2e347d7f6e1576cbda0e958b5bd  gcc/fortran/misc.cc
  3b3c13f513e2236a6456d1d3b112404c  gcc/fortran/module.cc
  055cdc9c702c67c02729328aedac6553  gcc/fortran/openmp.cc
! 5b63ee69316bceb14ed8172adcfedf6b  gcc/fortran/options.cc
  f9dfcfe624705f792e9784bfbd2020f8  gcc/fortran/parse.cc
  c1b40e866a8bbe611aa65278fe2508d3  gcc/fortran/parse.h
  8282ea5f4e00d5c64da552ea2f31dcc6  gcc/fortran/primary.cc
*************** d78cc6d6b48b8228757fb8b674f6ad9b  gcc/fo
*** 6150,6162 ****
  7fc6fb7f159830fc0d98a9cd72e5cdf9  gcc/fortran/symbol.cc
  c9238712914e77b971fde08221a31bf7  gcc/fortran/target-memory.cc
  50451f5a575ab606948f8e72d8cc4721  gcc/fortran/target-memory.h
! f46b8f88b0634e92490a82980d24996c  gcc/fortran/trans-array.cc
  a4f5f15bbfd3cf3b780e3a8875ebf0df  gcc/fortran/trans-array.h
  134a72b3349d427eccb35198acc48a71  gcc/fortran/trans-common.cc
  d555f911945a83db335013815934e941  gcc/fortran/trans-const.cc
  857805820c2a6ac77d2652c610d23de8  gcc/fortran/trans-const.h
! d8e305ea46f72c347ae93f0ab9d8337a  gcc/fortran/trans-decl.cc
! 67d9ed79c93a6bd0af7ea803b4387c72  gcc/fortran/trans-expr.cc
  3ad3e35ee05a5e83c9c5fde26d452722  gcc/fortran/trans-intrinsic.cc
  9cf7c294c06fdaea67dcd2b9ff2cf5ad  gcc/fortran/trans-io.cc
  ec953a4922656d79301eb36337b9d297  gcc/fortran/trans-openmp.cc
--- 6170,6182 ----
  7fc6fb7f159830fc0d98a9cd72e5cdf9  gcc/fortran/symbol.cc
  c9238712914e77b971fde08221a31bf7  gcc/fortran/target-memory.cc
  50451f5a575ab606948f8e72d8cc4721  gcc/fortran/target-memory.h
! f6644c278d429d90b5c23f7a262fd118  gcc/fortran/trans-array.cc
  a4f5f15bbfd3cf3b780e3a8875ebf0df  gcc/fortran/trans-array.h
  134a72b3349d427eccb35198acc48a71  gcc/fortran/trans-common.cc
  d555f911945a83db335013815934e941  gcc/fortran/trans-const.cc
  857805820c2a6ac77d2652c610d23de8  gcc/fortran/trans-const.h
! 3e27bb8c98def7d0d88d99c5cc56209b  gcc/fortran/trans-decl.cc
! ab53841e23e9f06876e6658aeceb9c5d  gcc/fortran/trans-expr.cc
  3ad3e35ee05a5e83c9c5fde26d452722  gcc/fortran/trans-intrinsic.cc
  9cf7c294c06fdaea67dcd2b9ff2cf5ad  gcc/fortran/trans-io.cc
  ec953a4922656d79301eb36337b9d297  gcc/fortran/trans-openmp.cc
*************** f574663ce227d0be2e77015c008d708b  gcc/fp
*** 6172,6191 ****
  7d49ef8f960daad31201f864eb1933d9  gcc/function-abi.cc
  12d3c07e3c878f7237f904820da28c93  gcc/function-abi.h
  6e9698e4411a03357b6e2b60bc91c827  gcc/function-tests.cc
! 1e983b0fc4c9627399efe21cd7b21863  gcc/function.cc
  da5d04420f440a4a085dc91d92c6bfbb  gcc/function.h
  3c08c56c1de3b165b954ab5c185284c5  gcc/fwprop.cc
  261433f3124bfa2a1421c42d657e0560  gcc/gcc-ar.cc
  97d2a41e7dd932e9ed72779b8745c81b  gcc/gcc-attribute-urlifier.cc
  ff36560b7e36617656e4dc3e8c550bf9  gcc/gcc-main.cc
  d34323b4d6fe1da82a9a4c157463d875  gcc/gcc-plugin.h
! 7363d36fbbd8919e19ab1c637e88d477  gcc/gcc-rich-location.cc
! 93234d5c1bba7882e07ba0a48cf8c8cf  gcc/gcc-rich-location.h
  63e27f828f6c936425703eb7f757958f  gcc/gcc-symtab.h
  74b8852724cd126309c2e814288bcaa4  gcc/gcc-urlifier.cc
  3ba51d67080efcd8791ea2eaf4103d72  gcc/gcc-urlifier.def
  7e2f3c81fe7c2381b433886ab2914fa7  gcc/gcc-urlifier.h
! f4276d234689e2787662f11ea4bcaffc  gcc/gcc.cc
  265ae8f124014a92ca7dee798d9c2b46  gcc/gcc.h
  d66e80f2ea9c1b6754479c999040b857  gcc/gcov-counter.def
  c4e07547b91be991d1bed6c22015cec2  gcc/gcov-dump.cc
--- 6192,6213 ----
  7d49ef8f960daad31201f864eb1933d9  gcc/function-abi.cc
  12d3c07e3c878f7237f904820da28c93  gcc/function-abi.h
  6e9698e4411a03357b6e2b60bc91c827  gcc/function-tests.cc
! dfdecc354c7e8c25aafb6cdbf17fc6c9  gcc/function.cc
  da5d04420f440a4a085dc91d92c6bfbb  gcc/function.h
  3c08c56c1de3b165b954ab5c185284c5  gcc/fwprop.cc
  261433f3124bfa2a1421c42d657e0560  gcc/gcc-ar.cc
  97d2a41e7dd932e9ed72779b8745c81b  gcc/gcc-attribute-urlifier.cc
+ e696a72487df5d8b9fd75688c88ff4aa  gcc/gcc-diagnostic-spec.cc
+ a53814de8b38cf15460e3f5a91a5e9a4  gcc/gcc-diagnostic-spec.h
  ff36560b7e36617656e4dc3e8c550bf9  gcc/gcc-main.cc
  d34323b4d6fe1da82a9a4c157463d875  gcc/gcc-plugin.h
! 534ebaaadaef86678ef8119a8a59528b  gcc/gcc-rich-location.cc
! cac72ec7acd3c0b9265d75c09766a847  gcc/gcc-rich-location.h
  63e27f828f6c936425703eb7f757958f  gcc/gcc-symtab.h
  74b8852724cd126309c2e814288bcaa4  gcc/gcc-urlifier.cc
  3ba51d67080efcd8791ea2eaf4103d72  gcc/gcc-urlifier.def
  7e2f3c81fe7c2381b433886ab2914fa7  gcc/gcc-urlifier.h
! c7818a207477a46ba26dcc5ce756de71  gcc/gcc.cc
  265ae8f124014a92ca7dee798d9c2b46  gcc/gcc.h
  d66e80f2ea9c1b6754479c999040b857  gcc/gcov-counter.def
  c4e07547b91be991d1bed6c22015cec2  gcc/gcov-dump.cc
*************** a44c1a607d9b75afc7b5bd869ae5342a  gcc/gc
*** 6199,6205 ****
  e5a3a3a1ad466d441c8c2f6c2ac6c208  gcc/gcse.h
  af83e4b4719ee065872080b713d24c2f  gcc/gdbasan.in
  73e9039221d34e77933a5626ce0294a5  gcc/gdbhooks.py
! b946235d2457563312c112ed6a14ed7e  gcc/gdbinit.in
  bc7dc03662da0207b2f137311e3d44ff  gcc/gen-pass-instances.awk
  243e310c8de5ec89a275b8a8fdaa3f23  gcc/genattr-common.cc
  9609960ab8977cec04088a4a80a047db  gcc/genattr.cc
--- 6221,6227 ----
  e5a3a3a1ad466d441c8c2f6c2ac6c208  gcc/gcse.h
  af83e4b4719ee065872080b713d24c2f  gcc/gdbasan.in
  73e9039221d34e77933a5626ce0294a5  gcc/gdbhooks.py
! 4a86e68e2feba4a0e46f5d39616a00ae  gcc/gdbinit.in
  bc7dc03662da0207b2f137311e3d44ff  gcc/gen-pass-instances.awk
  243e310c8de5ec89a275b8a8fdaa3f23  gcc/genattr-common.cc
  9609960ab8977cec04088a4a80a047db  gcc/genattr.cc
*************** a5a23bee543191529294d325e1de0424  gcc/ge
*** 6222,6228 ****
  f08758617a3d032ae009840210c23753  gcc/gengtype-lex.l
  8b99c04e54d5d4377c4fbf3dcab54659  gcc/gengtype-parse.cc
  fc2add74b25837de88ed3c40f4f1193d  gcc/gengtype-state.cc
! f1606c6699e344ee4dc5c689c8bd5c4f  gcc/gengtype.cc
  f8db11f7873a70ad5009e0d6d239f1c8  gcc/gengtype.h
  874e9cb69e600858eae535758d8a1440  gcc/genhooks.cc
  f462d5a18a683a40d6f1e731674d483f  gcc/genmatch.cc
--- 6244,6250 ----
  f08758617a3d032ae009840210c23753  gcc/gengtype-lex.l
  8b99c04e54d5d4377c4fbf3dcab54659  gcc/gengtype-parse.cc
  fc2add74b25837de88ed3c40f4f1193d  gcc/gengtype-state.cc
! 1e163a15894754209927f6da377f7eb3  gcc/gengtype.cc
  f8db11f7873a70ad5009e0d6d239f1c8  gcc/gengtype.h
  874e9cb69e600858eae535758d8a1440  gcc/genhooks.cc
  f462d5a18a683a40d6f1e731674d483f  gcc/genmatch.cc
*************** a97b3578ac581dcde94c740fbde65486  gcc/ge
*** 6231,6239 ****
  2d5f79e0543565e8a2c55a08a6ba8393  gcc/genmodes.cc
  78862d5c4a5e1a707d3e63e4857adb04  gcc/genmultilib
  eb743d2855e55ff1778bae601dc38551  gcc/genopinit.cc
! 9148adb889b52d0f37320b52603ebab6  gcc/genoutput.cc
  29ee68ccc9844e3580e3e9f6da577778  gcc/genpeep.cc
! 28d50caf61c98bed97742228c437ee13  gcc/genpreds.cc
  7ef07a14a26d6ca95f84a510ac497b42  gcc/genrecog.cc
  a9256309230010e93a8b24790769ea6d  gcc/gensupport.cc
  5dcde5b50273b87ac36d108b0a6fe1df  gcc/gensupport.h
--- 6253,6261 ----
  2d5f79e0543565e8a2c55a08a6ba8393  gcc/genmodes.cc
  78862d5c4a5e1a707d3e63e4857adb04  gcc/genmultilib
  eb743d2855e55ff1778bae601dc38551  gcc/genopinit.cc
! 697e0460c5aaa13d0d52fcc0000b409c  gcc/genoutput.cc
  29ee68ccc9844e3580e3e9f6da577778  gcc/genpeep.cc
! b940d92348f0952ba35f08f1992dce11  gcc/genpreds.cc
  7ef07a14a26d6ca95f84a510ac497b42  gcc/genrecog.cc
  a9256309230010e93a8b24790769ea6d  gcc/gensupport.cc
  5dcde5b50273b87ac36d108b0a6fe1df  gcc/gensupport.h
*************** c33f19efabf2e1331a65e467f6a2e7fc  gcc/gi
*** 6314,6329 ****
  7f8c492dbd88d8d371f858c251bb8d5c  gcc/gimple-streamer-in.cc
  c46e71acb17764a720ac6a68007b7298  gcc/gimple-streamer-out.cc
  469e775c51a02638e22300d5645b22ce  gcc/gimple-streamer.h
! fc5706ae421aa8f2f9bba7fe2c637237  gcc/gimple-walk.cc
  898d5f9cd9c732cb06cb7e84ca28c99b  gcc/gimple-walk.h
  19e41ad97511268bfc78109e4dbf8065  gcc/gimple-warn-recursion.cc
  b42b320008114fef074bfc7fdb234491  gcc/gimple.cc
  2b31c9448b3ca4914742ffde943425c0  gcc/gimple.def
  0d2ea6d085781aa930769ca37d5d3a08  gcc/gimple.h
! 140b5c45a362b9c0c981b683560d4ef8  gcc/gimplify-me.cc
  84814cb09300f3db388dd0d22133ccb4  gcc/gimplify-me.h
! 73e34bd428b8e4493a229bf917e9eda5  gcc/gimplify.cc
  06f2b5470f6bc6f77e9b7966e34e5785  gcc/gimplify.h
  7df17d7c2bcdff0a474d633a02195544  gcc/ginclude/float.h
  d22f0a286107015428c4b28c0d17abda  gcc/ginclude/iso646.h
  dbde1f58891027c57962904adf116dea  gcc/ginclude/stdalign.h
--- 6336,6352 ----
  7f8c492dbd88d8d371f858c251bb8d5c  gcc/gimple-streamer-in.cc
  c46e71acb17764a720ac6a68007b7298  gcc/gimple-streamer-out.cc
  469e775c51a02638e22300d5645b22ce  gcc/gimple-streamer.h
! b5b13ba4f92b3ef5294cee911b571925  gcc/gimple-walk.cc
  898d5f9cd9c732cb06cb7e84ca28c99b  gcc/gimple-walk.h
  19e41ad97511268bfc78109e4dbf8065  gcc/gimple-warn-recursion.cc
  b42b320008114fef074bfc7fdb234491  gcc/gimple.cc
  2b31c9448b3ca4914742ffde943425c0  gcc/gimple.def
  0d2ea6d085781aa930769ca37d5d3a08  gcc/gimple.h
! 69057cf60d71bd04ced5e457138629e1  gcc/gimplify-me.cc
  84814cb09300f3db388dd0d22133ccb4  gcc/gimplify-me.h
! 026a1d7476de3f8ac1dfff54fe5d301d  gcc/gimplify.cc
  06f2b5470f6bc6f77e9b7966e34e5785  gcc/gimplify.h
+ ba3039c0ed9645080c52c0d4bc46096f  gcc/gimplify_reg_info.h
  7df17d7c2bcdff0a474d633a02195544  gcc/ginclude/float.h
  d22f0a286107015428c4b28c0d17abda  gcc/ginclude/iso646.h
  dbde1f58891027c57962904adf116dea  gcc/ginclude/stdalign.h
*************** f380ce65b15eedb6d55a9848beb1ec3b  gcc/in
*** 6452,6465 ****
  a82ca6f10995888441918acc568477fc  gcc/incpath.cc
  078efe9e89bf7fcd6a66cd085de2d676  gcc/incpath.h
  9d517f2c2919033bb8c4d62108dd6973  gcc/init-regs.cc
! b3d2e0a4fdb1acc7d7c1d1222ec7077d  gcc/input.cc
! 61ec39febc0596c9836bf3c2bd87907c  gcc/input.h
  0dc4e5a1c70a5b34153b06594dd3ae85  gcc/insn-addr.h
  eec072fb4c8277a3634cf4cdc0846598  gcc/insn-notes.def
  769443add1b7187045688cd8b1129647  gcc/int-vector-builder.h
! 072b5fe703f4a0dcbcfb4af0dff9645b  gcc/internal-fn.cc
  9f50a396585727515baa235ec39f1f04  gcc/internal-fn.def
! ef535a32c5b6f227a666c63523f6bb80  gcc/internal-fn.h
  bcb802c64e78f80e8e46c799c7e449ad  gcc/intl.cc
  deb111e00b2b07aa631595045bce5003  gcc/intl.h
  47a65e558aff89879902e88b055c7b12  gcc/ipa-comdats.cc
--- 6475,6488 ----
  a82ca6f10995888441918acc568477fc  gcc/incpath.cc
  078efe9e89bf7fcd6a66cd085de2d676  gcc/incpath.h
  9d517f2c2919033bb8c4d62108dd6973  gcc/init-regs.cc
! ed81054ca33b28b1e20c8ccfb921eb10  gcc/input.cc
! 846f20b3f20d9b8d41c137612dbdd8dc  gcc/input.h
  0dc4e5a1c70a5b34153b06594dd3ae85  gcc/insn-addr.h
  eec072fb4c8277a3634cf4cdc0846598  gcc/insn-notes.def
  769443add1b7187045688cd8b1129647  gcc/int-vector-builder.h
! 76df3f73b405209726466587252d27ce  gcc/internal-fn.cc
  9f50a396585727515baa235ec39f1f04  gcc/internal-fn.def
! 1a0765d6579bac8e055ff735b357f45d  gcc/internal-fn.h
  bcb802c64e78f80e8e46c799c7e449ad  gcc/intl.cc
  deb111e00b2b07aa631595045bce5003  gcc/intl.h
  47a65e558aff89879902e88b055c7b12  gcc/ipa-comdats.cc
*************** d33136e7edecd120aa035f0e1ad240b0  gcc/ip
*** 6491,6497 ****
  fa8b12710ac89ee0802b55aec4fe4cda  gcc/ipa-profile.cc
  be8b91a88b033749209c11844ab4ebd7  gcc/ipa-prop.cc
  769c7da3be6c74b69be2f9572626e59f  gcc/ipa-prop.h
! 1ab3b52af464e998b39403664a5ee0c4  gcc/ipa-pure-const.cc
  ce0496bede6d40e2fcfbc8277856fc23  gcc/ipa-ref.cc
  ee6c4ff9a86c5d0a68fa41c8da2b5c6f  gcc/ipa-ref.h
  e02101954d14c2f0b6a7667db7690ade  gcc/ipa-reference.cc
--- 6514,6520 ----
  fa8b12710ac89ee0802b55aec4fe4cda  gcc/ipa-profile.cc
  be8b91a88b033749209c11844ab4ebd7  gcc/ipa-prop.cc
  769c7da3be6c74b69be2f9572626e59f  gcc/ipa-prop.h
! 33f941deca3150b6ccaa310cd69f68f2  gcc/ipa-pure-const.cc
  ce0496bede6d40e2fcfbc8277856fc23  gcc/ipa-ref.cc
  ee6c4ff9a86c5d0a68fa41c8da2b5c6f  gcc/ipa-ref.h
  e02101954d14c2f0b6a7667db7690ade  gcc/ipa-reference.cc
*************** a6162cabbfeb130d9e619b6dc2676776  gcc/ir
*** 6511,6521 ****
  ed94ab1f6976f64c8d20b7b65da14438  gcc/ira-emit.cc
  43cca7ef68de29884afbceb8e3fa19bb  gcc/ira-int.h
  947f563def1cc07c1f6d1def7fbdf142  gcc/ira-lives.cc
! beaf75ec60bb1985c10c2c6c1f98ebd6  gcc/ira.cc
  e02a7a08ca9acaac686d9cb897ac121b  gcc/ira.h
  101bad313081e351312c8d42e0b24b31  gcc/is-a.h
  4e832d29f0e621d177da3fa9c3e11b69  gcc/iterator-utils.h
! d4e897bb7165cf761df2e86e0c455408  gcc/jit/ChangeLog
  6071bdf04fb356c5ac99a99ec00c9a12  gcc/jit/ChangeLog.jit
  40388d7c9424c7364e6ace25461e381e  gcc/jit/Make-lang.in
  fd0d76b6467c987f813d430a35d4760a  gcc/jit/TODO.rst
--- 6534,6544 ----
  ed94ab1f6976f64c8d20b7b65da14438  gcc/ira-emit.cc
  43cca7ef68de29884afbceb8e3fa19bb  gcc/ira-int.h
  947f563def1cc07c1f6d1def7fbdf142  gcc/ira-lives.cc
! c199b1c0b9259e2411da29e6ad6f1ba5  gcc/ira.cc
  e02a7a08ca9acaac686d9cb897ac121b  gcc/ira.h
  101bad313081e351312c8d42e0b24b31  gcc/is-a.h
  4e832d29f0e621d177da3fa9c3e11b69  gcc/iterator-utils.h
! b3324595dfde644ae738bd923f6c771f  gcc/jit/ChangeLog
  6071bdf04fb356c5ac99a99ec00c9a12  gcc/jit/ChangeLog.jit
  40388d7c9424c7364e6ace25461e381e  gcc/jit/Make-lang.in
  fd0d76b6467c987f813d430a35d4760a  gcc/jit/TODO.rst
*************** dab4dd8e541f9d4c6422eb806e0bfcec  gcc/ji
*** 6579,6593 ****
  770a03b89b33245a768643117a02362f  gcc/jit/docs/topics/objects.rst
  7055e31ff2b8438e10a1c81fa9da98e1  gcc/jit/docs/topics/performance.rst
  fc1e7581ada3a6da480f75ac6b2b475c  gcc/jit/docs/topics/types.rst
! 8b26a683cd09ccd872ac935f98eb35bc  gcc/jit/dummy-frontend.cc
  76b7395b4989eb6c5e3bd7902fa470e5  gcc/jit/jit-builtins.cc
  11f041f38ecb2e1facf846f0441467a3  gcc/jit/jit-builtins.h
  e1c3d6e61769638ca605182151b74fc4  gcc/jit/jit-common.h
  2cd46a46000f2977ffb0f8cdcedfe27b  gcc/jit/jit-dejagnu.h
  d1ecf9f1fa6c7b403bac530b8d4536ca  gcc/jit/jit-logging.cc
  45e3e913a08f0789f718ae5e5a0d44c6  gcc/jit/jit-logging.h
! 2b4f980caf34069ceab3005ffee109e9  gcc/jit/jit-playback.cc
! 9f258004ae27b0419c8b3e2feea5d4f3  gcc/jit/jit-playback.h
  e0a4fc4ec36c10b296bd3e4dd66259ae  gcc/jit/jit-recording.cc
  0136c2352b4d9079f9ba133490e0014d  gcc/jit/jit-recording.h
  76d67feccd94f3bac32d69f32462dc16  gcc/jit/jit-result.cc
--- 6602,6616 ----
  770a03b89b33245a768643117a02362f  gcc/jit/docs/topics/objects.rst
  7055e31ff2b8438e10a1c81fa9da98e1  gcc/jit/docs/topics/performance.rst
  fc1e7581ada3a6da480f75ac6b2b475c  gcc/jit/docs/topics/types.rst
! 7b86408db4b0bf74d9f8a052dd9c61a4  gcc/jit/dummy-frontend.cc
  76b7395b4989eb6c5e3bd7902fa470e5  gcc/jit/jit-builtins.cc
  11f041f38ecb2e1facf846f0441467a3  gcc/jit/jit-builtins.h
  e1c3d6e61769638ca605182151b74fc4  gcc/jit/jit-common.h
  2cd46a46000f2977ffb0f8cdcedfe27b  gcc/jit/jit-dejagnu.h
  d1ecf9f1fa6c7b403bac530b8d4536ca  gcc/jit/jit-logging.cc
  45e3e913a08f0789f718ae5e5a0d44c6  gcc/jit/jit-logging.h
! d8c6e4c3dcaa7abf23f3eb2b537031b8  gcc/jit/jit-playback.cc
! 153851e635fe147cd9ebec79032f140c  gcc/jit/jit-playback.h
  e0a4fc4ec36c10b296bd3e4dd66259ae  gcc/jit/jit-recording.cc
  0136c2352b4d9079f9ba133490e0014d  gcc/jit/jit-recording.h
  76d67feccd94f3bac32d69f32462dc16  gcc/jit/jit-result.cc
*************** aa4d0dc684f454901e907706abe9140d  gcc/js
*** 6608,6628 ****
  5795b18f6b7644bbcfadbe147ba58909  gcc/json.cc
  96e080f101e620931eac6ae509674dd3  gcc/json.h
  47f18749c5685cd9ae918c4288aa5bf4  gcc/jump.cc
! f74891b3d3f9b6b3e0cbe66a7252cd83  gcc/langhooks-def.h
! fffab8c77115c6471e5e10dea11739e1  gcc/langhooks.cc
! 5918c7467c079a50e076e834bb3839c7  gcc/langhooks.h
  75deba840ba0746416d8a7516027f7b7  gcc/late-combine.cc
! 4e66997286420d91228be7e74c158c9f  gcc/lazy-diagnostic-path.cc
! dc9c6fb11d3b3fffe354eff3daf0454c  gcc/lazy-diagnostic-path.h
  82e3d15b2545a4e7a7397d6396eb74fe  gcc/lcm.cc
  bdf8ae675ae5000d854fe2874116b2f8  gcc/lcm.h
  027270d0be504f25a7efb49e1e3179bb  gcc/libfuncs.h
  4934dab1d3161ae645ccdd3dac3052e5  gcc/libgdiagnostics++.h
  bce08e1b835bdbc920273360f191e171  gcc/libgdiagnostics-private.h
! 50ac57870c0750f8487e1ad7668dd606  gcc/libgdiagnostics.cc
  ca1796ca207d8fcda43cdef3d49a39fb  gcc/libgdiagnostics.h
  02da43cd6bde252a34ecb0feb6468592  gcc/libgdiagnostics.map
! b880ba39f0ac4bfd6f9a6202231ebada  gcc/libsarifreplay.cc
  5e320a3249f5b8b266e2c69c6282315e  gcc/libsarifreplay.h
  5c6a6e21474ca46c652e3149d4068fe3  gcc/limitx.h
  83de5c6450456e215a5484083afcd32a  gcc/limity.h
--- 6631,6650 ----
  5795b18f6b7644bbcfadbe147ba58909  gcc/json.cc
  96e080f101e620931eac6ae509674dd3  gcc/json.h
  47f18749c5685cd9ae918c4288aa5bf4  gcc/jump.cc
! d0727ac0c6842b68e046f42e27e66165  gcc/langhooks-def.h
! 4d0a0855b356aa25be607aaf932bde59  gcc/langhooks.cc
! 7899320dd5da16cc68d6f63cd8d5ddf9  gcc/langhooks.h
  75deba840ba0746416d8a7516027f7b7  gcc/late-combine.cc
! de8c4845432dd4e64d6fa53d34cb4a09  gcc/lazily-created.h
  82e3d15b2545a4e7a7397d6396eb74fe  gcc/lcm.cc
  bdf8ae675ae5000d854fe2874116b2f8  gcc/lcm.h
  027270d0be504f25a7efb49e1e3179bb  gcc/libfuncs.h
  4934dab1d3161ae645ccdd3dac3052e5  gcc/libgdiagnostics++.h
  bce08e1b835bdbc920273360f191e171  gcc/libgdiagnostics-private.h
! b31bd4d16ac593d8cc91a8dee4e41f82  gcc/libgdiagnostics.cc
  ca1796ca207d8fcda43cdef3d49a39fb  gcc/libgdiagnostics.h
  02da43cd6bde252a34ecb0feb6468592  gcc/libgdiagnostics.map
! a612b9f7ada478641e333f1730120dfc  gcc/libsarifreplay.cc
  5e320a3249f5b8b266e2c69c6282315e  gcc/libsarifreplay.h
  5c6a6e21474ca46c652e3149d4068fe3  gcc/limitx.h
  83de5c6450456e215a5484083afcd32a  gcc/limity.h
*************** b880ba39f0ac4bfd6f9a6202231ebada  gcc/li
*** 6630,6636 ****
  30b8e3e407f46ad2cb39260ec4bab9f6  gcc/lock-and-run.sh
  7bf480c85a74d6690a5657de1434aef1  gcc/lockfile.cc
  03fdf33413400a8644c324d657debba0  gcc/lockfile.h
- a65e9a278dce075c0c22b4a9aa5c3a37  gcc/logical-location.h
  0816d05453d7e9ce04f5d1bd97b7872b  gcc/loop-doloop.cc
  154eba32ec80f6804e8861149e26652c  gcc/loop-init.cc
  6e39bd9aab94c794b8cc992d0cadd9ae  gcc/loop-invariant.cc
--- 6652,6657 ----
*************** b54054c495232a416b1cdea9032d1d9f  gcc/lo
*** 6641,6647 ****
  05bf78e6d3e36587723b1177ffcd9c6e  gcc/lower-subreg.h
  755a196fed2cd7b5878159035d75b39b  gcc/lra-assigns.cc
  0232e051e662ebb7fd2fa507d9c581b8  gcc/lra-coalesce.cc
! 143761c4da81475ca25d3233f368bc8f  gcc/lra-constraints.cc
  ebe278d864d3a7e33fbcc46f02926248  gcc/lra-eliminations.cc
  c9f048755e3742fbe86e02e2b4b1eb6d  gcc/lra-int.h
  52ba28cd117bff034bd9a26fe150f692  gcc/lra-lives.cc
--- 6662,6668 ----
  05bf78e6d3e36587723b1177ffcd9c6e  gcc/lower-subreg.h
  755a196fed2cd7b5878159035d75b39b  gcc/lra-assigns.cc
  0232e051e662ebb7fd2fa507d9c581b8  gcc/lra-coalesce.cc
! 59453d363dea8462e92bbe1acae9b308  gcc/lra-constraints.cc
  ebe278d864d3a7e33fbcc46f02926248  gcc/lra-eliminations.cc
  c9f048755e3742fbe86e02e2b4b1eb6d  gcc/lra-int.h
  52ba28cd117bff034bd9a26fe150f692  gcc/lra-lives.cc
*************** f2a9985147f87fd566d4ae2dd8fceabc  gcc/lt
*** 6662,6668 ****
  295f167dcf44ebe2d16bceae99571c42  gcc/lto-streamer-out.cc
  8caf9a68892d64dc294b20c27291b749  gcc/lto-streamer.cc
  89440b8d71857e40c8fa12dd9aa25491  gcc/lto-streamer.h
! e94a0111912c76e65824bb88bf99f44c  gcc/lto-wrapper.cc
  480bc7be0cd5b12023154916672aeb69  gcc/lto/ChangeLog
  e33b56ae6d73ecb6b658dd2ffff4202a  gcc/lto/Make-lang.in
  705d8eaa74b456d79367c2c42b7a2fef  gcc/lto/common.cc
--- 6683,6689 ----
  295f167dcf44ebe2d16bceae99571c42  gcc/lto-streamer-out.cc
  8caf9a68892d64dc294b20c27291b749  gcc/lto-streamer.cc
  89440b8d71857e40c8fa12dd9aa25491  gcc/lto-streamer.h
! b5a651e1f0e9206664f446c212ff89c9  gcc/lto-wrapper.cc
  480bc7be0cd5b12023154916672aeb69  gcc/lto/ChangeLog
  e33b56ae6d73ecb6b658dd2ffff4202a  gcc/lto/Make-lang.in
  705d8eaa74b456d79367c2c42b7a2fef  gcc/lto/common.cc
*************** e44c0bf9cc0411d7bd57c6585eb6d0e4  gcc/lt
*** 6687,6693 ****
  b417a4bd52371186803e70c49d24764d  gcc/m2/COPYING.RUNTIME
  8f0e2cd40e05189ec81232da84bd6e1a  gcc/m2/COPYING3
  6a6a8e020838b23406c81b19c1d46df6  gcc/m2/COPYING3.LIB
! aaffdd064a07b0d2264930fa08c87dfb  gcc/m2/ChangeLog
  33352ea845a8d2399793299f3e58a218  gcc/m2/Make-lang.in
  93fe99bf456561cd217f1c93d2ab7da7  gcc/m2/Make-maintainer.in
  6a74129fda00ca52ba9f953538250c45  gcc/m2/NEWS
--- 6708,6714 ----
  b417a4bd52371186803e70c49d24764d  gcc/m2/COPYING.RUNTIME
  8f0e2cd40e05189ec81232da84bd6e1a  gcc/m2/COPYING3
  6a6a8e020838b23406c81b19c1d46df6  gcc/m2/COPYING3.LIB
! edf1b3ab9c68795daea614582a20ecd6  gcc/m2/ChangeLog
  33352ea845a8d2399793299f3e58a218  gcc/m2/Make-lang.in
  93fe99bf456561cd217f1c93d2ab7da7  gcc/m2/Make-maintainer.in
  6a74129fda00ca52ba9f953538250c45  gcc/m2/NEWS
*************** b347f8b97c2042773c008adffe4e54d9  gcc/m2
*** 6813,6831 ****
  602cc39ece2e20e647562bea41cf5716  gcc/m2/gm2-compiler/P1Build.bnf
  7f0d77f27044b69065c97e7e1f2f361b  gcc/m2/gm2-compiler/P1Build.def
  022dddb1d109a1c84112ee601cb7e4fb  gcc/m2/gm2-compiler/P1SymBuild.def
! f84c328e57949cf1d3f9714ac54e6423  gcc/m2/gm2-compiler/P1SymBuild.mod
  dfc36d5f0832b9dd188d6557ffef76d3  gcc/m2/gm2-compiler/P2Build.bnf
  5d3aa3c32f62966992c31b5bd6fe9bdb  gcc/m2/gm2-compiler/P2Build.def
  7d034c383eee29111871cfe944a77b96  gcc/m2/gm2-compiler/P2SymBuild.def
! caa873bb1109b87a03db4edde0bca2dc  gcc/m2/gm2-compiler/P2SymBuild.mod
  3fd9aa5301c284bb3b4ee2d6479b711b  gcc/m2/gm2-compiler/P3Build.bnf
  41f585d1e8e6fd1786dd36cb69cf3e82  gcc/m2/gm2-compiler/P3Build.def
  ad7a010b25f95dc012f12d3c97133a4b  gcc/m2/gm2-compiler/P3SymBuild.def
! feac1271dd2de34f953140b4b62a2c73  gcc/m2/gm2-compiler/P3SymBuild.mod
  e00cf6ed8d0c099ab8f33394bfeb4dc3  gcc/m2/gm2-compiler/PCBuild.bnf
  428e2092f5708fd9cf986ae14771fff1  gcc/m2/gm2-compiler/PCBuild.def
  333e3b954ec138cdfb9ac52c7fc37ee9  gcc/m2/gm2-compiler/PCSymBuild.def
! e524773f84b80cb2ecbe501fc5711e67  gcc/m2/gm2-compiler/PCSymBuild.mod
  08d1991abfb4f71b76010396a93251eb  gcc/m2/gm2-compiler/PHBuild.bnf
  08361e38dfa7f065be723afaa04d8986  gcc/m2/gm2-compiler/PHBuild.def
  b521bc37b844fd46fdfddcf3d2287f13  gcc/m2/gm2-compiler/PathName.def
--- 6834,6852 ----
  602cc39ece2e20e647562bea41cf5716  gcc/m2/gm2-compiler/P1Build.bnf
  7f0d77f27044b69065c97e7e1f2f361b  gcc/m2/gm2-compiler/P1Build.def
  022dddb1d109a1c84112ee601cb7e4fb  gcc/m2/gm2-compiler/P1SymBuild.def
! a034245ef0e759dd251bf062c90dbfb4  gcc/m2/gm2-compiler/P1SymBuild.mod
  dfc36d5f0832b9dd188d6557ffef76d3  gcc/m2/gm2-compiler/P2Build.bnf
  5d3aa3c32f62966992c31b5bd6fe9bdb  gcc/m2/gm2-compiler/P2Build.def
  7d034c383eee29111871cfe944a77b96  gcc/m2/gm2-compiler/P2SymBuild.def
! d6ca7bf00d339b38b18c4a9d412f0d77  gcc/m2/gm2-compiler/P2SymBuild.mod
  3fd9aa5301c284bb3b4ee2d6479b711b  gcc/m2/gm2-compiler/P3Build.bnf
  41f585d1e8e6fd1786dd36cb69cf3e82  gcc/m2/gm2-compiler/P3Build.def
  ad7a010b25f95dc012f12d3c97133a4b  gcc/m2/gm2-compiler/P3SymBuild.def
! 565aff18ea212b1dd1543f9c271ad130  gcc/m2/gm2-compiler/P3SymBuild.mod
  e00cf6ed8d0c099ab8f33394bfeb4dc3  gcc/m2/gm2-compiler/PCBuild.bnf
  428e2092f5708fd9cf986ae14771fff1  gcc/m2/gm2-compiler/PCBuild.def
  333e3b954ec138cdfb9ac52c7fc37ee9  gcc/m2/gm2-compiler/PCSymBuild.def
! 7204921904868e8be413f561906f6f54  gcc/m2/gm2-compiler/PCSymBuild.mod
  08d1991abfb4f71b76010396a93251eb  gcc/m2/gm2-compiler/PHBuild.bnf
  08361e38dfa7f065be723afaa04d8986  gcc/m2/gm2-compiler/PHBuild.def
  b521bc37b844fd46fdfddcf3d2287f13  gcc/m2/gm2-compiler/PathName.def
*************** fabfc816f99fb184266e92ed4a85b7a4  gcc/m2
*** 6837,6844 ****
  134ce3e4731c6306ad3c640bab2b256d  gcc/m2/gm2-compiler/SymbolConversion.mod
  7e7c5313b631435b03f974e72c20d104  gcc/m2/gm2-compiler/SymbolKey.def
  be245258e0123a45bbd9a47e859deb50  gcc/m2/gm2-compiler/SymbolKey.mod
! cf0941f82ecf4cf575e26e963235b675  gcc/m2/gm2-compiler/SymbolTable.def
! a0b7d3f4130fcfabdf1ce7311a3c9c7c  gcc/m2/gm2-compiler/SymbolTable.mod
  4e5bbaec9cd1341e4e14b9951485e75b  gcc/m2/gm2-compiler/bnflex.def
  34956a3ca2f84a677fbf711642452563  gcc/m2/gm2-compiler/bnflex.mod
  3ba721399af75ed8db2b223d9947d26d  gcc/m2/gm2-compiler/cflex.def
--- 6858,6865 ----
  134ce3e4731c6306ad3c640bab2b256d  gcc/m2/gm2-compiler/SymbolConversion.mod
  7e7c5313b631435b03f974e72c20d104  gcc/m2/gm2-compiler/SymbolKey.def
  be245258e0123a45bbd9a47e859deb50  gcc/m2/gm2-compiler/SymbolKey.mod
! 74520973769eed309d975fde57dfd937  gcc/m2/gm2-compiler/SymbolTable.def
! 020a16ce4cfedb7743487867d50fff0b  gcc/m2/gm2-compiler/SymbolTable.mod
  4e5bbaec9cd1341e4e14b9951485e75b  gcc/m2/gm2-compiler/bnflex.def
  34956a3ca2f84a677fbf711642452563  gcc/m2/gm2-compiler/bnflex.mod
  3ba721399af75ed8db2b223d9947d26d  gcc/m2/gm2-compiler/cflex.def
*************** feb359721fb6257ba2bf35f3036eb912  gcc/m2
*** 6864,6870 ****
  0abd581bbf48e46bf790eb67ffc47ad1  gcc/m2/gm2-gcc/m2builtins.cc
  e06b3bbf4040715ab6ee88cdd17886e4  gcc/m2/gm2-gcc/m2builtins.def
  a1d688331ef6553e581189d32227a73d  gcc/m2/gm2-gcc/m2builtins.h
! bc40b3fb10e0fb263164baa828a91fd1  gcc/m2/gm2-gcc/m2color.cc
  ca132f6d8454bc4c690072b56a3d8eb8  gcc/m2/gm2-gcc/m2color.def
  6fccaa4515b239badf614b27d2329d95  gcc/m2/gm2-gcc/m2color.h
  796c2c893ce45917d2edf672f2dc8523  gcc/m2/gm2-gcc/m2configure.cc
--- 6885,6891 ----
  0abd581bbf48e46bf790eb67ffc47ad1  gcc/m2/gm2-gcc/m2builtins.cc
  e06b3bbf4040715ab6ee88cdd17886e4  gcc/m2/gm2-gcc/m2builtins.def
  a1d688331ef6553e581189d32227a73d  gcc/m2/gm2-gcc/m2builtins.h
! 44c1ba8541fafa06f7271bd9bbe3a253  gcc/m2/gm2-gcc/m2color.cc
  ca132f6d8454bc4c690072b56a3d8eb8  gcc/m2/gm2-gcc/m2color.def
  6fccaa4515b239badf614b27d2329d95  gcc/m2/gm2-gcc/m2color.h
  796c2c893ce45917d2edf672f2dc8523  gcc/m2/gm2-gcc/m2configure.cc
*************** cb45da13a7101c6b9f63499a31c77142  gcc/m2
*** 6883,6889 ****
  d77ae5a027edcf4593595afe73be800b  gcc/m2/gm2-gcc/m2expr.def
  d3b9f0202b6a0cc04b90bd4efdd4471d  gcc/m2/gm2-gcc/m2expr.h
  3c3bbf0b28f81bc0a6bb40b29c511e8f  gcc/m2/gm2-gcc/m2langdump.h
! baf94cac8cc605d24a47a02c810f4464  gcc/m2/gm2-gcc/m2linemap.cc
  bac8f292255c366257842d90edd29842  gcc/m2/gm2-gcc/m2linemap.def
  fcea7fa814eb36ddef577d6be2c93e63  gcc/m2/gm2-gcc/m2linemap.h
  5788cdee0acc63304e8a5005f050e8db  gcc/m2/gm2-gcc/m2misc.cc
--- 6904,6910 ----
  d77ae5a027edcf4593595afe73be800b  gcc/m2/gm2-gcc/m2expr.def
  d3b9f0202b6a0cc04b90bd4efdd4471d  gcc/m2/gm2-gcc/m2expr.h
  3c3bbf0b28f81bc0a6bb40b29c511e8f  gcc/m2/gm2-gcc/m2langdump.h
! 03afb6ebe067bff08fd4da75c78b5382  gcc/m2/gm2-gcc/m2linemap.cc
  bac8f292255c366257842d90edd29842  gcc/m2/gm2-gcc/m2linemap.def
  fcea7fa814eb36ddef577d6be2c93e63  gcc/m2/gm2-gcc/m2linemap.h
  5788cdee0acc63304e8a5005f050e8db  gcc/m2/gm2-gcc/m2misc.cc
*************** fa235ac656c58414068acb39a450b98c  gcc/m2
*** 6910,6916 ****
  bbeb8468025c6ed85f1eb7d99fd18660  gcc/m2/gm2-gcc/m2type.cc
  651712327499570038a843c898f0f1c7  gcc/m2/gm2-gcc/m2type.def
  7214f01ef0c4f2ea27236613dbb9349b  gcc/m2/gm2-gcc/m2type.h
! 106f1b090f7263f437e9846c550f589a  gcc/m2/gm2-gcc/rtegraph.cc
  65065f39d7a055627ba2d372c1e9cc07  gcc/m2/gm2-gcc/rtegraph.h
  b014a5a5babb9953d9f203bf4fd10046  gcc/m2/gm2-ici/M2Emit.mod
  d5db4a0704741e24958241fe74fd007c  gcc/m2/gm2-ici/README
--- 6931,6937 ----
  bbeb8468025c6ed85f1eb7d99fd18660  gcc/m2/gm2-gcc/m2type.cc
  651712327499570038a843c898f0f1c7  gcc/m2/gm2-gcc/m2type.def
  7214f01ef0c4f2ea27236613dbb9349b  gcc/m2/gm2-gcc/m2type.h
! 86657d918610ac339071aadeefa0b552  gcc/m2/gm2-gcc/rtegraph.cc
  65065f39d7a055627ba2d372c1e9cc07  gcc/m2/gm2-gcc/rtegraph.h
  b014a5a5babb9953d9f203bf4fd10046  gcc/m2/gm2-ici/M2Emit.mod
  d5db4a0704741e24958241fe74fd007c  gcc/m2/gm2-ici/README
*************** c7eadbee0c5ae61a47b11bbb7c04941d  gcc/m2
*** 7209,7215 ****
  3d47773d0b2a2e842bc90ce1817ec304  gcc/m2/gm2-libs/M2Dependent.def
  3c65d10228392609f0596c9f655c18aa  gcc/m2/gm2-libs/M2Dependent.mod
  503afc422ba450b5d8f2bdb4b84b9ada  gcc/m2/gm2-libs/M2EXCEPTION.def
! 8f10171e5a0b0d8546348cb398a55250  gcc/m2/gm2-libs/M2EXCEPTION.mod
  8cd96743ee1f96df6f01c98df07854c3  gcc/m2/gm2-libs/M2RTS.def
  12f5ce990d5817b569dc48a1a3d2d37e  gcc/m2/gm2-libs/M2RTS.mod
  155b41f4ed2007e7f7eeb0df24463acf  gcc/m2/gm2-libs/MathLib0.def
--- 7230,7236 ----
  3d47773d0b2a2e842bc90ce1817ec304  gcc/m2/gm2-libs/M2Dependent.def
  3c65d10228392609f0596c9f655c18aa  gcc/m2/gm2-libs/M2Dependent.mod
  503afc422ba450b5d8f2bdb4b84b9ada  gcc/m2/gm2-libs/M2EXCEPTION.def
! 314fd76d36f9918545cd6932a994432f  gcc/m2/gm2-libs/M2EXCEPTION.mod
  8cd96743ee1f96df6f01c98df07854c3  gcc/m2/gm2-libs/M2RTS.def
  12f5ce990d5817b569dc48a1a3d2d37e  gcc/m2/gm2-libs/M2RTS.mod
  155b41f4ed2007e7f7eeb0df24463acf  gcc/m2/gm2-libs/MathLib0.def
*************** f9608e9005487c369e6c38949ab36fa1  gcc/m2
*** 7643,7649 ****
  88e10618d6f39a411b34e2245b93307b  gcc/machmode.def
  db2ee1a68662c8370d59f7e4f6cf917b  gcc/machmode.h
  486412acbbb6de10b080e31410a14f33  gcc/main.cc
! c845d5d7e04ea934ec3a5ca0ea44a754  gcc/match.pd
  63bf182c7c3a100e101b2129976be89b  gcc/mcf.cc
  795fbbc034a60f5af7e79dbe3bac65a0  gcc/mem-stats-traits.h
  295dcd7618653c13dcf063266752d06f  gcc/mem-stats.h
--- 7664,7670 ----
  88e10618d6f39a411b34e2245b93307b  gcc/machmode.def
  db2ee1a68662c8370d59f7e4f6cf917b  gcc/machmode.h
  486412acbbb6de10b080e31410a14f33  gcc/main.cc
! 20aa5bd493b4feb36e5b9dbe201ba046  gcc/match.pd
  63bf182c7c3a100e101b2129976be89b  gcc/mcf.cc
  795fbbc034a60f5af7e79dbe3bac65a0  gcc/mem-stats-traits.h
  295dcd7618653c13dcf063266752d06f  gcc/mem-stats.h
*************** b8f8b627140b8daf237cdd93d7acd698  gcc/op
*** 7708,7738 ****
  23d7d31706fa1ace036f8659d1dcf806  gcc/opt-suggestions.h
  f731cb7ebdb94eb79e6d1f93d1f488ec  gcc/optabs-libfuncs.cc
  301353d263ba0e1eac3f3242d9e7af47  gcc/optabs-libfuncs.h
! b5fc1a94542b80b1683d2bee465e42be  gcc/optabs-query.cc
  28bb97827aab6913c7fa55727bd8cea0  gcc/optabs-query.h
  933d872e7e60ed7a16f387f74cf5dcd7  gcc/optabs-tree.cc
  295bbec8fcdeeac30d6f914e52d4adc4  gcc/optabs-tree.h
  c9fef63de59454b93afa15203c1e321c  gcc/optabs.cc
  4e3c77b6001e2e7044652824b6551d11  gcc/optabs.def
  fe27687b66727b0800e152caad7a6829  gcc/optabs.h
! d272f0cd2742999e36feb3973232a1dc  gcc/optc-gen.awk
  91c3b3785b12feb3fa4912e114cdd5a0  gcc/optc-save-gen.awk
! 21519acd3156dd76a5986d7456365dc4  gcc/opth-gen.awk
  735656dff2a0bd83f378c9e8756e0d1a  gcc/optinfo-emit-json.cc
  fcb5b7227342c442bcddbcc06eaddcdc  gcc/optinfo-emit-json.h
  040a2f6d1fb908c9fb9879dca90e4516  gcc/optinfo.cc
  58f02a8817c05c6681ba150251b166e8  gcc/optinfo.h
  1c30e8950551cbe97bda991d288b7bb7  gcc/options-urls-cc-gen.awk
! 06a83d971fd3a11f54c904ab9260cc09  gcc/opts-common.cc
! 055bde0cea0132b2f8f8ae1a70bf3ab3  gcc/opts-diagnostic.cc
! bd138c731d5ef02ebe19e25375c465c8  gcc/opts-diagnostic.h
! dc49add7ae35ac8842b786b817fd79b3  gcc/opts-global.cc
  079a115ae417106f3e7f42b0272b866d  gcc/opts-jobserver.h
! a2b81ccfbe5caf8de41ebe5c645667fe  gcc/opts.cc
! 367fa9ca17175fb2e8651a43bc0d5ca3  gcc/opts.h
  b7a4b3edfca283f972cdeb23102a28a4  gcc/ordered-hash-map-tests.cc
  fccd951e3de91d49d3824e482c12e070  gcc/ordered-hash-map.h
! c77558a1c1f43463b3acae9243006ef9  gcc/output.h
  c9e6163e1eaa8f82c57f03f76e86da75  gcc/pair-fusion.cc
  b2f692287d25760afcef126c010f7078  gcc/pair-fusion.h
  9f740832b80d1afc73e79184f1e84f22  gcc/params.opt
--- 7729,7759 ----
  23d7d31706fa1ace036f8659d1dcf806  gcc/opt-suggestions.h
  f731cb7ebdb94eb79e6d1f93d1f488ec  gcc/optabs-libfuncs.cc
  301353d263ba0e1eac3f3242d9e7af47  gcc/optabs-libfuncs.h
! a1718f4e4de96a072fce29c3cef4017a  gcc/optabs-query.cc
  28bb97827aab6913c7fa55727bd8cea0  gcc/optabs-query.h
  933d872e7e60ed7a16f387f74cf5dcd7  gcc/optabs-tree.cc
  295bbec8fcdeeac30d6f914e52d4adc4  gcc/optabs-tree.h
  c9fef63de59454b93afa15203c1e321c  gcc/optabs.cc
  4e3c77b6001e2e7044652824b6551d11  gcc/optabs.def
  fe27687b66727b0800e152caad7a6829  gcc/optabs.h
! 4b8341a8e70bcb44afdbe2e4be1dcc46  gcc/optc-gen.awk
  91c3b3785b12feb3fa4912e114cdd5a0  gcc/optc-save-gen.awk
! 7e73ab7724d88cc330124e05331fe3e2  gcc/opth-gen.awk
  735656dff2a0bd83f378c9e8756e0d1a  gcc/optinfo-emit-json.cc
  fcb5b7227342c442bcddbcc06eaddcdc  gcc/optinfo-emit-json.h
  040a2f6d1fb908c9fb9879dca90e4516  gcc/optinfo.cc
  58f02a8817c05c6681ba150251b166e8  gcc/optinfo.h
  1c30e8950551cbe97bda991d288b7bb7  gcc/options-urls-cc-gen.awk
! cbc8e9dfe7d33c6f0f99c2440bab2595  gcc/opts-common.cc
! 5ccf682ebfbb9afdfc7f972ea6ef51fe  gcc/opts-diagnostic.cc
! 4b4c361908a7ba89bc981ee699a6e9fd  gcc/opts-diagnostic.h
! dd6379e65503d93b6eb08844e8bf2d09  gcc/opts-global.cc
  079a115ae417106f3e7f42b0272b866d  gcc/opts-jobserver.h
! 4c597f95761d061e08a4a92c6a2b990c  gcc/opts.cc
! e77c0b4ff21959cc040b49d1945bbc5b  gcc/opts.h
  b7a4b3edfca283f972cdeb23102a28a4  gcc/ordered-hash-map-tests.cc
  fccd951e3de91d49d3824e482c12e070  gcc/ordered-hash-map.h
! 536026501ca89687d46225728dc64047  gcc/output.h
  c9e6163e1eaa8f82c57f03f76e86da75  gcc/pair-fusion.cc
  b2f692287d25760afcef126c010f7078  gcc/pair-fusion.h
  9f740832b80d1afc73e79184f1e84f22  gcc/params.opt
*************** a4c4b609df2262702bd9691ce3ef1b39  gcc/pr
*** 7781,7791 ****
  5494603f698198c1a7d327aa6bbdb09a  gcc/predict.h
  00fb3c12fcc945bd00d0da1986741e41  gcc/prefix.cc
  5181d614dc205a1b7acf823c34e596ed  gcc/prefix.h
! a2fed47b1d856d59ba7f1884ca1e7282  gcc/pretty-print-format-impl.h
! 7d14f068456642f4e7720c1cad9bc313  gcc/pretty-print-markup.h
  445beb21a2f28b79808b2eebd0fe4856  gcc/pretty-print-urlifier.h
! a9d12e1bd0b6346eb6833a4bdc6138dd  gcc/pretty-print.cc
! 191fccc415dd02373e9969178df93d03  gcc/pretty-print.h
  3612c0ba4344ce8d21ab5bab244d397b  gcc/prime-paths.cc
  a6e4e4fab174379976dcb09269c8de98  gcc/print-rtl-function.cc
  a5461dd81ec55dc6f56817a1f356f345  gcc/print-rtl.cc
--- 7802,7812 ----
  5494603f698198c1a7d327aa6bbdb09a  gcc/predict.h
  00fb3c12fcc945bd00d0da1986741e41  gcc/prefix.cc
  5181d614dc205a1b7acf823c34e596ed  gcc/prefix.h
! 8b012f60c9f103ffb724c1b1d376f543  gcc/pretty-print-format-impl.h
! 632683d988f73b65e11e73cc27d8fa3b  gcc/pretty-print-markup.h
  445beb21a2f28b79808b2eebd0fe4856  gcc/pretty-print-urlifier.h
! dac7c1e2da55e7c5dae0c389e16a8247  gcc/pretty-print.cc
! a7b954c4a7bcd0141c6405a59ac196b7  gcc/pretty-print.h
  3612c0ba4344ce8d21ab5bab244d397b  gcc/prime-paths.cc
  a6e4e4fab174379976dcb09269c8de98  gcc/print-rtl-function.cc
  a5461dd81ec55dc6f56817a1f356f345  gcc/print-rtl.cc
*************** cd83aae447be541259a39119965eecb3  gcc/re
*** 7814,7820 ****
  cfd72298c4b4412115571bb0330d1cb4  gcc/real.h
  45eaf15130a976ff2f72716853fe77c6  gcc/realmpfr.cc
  ec455f45b6b3263f840fb385563308d7  gcc/realmpfr.h
! 449f854c654a1e9f1d268858607c576e  gcc/recog.cc
  d6625bf8e7676e7c0d45da5ca515ab06  gcc/recog.h
  d88ebbb33fb2dcd60634dd11046fb909  gcc/ree.cc
  40ff12eae68d7c45fee63cfa20a67634  gcc/reg-notes.def
--- 7835,7841 ----
  cfd72298c4b4412115571bb0330d1cb4  gcc/real.h
  45eaf15130a976ff2f72716853fe77c6  gcc/realmpfr.cc
  ec455f45b6b3263f840fb385563308d7  gcc/realmpfr.h
! 718f543d030c0547d1c5439b92bd842a  gcc/recog.cc
  d6625bf8e7676e7c0d45da5ca515ab06  gcc/recog.h
  d88ebbb33fb2dcd60634dd11046fb909  gcc/ree.cc
  40ff12eae68d7c45fee63cfa20a67634  gcc/reg-notes.def
*************** cc2f2f430f74c1a27d90af76f5ba9968  gcc/re
*** 7835,7841 ****
  5f98bc970b6b57607551ccefdca5ef67  gcc/reorg.cc
  94c50f93bf70c1392a5a5101e39945e3  gcc/resource.cc
  8fa0648a64843c58c93433f33ae94d2b  gcc/resource.h
! ae3ad005e8aa99428875298a3a4a9807  gcc/rtl-error.cc
  45f3e0a4a568096b755122a59fb9827a  gcc/rtl-error.h
  7948f19af7c7a128dd0ae8670c3fc343  gcc/rtl-iter.h
  8c3b34bb9f512d3d639e53c5b1cbb307  gcc/rtl-ssa.h
--- 7856,7862 ----
  5f98bc970b6b57607551ccefdca5ef67  gcc/reorg.cc
  94c50f93bf70c1392a5a5101e39945e3  gcc/resource.cc
  8fa0648a64843c58c93433f33ae94d2b  gcc/resource.h
! 969cca4364b3abbb8f34794ef9613dc3  gcc/rtl-error.cc
  45f3e0a4a568096b755122a59fb9827a  gcc/rtl-error.h
  7948f19af7c7a128dd0ae8670c3fc343  gcc/rtl-iter.h
  8c3b34bb9f512d3d639e53c5b1cbb307  gcc/rtl-ssa.h
*************** c08edc659010d9072c249418c1be7fe6  gcc/rt
*** 7874,7880 ****
  ecb31a48caf7998f695601ec7350bdc0  gcc/run-rtl-passes.cc
  c4bc204b62fdb61848c09abf05a60a9d  gcc/run-rtl-passes.h
  add9bd82fcec23469a4d0f7df03d9589  gcc/rust/CONTRIBUTING.md
! 948f127b0b718905120a5411d2cc0dde  gcc/rust/ChangeLog
  c2a8648800b13beaa7b2efef8e94ea6f  gcc/rust/Make-lang.in
  f3527e161e6e2827d299c1a928ebe1c6  gcc/rust/README.md
  1bde08bec2946c34ff76bc8cdc25d05c  gcc/rust/ast/rust-ast-builder-type.cc
--- 7895,7901 ----
  ecb31a48caf7998f695601ec7350bdc0  gcc/run-rtl-passes.cc
  c4bc204b62fdb61848c09abf05a60a9d  gcc/run-rtl-passes.h
  add9bd82fcec23469a4d0f7df03d9589  gcc/rust/CONTRIBUTING.md
! 66777b962f75627837d020247260b560  gcc/rust/ChangeLog
  c2a8648800b13beaa7b2efef8e94ea6f  gcc/rust/Make-lang.in
  f3527e161e6e2827d299c1a928ebe1c6  gcc/rust/README.md
  1bde08bec2946c34ff76bc8cdc25d05c  gcc/rust/ast/rust-ast-builder-type.cc
*************** bef8332d7c99228e46b17e35e62ab385  gcc/ru
*** 7956,7963 ****
  fd3249cd86e1c67112cdeed5a5067b18  gcc/rust/backend/rust-mangle-v0.cc
  21b6254246aa6d0468462df2e633b78b  gcc/rust/backend/rust-mangle.cc
  512554d11e53c000f4acc53f4b5c960a  gcc/rust/backend/rust-mangle.h
! 9f7e749dbb134497fdcc9cd05e39a37f  gcc/rust/backend/rust-tree.cc
! 142874544cb904f8757167f9c26b4a2b  gcc/rust/backend/rust-tree.h
  675e019161664f914b95bbc7799e517c  gcc/rust/checks/errors/borrowck/bir-design-notes.md
  eee383c6d924f06fa96c8f58f21fc6af  gcc/rust/checks/errors/borrowck/dev-notes.md
  280db2cd4a7844c95895b2a0a282b858  gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.lock
--- 7977,7984 ----
  fd3249cd86e1c67112cdeed5a5067b18  gcc/rust/backend/rust-mangle-v0.cc
  21b6254246aa6d0468462df2e633b78b  gcc/rust/backend/rust-mangle.cc
  512554d11e53c000f4acc53f4b5c960a  gcc/rust/backend/rust-mangle.h
! c21238b47104a4ecee47baf9192cdb4d  gcc/rust/backend/rust-tree.cc
! 2df16cbe6a4b532bc5bb1888b908578d  gcc/rust/backend/rust-tree.h
  675e019161664f914b95bbc7799e517c  gcc/rust/checks/errors/borrowck/bir-design-notes.md
  eee383c6d924f06fa96c8f58f21fc6af  gcc/rust/checks/errors/borrowck/dev-notes.md
  280db2cd4a7844c95895b2a0a282b858  gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.lock
*************** ac035bc655eef0f0bb02d11545319bef  gcc/ru
*** 8197,8203 ****
  13ffaa13f0d7c2b381a7fffc394abc00  gcc/rust/parse/rust-parse.h
  904bb5961d18d0251b99c1c8ed546a98  gcc/rust/resolve/rust-ast-resolve-base.cc
  270643c7f92b72895cd7064f274a4941  gcc/rust/resolve/rust-ast-resolve-base.h
! e7b8122dae232f162801892fff840c45  gcc/rust/resolve/rust-ast-resolve-expr.cc
  71d5f4ade83a5f8c494a92ef12023446  gcc/rust/resolve/rust-ast-resolve-expr.h
  8f68f019c34cda122cc27f3b94c06274  gcc/rust/resolve/rust-ast-resolve-implitem.h
  7b1233dbdd87d481a440efd33735d4b5  gcc/rust/resolve/rust-ast-resolve-item.cc
--- 8218,8224 ----
  13ffaa13f0d7c2b381a7fffc394abc00  gcc/rust/parse/rust-parse.h
  904bb5961d18d0251b99c1c8ed546a98  gcc/rust/resolve/rust-ast-resolve-base.cc
  270643c7f92b72895cd7064f274a4941  gcc/rust/resolve/rust-ast-resolve-base.h
! 85a3f360ec46392a302c089405d3f801  gcc/rust/resolve/rust-ast-resolve-expr.cc
  71d5f4ade83a5f8c494a92ef12023446  gcc/rust/resolve/rust-ast-resolve-expr.h
  8f68f019c34cda122cc27f3b94c06274  gcc/rust/resolve/rust-ast-resolve-implitem.h
  7b1233dbdd87d481a440efd33735d4b5  gcc/rust/resolve/rust-ast-resolve-item.cc
*************** f181c944f9bbea9c2954427b2334c87a  gcc/ru
*** 8226,8236 ****
  dec0e54b8d4239c44cd88b409b7e74c3  gcc/rust/resolve/rust-forever-stack.cc
  c13aecea9c8a8b70e55edcb8735f7fec  gcc/rust/resolve/rust-forever-stack.h
  3270da3abfe88fffc0089adc897f69ed  gcc/rust/resolve/rust-forever-stack.hxx
! 5fb949b91154caa7fd14b38ee44c06a8  gcc/rust/resolve/rust-ice-finalizer.cc
! 52b9b9a65bae9a38ed82a218f84f5105  gcc/rust/resolve/rust-ice-finalizer.h
  98f1d330caf4f27bd13e2a60d632182b  gcc/rust/resolve/rust-immutable-name-resolution-context.cc
  927471efaee1f85624e6e7eb00584819  gcc/rust/resolve/rust-immutable-name-resolution-context.h
! 6a9b7bc55dd80fc91180098a015cb032  gcc/rust/resolve/rust-late-name-resolver-2.0.cc
  452ab0fe9c6f9e1e259d45df8004a3c0  gcc/rust/resolve/rust-late-name-resolver-2.0.h
  4bb779fc95a8d132060b01520618c019  gcc/rust/resolve/rust-name-resolution-context.cc
  4bca16219d1f43f47810f63532118616  gcc/rust/resolve/rust-name-resolution-context.h
--- 8247,8257 ----
  dec0e54b8d4239c44cd88b409b7e74c3  gcc/rust/resolve/rust-forever-stack.cc
  c13aecea9c8a8b70e55edcb8735f7fec  gcc/rust/resolve/rust-forever-stack.h
  3270da3abfe88fffc0089adc897f69ed  gcc/rust/resolve/rust-forever-stack.hxx
! c37894be52ba5cc4406613a60ba6b289  gcc/rust/resolve/rust-ice-finalizer.cc
! f022a4ee2cba026a3593bb6b701ae2f8  gcc/rust/resolve/rust-ice-finalizer.h
  98f1d330caf4f27bd13e2a60d632182b  gcc/rust/resolve/rust-immutable-name-resolution-context.cc
  927471efaee1f85624e6e7eb00584819  gcc/rust/resolve/rust-immutable-name-resolution-context.h
! d26a3f8dd06a0d59396272c4f64e176e  gcc/rust/resolve/rust-late-name-resolver-2.0.cc
  452ab0fe9c6f9e1e259d45df8004a3c0  gcc/rust/resolve/rust-late-name-resolver-2.0.h
  4bb779fc95a8d132060b01520618c019  gcc/rust/resolve/rust-name-resolution-context.cc
  4bca16219d1f43f47810f63532118616  gcc/rust/resolve/rust-name-resolution-context.h
*************** df264ba2847fb2a38b3bb3b4033a197d  gcc/ru
*** 8242,8248 ****
  d779ac3d5d0f6ee1b5f47a4ce0cf1e60  gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
  e49a12846f730d069c04127857f8d468  gcc/rust/rust-attribs.cc
  55479ad90a5fe7884edef780c31833b9  gcc/rust/rust-backend.h
! e4e5aa68cf24f2e0046ae5295d07d56c  gcc/rust/rust-diagnostics.cc
  5aaf7f890efa698d89b6c1785288f84d  gcc/rust/rust-diagnostics.h
  a29710a52aae45b7a844ae73c125e33f  gcc/rust/rust-error-codes.def
  658ebc1dc7af53db42dbe35be128a3d3  gcc/rust/rust-gcc.cc
--- 8263,8269 ----
  d779ac3d5d0f6ee1b5f47a4ce0cf1e60  gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
  e49a12846f730d069c04127857f8d468  gcc/rust/rust-attribs.cc
  55479ad90a5fe7884edef780c31833b9  gcc/rust/rust-backend.h
! d37141631e779efc27f48019136756d4  gcc/rust/rust-diagnostics.cc
  5aaf7f890efa698d89b6c1785288f84d  gcc/rust/rust-diagnostics.h
  a29710a52aae45b7a844ae73c125e33f  gcc/rust/rust-error-codes.def
  658ebc1dc7af53db42dbe35be128a3d3  gcc/rust/rust-gcc.cc
*************** b69c0a60b87460456bf02111f39310dd  gcc/se
*** 8378,8407 ****
  8352df111cb1e4c8fe8cbf4b30002511  gcc/sel-sched-ir.h
  3c55426387224f4699c9d51fdbd5b547  gcc/sel-sched.cc
  22faf0ae842883b3a08f6e9137ac2315  gcc/sel-sched.h
- 0f03d3badfef7fb7c66d72631c12e55f  gcc/selftest-diagnostic-path.cc
- 077cb17f489943323e35c165fe527d78  gcc/selftest-diagnostic-path.h
- 60a6c5bd5960cea7c7c426b1443c533e  gcc/selftest-diagnostic-show-locus.h
- da289341188bb47929b58cb05089f2b1  gcc/selftest-diagnostic.cc
- aa7a992403f9436fb020f56988773ed5  gcc/selftest-diagnostic.h
  109061be2ca9df2d7941d134aabdf120  gcc/selftest-json.cc
  065d0522cc6ea795703e89270514b149  gcc/selftest-json.h
- d90d59efc5dfd5359241062d80e3e745  gcc/selftest-logical-location.cc
- 74ebb02c30bec8d1c45c78a387c5ee18  gcc/selftest-logical-location.h
  22224372e5a2696e660289e86b2696a5  gcc/selftest-rtl.cc
  ab96230d11b93b85d4d1b85cc5d494ab  gcc/selftest-rtl.h
! 6da80e904a4158492848eedc8baaa036  gcc/selftest-run-tests.cc
  777b0025fe2356f118cb24f2302ae4ff  gcc/selftest-tree.h
  fdc04e5af7ee387dce07c6ba9a99eaa8  gcc/selftest-xml.h
! 220320c985328c0546a9a80a7353964e  gcc/selftest.cc
! 960f5bbdef76a206066a5ef84a206016  gcc/selftest.h
  71b83bf173726493d9fee558216a2e02  gcc/sese.cc
  62e0bec4b0ac9f8e027af35a2c2e2330  gcc/sese.h
  9123313dafdd85df1e747e738274ee2c  gcc/shortest-paths.h
  2b3e8f7222148471de23e5a550500206  gcc/shrink-wrap.cc
  125f9b6a6cf86e28e0a76470fb3c1f11  gcc/shrink-wrap.h
  50d9999185408bcae454174489317b68  gcc/signop.h
! 4e7769929646b581f3e42b51a8e030e0  gcc/simple-diagnostic-path.cc
! 4155965d1db5d3c178f502d51e128b2f  gcc/simple-diagnostic-path.h
  69be67be8ae9d985309259e0c8c8f361  gcc/simplify-rtx.cc
  456e0937ae4b3a0f49fd44fb0d05eb52  gcc/sort.cc
  599fc125220850c86939202313a6f733  gcc/sparseset.cc
--- 8399,8421 ----
  8352df111cb1e4c8fe8cbf4b30002511  gcc/sel-sched-ir.h
  3c55426387224f4699c9d51fdbd5b547  gcc/sel-sched.cc
  22faf0ae842883b3a08f6e9137ac2315  gcc/sel-sched.h
  109061be2ca9df2d7941d134aabdf120  gcc/selftest-json.cc
  065d0522cc6ea795703e89270514b149  gcc/selftest-json.h
  22224372e5a2696e660289e86b2696a5  gcc/selftest-rtl.cc
  ab96230d11b93b85d4d1b85cc5d494ab  gcc/selftest-rtl.h
! 18222e76e678d1f3b0fb1f6a8bb988bf  gcc/selftest-run-tests.cc
  777b0025fe2356f118cb24f2302ae4ff  gcc/selftest-tree.h
  fdc04e5af7ee387dce07c6ba9a99eaa8  gcc/selftest-xml.h
! 29b9fb35d2661970d1fca96aa61a4fe8  gcc/selftest.cc
! 9f802ccd7cb09c3c1107ca1717d7651b  gcc/selftest.h
  71b83bf173726493d9fee558216a2e02  gcc/sese.cc
  62e0bec4b0ac9f8e027af35a2c2e2330  gcc/sese.h
  9123313dafdd85df1e747e738274ee2c  gcc/shortest-paths.h
  2b3e8f7222148471de23e5a550500206  gcc/shrink-wrap.cc
  125f9b6a6cf86e28e0a76470fb3c1f11  gcc/shrink-wrap.h
  50d9999185408bcae454174489317b68  gcc/signop.h
! 97a13c24fa48c474198b5767f228fd93  gcc/simple-diagnostic-path.cc
! 4daee3acc61f789d9c4c04a27a5bb351  gcc/simple-diagnostic-path.h
  69be67be8ae9d985309259e0c8c8f361  gcc/simplify-rtx.cc
  456e0937ae4b3a0f49fd44fb0d05eb52  gcc/sort.cc
  599fc125220850c86939202313a6f733  gcc/sparseset.cc
*************** f5e5ba1329ffae51d286f6c8932308d6  gcc/sr
*** 8420,8427 ****
  d0b55fa9a0f86f4f03bdbfcff3e068d8  gcc/stack-ptr-mod.cc
  bbd5abaa55463a5497e6ff9d14de3a1b  gcc/statistics.cc
  3fc844db346b8f5e70da401bd3f4ad0d  gcc/statistics.h
! ef637b5ca39d975c9e9bb73f830eacd9  gcc/stmt.cc
! dbd64f0fc5e750c51b3fae1183025ef5  gcc/stmt.h
  505fadce4b59d904957e16a30ade9c42  gcc/stor-layout.cc
  eb7d04020ade148a4c8969151c6d5478  gcc/stor-layout.h
  2937cf13aa5116018232748c5e245c4f  gcc/store-motion.cc
--- 8434,8441 ----
  d0b55fa9a0f86f4f03bdbfcff3e068d8  gcc/stack-ptr-mod.cc
  bbd5abaa55463a5497e6ff9d14de3a1b  gcc/statistics.cc
  3fc844db346b8f5e70da401bd3f4ad0d  gcc/statistics.h
! f68db16b6608c63017b01bf1eab86baa  gcc/stmt.cc
! af846ee244cf1bf3dfb75aaeb1117dc6  gcc/stmt.h
  505fadce4b59d904957e16a30ade9c42  gcc/stor-layout.cc
  eb7d04020ade148a4c8969151c6d5478  gcc/stor-layout.h
  2937cf13aa5116018232748c5e245c4f  gcc/store-motion.cc
*************** c1c0312db7dfa4c3180e5d38177bfaf0  gcc/st
*** 8429,8436 ****
  64189c14238c2f2daa94fc4b2270e582  gcc/streamer-hooks.h
  a93a9f9f9c74ce88e3583d057e62fe95  gcc/stringpool.cc
  457c5c44d4723a6f9aa3647526230be2  gcc/stringpool.h
! 13db2f479822629cb796257a775dddcd  gcc/substring-locations.cc
! b5f0b60c4a11cda62c1fe82b49e1d4f3  gcc/substring-locations.h
  790f6e7fd4a4a46a0741be9c06b98420  gcc/sym-exec/sym-exec-condition.cc
  a4d1b16964764ca0f824cca665251ba6  gcc/sym-exec/sym-exec-condition.h
  6203227c10015e98b238eea32aef108d  gcc/sym-exec/sym-exec-expr-is-a-helper.h
--- 8443,8450 ----
  64189c14238c2f2daa94fc4b2270e582  gcc/streamer-hooks.h
  a93a9f9f9c74ce88e3583d057e62fe95  gcc/stringpool.cc
  457c5c44d4723a6f9aa3647526230be2  gcc/stringpool.h
! 2d4e5a193503f7ce9c7c05eddfc721e2  gcc/substring-locations.cc
! 4211ba05d2f57bf193857d26c7087dd1  gcc/substring-locations.h
  790f6e7fd4a4a46a0741be9c06b98420  gcc/sym-exec/sym-exec-condition.cc
  a4d1b16964764ca0f824cca665251ba6  gcc/sym-exec/sym-exec-condition.h
  6203227c10015e98b238eea32aef108d  gcc/sym-exec/sym-exec-expr-is-a-helper.h
*************** d52852ab0122f14cd4f7658db8b9c6df  gcc/sy
*** 8443,8449 ****
  5dcfbac7f32752af3034f02319af81d7  gcc/symtab-clones.h
  f849345d69b622ff9e7b96095bc2c34e  gcc/symtab-thunks.cc
  c9829745147a0b8ec026a3c5029fe2ff  gcc/symtab-thunks.h
! aa2f440763246662044c0f16f1c5e858  gcc/symtab.cc
  b3a965e425e6cf7888319667faf58da9  gcc/sync-builtins.def
  b1497a03867668af210c32280876fdd7  gcc/system.h
  480d916fe042a150001ad88e88521c08  gcc/target-def.h
--- 8457,8463 ----
  5dcfbac7f32752af3034f02319af81d7  gcc/symtab-clones.h
  f849345d69b622ff9e7b96095bc2c34e  gcc/symtab-thunks.cc
  c9829745147a0b8ec026a3c5029fe2ff  gcc/symtab-thunks.h
! 3481872e762c16ee9f1e22d0a01f0f6a  gcc/symtab.cc
  b3a965e425e6cf7888319667faf58da9  gcc/sync-builtins.def
  b1497a03867668af210c32280876fdd7  gcc/system.h
  480d916fe042a150001ad88e88521c08  gcc/target-def.h
*************** b1497a03867668af210c32280876fdd7  gcc/sy
*** 8451,8462 ****
  32c99c974fd34089d47160168688da1d  gcc/target-globals.h
  84051f22ca8c9ee213931106395ac151  gcc/target-hooks-macros.h
  354306a484432bca2f94887455f25599  gcc/target-insns.def
! 5f3070e293ba7a48df98a08b1ad72aef  gcc/target.def
! 7945120876914759f582dba50044b18d  gcc/target.h
! b4bbfe8a8f62eed5c75429762e88d324  gcc/targhooks.cc
! ae57260b8b60d8b8dfaef3556c3ac5e5  gcc/targhooks.h
  f39fcaa8197187283ccfed40107b426d  gcc/testsuite/.gitattributes
! ce7969661ea3c6cf59c9bc077bded17b  gcc/testsuite/ChangeLog
  47e8e29b649ead73b8a1e4797da470ed  gcc/testsuite/ChangeLog-1993-2007
  35198a9e4fd31b935de8789faabf3351  gcc/testsuite/ChangeLog-2008
  0f19934540750356d1b91595cebfd9a8  gcc/testsuite/ChangeLog-2009
--- 8465,8476 ----
  32c99c974fd34089d47160168688da1d  gcc/target-globals.h
  84051f22ca8c9ee213931106395ac151  gcc/target-hooks-macros.h
  354306a484432bca2f94887455f25599  gcc/target-insns.def
! bc392815b44da6e3bc16ba972081f650  gcc/target.def
! 5e326cfe9b9871c8077b30f9a44e6663  gcc/target.h
! 143ba02938f6a6df9b9495eb6bce4be1  gcc/targhooks.cc
! 7b362870a640a56a8b05ca807b02f07d  gcc/targhooks.h
  f39fcaa8197187283ccfed40107b426d  gcc/testsuite/.gitattributes
! ba73f3fd6401a4f8de3ee4ca7451aafb  gcc/testsuite/ChangeLog
  47e8e29b649ead73b8a1e4797da470ed  gcc/testsuite/ChangeLog-1993-2007
  35198a9e4fd31b935de8789faabf3351  gcc/testsuite/ChangeLog-2008
  0f19934540750356d1b91595cebfd9a8  gcc/testsuite/ChangeLog-2009
*************** bf21188860d25a68d2f9c85951bdde9b  gcc/te
*** 20614,20621 ****
  bdbf9d12e14720fb7081dad4477a7bae  gcc/testsuite/cobol.dg/group2/UNSTRING_DELIMITER_IN.cob
  94779fadfcd69b9dabbc720f231c4593  gcc/testsuite/cobol.dg/group2/UNSTRING_with_FUNCTION___literal.cob
  db11d5a6931ffe03ab944182745e5364  gcc/testsuite/cobol.dg/group2/UNSTRING_with_FUNCTION___literal.out
! 3d52c7ffaea8a5516030f13da4a7ec1a  gcc/testsuite/cobol.dg/group2/_-static__compilation.cob
! 57663a45c549ad6b8504e86b91faf92b  gcc/testsuite/cobol.dg/group2/_-static__compilation.out
  7ccbb0b17254a4346153a02e58218979  gcc/testsuite/cobol.dg/group2/access_to_OPTIONAL_LINKAGE_item_not_passed.cob
  e54e577d8de75b710938fa62794487fc  gcc/testsuite/cobol.dg/group2/access_to_OPTIONAL_LINKAGE_item_not_passed.out
  a75f94d635d6f81fcf6e666df78229f2  gcc/testsuite/cobol.dg/group2/call_subprogram_using_pointer__passing_pointer.cob
--- 20628,20634 ----
  bdbf9d12e14720fb7081dad4477a7bae  gcc/testsuite/cobol.dg/group2/UNSTRING_DELIMITER_IN.cob
  94779fadfcd69b9dabbc720f231c4593  gcc/testsuite/cobol.dg/group2/UNSTRING_with_FUNCTION___literal.cob
  db11d5a6931ffe03ab944182745e5364  gcc/testsuite/cobol.dg/group2/UNSTRING_with_FUNCTION___literal.out
! 8b384b3032fcac908a2fdc502dc156e8  gcc/testsuite/cobol.dg/group2/_-static__compilation.cob
  7ccbb0b17254a4346153a02e58218979  gcc/testsuite/cobol.dg/group2/access_to_OPTIONAL_LINKAGE_item_not_passed.cob
  e54e577d8de75b710938fa62794487fc  gcc/testsuite/cobol.dg/group2/access_to_OPTIONAL_LINKAGE_item_not_passed.out
  a75f94d635d6f81fcf6e666df78229f2  gcc/testsuite/cobol.dg/group2/call_subprogram_using_pointer__passing_pointer.cob
*************** ab314765ac0eb201bb3e11222207ee40  gcc/te
*** 22066,22071 ****
--- 22079,22085 ----
  f5e05a528274f5ccbd128504d532f540  gcc/testsuite/g++.dg/coroutines/torture/pr119916.C
  7056081fe2b2eea558f97e0e51454360  gcc/testsuite/g++.dg/coroutines/torture/pr120243-unhandled-1.C
  4462334c65b930d35ef9130fd5dee6e3  gcc/testsuite/g++.dg/coroutines/torture/pr120243-unhandled-2.C
+ 63b467f89662af371e2a58a44b0b9042  gcc/testsuite/g++.dg/coroutines/torture/pr121219.C
  33c54ba08ef1e709e2fb67d90cc048b4  gcc/testsuite/g++.dg/coroutines/torture/pr92933.C
  56811f88338809bbea0a94b564f9b4da  gcc/testsuite/g++.dg/coroutines/torture/pr95003.C
  2248a954a08f9c689c19929abad2771e  gcc/testsuite/g++.dg/coroutines/torture/pr95519-00-return_void.C
*************** ad90458ad42ff08d4a1c948d0770dd89  gcc/te
*** 26676,26681 ****
--- 26690,26696 ----
  51978f30a781d2e3a3434b8d371737b6  gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda15.C
  4e4eee2cc98e967eb67c2b28b145f331  gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda16.C
  fe56bf124d429ccaa887937cdd60d625  gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda17.C
+ d3a5a9df5514968709862976635c8094  gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C
  87abca8eb660254fbf201e771eef3751  gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda2.C
  e8adbb443f8b231b244ffbcd64ee7da2  gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda3.C
  0a50eb80a181d4196ff68849d37d2615  gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda4.C
*************** e408b3d8d3b64969041e538afc7dd797  gcc/te
*** 26758,26763 ****
--- 26773,26779 ----
  e44e5999e0fcf946fbaf4cc4247b99ae  gcc/testsuite/g++.dg/cpp23/static-operator-call4.C
  40f2c082ef41617a245e900009ecd2cf  gcc/testsuite/g++.dg/cpp23/static-operator-call5.C
  8b801aeeb85c01c051a33fa163907dc5  gcc/testsuite/g++.dg/cpp23/static-operator-call6.C
+ 72ea342064a8f8e14889eb8dd6c56d16  gcc/testsuite/g++.dg/cpp23/static-operator-call7.C
  36f6327df1a56ea4e9b05f09e62c676c  gcc/testsuite/g++.dg/cpp23/subscript1.C
  cc99147510a4c52615413a1c85c79b07  gcc/testsuite/g++.dg/cpp23/subscript10.C
  d685ca7f6c3f6496ec36569ed507b984  gcc/testsuite/g++.dg/cpp23/subscript11.C
*************** dc502eef9ceb703b539a3e2b2b75a0b1  gcc/te
*** 26798,26803 ****
--- 26814,26820 ----
  c3a9b6852b1f09d9ece1fdf2078d65c2  gcc/testsuite/g++.dg/cpp26/constexpr-new1.C
  92cd7c8e3355d7acc8819940fc96bc7d  gcc/testsuite/g++.dg/cpp26/constexpr-new2.C
  dbe4cf9df545b2cb75b00993e494cc66  gcc/testsuite/g++.dg/cpp26/constexpr-new3.C
+ de9765a13f0dc8289ae4d66360d163f6  gcc/testsuite/g++.dg/cpp26/constexpr-new4.C
  354260f99fd60e96c277a56929f1d6e9  gcc/testsuite/g++.dg/cpp26/constexpr-virt-inherit1.C
  00668a798f242a6125673c04eb06a10e  gcc/testsuite/g++.dg/cpp26/constexpr-virt-inherit2.C
  9bbb24eae9cc5e4431f138520f489213  gcc/testsuite/g++.dg/cpp26/constexpr-virt-inherit3.C
*************** ee36c7ebc03385f37bcba1c49e06c808  gcc/te
*** 27345,27351 ****
  8fe2b0550580edd7f36bb9d150fad6c4  gcc/testsuite/g++.dg/cpp2a/concepts-throw1.C
  39c15f1dc604f714304d144250164089  gcc/testsuite/g++.dg/cpp2a/concepts-traits1.C
  c9a6ab7bc0f1947e843b9c7150ccb98c  gcc/testsuite/g++.dg/cpp2a/concepts-traits2.C
! c7b62b8031571fb8bca4923e94717551  gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C
  427561cea6003909c32f28fbe3d276c7  gcc/testsuite/g++.dg/cpp2a/concepts-ttp1.C
  e9afe83f998c36b2fb7c1f09347d0bde  gcc/testsuite/g++.dg/cpp2a/concepts-ttp2.C
  61d4933dc5691f3ec1773e39ad6449b4  gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C
--- 27362,27369 ----
  8fe2b0550580edd7f36bb9d150fad6c4  gcc/testsuite/g++.dg/cpp2a/concepts-throw1.C
  39c15f1dc604f714304d144250164089  gcc/testsuite/g++.dg/cpp2a/concepts-traits1.C
  c9a6ab7bc0f1947e843b9c7150ccb98c  gcc/testsuite/g++.dg/cpp2a/concepts-traits2.C
! a25a4c85f70241ed0e288dd36ade68a7  gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C
! 024b05cd463d21d4dec3d5089b33b061  gcc/testsuite/g++.dg/cpp2a/concepts-traits4.C
  427561cea6003909c32f28fbe3d276c7  gcc/testsuite/g++.dg/cpp2a/concepts-ttp1.C
  e9afe83f998c36b2fb7c1f09347d0bde  gcc/testsuite/g++.dg/cpp2a/concepts-ttp2.C
  61d4933dc5691f3ec1773e39ad6449b4  gcc/testsuite/g++.dg/cpp2a/concepts-ttp3.C
*************** a9a14bb307d24157192c2d361ae5fcbe  gcc/te
*** 27569,27575 ****
  64db89fe8184ef8910fbbef6f4db6984  gcc/testsuite/g++.dg/cpp2a/constexpr-union3.C
  c0b015cd02e07242444c2700f64e070a  gcc/testsuite/g++.dg/cpp2a/constexpr-union4.C
  506a486b7e3cc863b24cd04db4e706cd  gcc/testsuite/g++.dg/cpp2a/constexpr-union5.C
! 5fd97c22b2996faaa87a3aa20de08243  gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C
  22d0d1f2f3c677d12d0e844ae12fd688  gcc/testsuite/g++.dg/cpp2a/constexpr-union7.C
  e94cea4fa4255420603d88768e70b36c  gcc/testsuite/g++.dg/cpp2a/constexpr-union8.C
  b00a4635a4c11366be17b4b6a45910f7  gcc/testsuite/g++.dg/cpp2a/constexpr-union9.C
--- 27587,27593 ----
  64db89fe8184ef8910fbbef6f4db6984  gcc/testsuite/g++.dg/cpp2a/constexpr-union3.C
  c0b015cd02e07242444c2700f64e070a  gcc/testsuite/g++.dg/cpp2a/constexpr-union4.C
  506a486b7e3cc863b24cd04db4e706cd  gcc/testsuite/g++.dg/cpp2a/constexpr-union5.C
! 304270bc22c605e31d399e4d5c782673  gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C
  22d0d1f2f3c677d12d0e844ae12fd688  gcc/testsuite/g++.dg/cpp2a/constexpr-union7.C
  e94cea4fa4255420603d88768e70b36c  gcc/testsuite/g++.dg/cpp2a/constexpr-union8.C
  b00a4635a4c11366be17b4b6a45910f7  gcc/testsuite/g++.dg/cpp2a/constexpr-union9.C
*************** b754a2ad578f67afe512ad74ff03b31f  gcc/te
*** 28603,28608 ****
--- 28621,28627 ----
  a7b5530f2822e6294b3a5ff037237c86  gcc/testsuite/g++.dg/diagnostic/static_assert2.C
  5b63c27824f84be4557ec3a9e40be0ce  gcc/testsuite/g++.dg/diagnostic/static_assert3.C
  356d9ff5d1d1c03e2a293f19c79c3b7a  gcc/testsuite/g++.dg/diagnostic/static_assert4.C
+ 7df6caeb261f0d3aa0979d15088e7da6  gcc/testsuite/g++.dg/diagnostic/static_assert5.C
  44f760c7519cb2fd28e1b57a7e670f75  gcc/testsuite/g++.dg/diagnostic/string-literal-concat.C
  a799316540e3d4a9d02c14db904fef43  gcc/testsuite/g++.dg/diagnostic/sys-narrow.h
  ed408dc0316b2762f979969a2b424c7c  gcc/testsuite/g++.dg/diagnostic/sys-narrow1.C
*************** f271483cc849c390e250605e54ae37b8  gcc/te
*** 29448,29453 ****
--- 29467,29473 ----
  a24f991beb2c5296f2e8144630b7bb1a  gcc/testsuite/g++.dg/ext/has_trivial_destructor-2.C
  d9a5225768f42f5bacffe98269f2d9d5  gcc/testsuite/g++.dg/ext/has_trivial_destructor-3.C
  72069a562c9156e50b3efde0f66048dc  gcc/testsuite/g++.dg/ext/has_virtual_destructor.C
+ cb784874a8e8bc4ad9151a995412be57  gcc/testsuite/g++.dg/ext/has_virtual_destructor2.C
  853c0d1bb8c4ec806df7ecfff1c64c10  gcc/testsuite/g++.dg/ext/init1.C
  04cb5500126619139ae126fdc51c8a1f  gcc/testsuite/g++.dg/ext/injected-ttp.C
  f2cf0baaaf489aa15f22210e07d052d1  gcc/testsuite/g++.dg/ext/inline1.C
*************** f695844e9b94f9b4c9ed5fec78d4bf27  gcc/te
*** 29489,29494 ****
--- 29509,29515 ----
  7b4bbb4468597cb28d850e0c03883be2  gcc/testsuite/g++.dg/ext/is_aggregate.C
  42b2f20fa118bd60afea32bb62088b6e  gcc/testsuite/g++.dg/ext/is_array.C
  d94cb7855d511cff1539f26e77d52c7d  gcc/testsuite/g++.dg/ext/is_assignable1.C
+ 5cef8d19bd49a631670a0a07753e4b57  gcc/testsuite/g++.dg/ext/is_assignable2.C
  1b0a6b246515ec52c50e4f6f1dccffd8  gcc/testsuite/g++.dg/ext/is_base_of.C
  574b1f21a40a06a23d8cf8a0233b80ed  gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
  4d8cb6dc054c0275b7ee9ca0c033fb93  gcc/testsuite/g++.dg/ext/is_base_of_incomplete-2.C
*************** ed04365b57dec8b58125996aefe86234  gcc/te
*** 29506,29520 ****
--- 29527,29544 ----
  dc3385dfd74c1bf2c03d4da78571f637  gcc/testsuite/g++.dg/ext/is_constructible5.C
  9553e2b6c2e80320fe1dbc53bb218083  gcc/testsuite/g++.dg/ext/is_constructible6.C
  c98f87283f462df05d8fe236ed206312  gcc/testsuite/g++.dg/ext/is_constructible8.C
+ ea992d71ef74179d4456f5da529233cb  gcc/testsuite/g++.dg/ext/is_constructible9.C
  c9c92d18a37f4f8ede2a39a1b3ad62f6  gcc/testsuite/g++.dg/ext/is_convertible1.C
  d84b4e6ad32eec6b47fea11f39244dd7  gcc/testsuite/g++.dg/ext/is_convertible2.C
  5ba6edf25552f47c87c7d5735f634b3c  gcc/testsuite/g++.dg/ext/is_convertible3.C
  3a805f1dafea1ecf418ab3dbdb6af96b  gcc/testsuite/g++.dg/ext/is_convertible4.C
  986a829ca110a6da40ad4e40333b4eb5  gcc/testsuite/g++.dg/ext/is_convertible5.C
  d74301fd930f4a488c9e941cdd242900  gcc/testsuite/g++.dg/ext/is_convertible6.C
+ 81df2803e04b58964bc97c0d499da3e6  gcc/testsuite/g++.dg/ext/is_convertible7.C
  ebb1df191bcea60ed6342dad182b8901  gcc/testsuite/g++.dg/ext/is_deducible1.C
  94a516051a47d1b7e866ec47efa5de01  gcc/testsuite/g++.dg/ext/is_destructible1.C
  aa081a16610eaae6eaa83ad85ce8aa33  gcc/testsuite/g++.dg/ext/is_destructible2.C
+ 31131faa8f100377aa10a66fcdf2a50d  gcc/testsuite/g++.dg/ext/is_destructible3.C
  9da1ecf7ca599ccc9c1677e62cfc809f  gcc/testsuite/g++.dg/ext/is_empty.C
  51590a59aaf8715b9fe4a7ae06414cb8  gcc/testsuite/g++.dg/ext/is_empty2.C
  904cd436fd5b5ebe1349610a0aa7c2da  gcc/testsuite/g++.dg/ext/is_enum.C
*************** aa081a16610eaae6eaa83ad85ce8aa33  gcc/te
*** 29525,29530 ****
--- 29549,29556 ----
  0da83314cec6d313a123af04a33e386b  gcc/testsuite/g++.dg/ext/is_invocable2.C
  a880bbf4a2491686f32ef99587f1d5d7  gcc/testsuite/g++.dg/ext/is_invocable3.C
  3bff0f23c0ea407c9137e25bbedce11c  gcc/testsuite/g++.dg/ext/is_invocable4.C
+ a2e288b15b5abf2aaab268a242e72400  gcc/testsuite/g++.dg/ext/is_invocable5.C
+ 3735ab99d3414c769aec2826982216a6  gcc/testsuite/g++.dg/ext/is_invocable6.C
  d97310b12ece2c21881785f78f44e64a  gcc/testsuite/g++.dg/ext/is_literal_type1.C
  cce82a97f2d80557fc2ee719db6afda2  gcc/testsuite/g++.dg/ext/is_literal_type2.C
  70b8167d4c887f159d75bd15861c519b  gcc/testsuite/g++.dg/ext/is_literal_type3.C
*************** c3525831665d7cbb0d4199640426a8c0  gcc/te
*** 29576,29581 ****
--- 29602,29608 ----
  dfc5fc4d8610f00c7cd27c7795c3494a  gcc/testsuite/g++.dg/ext/is_union.C
  c5162f49c04a31e896fa6b3b85ddc718  gcc/testsuite/g++.dg/ext/is_virtual_base_of.C
  75fff22de399b6176636c77897e0835a  gcc/testsuite/g++.dg/ext/is_virtual_base_of_diagnostic.C
+ dd123db08b1e504d0c40a8f9a4b26e72  gcc/testsuite/g++.dg/ext/is_virtual_base_of_diagnostic2.C
  4f23cfdb876ae1f2a68ee65231f5e7d6  gcc/testsuite/g++.dg/ext/is_volatile.C
  db0b295df95be25a97d67c002c45679e  gcc/testsuite/g++.dg/ext/ivdep-1.C
  81d5dcb570c603e51795c99355ec35f2  gcc/testsuite/g++.dg/ext/label1.C
*************** a2b014e2e43329bb9803e683981e2a7c  gcc/te
*** 31435,31441 ****
  a1ec3c39e5a1beac0e1f9dbbc1635692  gcc/testsuite/g++.dg/lookup/operator-5a.C
  f5603b028cb5e4f040fc3af7776ea00e  gcc/testsuite/g++.dg/lookup/operator-6.C
  60fb08261559503592bcae8f4f347885  gcc/testsuite/g++.dg/lookup/operator-7.C
! 8a4bc664943ba55e02c1041859cf9c36  gcc/testsuite/g++.dg/lookup/operator-8.C
  ed588fcfdd755a45d961e507c96ba9e2  gcc/testsuite/g++.dg/lookup/pr21802.C
  2378e813c805e961b5f594f4a76ec56d  gcc/testsuite/g++.dg/lookup/pr60994.C
  e8c219b570d08e589efca8f832a6b0b3  gcc/testsuite/g++.dg/lookup/pr67074.C
--- 31462,31468 ----
  a1ec3c39e5a1beac0e1f9dbbc1635692  gcc/testsuite/g++.dg/lookup/operator-5a.C
  f5603b028cb5e4f040fc3af7776ea00e  gcc/testsuite/g++.dg/lookup/operator-6.C
  60fb08261559503592bcae8f4f347885  gcc/testsuite/g++.dg/lookup/operator-7.C
! 1d63b8dab73c84e20ebcf810602869f5  gcc/testsuite/g++.dg/lookup/operator-8.C
  ed588fcfdd755a45d961e507c96ba9e2  gcc/testsuite/g++.dg/lookup/pr21802.C
  2378e813c805e961b5f594f4a76ec56d  gcc/testsuite/g++.dg/lookup/pr60994.C
  e8c219b570d08e589efca8f832a6b0b3  gcc/testsuite/g++.dg/lookup/pr67074.C
*************** b8735311421a9557b475c780e1712295  gcc/te
*** 31919,31925 ****
  1fa0bf497eddaf27bc8b579ea2b690fc  gcc/testsuite/g++.dg/lto/pr97565_0.C
  540253034f25055f8bf0879bf3a5aff5  gcc/testsuite/g++.dg/lto/pr97565_1.C
  6232508298dd20a759cf64fffbca9f5e  gcc/testsuite/g++.dg/lto/v1-plugin-api-not-supported_0.C
! dbe30d4af4bd2caeabf4784c3ef0ca9d  gcc/testsuite/g++.dg/missing-return.C
  0611288c84e3f846cb789e1b0d0e7706  gcc/testsuite/g++.dg/missing-symbol-2.C
  5ea15da0c6d0bfcf59702e2fe7b87c1f  gcc/testsuite/g++.dg/modules/100616_a.H
  944c3e30374eb421d84a8c5426b2e660  gcc/testsuite/g++.dg/modules/100616_b.C
--- 31946,31952 ----
  1fa0bf497eddaf27bc8b579ea2b690fc  gcc/testsuite/g++.dg/lto/pr97565_0.C
  540253034f25055f8bf0879bf3a5aff5  gcc/testsuite/g++.dg/lto/pr97565_1.C
  6232508298dd20a759cf64fffbca9f5e  gcc/testsuite/g++.dg/lto/v1-plugin-api-not-supported_0.C
! 3147f7d614489a0acd92a11c7c1fb038  gcc/testsuite/g++.dg/missing-return.C
  0611288c84e3f846cb789e1b0d0e7706  gcc/testsuite/g++.dg/missing-symbol-2.C
  5ea15da0c6d0bfcf59702e2fe7b87c1f  gcc/testsuite/g++.dg/modules/100616_a.H
  944c3e30374eb421d84a8c5426b2e660  gcc/testsuite/g++.dg/modules/100616_b.C
*************** e7d806e1771c11cb72e41af12e6d57e4  gcc/te
*** 32067,32072 ****
--- 32094,32101 ----
  cedd15f6c5ea2087db7309f8e58574a4  gcc/testsuite/g++.dg/modules/circ-1_d.C
  188cf637178b71d74de58bdbada43b0d  gcc/testsuite/g++.dg/modules/class-10_a.H
  de9e83ce6d7d5406399b3d0d434e98a7  gcc/testsuite/g++.dg/modules/class-10_b.C
+ 1b0338b721370cc46b8de1d0485fae6d  gcc/testsuite/g++.dg/modules/class-11_a.H
+ 70dc327c941ed93d4c7fbbe0ddbfae6a  gcc/testsuite/g++.dg/modules/class-11_b.C
  86586d456dae6a665b6dc0eea845c1d2  gcc/testsuite/g++.dg/modules/class-1_a.C
  52c0c896346bdeeeb006d315251b80a8  gcc/testsuite/g++.dg/modules/class-1_b.C
  10b7bdfdbc0bf357572444729f4dafc4  gcc/testsuite/g++.dg/modules/class-1_c.C
*************** e6b16a33fb2c85abf4f99ad0d5ad33bb  gcc/te
*** 32481,32486 ****
--- 32510,32518 ----
  f521d5e26375a6db232f71e6ef7b21f5  gcc/testsuite/g++.dg/modules/internal-12_a.C
  271d623e43c91425c2bf224100933996  gcc/testsuite/g++.dg/modules/internal-12_b.C
  c087af9321ac0e24731d2a4d1bb3e319  gcc/testsuite/g++.dg/modules/internal-13.C
+ 4fffea4cdfd477df735c06f198229d8f  gcc/testsuite/g++.dg/modules/internal-14_a.C
+ 10a79d90c63564fa8794a477cbcaed50  gcc/testsuite/g++.dg/modules/internal-14_b.C
+ f3dc43a1a76c9644a2c2a98b1094e62a  gcc/testsuite/g++.dg/modules/internal-14_c.C
  c66d17d0fb2dc80371978510d0cc1f0f  gcc/testsuite/g++.dg/modules/internal-2_a.H
  21bb55995bb6fa8ed6a8fa69368f7f36  gcc/testsuite/g++.dg/modules/internal-2_b.H
  ba3bc4f8f333742fb78f03db052c4ffa  gcc/testsuite/g++.dg/modules/internal-2_c.C
*************** bb9719af4ef365b9625ed93e9794b8b2  gcc/te
*** 35317,35327 ****
  436d3d1e052b227d2661a53bc1d71e69  gcc/testsuite/g++.dg/plugin/self-assign-test-2.C
  e051d5cb1d92744fe18b74552249a54e  gcc/testsuite/g++.dg/plugin/self-assign-test-3.C
  5f9b6973b5f55304febb17e03d56165d  gcc/testsuite/g++.dg/plugin/selfassign.cc
! efc88a1fcd8ac51821ec0b7d0de5ad56  gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
  669d6447cc7cb76ea3787b8008016b3f  gcc/testsuite/g++.dg/plugin/show-template-tree-color-no-elide-type.C
  6a6dbcbab6d373e63c771d4d3f143ebb  gcc/testsuite/g++.dg/plugin/show-template-tree-color-no-highlight-colors.C
  946f03549b5d21aa38c5f97b1f198eac  gcc/testsuite/g++.dg/plugin/show-template-tree-color.C
! e5eb25915d90be387b16fee31586067e  gcc/testsuite/g++.dg/plugin/show_template_tree_color_plugin.cc
  d52f4cb5f64b45258d5b1297ad88b4d1  gcc/testsuite/g++.dg/pr100253.C
  8565710d6f77641a38bd4e09919a3fb2  gcc/testsuite/g++.dg/pr100574.C
  fff532cdcec98c1dd1cffeb35a951441  gcc/testsuite/g++.dg/pr100774.C
--- 35349,35359 ----
  436d3d1e052b227d2661a53bc1d71e69  gcc/testsuite/g++.dg/plugin/self-assign-test-2.C
  e051d5cb1d92744fe18b74552249a54e  gcc/testsuite/g++.dg/plugin/self-assign-test-3.C
  5f9b6973b5f55304febb17e03d56165d  gcc/testsuite/g++.dg/plugin/selfassign.cc
! 649a9b4c04ffbac71af84efe7b87fe2d  gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
  669d6447cc7cb76ea3787b8008016b3f  gcc/testsuite/g++.dg/plugin/show-template-tree-color-no-elide-type.C
  6a6dbcbab6d373e63c771d4d3f143ebb  gcc/testsuite/g++.dg/plugin/show-template-tree-color-no-highlight-colors.C
  946f03549b5d21aa38c5f97b1f198eac  gcc/testsuite/g++.dg/plugin/show-template-tree-color.C
! 67cf82e34825298adb69e14878eb5af8  gcc/testsuite/g++.dg/plugin/show_template_tree_color_plugin.cc
  d52f4cb5f64b45258d5b1297ad88b4d1  gcc/testsuite/g++.dg/pr100253.C
  8565710d6f77641a38bd4e09919a3fb2  gcc/testsuite/g++.dg/pr100574.C
  fff532cdcec98c1dd1cffeb35a951441  gcc/testsuite/g++.dg/pr100774.C
*************** ae883844cdffe266994223192fd8cd35  gcc/te
*** 37567,37572 ****
--- 37599,37605 ----
  f298eddbaaad3dfdc15f6cf9683ff08a  gcc/testsuite/g++.dg/torture/pr11911.C
  9df51f0b5a7e716286f2e97dfd28d477  gcc/testsuite/g++.dg/torture/pr119610.C
  9cede7e8b587157ccdf0f9f6667d6cc8  gcc/testsuite/g++.dg/torture/pr119778.C
+ 34ccf862a19942e4a76e7409c03669c6  gcc/testsuite/g++.dg/torture/pr120119-1.C
  a7a00125ef903c9e5ba25788e8c60eab  gcc/testsuite/g++.dg/torture/pr120721.C
  161154ed9f6193a2a7da119e068c3f3f  gcc/testsuite/g++.dg/torture/pr27218.C
  a84e9fff95df4801f8e582fbc33303b8  gcc/testsuite/g++.dg/torture/pr30252.C
*************** d183cd43f2c2caf1b71024ba3762ff44  gcc/te
*** 38887,38893 ****
  74decc16b8ca63b12db874b7dde868cf  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-2.C
  5c4cad449e21fe0fade92c9c0d19fb5f  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-3.C
  da3dbc8526151b41f4a741a5d5e51eae  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-4.C
! f53b1f90733acd430c8cdf6142c6d0ae  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C
  8afe47a7579150c18e697be841db6df5  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-6.C
  c6df77cbbce60aad70c6bc987ecd4bd2  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-7.C
  42429ebb9efa51a442c7b9c8a566923a  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-8.C
--- 38920,38926 ----
  74decc16b8ca63b12db874b7dde868cf  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-2.C
  5c4cad449e21fe0fade92c9c0d19fb5f  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-3.C
  da3dbc8526151b41f4a741a5d5e51eae  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-4.C
! fef7a83173bbbc642fd475e4c5dbf6ea  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C
  8afe47a7579150c18e697be841db6df5  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-6.C
  c6df77cbbce60aad70c6bc987ecd4bd2  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-7.C
  42429ebb9efa51a442c7b9c8a566923a  gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-8.C
*************** d4ca4a940822b140b8a1ada40f4e60af  gcc/te
*** 43079,43084 ****
--- 43112,43120 ----
  6979d0ef19d61a437acf8559362a5af8  gcc/testsuite/g++.target/aarch64/sve/pr99813.C
  eb290283439217e61bf7146ea947386f  gcc/testsuite/g++.target/aarch64/sve/static-var-in-template.C
  221b0724e04f13318fe418921311ae33  gcc/testsuite/g++.target/aarch64/sve/tls_2.C
+ f2969d067e4c537b5662ae46aa21e47a  gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_1.C
+ 3c9eab8b5dd49173ece65c23ccd7e870  gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_2.C
+ 1a2d0298a4b483775c5e71824c6036c5  gcc/testsuite/g++.target/aarch64/sve/unpacked_cond_binary_bf16_1.C
  a107043aa6d78c7f248ca1ffca6ac183  gcc/testsuite/g++.target/aarch64/sve/vcond_1.C
  aa928203aafdb1f6793fe73d77390fc9  gcc/testsuite/g++.target/aarch64/sve/vcond_1_run.C
  909fc314136664c317df5b6968da7f07  gcc/testsuite/g++.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp
*************** c9481d742a48253660d16743a6beecf9  gcc/te
*** 49002,49007 ****
--- 49038,49056 ----
  bcbbadd260cb26dea44e22620dc945b0  gcc/testsuite/gcc.dg/asm-a.c
  854712dcdce9c518846f9d22895c1fff  gcc/testsuite/gcc.dg/asm-b.c
  e370903640e76bf4ef407aafe0286689  gcc/testsuite/gcc.dg/asm-fs-1.c
+ eb1745cbc57b196ac34cc1aa088f8ce5  gcc/testsuite/gcc.dg/asm-hard-reg-1.c
+ 325832a9cf0ca182b0a51d48a9a9d098  gcc/testsuite/gcc.dg/asm-hard-reg-2.c
+ f60c7b0f361b02f30b6eca3c14c7a5ed  gcc/testsuite/gcc.dg/asm-hard-reg-3.c
+ 19553371b048e81f63e602bb709f9bcd  gcc/testsuite/gcc.dg/asm-hard-reg-4.c
+ 68e110aa154448d95f0634f0b8537cbc  gcc/testsuite/gcc.dg/asm-hard-reg-5.c
+ 61c0d51996da17f2618f52628326324d  gcc/testsuite/gcc.dg/asm-hard-reg-6.c
+ 1a27715b4b755fb46b13300fd15e4690  gcc/testsuite/gcc.dg/asm-hard-reg-7.c
+ 518c17261bb078d2460f83de54b6ca4e  gcc/testsuite/gcc.dg/asm-hard-reg-8.c
+ 6efc44e8421733f17459df29fad822ab  gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c
+ 9db82ff602331dd327582c106428d7c7  gcc/testsuite/gcc.dg/asm-hard-reg-error-2.c
+ cab2f6614936ad8277c5e69a7b79833e  gcc/testsuite/gcc.dg/asm-hard-reg-error-3.c
+ 0ad9fe09c331698259e82b017fc2ad67  gcc/testsuite/gcc.dg/asm-hard-reg-error-4.c
+ 48a03a36e0e3524536d964fce50cc8d7  gcc/testsuite/gcc.dg/asm-hard-reg-error-5.c
  6c3cba24c3d3fbf660605697935b9be5  gcc/testsuite/gcc.dg/asm-names.c
  9c3b7de14ce6ac49627b91e2808376e5  gcc/testsuite/gcc.dg/asm-pr24146.c
  bb1414d3448a4d73560e8bf9f884913a  gcc/testsuite/gcc.dg/asm-qual-1.c
*************** d9f2439f176b4f73afa0c30baa468855  gcc/te
*** 54917,54926 ****
  72712f41dcc921ba1827000fc0809a9c  gcc/testsuite/gcc.dg/pie-link.c
  000d3a6c8dca7e54f5be771190d10f29  gcc/testsuite/gcc.dg/pie-static-1.c
  be052bceddbf752586b645bc9e048e9c  gcc/testsuite/gcc.dg/pie-static-2.c
! 06fc0933356fe57959666abea2f07f59  gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
! 496791c2cd4980ffdc9a17ee52e31ebc  gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc
! f256e1fca9dce4089a6d9d913c5f5e6a  gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc
! e894a2297a56ca0e7301582b3b1c8141  gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc
  cb4eac35bee8576a953631c035c2ff66  gcc/testsuite/gcc.dg/plugin/copy_from_user-1.c
  47f23deacf7629644591a6e9f024a065  gcc/testsuite/gcc.dg/plugin/cpython-plugin-test-PyList_Append.c
  77898c598fcadce69594a47533fa5d08  gcc/testsuite/gcc.dg/plugin/cpython-plugin-test-PyList_New.c
--- 54966,54975 ----
  72712f41dcc921ba1827000fc0809a9c  gcc/testsuite/gcc.dg/pie-link.c
  000d3a6c8dca7e54f5be771190d10f29  gcc/testsuite/gcc.dg/pie-static-1.c
  be052bceddbf752586b645bc9e048e9c  gcc/testsuite/gcc.dg/pie-static-2.c
! 8b0a96b67b0859d07a24f9cc75b1183d  gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
! ac8e52344745ed81a70289dfea4373ae  gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc
! c94d4ef0e82eca288b0c546b6207ad15  gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc
! 6c6d7fd4315fca848e6c40146ad26593  gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc
  cb4eac35bee8576a953631c035c2ff66  gcc/testsuite/gcc.dg/plugin/copy_from_user-1.c
  47f23deacf7629644591a6e9f024a065  gcc/testsuite/gcc.dg/plugin/cpython-plugin-test-PyList_Append.c
  77898c598fcadce69594a47533fa5d08  gcc/testsuite/gcc.dg/plugin/cpython-plugin-test-PyList_New.c
*************** a59c3c55e77b2ab336a32f5ffc9ed6ba  gcc/te
*** 54984,54990 ****
  7288fef9790277fe3bb349e82cef1875  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c
  c1874b847baa5d41d58aa2db643143da  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c
  2c7e32cd8f076c6b6406aef7209045e7  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-parseable-fixits.c
! 2ce8701c16038d138e802d62e66c4cba  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus.py
  39f1ab78432ac25892fad284e179d8ac  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c
  bb20191ab0ad6e0d6ba368003d857339  gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
  1a45355cf06403e775b5d7ab5b2a59f7  gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-2.c
--- 55033,55039 ----
  7288fef9790277fe3bb349e82cef1875  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-generate-patch.c
  c1874b847baa5d41d58aa2db643143da  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-no-labels.c
  2c7e32cd8f076c6b6406aef7209045e7  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-parseable-fixits.c
! 07721d53fa9641d19eb23ad4e87142ac  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus.py
  39f1ab78432ac25892fad284e179d8ac  gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-trees-1.c
  bb20191ab0ad6e0d6ba368003d857339  gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
  1a45355cf06403e775b5d7ab5b2a59f7  gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-2.c
*************** bb20191ab0ad6e0d6ba368003d857339  gcc/te
*** 54995,55016 ****
  ac52c5d4de0c71ac6754e0b97aa2d1aa  gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-none.c
  42f7a9a0ce93b9a8f3456309a30456af  gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-bw.c
  60342111ed9bfef70e8686e973bb3988  gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-color.c
! 9bcc777bd2ff3fade830e2b8c7a4cacd  gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.cc
! 760ef2ce64f353acb078fd7035069296  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.cc
! 7e003500609bf7d82a052a5c042cbb5e  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc
! db3e6ef9ec4da923b133090fdbe255cc  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.cc
! 55c90f2e521240707723c45e6dbb1902  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc
  75e9c4ca32ac5c1329afb3fd1be6a829  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_nesting.cc
! 7a7a20c91af2e903f8c7c359a1fc02b5  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc
! 0a37946450abc0b85ed4c74f29640091  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc
! 1ccc719787fbe42fe419d1cbaff567f7  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.cc
! b6d4440d9bc5c3c1e7f4a283f75cdff7  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.cc
! 5717eba351963438141001f9817dac7f  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.cc
  07558668b4c054118c12c8514bb94698  gcc/testsuite/gcc.dg/plugin/dump-1.c
  88c83e306ac4f214fd9bc80a3eba0054  gcc/testsuite/gcc.dg/plugin/dump-2.c
  2f6c0c2319ecba4687d8ba0acc7e8ffd  gcc/testsuite/gcc.dg/plugin/dump_plugin.cc
  3364b35e14d37af3ceb073f305b97409  gcc/testsuite/gcc.dg/plugin/expensive-selftests-1.c
! 25598979f9d3916bc01148a4a65c04ee  gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.cc
  17affb987043f39ff846effdbaa6040c  gcc/testsuite/gcc.dg/plugin/finish_unit-test-1.c
  f73dcf28a556d348a80ecf63c3650bad  gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.cc
  232d54c69029a45c46660ba009ebdf28  gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c
--- 55044,55065 ----
  ac52c5d4de0c71ac6754e0b97aa2d1aa  gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-none.c
  42f7a9a0ce93b9a8f3456309a30456af  gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-bw.c
  60342111ed9bfef70e8686e973bb3988  gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-color.c
! 31960c8f8160ddbe657000006c0f2b26  gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.cc
! 84ed0757ba99c1e83f1a5e4fefddc5ae  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.cc
! 36948e85961037bf9113d58e6ae69a7d  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc
! d4d1eb70aaafc800a751ded4bc9f9fd6  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.cc
! 04b1c27ed8364e0abc5c25eef8f78fc1  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc
  75e9c4ca32ac5c1329afb3fd1be6a829  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_nesting.cc
! 47f9a604bf80ed29b8317e210244e4f4  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc
! e4f0ad5229354470634368d940ddd0c5  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc
! 5a7575f0a8605ea8a15a136481b6c505  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.cc
! ac48582404b79145b5d9911649cfbd68  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.cc
! 35b21ecd7b9c196c7811d1b485da063b  gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.cc
  07558668b4c054118c12c8514bb94698  gcc/testsuite/gcc.dg/plugin/dump-1.c
  88c83e306ac4f214fd9bc80a3eba0054  gcc/testsuite/gcc.dg/plugin/dump-2.c
  2f6c0c2319ecba4687d8ba0acc7e8ffd  gcc/testsuite/gcc.dg/plugin/dump_plugin.cc
  3364b35e14d37af3ceb073f305b97409  gcc/testsuite/gcc.dg/plugin/expensive-selftests-1.c
! 5b0ef269e1d59eb14a6e7a30b137f556  gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.cc
  17affb987043f39ff846effdbaa6040c  gcc/testsuite/gcc.dg/plugin/finish_unit-test-1.c
  f73dcf28a556d348a80ecf63c3650bad  gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.cc
  232d54c69029a45c46660ba009ebdf28  gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c
*************** d599542d2bc9679a29260101b5c82178  gcc/te
*** 55045,55051 ****
  8bc743f30102ffbfb1bc6a409fc63a2e  gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr83173-2.h
  6d6028de00b79eb5be6f42b7a4332c90  gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr83173.c
  96ff609825b6520f9e9cc6f866930933  gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr83173.h
! 47922d1e280d753ecebc1c5e88e9463e  gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.cc
  c323b7b4ac0cf2caa641c6bb31350375  gcc/testsuite/gcc.dg/plugin/must-tail-call-1.c
  de7a6b85ff1667e6ef4b89117e774f2d  gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c
  4905199fc259967af414db22821f7f74  gcc/testsuite/gcc.dg/plugin/must_tail_call_plugin.cc
--- 55094,55100 ----
  8bc743f30102ffbfb1bc6a409fc63a2e  gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr83173-2.h
  6d6028de00b79eb5be6f42b7a4332c90  gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr83173.c
  96ff609825b6520f9e9cc6f866930933  gcc/testsuite/gcc.dg/plugin/location-overflow-test-pr83173.h
! b6a1549985613ad4e6ea445d5e766ff8  gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.cc
  c323b7b4ac0cf2caa641c6bb31350375  gcc/testsuite/gcc.dg/plugin/must-tail-call-1.c
  de7a6b85ff1667e6ef4b89117e774f2d  gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c
  4905199fc259967af414db22821f7f74  gcc/testsuite/gcc.dg/plugin/must_tail_call_plugin.cc
*************** b2cc9b3414f5f8e47e69d7429d38f51b  gcc/te
*** 55431,55436 ****
--- 55480,55487 ----
  b108b00c49aeb9d5d164d8d72e3dcc50  gcc/testsuite/gcc.dg/pr109187.c
  c66fee8d96a854eabadb8ee243caabd6  gcc/testsuite/gcc.dg/pr109230.c
  fef759074d2405b19218d52a2f1d4c87  gcc/testsuite/gcc.dg/pr109238.c
+ 2452f78f1250d8450bd43ff624d0375c  gcc/testsuite/gcc.dg/pr109267-1.c
+ 29c5a68571c10dce111bfab3d03b0494  gcc/testsuite/gcc.dg/pr109267-2.c
  024ef2629cf4c28ff2dfffc47f34bf27  gcc/testsuite/gcc.dg/pr109274.c
  0c748fdbad039c05fc772087b11f05ae  gcc/testsuite/gcc.dg/pr109301.c
  7fdf5b5bab6aec81de409bfb1430ba9f  gcc/testsuite/gcc.dg/pr109303.c
*************** d2c0f87695635c09b6a893cd2d5c5478  gcc/te
*** 55712,55717 ****
--- 55763,55770 ----
  799c5822cecd54a85c86ba442df0a63e  gcc/testsuite/gcc.dg/pr120661-2.c
  3617a8786eb32339e9abd40e5a0323eb  gcc/testsuite/gcc.dg/pr120701.c
  c57884e34f257e33d206372fc675b716  gcc/testsuite/gcc.dg/pr121035.c
+ d602fec0c129037ce49acd7cccfd6266  gcc/testsuite/gcc.dg/pr121202.c
+ 942ef1841a793e5e296b868a6cfed912  gcc/testsuite/gcc.dg/pr121216.c
  bc5ddfbbc46f4e0cce1629d1b58d3090  gcc/testsuite/gcc.dg/pr12603.c
  72a2fca76cb69617ae36bab93c7ec0d7  gcc/testsuite/gcc.dg/pr12625-1.c
  6f0ef61e5a12db5f11da839b2988c5e1  gcc/testsuite/gcc.dg/pr13519-1.c
*************** b0750cc8ba04869cc1e70217f4eebdbc  gcc/te
*** 57377,57383 ****
  b1250df26ff8ccc22fe46e310c4934e6  gcc/testsuite/gcc.dg/pr87485.c
  a357c4dca7ce74a04dd61ff432ff8404  gcc/testsuite/gcc.dg/pr87490.c
  2074c70265dd55ff5184741b46a809c2  gcc/testsuite/gcc.dg/pr87600-1.c
! b96db39862d2314709fc8f443e2377ae  gcc/testsuite/gcc.dg/pr87600-2.c
  74d28a5be04fc65ca20ae9dde0fb1194  gcc/testsuite/gcc.dg/pr87600.h
  b7d45912d0dac5e2ce046c07528b0357  gcc/testsuite/gcc.dg/pr87672.c
  1e2ee0fcf0cc52376376b86486419c06  gcc/testsuite/gcc.dg/pr87746.c
--- 57430,57437 ----
  b1250df26ff8ccc22fe46e310c4934e6  gcc/testsuite/gcc.dg/pr87485.c
  a357c4dca7ce74a04dd61ff432ff8404  gcc/testsuite/gcc.dg/pr87490.c
  2074c70265dd55ff5184741b46a809c2  gcc/testsuite/gcc.dg/pr87600-1.c
! 7374c7fb7ac6f5385bc4d7a0939d9f1e  gcc/testsuite/gcc.dg/pr87600-2.c
! 0918291826befd2f5bff5fb1d8072547  gcc/testsuite/gcc.dg/pr87600-3.c
  74d28a5be04fc65ca20ae9dde0fb1194  gcc/testsuite/gcc.dg/pr87600.h
  b7d45912d0dac5e2ce046c07528b0357  gcc/testsuite/gcc.dg/pr87672.c
  1e2ee0fcf0cc52376376b86486419c06  gcc/testsuite/gcc.dg/pr87746.c
*************** d3793bbe48652d7af1be40301a35eae3  gcc/te
*** 57949,57955 ****
  6aae73039d4bc746b5807f91287c3d44  gcc/testsuite/gcc.dg/sarif-output/include-chain-1.h
  ec17506807c0ad221173ac50eb2b7117  gcc/testsuite/gcc.dg/sarif-output/include-chain-1.py
  123e8648e30cb6b9f1ef85cb13863be6  gcc/testsuite/gcc.dg/sarif-output/include-chain-2.c
! e1a602f18f30b6a8dddbcb96660d20e6  gcc/testsuite/gcc.dg/sarif-output/include-chain-2.h
  ca7553d76ac8b430a8cfeac7248e81d5  gcc/testsuite/gcc.dg/sarif-output/include-chain-2.py
  59bdcef55b29b7c5ef21ae717011bfec  gcc/testsuite/gcc.dg/sarif-output/missing-semicolon.c
  3af1297812eb004e222716d3f9c08a47  gcc/testsuite/gcc.dg/sarif-output/missing-semicolon.py
--- 58003,58009 ----
  6aae73039d4bc746b5807f91287c3d44  gcc/testsuite/gcc.dg/sarif-output/include-chain-1.h
  ec17506807c0ad221173ac50eb2b7117  gcc/testsuite/gcc.dg/sarif-output/include-chain-1.py
  123e8648e30cb6b9f1ef85cb13863be6  gcc/testsuite/gcc.dg/sarif-output/include-chain-2.c
! 472dad2057e4615f1f0f19f292968314  gcc/testsuite/gcc.dg/sarif-output/include-chain-2.h
  ca7553d76ac8b430a8cfeac7248e81d5  gcc/testsuite/gcc.dg/sarif-output/include-chain-2.py
  59bdcef55b29b7c5ef21ae717011bfec  gcc/testsuite/gcc.dg/sarif-output/missing-semicolon.c
  3af1297812eb004e222716d3f9c08a47  gcc/testsuite/gcc.dg/sarif-output/missing-semicolon.py
*************** a789d5fa70ddcb7ea1760ee8688e331c  gcc/te
*** 59456,59461 ****
--- 59510,59516 ----
  e23df6b1422011499b9a500d2bf25add  gcc/testsuite/gcc.dg/torture/pr120944.c
  2109362b50e367ef8730288e7461163d  gcc/testsuite/gcc.dg/torture/pr120951-1.c
  e0878b10bf90cdd28ee181056e4566f9  gcc/testsuite/gcc.dg/torture/pr121116.c
+ a0f8ab77c0d77ef71974e1bd49ecec66  gcc/testsuite/gcc.dg/torture/pr121194.c
  ded4330fd1cd52783bd9b1761db038ef  gcc/testsuite/gcc.dg/torture/pr16104-1.c
  fc265ee05da2f29f0e92804661cd1f28  gcc/testsuite/gcc.dg/torture/pr17526.c
  01c583edb41b632b835aa892b9c1cb14  gcc/testsuite/gcc.dg/torture/pr17933-1.c
*************** edbd9c8149ee7f7444bccf51ba92d4d3  gcc/te
*** 61040,61045 ****
--- 61095,61101 ----
  a3b38bae98a3e59b214495d7876b628d  gcc/testsuite/gcc.dg/tree-ssa/clz-long-long.c
  b81775b8e2a31310b44c81245fcf9eec  gcc/testsuite/gcc.dg/tree-ssa/clz-long.c
  33f85eb0abc0ef1a76d386a351d636de  gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c
+ fb25857d234677e77b3d70ba58f5a982  gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c
  f4e19c8828a0d6f955101c070bea8b7b  gcc/testsuite/gcc.dg/tree-ssa/cmpbit-1.c
  a39dab289b7a420b65c6f1cfa6d4b033  gcc/testsuite/gcc.dg/tree-ssa/cmpbit-2.c
  67cdad9dd803b591ec81ea144f12ade1  gcc/testsuite/gcc.dg/tree-ssa/cmpbit-3.c
*************** f2fb3151add498ea76d57eb5397270d9  gcc/te
*** 61466,61471 ****
--- 61522,61528 ----
  0b0f06ef0d088201a656eef58febfabf  gcc/testsuite/gcc.dg/tree-ssa/loop-niter-1.c
  3585c145cba008fa15dffe90270f4cc5  gcc/testsuite/gcc.dg/tree-ssa/loop-niter-2.c
  a83f3f323f8f4ab72419c34630657fda  gcc/testsuite/gcc.dg/tree-ssa/loopclosedphi.c
+ 12d912e24657e2b7d272708953b4aa05  gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c
  f11323cf409551d134864434f043878e  gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c
  1ec5297885ed15753a6dc4db4543306f  gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c
  03f2e136e4fd829b170e29613889a81e  gcc/testsuite/gcc.dg/tree-ssa/minmax-1.c
*************** ad2bfdd6a893fdb581e5cffc0c618d52  gcc/te
*** 61780,61785 ****
--- 61837,61843 ----
  b8236d8ce423075243050d2ed9692781  gcc/testsuite/gcc.dg/tree-ssa/pr118517.c
  6d2d98158a34d9ab09e487779a321f3d  gcc/testsuite/gcc.dg/tree-ssa/pr118637.c
  269c5fb72451371e1dde1dd85e06c989  gcc/testsuite/gcc.dg/tree-ssa/pr118902-1.c
+ b0891b1dddf226da47f4f976abdd7cb0  gcc/testsuite/gcc.dg/tree-ssa/pr119085.c
  9f16ee3f51fd11f2ecc69288d35eb523  gcc/testsuite/gcc.dg/tree-ssa/pr120080.c
  7f3a7c07aebf7f97b00e05ed858383da  gcc/testsuite/gcc.dg/tree-ssa/pr120231-1.c
  dab88e25e03ff735e2c1de465e1513fc  gcc/testsuite/gcc.dg/tree-ssa/pr120231-2.c
*************** d33f4213b2023b5f7798fbdda71e4dce  gcc/te
*** 62143,62149 ****
  b32558d490c5c73277ce27875bb1bfc0  gcc/testsuite/gcc.dg/tree-ssa/pr81588.c
  6da94e378d2807aa10551762fa89a6c6  gcc/testsuite/gcc.dg/tree-ssa/pr81620-1.c
  12aef6fb81e4885a0f93eb2c000f331d  gcc/testsuite/gcc.dg/tree-ssa/pr81620-2.c
! fdce0a001914fdb36e217ac7fb305fd7  gcc/testsuite/gcc.dg/tree-ssa/pr81627.c
  e5092fb25b6f25aec065f319edc5aa8c  gcc/testsuite/gcc.dg/tree-ssa/pr81741.c
  24cc934a07086354accf389a7abdcc92  gcc/testsuite/gcc.dg/tree-ssa/pr81744.c
  19a84f872ab2582af0078ed8363bb611  gcc/testsuite/gcc.dg/tree-ssa/pr81799.c
--- 62201,62207 ----
  b32558d490c5c73277ce27875bb1bfc0  gcc/testsuite/gcc.dg/tree-ssa/pr81588.c
  6da94e378d2807aa10551762fa89a6c6  gcc/testsuite/gcc.dg/tree-ssa/pr81620-1.c
  12aef6fb81e4885a0f93eb2c000f331d  gcc/testsuite/gcc.dg/tree-ssa/pr81620-2.c
! 4f7cd098e8ac5e1ff59bb254ac4a8158  gcc/testsuite/gcc.dg/tree-ssa/pr81627.c
  e5092fb25b6f25aec065f319edc5aa8c  gcc/testsuite/gcc.dg/tree-ssa/pr81741.c
  24cc934a07086354accf389a7abdcc92  gcc/testsuite/gcc.dg/tree-ssa/pr81744.c
  19a84f872ab2582af0078ed8363bb611  gcc/testsuite/gcc.dg/tree-ssa/pr81799.c
*************** d869cf884bf06167758bc9df313cee97  gcc/te
*** 62911,62916 ****
--- 62969,62975 ----
  55b0bbd3097383eac55fcb6866cb5adc  gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-20.c
  482d80e92a069d08635a39d530a4ec3e  gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-21.c
  b59c690dac317381a21e2e6cdf9a7525  gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-22.c
+ 1b2868fc75b0422f80ae23c634ed5621  gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-23.c
  9825bb51561846515088fa3daf93eb2c  gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c
  3c498a479ee03a4591c4e96f4a6bf880  gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-4.c
  5cbdfbf1e670807b4bbad98ff1c27449  gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-5.c
*************** db016c873ed206041bc50ac092ce545d  gcc/te
*** 64149,64155 ****
  ea3272b0a6fbd82aefd459202d8b2afc  gcc/testsuite/gcc.dg/vect/pr115841.c
  f4dccafbd979e394e9963f12d52ce1c2  gcc/testsuite/gcc.dg/vect/pr115843.c
  1f0dd6165a23cae6ea231f351632f121  gcc/testsuite/gcc.dg/vect/pr115959.c
! 3617874dc8f0f764b079db5c7e0fa79b  gcc/testsuite/gcc.dg/vect/pr116125.c
  a57032340d085147bd51078386a121d7  gcc/testsuite/gcc.dg/vect/pr116352.c
  fe47826bbf472c7e1ba0157e8f200635  gcc/testsuite/gcc.dg/vect/pr116575.c
  125b0e9fa6165f1885391cf7f88611b5  gcc/testsuite/gcc.dg/vect/pr116628.c
--- 64208,64214 ----
  ea3272b0a6fbd82aefd459202d8b2afc  gcc/testsuite/gcc.dg/vect/pr115841.c
  f4dccafbd979e394e9963f12d52ce1c2  gcc/testsuite/gcc.dg/vect/pr115843.c
  1f0dd6165a23cae6ea231f351632f121  gcc/testsuite/gcc.dg/vect/pr115959.c
! 02a606070b271bd007173d3b9f5551b9  gcc/testsuite/gcc.dg/vect/pr116125.c
  a57032340d085147bd51078386a121d7  gcc/testsuite/gcc.dg/vect/pr116352.c
  fe47826bbf472c7e1ba0157e8f200635  gcc/testsuite/gcc.dg/vect/pr116575.c
  125b0e9fa6165f1885391cf7f88611b5  gcc/testsuite/gcc.dg/vect/pr116628.c
*************** d63a3ba805f750904ac56d5a3099e28f  gcc/te
*** 64605,64611 ****
  7366b1c35af385466b2fb3e0ac751199  gcc/testsuite/gcc.dg/vect/slp-24.c
  e3153e4fa0cd57f31cd27ff2a5e3e509  gcc/testsuite/gcc.dg/vect/slp-25.c
  12b26338d07e33733f60949b9879a355  gcc/testsuite/gcc.dg/vect/slp-26.c
! 1400ec4b5a057164a2b0f27db7323166  gcc/testsuite/gcc.dg/vect/slp-28.c
  4e1ffccecc23382df688437a5f471a8e  gcc/testsuite/gcc.dg/vect/slp-3-big-array.c
  8e4d813bb5abc2214d5c49998ce56f69  gcc/testsuite/gcc.dg/vect/slp-3.c
  790fc2743ec1a739262fae4d397bacfa  gcc/testsuite/gcc.dg/vect/slp-33.c
--- 64664,64670 ----
  7366b1c35af385466b2fb3e0ac751199  gcc/testsuite/gcc.dg/vect/slp-24.c
  e3153e4fa0cd57f31cd27ff2a5e3e509  gcc/testsuite/gcc.dg/vect/slp-25.c
  12b26338d07e33733f60949b9879a355  gcc/testsuite/gcc.dg/vect/slp-26.c
! 72867fd93d334910b817557f3c9596f9  gcc/testsuite/gcc.dg/vect/slp-28.c
  4e1ffccecc23382df688437a5f471a8e  gcc/testsuite/gcc.dg/vect/slp-3-big-array.c
  8e4d813bb5abc2214d5c49998ce56f69  gcc/testsuite/gcc.dg/vect/slp-3.c
  790fc2743ec1a739262fae4d397bacfa  gcc/testsuite/gcc.dg/vect/slp-33.c
*************** eb957e8021e48e5316de303f90acf93d  gcc/te
*** 64889,64894 ****
--- 64948,64954 ----
  17e1fd733b776ac37fe82aa4e0e672c7  gcc/testsuite/gcc.dg/vect/vect-124.c
  d1187d0e4af6272062f2c0272cefedc0  gcc/testsuite/gcc.dg/vect/vect-125.c
  2f1d70fac40824a935446a6fbe98a4b9  gcc/testsuite/gcc.dg/vect/vect-126.c
+ fdc14626a4ceb8299c001f97cc969cc8  gcc/testsuite/gcc.dg/vect/vect-127.c
  d6bd417d3eca5baa91e6702748a3c1cc  gcc/testsuite/gcc.dg/vect/vect-13.c
  2f4ebdd8f30675c3e85c475850edbf37  gcc/testsuite/gcc.dg/vect/vect-14.c
  1a0be8fa1ed53c514993f7dcb4962ac8  gcc/testsuite/gcc.dg/vect/vect-15-big-array.c
*************** dec6fa45fd2a29df2bb34f29716542bd  gcc/te
*** 67006,67011 ****
--- 67066,67073 ----
  84cc9bafe1857dc2a9bd4ae96b8c27e3  gcc/testsuite/gcc.target/aarch64/asm-flag-5.c
  81557d2f721a4a556b0a0651b5d87cbd  gcc/testsuite/gcc.target/aarch64/asm-flag-6.c
  58ce71dec34e038ef9935b9ddf669c0b  gcc/testsuite/gcc.target/aarch64/asm-flag-7.c
+ 375f0c6e1488193a7f098d82f5eba427  gcc/testsuite/gcc.target/aarch64/asm-hard-reg-1.c
+ a9fdebc57818793aef3a5e64bd82fd28  gcc/testsuite/gcc.target/aarch64/asm-hard-reg-2.c
  d1ef31752e82f204d0e8943181982368  gcc/testsuite/gcc.target/aarch64/asm-x-constraint-1.c
  9ddf4430e4abf2352e0ad119aab27915  gcc/testsuite/gcc.target/aarch64/asm-y-constraint-1.c
  4243a23aa0a384578b2d05d3f99be487  gcc/testsuite/gcc.target/aarch64/assembler_arch_1.c
*************** e133d603af3ecab67fb41464a457b091  gcc/te
*** 67498,67503 ****
--- 67560,67566 ----
  825a05cc66dd3bb694b37457fcfbf490  gcc/testsuite/gcc.target/aarch64/ins_bitfield_6.c
  b37a5781e82510dfa7ecdf3ce4922a58  gcc/testsuite/gcc.target/aarch64/insv_1.c
  a897ae01d807185bd4ca7f1587e181d9  gcc/testsuite/gcc.target/aarch64/insv_2.c
+ 991106b935a581db429c79eb1313b434  gcc/testsuite/gcc.target/aarch64/inszero_split_1.c
  18f0bd2efa738426efce6208b83e0cbd  gcc/testsuite/gcc.target/aarch64/int_mov_immediate_1.c
  2feabf7a23a544e445cd6f1d402811d0  gcc/testsuite/gcc.target/aarch64/lane-bound-1.c
  49907aab7182a2a85495455c2d574117  gcc/testsuite/gcc.target/aarch64/lane-bound-2.c
*************** df08a7f1b91a8c0f914aab7f291c95e7  gcc/te
*** 68106,68112 ****
  1ac38190a51cc9809d49e9f6c2a922af  gcc/testsuite/gcc.target/aarch64/simd/lut-incorrect-range.c
  060c37e72d9cafd6e03a9988b7a1d094  gcc/testsuite/gcc.target/aarch64/simd/lut-no-flag.c
  670855cbe72625722e02671619b6566b  gcc/testsuite/gcc.target/aarch64/simd/lut.c
! eee3684fddf95ff5545c7c4454331e54  gcc/testsuite/gcc.target/aarch64/simd/mf8_data_1.c
  7a8dbe7357968ea67da61dae6606ebcd  gcc/testsuite/gcc.target/aarch64/simd/mf8_data_2.c
  2f6c6fee34ced3b932053a03d9906520  gcc/testsuite/gcc.target/aarch64/simd/pr117048.c
  2797bd4410da16b66ebb2f474c595ee5  gcc/testsuite/gcc.target/aarch64/simd/pr117048_2.c
--- 68169,68175 ----
  1ac38190a51cc9809d49e9f6c2a922af  gcc/testsuite/gcc.target/aarch64/simd/lut-incorrect-range.c
  060c37e72d9cafd6e03a9988b7a1d094  gcc/testsuite/gcc.target/aarch64/simd/lut-no-flag.c
  670855cbe72625722e02671619b6566b  gcc/testsuite/gcc.target/aarch64/simd/lut.c
! 490999093edf0ba9bd6941da62d8c8cd  gcc/testsuite/gcc.target/aarch64/simd/mf8_data_1.c
  7a8dbe7357968ea67da61dae6606ebcd  gcc/testsuite/gcc.target/aarch64/simd/mf8_data_2.c
  2f6c6fee34ced3b932053a03d9906520  gcc/testsuite/gcc.target/aarch64/simd/pr117048.c
  2797bd4410da16b66ebb2f474c595ee5  gcc/testsuite/gcc.target/aarch64/simd/pr117048_2.c
*************** b7284adec21d80573a852744d3773966  gcc/te
*** 72274,72279 ****
--- 72337,72343 ----
  d1c2e2a901e87fb52c1cfd1ff79df779  gcc/testsuite/gcc.target/aarch64/sve/mask_gather_load_7.c
  52379e5a1fc8215095293f9e8d860994  gcc/testsuite/gcc.target/aarch64/sve/mask_gather_load_8.c
  649716e3727c061dd3cee9567b1ab97b  gcc/testsuite/gcc.target/aarch64/sve/mask_load_1.c
+ 360f665ab7f041b257409ffaa81a2b56  gcc/testsuite/gcc.target/aarch64/sve/mask_load_2.c
  f6a3d086c2e96143317e844a1a523358  gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c
  33047a915e1581d35186161bbca699ee  gcc/testsuite/gcc.target/aarch64/sve/mask_scatter_store_1.c
  606025785cdd6d1660f408e9fe34b4b3  gcc/testsuite/gcc.target/aarch64/sve/mask_scatter_store_2.c
*************** e7a3b62d81ab7c0991182b370fdfe06f  gcc/te
*** 72898,72906 ****
--- 72962,72997 ----
  0dac8ce2706a1e811d4ef39d2e7c0c52  gcc/testsuite/gcc.target/aarch64/sve/unpack_signed_1_run.c
  5fc3acd66e8ad342f32e01a87a71ead4  gcc/testsuite/gcc.target/aarch64/sve/unpack_unsigned_1.c
  61ef61cfc6c64004c59a9698eaaf6e47  gcc/testsuite/gcc.target/aarch64/sve/unpack_unsigned_1_run.c
+ cbb583e769346a705a9db461beac3cce  gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_1.c
+ 3ab7a2f6a722a3131c217e8487c03083  gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_2.c
+ f98eb15f5da9c587cbd1580ea81e5fbf  gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_1.c
+ cbe11590ece9cd105540edd94c362e47  gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_2.c
+ 3f65e7887a5656b25906f7d1b2c438af  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmax_1.c
+ 8fff1349c5ac21d174e07a4f8dd38434  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmin_1.c
+ d1a0e57ad5dfe004c98097ce46500520  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_cvtf_1.c
+ 0d69b015b580bb570e5654163b582ed1  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fabs_1.c
+ 1c4878d0b33c17d59a4cd75faa0fc67c  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fadd_1.c
+ 08f38ba7a09366db8ac60d2e12db8456  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvt_1.c
+ c33fc567781611336499b31852c61259  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvtz_1.c
+ 0f5f9d4420133526a5c8284fe7432d8f  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fdiv_1.c
+ ccc42fc28c14703e041fd7c1c35a9244  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmaxnm_1.c
+ 9cf2f8650cfa8bf692e88ced6671bab2  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fminnm_1.c
+ ccb24dc405151cf8e646e111b7ce5514  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmul_1.c
+ 069ecd4a2b183d322e8facd1e446fcee  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fneg_1.c
+ ebd8cdc7fe2cbb8de5fcb08dc199bdf9  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_1.c
+ 6b026d6dcc7b84167556c755a7bed405  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_2.c
+ 11b10c25c0181ea348fd2c16bdf36f23  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinti_1.c
+ c5dbe0f561a5572079d3e303a7db6aaf  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintm_1.c
+ d481cf4a2ab0cc169ad85e9c84f01760  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintp_1.c
+ 0d4f8c8ff4646a69730213b74ca16eb0  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintx_1.c
+ c9cc1727956e7a03a48bd31118124788  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintz_1.c
+ 0ba39ded12f66b3b3c5019f1ab650a70  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fsubr_1.c
  a2b8cc7a8d9d0d79ca11573d406f7f6d  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cvtf_1.c
  8e60d86282221f5b0f2ca4fb58eb76f8  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cvtf_2.c
  ea24ecb4164b07ea882a7df9a25bae2e  gcc/testsuite/gcc.target/aarch64/sve/unpacked_cvtf_3.c
+ 13d5025f41f71daa00011567791bb0d6  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fabs_1.c
+ 8a9f3906e78fe5bc65a615b8dec4e42c  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_1.c
+ 4e078634520afd28b68f0af789569b50  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_2.c
  30ed6269d6e0348a31d60f5834b0f4a6  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcm_1.c
  c64a67d6ed2bf2b1ee2654a6ab54faec  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcm_2.c
  f97f494d93b00c2c0927d5724526059c  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcm_combines_1.c
*************** f97f494d93b00c2c0927d5724526059c  gcc/te
*** 72909,72914 ****
--- 73000,73029 ----
  cc5ae2e9ab4c84fdefc8af75fc17d5ab  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcvt_2.c
  53191c2f3e19f7d558c0a0e9ad1a7755  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcvtz_1.c
  0b800e2a318d40e9898cab825ffe9a5f  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcvtz_2.c
+ 380053c36fe5deaf302d6d1aa62fb267  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_1.c
+ b2171bd2b588aa5acb2e5ab240c2c863  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_2.c
+ 6990b1905547fb549a3c0037145c19f2  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_3.c
+ 90991060d5187e3e4a551e6844f226e3  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_1.c
+ 676b9f5ab7fd0d4bcf286ea474a80964  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_2.c
+ cab94f764a3ca73ed38202f14cc3fd19  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_1.c
+ 7b65fff751fd4988d48526c4a17010a3  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_2.c
+ b7775c7a3a06011254f2b820b3eae29e  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_1.c
+ 6fe41f6f621c177359a0a7e3916bd16d  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_2.c
+ 9e008589364239009e835aa3ce893ae4  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fneg_1.c
+ f9bce5b945adc4290b9ddf5e140d6b71  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_1.c
+ 1b0091a8a0ac4545afe9b83226f3bb1f  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_2.c
+ f403e19ebdde69549127cfc481fef4b5  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_1.c
+ 1d4e38e0dc4066365dfc747dce92b914  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_2.c
+ ca439794553a37fd1f6e6fd863e44627  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_1.c
+ 6cb472f7723a40c804f7067d143cc971  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_2.c
+ 8a399ad98095550331f1757ad592d77b  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_1.c
+ 3d4bda49704b3bda84389db7fb4466af  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_2.c
+ 655fbad5d3320cf558a8552e2d986953  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_1.c
+ b13c7c8deb78b44b53ec57f1d9a8710e  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_2.c
+ 48a0b2015c3e534c27e6a5771c60a7c5  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_1.c
+ 0bd4cd33c9f33955d7346492744e9b1b  gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_2.c
+ a776e5d06dee43e7816ef9453b3f3c06  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_1.c
+ 15d554c4d9d7f3a379a7a0ff18c71c74  gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_2.c
  f202a910bae302c6c775c55d23a33bc1  gcc/testsuite/gcc.target/aarch64/sve/unroll-1.c
  244a74375a0c2fe6ee32afc4c0cc347c  gcc/testsuite/gcc.target/aarch64/sve/uzp1_1.c
  d876021ee15812d1dc53c0bd7c9fc144  gcc/testsuite/gcc.target/aarch64/sve/uzp1_1_run.c
*************** a0d7ee23594a897783efec837fcc9a89  gcc/te
*** 74617,74623 ****
  94984b8886aab5d70d86c49c090fc10a  gcc/testsuite/gcc.target/aarch64/vec-init-single-const-be.c
  2a52f8c315f452dcdf472938c1cbaee5  gcc/testsuite/gcc.target/aarch64/vec-init-single-const.c
  c04188bb2b4a3589f00728d8e90d679f  gcc/testsuite/gcc.target/aarch64/vec-rot-exec.c
! ea714644678a19125b30ea9d003ff65f  gcc/testsuite/gcc.target/aarch64/vec-set-zero.c
  b1c97e59631c205f913afab4e1ffde4a  gcc/testsuite/gcc.target/aarch64/vec_init_1.c
  96b0c4ebb4ed6713b9f9e7fbb787a46c  gcc/testsuite/gcc.target/aarch64/vec_zeroextend.c
  a8bd653ddae99985293ee04dc707de34  gcc/testsuite/gcc.target/aarch64/vect-abs-compile.c
--- 74732,74738 ----
  94984b8886aab5d70d86c49c090fc10a  gcc/testsuite/gcc.target/aarch64/vec-init-single-const-be.c
  2a52f8c315f452dcdf472938c1cbaee5  gcc/testsuite/gcc.target/aarch64/vec-init-single-const.c
  c04188bb2b4a3589f00728d8e90d679f  gcc/testsuite/gcc.target/aarch64/vec-rot-exec.c
! f66a2dc11214cc437d96ec038cc0e85e  gcc/testsuite/gcc.target/aarch64/vec-set-zero.c
  b1c97e59631c205f913afab4e1ffde4a  gcc/testsuite/gcc.target/aarch64/vec_init_1.c
  96b0c4ebb4ed6713b9f9e7fbb787a46c  gcc/testsuite/gcc.target/aarch64/vec_zeroextend.c
  a8bd653ddae99985293ee04dc707de34  gcc/testsuite/gcc.target/aarch64/vect-abs-compile.c
*************** cca7e10ee55fb1f96e6f6f5962a52b47  gcc/te
*** 80161,80166 ****
--- 80276,80283 ----
  3e9a12e002713da0e72fa6fb23a52948  gcc/testsuite/gcc.target/i386/asm-flag-5.c
  12e90c2a4e4c615ce5067b4215a5d18b  gcc/testsuite/gcc.target/i386/asm-flag-6.c
  c9e95a50e4c08ce058a523de15b6c8fd  gcc/testsuite/gcc.target/i386/asm-flag-7.c
+ 9f878b07bed3798501be7940ffac2844  gcc/testsuite/gcc.target/i386/asm-hard-reg-1.c
+ 317a07e8b56b299b99f2de47c7dada42  gcc/testsuite/gcc.target/i386/asm-hard-reg-2.c
  837d6eb699db50d462ddc69fd4d051c2  gcc/testsuite/gcc.target/i386/asm-mem.c
  4ae3c20d33728cb22ef071075de01013  gcc/testsuite/gcc.target/i386/asm-raw-symbol.c
  60b9c38ffe8be2c784e795ea98607891  gcc/testsuite/gcc.target/i386/asm-redzone-1.c
*************** d128b18a20f2a55978e519508f48f1ae  gcc/te
*** 93749,93755 ****
  db5d1e3c602d7352acfe4e2bd42aa314  gcc/testsuite/gcc.target/powerpc/vsx-builtin-4.c
  0dc1b977f9f3965f6a1537554d57ebdc  gcc/testsuite/gcc.target/powerpc/vsx-builtin-5.c
  69b4e6af3daccab6666b3b17e26175fb  gcc/testsuite/gcc.target/powerpc/vsx-builtin-6.c
! cb404ead9c4f91da9ac4ca280474d7dd  gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c
  2c3abdb62eb2a43590aa3c4938aa05c6  gcc/testsuite/gcc.target/powerpc/vsx-builtin-8.c
  33633751eb0bfabbb2951a0070770508  gcc/testsuite/gcc.target/powerpc/vsx-builtin-9a.c
  2e9c4b2355be46611bfe42e4a9f8d1f3  gcc/testsuite/gcc.target/powerpc/vsx-builtin-9b.c
--- 93866,93872 ----
  db5d1e3c602d7352acfe4e2bd42aa314  gcc/testsuite/gcc.target/powerpc/vsx-builtin-4.c
  0dc1b977f9f3965f6a1537554d57ebdc  gcc/testsuite/gcc.target/powerpc/vsx-builtin-5.c
  69b4e6af3daccab6666b3b17e26175fb  gcc/testsuite/gcc.target/powerpc/vsx-builtin-6.c
! 2d4b274537060accb8588a288971c71c  gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c
  2c3abdb62eb2a43590aa3c4938aa05c6  gcc/testsuite/gcc.target/powerpc/vsx-builtin-8.c
  33633751eb0bfabbb2951a0070770508  gcc/testsuite/gcc.target/powerpc/vsx-builtin-9a.c
  2e9c4b2355be46611bfe42e4a9f8d1f3  gcc/testsuite/gcc.target/powerpc/vsx-builtin-9b.c
*************** b24e931e97473ad3344268fc34d9a089  gcc/te
*** 94548,94554 ****
  2c4e63df0ea453e7839094f9d7beb67b  gcc/testsuite/gcc.target/riscv/interrupt-3.c
  8f051d0b3bea4d4fffe124ffc69cc499  gcc/testsuite/gcc.target/riscv/interrupt-4.c
  9123fc821c454516a841bd5d016f9f25  gcc/testsuite/gcc.target/riscv/interrupt-5.c
! 9505a89fb61ad2da955a88ba280be95d  gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c
  adbaeb88f854d032ccb024f677c39231  gcc/testsuite/gcc.target/riscv/interrupt-debug.c
  c7ca14eb060960c19c3fd942f85d5fe3  gcc/testsuite/gcc.target/riscv/interrupt-fcsr-1.c
  c36c6439efa266a1451a2f487ec7e09b  gcc/testsuite/gcc.target/riscv/interrupt-fcsr-2.c
--- 94665,94671 ----
  2c4e63df0ea453e7839094f9d7beb67b  gcc/testsuite/gcc.target/riscv/interrupt-3.c
  8f051d0b3bea4d4fffe124ffc69cc499  gcc/testsuite/gcc.target/riscv/interrupt-4.c
  9123fc821c454516a841bd5d016f9f25  gcc/testsuite/gcc.target/riscv/interrupt-5.c
! 81118c6628b335c0d383666fa49a332e  gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c
  adbaeb88f854d032ccb024f677c39231  gcc/testsuite/gcc.target/riscv/interrupt-debug.c
  c7ca14eb060960c19c3fd942f85d5fe3  gcc/testsuite/gcc.target/riscv/interrupt-fcsr-1.c
  c36c6439efa266a1451a2f487ec7e09b  gcc/testsuite/gcc.target/riscv/interrupt-fcsr-2.c
*************** c36c6439efa266a1451a2f487ec7e09b  gcc/te
*** 94556,94563 ****
  fee79ad9a3947e1e6e8791239807aeb4  gcc/testsuite/gcc.target/riscv/interrupt-misaligned.c
  a0ec9e9b1278bec59b5f6fb4473ae0be  gcc/testsuite/gcc.target/riscv/interrupt-mmode.c
  1f185dea80449f2a4c268c953b9fbe22  gcc/testsuite/gcc.target/riscv/interrupt-no-lpad.c
  756572791a9293ef57d0855c156c1c04  gcc/testsuite/gcc.target/riscv/interrupt-smode.c
- 1cc7f11cb8b3790c544cfd62150e6d44  gcc/testsuite/gcc.target/riscv/interrupt-umode.c
  371709295f3134754428c912bd5e3ee4  gcc/testsuite/gcc.target/riscv/ior-synthesis-1.c
  016fae660b0d8d24c12a8ce81c7bc0c0  gcc/testsuite/gcc.target/riscv/ior-synthesis-2.c
  b656a9e0d73427727bb0cc6df44334ab  gcc/testsuite/gcc.target/riscv/jump-table-large-code-model.c
--- 94673,94680 ----
  fee79ad9a3947e1e6e8791239807aeb4  gcc/testsuite/gcc.target/riscv/interrupt-misaligned.c
  a0ec9e9b1278bec59b5f6fb4473ae0be  gcc/testsuite/gcc.target/riscv/interrupt-mmode.c
  1f185dea80449f2a4c268c953b9fbe22  gcc/testsuite/gcc.target/riscv/interrupt-no-lpad.c
+ a1e26ab7f1c0fd4128be164780eb6afc  gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c
  756572791a9293ef57d0855c156c1c04  gcc/testsuite/gcc.target/riscv/interrupt-smode.c
  371709295f3134754428c912bd5e3ee4  gcc/testsuite/gcc.target/riscv/ior-synthesis-1.c
  016fae660b0d8d24c12a8ce81c7bc0c0  gcc/testsuite/gcc.target/riscv/ior-synthesis-2.c
  b656a9e0d73427727bb0cc6df44334ab  gcc/testsuite/gcc.target/riscv/jump-table-large-code-model.c
*************** d700db1f930733fdbd313bf89720f0b0  gcc/te
*** 96838,96844 ****
  83e6dc1995a15780ac580d7539d56e36  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-3.c
  4392cb67d79b614fe40eafbab14483b4  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-4.c
  3bf9e5664d3defdbbf5c2a9b1fbce4e7  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-5.c
! d15d43b7a75ff677b061c9e55b720363  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-6.c
  2e16238a38c4e7a5d0a702db0dee4797  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat_run-1.c
  74635431f43d2f1a6933b055dd25692b  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat_run-2.c
  b3bcd506c350c34cc4adaa0a66028adb  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat_run-3.c
--- 96955,96961 ----
  83e6dc1995a15780ac580d7539d56e36  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-3.c
  4392cb67d79b614fe40eafbab14483b4  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-4.c
  3bf9e5664d3defdbbf5c2a9b1fbce4e7  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-5.c
! a134513ba68a9a6c683ee2b667056860  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-6.c
  2e16238a38c4e7a5d0a702db0dee4797  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat_run-1.c
  74635431f43d2f1a6933b055dd25692b  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat_run-2.c
  b3bcd506c350c34cc4adaa0a66028adb  gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat_run-3.c
*************** ba43fd40137d2e6509066eaad9266691  gcc/te
*** 97325,97413 ****
  1c4119935df2b0a9b4ab87cf47a3cdd7  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_data.h
  2714f0d833a302283af9fa8d888862ad  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h
  941e2ccb37cdbf0216c404d1a4cd6745  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_widen_run.h
! dd30805eacb1ee8bb47eadcb330548a0  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c
  7eb8dc7e69dd9f6638980e77cd6e6efe  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f32.c
  db6c9fd046686fdd17cc7ffc5fbfe33a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f64.c
! 16f7bde560b566c6bc62dbf4e65c717c  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c
  f111fb341a6ca7e95c2fa3bb7c758f27  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f32.c
  93a4d811d524303ed690e8cd8e527806  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f64.c
! 65a3ba7317f0f6b0627c6244549040e4  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c
  007ec5abf9cca9e34ba75e11dd5d4f2e  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f32.c
  706fdab09ac27674ccdcb6d34688ccb8  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f64.c
! 9d055a64e738ef5b1adc2c34090c2e52  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c
  bdefbf3eeea1f08fffd42d2bde350dea  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f32.c
  5a1f7f5afdbbfcecd97cb5d7098ff707  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f64.c
! 37dd15c773e1030e4d65d800995ea5ec  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c
  87786f9293eedd4f262ccf4e09d478f9  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f32.c
  634b2fb5bed1d8ed41e55b271de9400c  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f64.c
! 72e1573d7725156e44f8cbbc3dbc764b  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c
  9c4307fc1db29e045adc4a9f15ddca66  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f32.c
  0515f842a58d067880c5658e5addbece  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f64.c
! 8a76ea49cbf8906afd77b6f07085eca3  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c
  585be3a51575d87dbf0cd1d5cbe0d062  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f32.c
  127ff44000f971b8e7e5ba53d71a55fc  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f64.c
! 018f106afd1a02469cdc269e5476f8ef  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c
  dfc52616a58f523908e41a5a4e0f72b2  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f32.c
  813960aebe71c2622a67c2b2649a8973  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f64.c
! 88d0a5ad2b4bec245f134652c1d08554  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmacc-run-1-f16.c
  3d2a7164ecf998191c3df62b3eb98cb0  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmacc-run-1-f32.c
! bafa6f54ebead2e225773e895d5d5654  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmsac-run-1-f16.c
  c8ea40c4b9abb00be5f9636824cb84e2  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmsac-run-1-f32.c
! afc1560698bb7aa6343a80f07aef828e  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmacc-run-1-f16.c
  12dbee70f513595c141538484edde7ca  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmacc-run-1-f32.c
! 43b815effcfa51f4135a489d2c07c8d0  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmsac-run-1-f16.c
  99b2ebb0aea4ec8f59a77cce1a6130c5  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmsac-run-1-f32.c
! 55a91078489ade32c51f8e4e2c6efb27  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c
! 6c4d3bb12b5bf6e00c3cedc0f432a18a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c
! 70954d5e009a5c0bebb0b80760f293b9  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c
! cea4afd705f6e1a560863a504eb3b7b8  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c
! fe76a50d7d2bfbb09a95cfdc870c5a58  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u16.c
! 921e064b1942db3570f71688901d6f1f  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u32.c
! 98873e11ae359ac12e78de0bbc15ea34  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u64.c
! 4ec78081df2f7e81954aab0e75d811ba  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u8.c
! 6f882f7f3369e0f334836a1d28592b56  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c
! bd2eb7564b01afba9c9a1a3ea1a94c56  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c
! 44b97194857d5f1465364ab262b0d1fb  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c
! 6f5b6a3427d8706ed9d623f8cee509a8  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c
! cf92ab1fc4a82779fedf31229361f8f1  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u16.c
! 90321b085c0e080446cd8279b8c538e6  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u32.c
! 58bc268739642ed05278bd0e0f13a3ce  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u64.c
! a910949e56a3ef0e897b90e588754b3d  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u8.c
! 897d8a47615fff639e7927c88508fd79  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c
! 8a14c5065c33fed260f6a4456fd00383  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c
! 320f88580dc1c0964ff34d0e2194791e  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c
! 47e2d381a25759e4a628f17827376240  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c
! 79037fe4dc3b77d0c479a553be761ffe  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u16.c
! 3ee990b72cb1f95d624564adf5ecc447  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u32.c
! 7d1d0c555dd4cbeab1ac3b5a60d234b3  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u64.c
! 84e2faf4513ba470a86ed4add88943ab  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u8.c
! adf04b1af843c8aed848997698d24ea3  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c
! cf89d06b095546819b77e22837a841ea  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c
! 0e8e2ad741aadb3f28343dd22fca1c63  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c
! b0590d0f7e33779142937854585b6ba6  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c
! f5dc40a82b7c036577fcc72024184f19  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u16.c
! 2e2eae8aaff09ef0f65f78335991c2e0  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u32.c
! e35b6b8d6395fc6a016f0a149caad6b5  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u64.c
! 8855c8bc73c7fcd3420091cb56a6f20b  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u8.c
! 549961ba7992fd0f69d7adcb973957f9  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c
! 612dc651ce030ea72e72ea526c7a2ff7  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c
! 8a32718391965cc0195cfb594ac95696  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c
! 797ac5597940e4c20a1e78c41eca50ff  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c
! 5157adb717b30c261cc526f84f2eb666  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u16.c
! 730f79a8aed25f4a0a3a60fd7a716294  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u32.c
! 74a13c6598de7d87d8e22ffd90478b5c  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u64.c
! 284e77c828fb264faf6caf3d9df1f3f7  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u8.c
! 8a99e27aec74ed31d928a743373f37fb  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c
! 09c835c5129a50e8125a7f575e0c123d  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c
! 6b0981752e51db79311598c9375c62ab  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c
! 5565e4eec4d27791f0ab9a57abf92de5  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c
! 38c5f36cf96f9240de3a2e233edb9cdc  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u16.c
! 047e370cea424e3ed1c8540a08f046c8  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u32.c
! b7a3bb5893c188ffb2b0336cd8014537  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u64.c
! bcf8b479d013180b261f51d17d36aeed  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u8.c
! 10df14ae1f4036a5773788873561cfda  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h
! 642d4abcd3ef8a128f7e759710d32fe7  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h
  ccb9cff4438796fd5c2c015df2204a55  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_run.h
  f82d1e3332267f884d6990983f9a5c50  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vadd-run-1-i16.c
  9f3b8184fd845e5425e43d0e12950ff1  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vadd-run-1-i32.c
  5e6b1620895fd56e1d1b787b1b328794  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vadd-run-1-i64.c
--- 97442,97547 ----
  1c4119935df2b0a9b4ab87cf47a3cdd7  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_data.h
  2714f0d833a302283af9fa8d888862ad  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h
  941e2ccb37cdbf0216c404d1a4cd6745  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_widen_run.h
! 197382b605bb3bd3471b11643b631898  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c
  7eb8dc7e69dd9f6638980e77cd6e6efe  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f32.c
  db6c9fd046686fdd17cc7ffc5fbfe33a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f64.c
! f85add7c942dcfb2067c4a6a9c3158d2  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c
  f111fb341a6ca7e95c2fa3bb7c758f27  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f32.c
  93a4d811d524303ed690e8cd8e527806  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f64.c
! 5d81f8e9a426009f137c0fb5e269453f  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c
  007ec5abf9cca9e34ba75e11dd5d4f2e  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f32.c
  706fdab09ac27674ccdcb6d34688ccb8  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f64.c
! d406dc8f142b6fd66ab63dba615a6bc6  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c
  bdefbf3eeea1f08fffd42d2bde350dea  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f32.c
  5a1f7f5afdbbfcecd97cb5d7098ff707  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f64.c
! 55ba9934457cc6b23471e8c6c9a323f6  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c
  87786f9293eedd4f262ccf4e09d478f9  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f32.c
  634b2fb5bed1d8ed41e55b271de9400c  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f64.c
! 4d773a548012bce61e19db8ef96eb18e  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c
  9c4307fc1db29e045adc4a9f15ddca66  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f32.c
  0515f842a58d067880c5658e5addbece  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f64.c
! 46edc4ded0a9bad02b13501780c7192f  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c
  585be3a51575d87dbf0cd1d5cbe0d062  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f32.c
  127ff44000f971b8e7e5ba53d71a55fc  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f64.c
! 4cfae0fd23302dd498e0dfcce7239224  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c
  dfc52616a58f523908e41a5a4e0f72b2  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f32.c
  813960aebe71c2622a67c2b2649a8973  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f64.c
! 6cfd0942bee0993d84ce6948d7594ca6  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmacc-run-1-f16.c
  3d2a7164ecf998191c3df62b3eb98cb0  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmacc-run-1-f32.c
! 384d136ea5719c1d3742f2ae2585c371  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmsac-run-1-f16.c
  c8ea40c4b9abb00be5f9636824cb84e2  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmsac-run-1-f32.c
! 2f7904e0249cc28fe3a3c461a6f46db3  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmacc-run-1-f16.c
  12dbee70f513595c141538484edde7ca  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmacc-run-1-f32.c
! 7652f594973d5fa2fb94986a22efaf65  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmsac-run-1-f16.c
  99b2ebb0aea4ec8f59a77cce1a6130c5  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmsac-run-1-f32.c
! 8af119596eae8873dd2d564ff4eac428  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c
! 874a878142ac49ae2dfe00b0e3cc6e02  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c
! c527d350a1acef3df4b4c8d3714e8cc7  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c
! eb064d657a5f020386097a3b2e533cd2  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c
! 55cf9b30ab51b503be7552d2b720d918  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u16.c
! 3b2766ec89d15e1050f60de15f055b3f  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u32.c
! 47c120c030104a3e048064fa93b7cda2  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u64.c
! bfc5713c17bc320774476f3a46b4a0dc  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u8.c
! e92ffd71a53fb7e2085faf419ef186dd  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c
! 30e5d51fc80e38aaba9e79d139278f29  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c
! 4e4b9bf963f4c01fef62f7a272624935  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c
! 7df88ecebea7ce588dba1f41c640f0f0  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c
! 766ad833d9289d3b0a28c43fbe02c706  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u16.c
! 532e5cc1fc4f15ce5a3eabb97af9bdf6  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u32.c
! 253f7e444ccae32f5cb2d5ab4e44b28c  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u64.c
! 3cac786faf5c30aa9b5ccec1fc52f09d  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u8.c
! 965cb322b597bbab68600a4417f07bed  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c
! 95ee8a639e10a131b93b48d8c5e09dfa  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c
! 100924041be07de7193abc6fb47a0799  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c
! 28acaf5002fc17931f0c8b6b049cd988  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c
! 0e1369c56ba4d347aa8352cf3a050bca  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u16.c
! 2e706b14c94fac4e135536131304ac93  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u32.c
! 4f50687b92dbb6ee4b107cb6a5973d52  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u64.c
! d40872af06bc3802929626083516d50a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u8.c
! 6a8bd6ce41b19d43b5c49cf248e4b184  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c
! 8d2c0cd8e0769bf95ec1156ffab91f09  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c
! d6955726f9d5a3a760d7cabf164f8c13  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c
! 4812c83ff93d47a31bb4b34ff475f41a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c
! 36e7b72bd068cb77dead42b1928825f3  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u16.c
! a3fa4bd47cc647adcdd1c35b702e646d  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u32.c
! a16c9b0bc9fcb40f069854f1640370ab  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u64.c
! ae12d8b8d33de7c9d3e16dafe3e05222  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u8.c
! ecc006785d84e1c3b83450797529a17a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c
! 0fd60fc63b127c7b5ac88ea7cee9f923  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c
! f4f7618873e37cbea1770f709ddc3e47  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c
! fd4f429a27307f841b1abef4283576b5  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c
! 56e42f6cd4818613adc14a86eee3550a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u16.c
! 700051d92aefeb4635d7c847ad9eb05b  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u32.c
! 1c8098d68dce2585d146919e9ae6e764  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u64.c
! 35080609c5384058b7f67d8f13fc56ba  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u8.c
! 11d02986d8e1e3658336d0546f5599f1  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c
! 64228a92826e4c6ddcd399166b050e61  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c
! 60d4492714aebdf0daf02ad1068ac232  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c
! 15c9a364d05e694c78b6366129139960  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c
! 1b201b7b0726363e02345795bf6f1f6a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u16.c
! 064b754566555604cea34f2f72d14654  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u32.c
! 9d23a19202488777b8ae2082bbe4162b  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u64.c
! d109c3f9fe1e041ee243ffab488a2912  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u8.c
! ddf54106623ccc30e43522c91db9f08a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c
! b18681535fd48293e486f41e6c065f37  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c
! fb53469a8a1b87439b25dac95eaf3d1f  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c
! 7cad1bae86f2fa72093dd83402c54133  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c
! d571d84f0813f68179888606b63b50a4  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u16.c
! bb3d21d4284904d9a83d853e198c3cb3  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u32.c
! 7831e156ccebb41613cce03ab43a93e7  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u64.c
! 3c96aba29fe23754f8f5f20635be58a0  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u8.c
! b887dd7f528aeb0a2bd4efd5e646e7c2  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm.h
! af2763e0de12a75aa3967092c3902656  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h
! ee978ea15ce3ce6bc32e5b88d15c828a  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h
  ccb9cff4438796fd5c2c015df2204a55  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_run.h
+ 2f23b92e9170e127daeb5d9860d9767f  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i16.c
+ aa5affb189e4fe4c4c6908a851c52957  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i32.c
+ 032764f0d87dd7e09ee3369db366511e  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i64.c
+ 458a67b6c4eeec39ad0b594374a7f5ab  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i8.c
+ f288a5fc807bdc77bee9717143d67597  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u16.c
+ 860d84262a791e6cc4312140ac229fba  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u32.c
+ 2c4c3e82c67a62f06978342e91910797  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u64.c
+ ce8703e0013182a56e306f3658c5b838  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u8.c
  f82d1e3332267f884d6990983f9a5c50  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vadd-run-1-i16.c
  9f3b8184fd845e5425e43d0e12950ff1  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vadd-run-1-i32.c
  5e6b1620895fd56e1d1b787b1b328794  gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vadd-run-1-i64.c
*************** dfab2d120358e9347328896588f09d7f  gcc/te
*** 98282,98292 ****
  f0ef727ad421676bfc8524d445606492  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-2.c
  6c7cdecd10fb8854fb71be95c2dd58c6  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-3.c
  8c21b304dcf8bfcea2ca1180cbeec2d2  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-4.c
! 40304c1228c3f33ee86cb65b66b166f9  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-5.c
! 49814f1ed128714363358aa09ed20c73  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-6.c
! f317ba2660d97eb065ac06ba5e3d9c80  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-7.c
! 28687edf951d1ee05a94b723c7533c0f  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-8.c
! 3e207f073e047580eb29a2b880bb0544  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-9.c
  9d67b7bcf56a9d5e0175ad39afd31d8c  gcc/testsuite/gcc.target/riscv/rvv/base/setmem-1.c
  c7b8c050c02b19e79d1fc07b2cbd9798  gcc/testsuite/gcc.target/riscv/rvv/base/setmem-2.c
  364ca0ddd4b74247076ccd4f9e232248  gcc/testsuite/gcc.target/riscv/rvv/base/setmem-3.c
--- 98416,98426 ----
  f0ef727ad421676bfc8524d445606492  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-2.c
  6c7cdecd10fb8854fb71be95c2dd58c6  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-3.c
  8c21b304dcf8bfcea2ca1180cbeec2d2  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-4.c
! 6664771566394a52d726e74dda9c8b1b  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-5.c
! 6daee8ed72e60f230e10827d13ea871e  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-6.c
! 13f53785a7384e28366f1fa2fe211302  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-7.c
! 24d9548de200fc4e0a34539da4df8b00  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-8.c
! dfa7bdc703178385c7e9fe50842850c2  gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-9.c
  9d67b7bcf56a9d5e0175ad39afd31d8c  gcc/testsuite/gcc.target/riscv/rvv/base/setmem-1.c
  c7b8c050c02b19e79d1fc07b2cbd9798  gcc/testsuite/gcc.target/riscv/rvv/base/setmem-2.c
  364ca0ddd4b74247076ccd4f9e232248  gcc/testsuite/gcc.target/riscv/rvv/base/setmem-3.c
*************** bd5fe2ac8c7ea125bd674e1aa8150399  gcc/te
*** 98476,98481 ****
--- 98610,98616 ----
  c408b1a7f84e4b815e85476963221ae9  gcc/testsuite/gcc.target/riscv/rvv/base/zvl-unimplemented-1.c
  527003a16d82851a0dd57a93c29bcab7  gcc/testsuite/gcc.target/riscv/rvv/base/zvl-unimplemented-2.c
  2865ee85ce614d77ff279bf2235dfe51  gcc/testsuite/gcc.target/riscv/rvv/pr120297.c
+ 999cc44bdd25aaa38b1dfd62ba9b84ab  gcc/testsuite/gcc.target/riscv/rvv/pr121073.c
  abcf176e84612215d7a4bb01e5aafc34  gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
  ecf4c4ab418350831d4471534a47d02a  gcc/testsuite/gcc.target/riscv/rvv/vsetvl/attribute-1.c
  0886d2586a892610401ae61b27c200f1  gcc/testsuite/gcc.target/riscv/rvv/vsetvl/attribute-2.c
*************** a8f53ad5180333afb72d569d125c3922  gcc/te
*** 98970,98976 ****
  fe865d9009af7551d830f6d4e3008ebe  gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/vlwu-vsw.c
  10c2fe61483d221e6648e72c6ff9f6a0  gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/vsext.c
  23788d7500abf7340ab20ef598d9da5e  gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/vzext.c
! 14b5de1cfd9e7e5da8f6205e783399b5  gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
  89d90b13c13c2658dcc8319771cd755f  gcc/testsuite/gcc.target/riscv/sat/sat_arith_data.h
  e52f03a6378cd78f7ea04149c2b8215a  gcc/testsuite/gcc.target/riscv/sat/sat_s_add-1-i16.c
  1de70dbaccb7e9fe73b8e90ec7430b4d  gcc/testsuite/gcc.target/riscv/sat/sat_s_add-1-i32.c
--- 99105,99111 ----
  fe865d9009af7551d830f6d4e3008ebe  gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/vlwu-vsw.c
  10c2fe61483d221e6648e72c6ff9f6a0  gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/vsext.c
  23788d7500abf7340ab20ef598d9da5e  gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/vzext.c
! 445889f8bf3d21630ee905237dc140e5  gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
  89d90b13c13c2658dcc8319771cd755f  gcc/testsuite/gcc.target/riscv/sat/sat_arith_data.h
  e52f03a6378cd78f7ea04149c2b8215a  gcc/testsuite/gcc.target/riscv/sat/sat_s_add-1-i16.c
  1de70dbaccb7e9fe73b8e90ec7430b4d  gcc/testsuite/gcc.target/riscv/sat/sat_s_add-1-i32.c
*************** f8b193c0679d5a3c67abd2571b7d930a  gcc/te
*** 99184,99189 ****
--- 99319,99332 ----
  411db43e27aeb5b779751c7523bbe018  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-7-u8-from-u16.c
  2999f54af1e8026e2f1a7e53a0f94cc3  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-7-u8-from-u32.c
  71bf5f9ac92822434bc486d6c6913a07  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-7-u8-from-u64.c
+ 91ea803e7ddc052793d7e4dfc8394b92  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u16.c
+ 2f05ee62edee1ef8dc3157892d2b0b36  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u32.c
+ a9bcd7e6fe3f1c08179d9e4d57193a28  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u64.c
+ 693cf77b8c3d716ab37a09307187fc41  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u8.c
+ 4837c15e0c8dfa7eecd494b79385c105  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u16.c
+ 82ce13125858327f1583d1a4efd3ca83  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u32.c
+ 4ca2ed37593f28a111189143b7810285  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u64.c
+ a904497db03f73e7de8b557e25f6b385  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u8.c
  31d76b84da64d10ea5b22fdd4f5be8f2  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u16.c
  9a622f228c3faa95e783147f1370ebf9  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u32.c
  f6c8a38f627a880030c5796f4da2686e  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u64.c
*************** d07a104e5333ce25cfe9ac473b65d4af  gcc/te
*** 99214,99219 ****
--- 99357,99370 ----
  047d211f5ca3225cdb91697c0cee161a  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u16.c
  137bf5a969a8ee4a5b5233bd668f9530  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u32.c
  59eef9b24b516bcebc311cfb904f64f7  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u64.c
+ 661e89138afd0c4af72600df1ee8e8b4  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u16.c
+ 76b5617183dbe1efd761a2cc93516805  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u32.c
+ 9090edab94efa3e3e53432c7ae6c54d9  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u64.c
+ 53c57a5d0ebecd570d38bb3e5674b037  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u8.c
+ abe8eb93d59266f95050bdfad7b8021b  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u16.c
+ c0006542ce61674310dbae51d512f1fb  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u32.c
+ 79bc7fe68dd48ca5b4df4c0f6fcf7a3d  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u64.c
+ d7c296a592bba0a44f2bba4ee6e1b9c0  gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u8.c
  1bd9dacdfc4086d15839a2c59a13219a  gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-1-u16.c
  aac3af7c06e383040cad10df2cd3aa66  gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-1-u32.c
  2e0635410b88b5548708ed02505d2ef6  gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-1-u64.c
*************** d72002750d8f9f6f373c1ba680c9a5da  gcc/te
*** 99736,99742 ****
  d76591e96cef314b7108574103443924  gcc/testsuite/gcc.target/riscv/xtheadfmemidx.c
  2bafb510f62e2b47544bf39329a60de2  gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c
  32ba3840c2e6fc20c916dbf78497a77f  gcc/testsuite/gcc.target/riscv/xtheadfmv.c
! cce657947a64d5d651a839020ddfc479  gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c
  361b703f5377b971c4acd8d9120092c4  gcc/testsuite/gcc.target/riscv/xtheadint.c
  44c5a42c298eada6ce33b6cd224a644b  gcc/testsuite/gcc.target/riscv/xtheadmac-mula-muls.c
  cb622bf180c28d77c3b239e9e6f4ea50  gcc/testsuite/gcc.target/riscv/xtheadmac.c
--- 99887,99893 ----
  d76591e96cef314b7108574103443924  gcc/testsuite/gcc.target/riscv/xtheadfmemidx.c
  2bafb510f62e2b47544bf39329a60de2  gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c
  32ba3840c2e6fc20c916dbf78497a77f  gcc/testsuite/gcc.target/riscv/xtheadfmv.c
! 04ea7db9e549c8548de56cf563098db0  gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c
  361b703f5377b971c4acd8d9120092c4  gcc/testsuite/gcc.target/riscv/xtheadint.c
  44c5a42c298eada6ce33b6cd224a644b  gcc/testsuite/gcc.target/riscv/xtheadmac-mula-muls.c
  cb622bf180c28d77c3b239e9e6f4ea50  gcc/testsuite/gcc.target/riscv/xtheadmac.c
*************** f41fae493f713bf85491d412efd9cebd  gcc/te
*** 99986,99991 ****
--- 100137,100150 ----
  c983687631a2e6c9dbb24e103ebd1364  gcc/testsuite/gcc.target/s390/arch13/popcount-1.c
  3c016ed407b9af1863b6adcef0bb891a  gcc/testsuite/gcc.target/s390/arch13/sel-1.c
  4ce603e2d83e4fcf4fa5babc96818e9b  gcc/testsuite/gcc.target/s390/ashr.c
+ 394c9c146974e9a7e13f1b58ea0df5ed  gcc/testsuite/gcc.target/s390/asm-hard-reg-1.c
+ 62c75d1d7df914897b00cdff5647499f  gcc/testsuite/gcc.target/s390/asm-hard-reg-2.c
+ 19d1c822df73af7a606839c325b0c9a9  gcc/testsuite/gcc.target/s390/asm-hard-reg-3.c
+ 76a5114e97c45c4bb3bbfc0904c4d48f  gcc/testsuite/gcc.target/s390/asm-hard-reg-4.c
+ 84138939e380b2f20dbb02f0badeed4d  gcc/testsuite/gcc.target/s390/asm-hard-reg-5.c
+ 726670c3cb7e8783d33f7f1e0b312e66  gcc/testsuite/gcc.target/s390/asm-hard-reg-6.c
+ bea465af3dbf1024e44e1574fe16c539  gcc/testsuite/gcc.target/s390/asm-hard-reg-7.c
+ 21a010549cf12740c375e5ece6e37dbb  gcc/testsuite/gcc.target/s390/asm-hard-reg-longdouble.h
  bf08d8ae3952e5a9f6d75de6c60a3a5f  gcc/testsuite/gcc.target/s390/asm-machine-1.c
  062c9cbdb4b33e5a9c45bd579c02df3b  gcc/testsuite/gcc.target/s390/asm-machine-2.c
  46b0c503c4e6198758f37694ae9566d1  gcc/testsuite/gcc.target/s390/asm-machine-3.c
*************** c8e89c3bb1a8878396e32769b9a78d05  gcc/te
*** 106598,106603 ****
--- 106757,106763 ----
  fbcbf467a3284c5a09b9e5e8efc5e0c7  gcc/testsuite/gfortran.dg/array_constructor_55.f90
  051843c0c65fec8a2e1118f76be9d705  gcc/testsuite/gfortran.dg/array_constructor_56.f90
  b9213dc9c7da43f7ac35cb2a5bf0c55b  gcc/testsuite/gfortran.dg/array_constructor_57.f90
+ ddaf878ce1cf2b6a4fed9a83158509ff  gcc/testsuite/gfortran.dg/array_constructor_58.f90
  3c35c0aa8a8229010e90452ed87d7792  gcc/testsuite/gfortran.dg/array_constructor_6.f90
  d3bb011093e16f988efba6816262fb16  gcc/testsuite/gfortran.dg/array_constructor_7.f90
  ae5f56f53be9d3bbc6c562e48080a252  gcc/testsuite/gfortran.dg/array_constructor_8.f90
*************** e9f58df1de071d2b106b16b3af8f6764  gcc/te
*** 106692,106697 ****
--- 106852,106859 ----
  2fadd08fe3904fa5e7b9e433747dd9e5  gcc/testsuite/gfortran.dg/assign_10.f90
  5a14c8021ea0007a87c0f2d24385903b  gcc/testsuite/gfortran.dg/assign_11.f90
  77968474ca7077dddd7b87844075962e  gcc/testsuite/gfortran.dg/assign_12.f90
+ 26913a24bb1ab1b93e82daf23e222c52  gcc/testsuite/gfortran.dg/assign_13.f90
+ 50e0aed1817a8d058a505bc64871b0dc  gcc/testsuite/gfortran.dg/assign_14.f90
  d13716000aff2182530213b6daeb5f10  gcc/testsuite/gfortran.dg/assign_2.f90
  a0494aa37ce786eddcb2107da73e9e9d  gcc/testsuite/gfortran.dg/assign_3.f90
  bd3eaa5ee0e2bbe2c28826271bd7069f  gcc/testsuite/gfortran.dg/assign_4.f
*************** c4ff958c7424124b0ee823af5b303872  gcc/te
*** 109244,109249 ****
--- 109406,109412 ----
  4d6a30403727d33b5324687b0cf26a2b  gcc/testsuite/gfortran.dg/function_charlen_1.f90
  d7737217545ebcdba2eec10ee6151f38  gcc/testsuite/gfortran.dg/function_charlen_2.f90
  4a958755730ebf90567051f0b55b3b6b  gcc/testsuite/gfortran.dg/function_charlen_3.f
+ 5dd72dfb4b021f28dfb067c720b04502  gcc/testsuite/gfortran.dg/function_charlen_4.f90
  c71397aec804c0b5ce001a1d5dbdb76e  gcc/testsuite/gfortran.dg/function_kinds_1.f90
  cbb70c4ec8b88d436fb61acf9486c6bf  gcc/testsuite/gfortran.dg/function_kinds_2.f90
  9d6188e05d3cc7589bb0f30729072f80  gcc/testsuite/gfortran.dg/function_kinds_3.f90
*************** e64523b7502cc4a326c69a5fb2bb632b  gcc/te
*** 116974,116979 ****
--- 117137,117144 ----
  04893bced6e84ae01eff30822adc8c39  gcc/testsuite/gm2/switches/optimization/run/pass/switches-optimization-run-pass.exp
  57f079fe3fae85c31093c689467ddf5c  gcc/testsuite/gm2/switches/pedantic-params/fail/a.def
  d083f2149e966c7f4a3cf7a592213e6e  gcc/testsuite/gm2/switches/pedantic-params/fail/a.mod
+ a6e8cb2a9ab54e9865ad3892aa0b5941  gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.def
+ 6c859878e0873eb436e217b7385b4881  gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.mod
  8a73f7d6d7f60bc44b16a61e8159d6d2  gcc/testsuite/gm2/switches/pedantic-params/fail/switches-pedantic-params-fail.exp
  fcbe31b3d4560713715a841f8730d29d  gcc/testsuite/gm2/switches/pedantic-params/pass/Strings.def
  fd422a739cead1ddd9341f7ffef6c32a  gcc/testsuite/gm2/switches/pedantic-params/pass/Strings.mod
*************** e87a7723ddb82de7bd960a324539538f  gcc/te
*** 121883,121890 ****
  9c1c18d54fa5811ce07e3c5d4a677fbf  gcc/testsuite/lib/fortran-torture.exp
  9da06fbaa0424093c2d9bf83783cc500  gcc/testsuite/lib/g++-dg.exp
  c345df92b75960dbcf02dc790324b5c6  gcc/testsuite/lib/g++.exp
! 8fd60242e028a3c0b9360a52d67cb069  gcc/testsuite/lib/gcc-defs.exp
! 64d94c4dd4533bc17b89e001336ef92b  gcc/testsuite/lib/gcc-dg.exp
  4ce14b2651c02595541e337529a858a7  gcc/testsuite/lib/gcc-gdb-test.exp
  5d11df299efe6269fcdaed3cf91ebd4a  gcc/testsuite/lib/gcc-simulate-thread.exp
  c652081610935366b7989df767a74c8b  gcc/testsuite/lib/gcc.exp
--- 122048,122055 ----
  9c1c18d54fa5811ce07e3c5d4a677fbf  gcc/testsuite/lib/fortran-torture.exp
  9da06fbaa0424093c2d9bf83783cc500  gcc/testsuite/lib/g++-dg.exp
  c345df92b75960dbcf02dc790324b5c6  gcc/testsuite/lib/g++.exp
! fe7ae089a7fe99208cbf6904aeac84a1  gcc/testsuite/lib/gcc-defs.exp
! 613c4bf9d9645d83e88918615b2efad9  gcc/testsuite/lib/gcc-dg.exp
  4ce14b2651c02595541e337529a858a7  gcc/testsuite/lib/gcc-gdb-test.exp
  5d11df299efe6269fcdaed3cf91ebd4a  gcc/testsuite/lib/gcc-simulate-thread.exp
  c652081610935366b7989df767a74c8b  gcc/testsuite/lib/gcc.exp
*************** a447115837a98ea4ab8390ca3c1d400a  gcc/te
*** 121926,121933 ****
  2d0f3bd65b46db089989d897e60ee550  gcc/testsuite/lib/sarif-replay.exp
  cdfac88acd33dec95625eb0cca4bc571  gcc/testsuite/lib/sarif-schema-2.1.0.json
  808895f3fef94ae1653cf826a4c6c9de  gcc/testsuite/lib/sarif-schema-2.2-prerelease-2024-08-08.json
! 0016ae6993594b35c7752ac29b616194  gcc/testsuite/lib/sarif.py
! 711ee35b92bb4edf40a27a9a879af83f  gcc/testsuite/lib/scanasm.exp
  83e6c25542a5f84dc92619a64a4fe0e7  gcc/testsuite/lib/scandump.exp
  67189798dcf413cd565b99dee45a8f39  gcc/testsuite/lib/scanhtml.exp
  f17c3b8bef5ec71bda9ad84ca4b914ae  gcc/testsuite/lib/scanipa.exp
--- 122091,122098 ----
  2d0f3bd65b46db089989d897e60ee550  gcc/testsuite/lib/sarif-replay.exp
  cdfac88acd33dec95625eb0cca4bc571  gcc/testsuite/lib/sarif-schema-2.1.0.json
  808895f3fef94ae1653cf826a4c6c9de  gcc/testsuite/lib/sarif-schema-2.2-prerelease-2024-08-08.json
! 5ab9c47ebaf746557a8f8a5d300abfe3  gcc/testsuite/lib/sarif.py
! bab70c146620e4a007335796c78aaa8b  gcc/testsuite/lib/scanasm.exp
  83e6c25542a5f84dc92619a64a4fe0e7  gcc/testsuite/lib/scandump.exp
  67189798dcf413cd565b99dee45a8f39  gcc/testsuite/lib/scanhtml.exp
  f17c3b8bef5ec71bda9ad84ca4b914ae  gcc/testsuite/lib/scanipa.exp
*************** eb1595e729e2eaac81c7ffe330d8f24e  gcc/te
*** 121943,121949 ****
  f7940f4f8c24d9f0bf4d062473f55777  gcc/testsuite/lib/scanwpaipa.exp
  23e89ca46b182663a4139064b179545f  gcc/testsuite/lib/target-libpath.exp
  d9a6726c38c578e1cd46631ee7f92d0a  gcc/testsuite/lib/target-supports-dg.exp
! a0246cbe3a685128e4bc90842286b74e  gcc/testsuite/lib/target-supports.exp
  cfe4a2f0a83382048de060dc6669cbb9  gcc/testsuite/lib/target-utils.exp
  e45ee1a35539730bd823a310ad306ded  gcc/testsuite/lib/timeout-dg.exp
  b755c82fb5ee43ef6c852f23fbdc8704  gcc/testsuite/lib/timeout.exp
--- 122108,122114 ----
  f7940f4f8c24d9f0bf4d062473f55777  gcc/testsuite/lib/scanwpaipa.exp
  23e89ca46b182663a4139064b179545f  gcc/testsuite/lib/target-libpath.exp
  d9a6726c38c578e1cd46631ee7f92d0a  gcc/testsuite/lib/target-supports-dg.exp
! 6293d5886f54e545f3c413caaa7c2039  gcc/testsuite/lib/target-supports.exp
  cfe4a2f0a83382048de060dc6669cbb9  gcc/testsuite/lib/target-utils.exp
  e45ee1a35539730bd823a310ad306ded  gcc/testsuite/lib/timeout-dg.exp
  b755c82fb5ee43ef6c852f23fbdc8704  gcc/testsuite/lib/timeout.exp
*************** e176c0fbb7714cb48455fa7550ec6452  gcc/te
*** 124388,124394 ****
  a8258abe100615e51bde1b34ad4b5faa  gcc/text-art/ruler.h
  ec0b84409192065e3ef03fbfec97ffa6  gcc/text-art/selftests.cc
  7322dcbdf178da68eec96a7835bd53f3  gcc/text-art/selftests.h
! 7f47082ca86e900e391983d787661b0f  gcc/text-art/style.cc
  60a21507434a42c9e5ffb1f995e3137a  gcc/text-art/styled-string.cc
  bb1d68366d38f270a98be14b26439127  gcc/text-art/table.cc
  87dbca160262db76a2d61735729e4ade  gcc/text-art/table.h
--- 124553,124559 ----
  a8258abe100615e51bde1b34ad4b5faa  gcc/text-art/ruler.h
  ec0b84409192065e3ef03fbfec97ffa6  gcc/text-art/selftests.cc
  7322dcbdf178da68eec96a7835bd53f3  gcc/text-art/selftests.h
! 36cf0d902cdfdb24737c161ff810d4ff  gcc/text-art/style.cc
  60a21507434a42c9e5ffb1f995e3137a  gcc/text-art/styled-string.cc
  bb1d68366d38f270a98be14b26439127  gcc/text-art/table.cc
  87dbca160262db76a2d61735729e4ade  gcc/text-art/table.h
*************** edcd6b4cfe25a7233b7c7b59f0889ef4  gcc/te
*** 124403,124409 ****
  00cbafca76647e207526939f6ce782be  gcc/timevar.cc
  a88c03e35b27a898cfa4d6810d58410a  gcc/timevar.def
  d1eee141f10cb25a673cf78888396745  gcc/timevar.h
! 9f620fa503fc8b7465e14eb5ab8f9728  gcc/toplev.cc
  1720dc69e58e480830de71ecb3eb364d  gcc/toplev.h
  cbb8fb6fcd7138a90fc489b10fe3c862  gcc/tracer.cc
  a58a166bda01c9a970218d3f6c5e330f  gcc/tracer.h
--- 124568,124574 ----
  00cbafca76647e207526939f6ce782be  gcc/timevar.cc
  a88c03e35b27a898cfa4d6810d58410a  gcc/timevar.def
  d1eee141f10cb25a673cf78888396745  gcc/timevar.h
! 45227f72caff92050d1ba91d6a550322  gcc/toplev.cc
  1720dc69e58e480830de71ecb3eb364d  gcc/toplev.h
  cbb8fb6fcd7138a90fc489b10fe3c862  gcc/tracer.cc
  a58a166bda01c9a970218d3f6c5e330f  gcc/tracer.h
*************** bcff760f6710b9047412aba72a381983  gcc/tr
*** 124415,124421 ****
  23590c969997d33ec2e1fa1da2a89526  gcc/tree-call-cdce.cc
  9e4acd63de4a8aef23a4a4d4d8e90b72  gcc/tree-cfg.cc
  591222e5199894b9b5d23b1822f7e309  gcc/tree-cfg.h
! ca2c309862705e4161a11efb32eb1ebf  gcc/tree-cfgcleanup.cc
  b528a0932f50504df146d112f7d01a5c  gcc/tree-cfgcleanup.h
  1718a36253ebbb17fe4570fc768216c9  gcc/tree-chrec.cc
  0e4a484c6387f9be0a506783637432f9  gcc/tree-chrec.h
--- 124580,124586 ----
  23590c969997d33ec2e1fa1da2a89526  gcc/tree-call-cdce.cc
  9e4acd63de4a8aef23a4a4d4d8e90b72  gcc/tree-cfg.cc
  591222e5199894b9b5d23b1822f7e309  gcc/tree-cfg.h
! 0bb909d63756c23161166845fb40462b  gcc/tree-cfgcleanup.cc
  b528a0932f50504df146d112f7d01a5c  gcc/tree-cfgcleanup.h
  1718a36253ebbb17fe4570fc768216c9  gcc/tree-chrec.cc
  0e4a484c6387f9be0a506783637432f9  gcc/tree-chrec.h
*************** b528a0932f50504df146d112f7d01a5c  gcc/tr
*** 124425,124433 ****
  e43a555cdaab9a97ba3910364910f865  gcc/tree-data-ref.h
  f01aeac56dffd44808096094e2bf76c1  gcc/tree-dfa.cc
  7ccb47a2df405aa08b45cb7f5fca6385  gcc/tree-dfa.h
! b25919ebfbe71d3f3113697ffdbf2ea7  gcc/tree-diagnostic-client-data-hooks.cc
! 2e869fb8c2c129d455393a91b03e0982  gcc/tree-diagnostic.cc
! 21e7c804e59b1471314ee9c773a41ed1  gcc/tree-diagnostic.h
  061a86cf1b2c01bdde3dc32a0701f5b5  gcc/tree-dump.cc
  f9731b5179d6c364587220c2aea59a3e  gcc/tree-dump.h
  5b2959d3865102e60e008c1ba95fa361  gcc/tree-eh.cc
--- 124590,124598 ----
  e43a555cdaab9a97ba3910364910f865  gcc/tree-data-ref.h
  f01aeac56dffd44808096094e2bf76c1  gcc/tree-dfa.cc
  7ccb47a2df405aa08b45cb7f5fca6385  gcc/tree-dfa.h
! ecbe7be63385b38e3cb9eca4ac949cbc  gcc/tree-diagnostic-client-data-hooks.cc
! b3f30c6854e7d3fdeb9ebe11a87888ac  gcc/tree-diagnostic.cc
! 3140b41a1c9dc80dbc2b6881fa0f9e15  gcc/tree-diagnostic.h
  061a86cf1b2c01bdde3dc32a0701f5b5  gcc/tree-dump.cc
  f9731b5179d6c364587220c2aea59a3e  gcc/tree-dump.h
  5b2959d3865102e60e008c1ba95fa361  gcc/tree-eh.cc
*************** f31771f899962118452faf887ba629b3  gcc/tr
*** 124443,124450 ****
  ef1cb0fba517532ecda9f4e0dd5218f7  gcc/tree-into-ssa.h
  71aa2d4206ac8bd978b5efd19148dd74  gcc/tree-iterator.cc
  1a3fc26573e4e592efe69f41168a65fa  gcc/tree-iterator.h
! dffcb3b5c014f0539c1d4ad44d7cfc4f  gcc/tree-logical-location.cc
! 0ffb67ad0ccbbc0705e9a36d7ad48724  gcc/tree-logical-location.h
  809e077fea6aa1e38be693ae0a16dee1  gcc/tree-loop-distribution.cc
  62502d6fd9aa927353d7437dc2a6da17  gcc/tree-nested.cc
  b9bad013f5186a6cf78fe8adbe457945  gcc/tree-nested.h
--- 124608,124615 ----
  ef1cb0fba517532ecda9f4e0dd5218f7  gcc/tree-into-ssa.h
  71aa2d4206ac8bd978b5efd19148dd74  gcc/tree-iterator.cc
  1a3fc26573e4e592efe69f41168a65fa  gcc/tree-iterator.h
! 4c932cc6b576a53aa0f5dd611b468413  gcc/tree-logical-location.cc
! c28ee18072affadaa4bdca56d51c3389  gcc/tree-logical-location.h
  809e077fea6aa1e38be693ae0a16dee1  gcc/tree-loop-distribution.cc
  62502d6fd9aa927353d7437dc2a6da17  gcc/tree-nested.cc
  b9bad013f5186a6cf78fe8adbe457945  gcc/tree-nested.h
*************** fd4dd1219acc650a4f7855faa0097964  gcc/tr
*** 124465,124471 ****
  7c11aa147a6d02acce5170cb35aed445  gcc/tree-profile.cc
  985d86fcc4c88e8e0b4532b175b34739  gcc/tree-scalar-evolution.cc
  dddd950fe463803c41bc0c7cddf0fe44  gcc/tree-scalar-evolution.h
! ee4b0158282edc26e35fda70ebe934b6  gcc/tree-sra.cc
  c022e816e38c8f399e6a16163c56d6db  gcc/tree-sra.h
  3e42023ef3fe5187ffffddbbb5740208  gcc/tree-ssa-address.cc
  c724c8becbea9eec0f806e3335942c32  gcc/tree-ssa-address.h
--- 124630,124636 ----
  7c11aa147a6d02acce5170cb35aed445  gcc/tree-profile.cc
  985d86fcc4c88e8e0b4532b175b34739  gcc/tree-scalar-evolution.cc
  dddd950fe463803c41bc0c7cddf0fe44  gcc/tree-scalar-evolution.h
! dc509816aacd28d6762f601c4d655972  gcc/tree-sra.cc
  c022e816e38c8f399e6a16163c56d6db  gcc/tree-sra.h
  3e42023ef3fe5187ffffddbbb5740208  gcc/tree-ssa-address.cc
  c724c8becbea9eec0f806e3335942c32  gcc/tree-ssa-address.h
*************** fbcc93539b376489c1256eb8cf2d4800  gcc/tr
*** 124503,124509 ****
  538146c17730f67ffcc58afdfcc93712  gcc/tree-ssa-loop.h
  7b8c5f8c75971835765b2c3c2949aa14  gcc/tree-ssa-math-opts.cc
  c0b0549adb2c1140cf285901abb5a78c  gcc/tree-ssa-math-opts.h
! 0ed882dedcd92c361bc556587aaa4b74  gcc/tree-ssa-operands.cc
  da72a60de8a6f51a635ead26120d3cc7  gcc/tree-ssa-operands.h
  487192303141111110ed63175019cf4f  gcc/tree-ssa-phiopt.cc
  482f2356d81c3633ca476cd6628908b8  gcc/tree-ssa-phiprop.cc
--- 124668,124674 ----
  538146c17730f67ffcc58afdfcc93712  gcc/tree-ssa-loop.h
  7b8c5f8c75971835765b2c3c2949aa14  gcc/tree-ssa-math-opts.cc
  c0b0549adb2c1140cf285901abb5a78c  gcc/tree-ssa-math-opts.h
! 8ccf736dffb311078aa79c9036502189  gcc/tree-ssa-operands.cc
  da72a60de8a6f51a635ead26120d3cc7  gcc/tree-ssa-operands.h
  487192303141111110ed63175019cf4f  gcc/tree-ssa-phiopt.cc
  482f2356d81c3633ca476cd6628908b8  gcc/tree-ssa-phiprop.cc
*************** fd8c3c4d8f8f65da42ff163b80d892aa  gcc/tr
*** 124516,124525 ****
  952cb2484413ce2cf094a52b596dc078  gcc/tree-ssa-sccvn.h
  a27c58eccc3d8929767feb76dc99399f  gcc/tree-ssa-scopedtables.cc
  aa25adbcb019dd38a66ce237df54ae1d  gcc/tree-ssa-scopedtables.h
! 1565dc0d975d174e5d53e4889ab223e3  gcc/tree-ssa-sink.cc
  f8a95ebe86d335b810e43ab71cae5b43  gcc/tree-ssa-strlen.cc
  817cd7b593b9ca11ac7464ee683d8f98  gcc/tree-ssa-strlen.h
! b76684a1a6be44a3823af76b7f763beb  gcc/tree-ssa-structalias.cc
  c55845e611a19b323a6c2debac84509e  gcc/tree-ssa-structalias.h
  8236d4d91b8701a8daadc2f8a12d4752  gcc/tree-ssa-tail-merge.cc
  18ba2469cfdfbd297fe2b0120e69a84c  gcc/tree-ssa-ter.cc
--- 124681,124690 ----
  952cb2484413ce2cf094a52b596dc078  gcc/tree-ssa-sccvn.h
  a27c58eccc3d8929767feb76dc99399f  gcc/tree-ssa-scopedtables.cc
  aa25adbcb019dd38a66ce237df54ae1d  gcc/tree-ssa-scopedtables.h
! 583837e3b3ea0f48929343eac1cc3e2e  gcc/tree-ssa-sink.cc
  f8a95ebe86d335b810e43ab71cae5b43  gcc/tree-ssa-strlen.cc
  817cd7b593b9ca11ac7464ee683d8f98  gcc/tree-ssa-strlen.h
! cdbaadcbac140f7877fb376bc71df9cd  gcc/tree-ssa-structalias.cc
  c55845e611a19b323a6c2debac84509e  gcc/tree-ssa-structalias.h
  8236d4d91b8701a8daadc2f8a12d4752  gcc/tree-ssa-tail-merge.cc
  18ba2469cfdfbd297fe2b0120e69a84c  gcc/tree-ssa-ter.cc
*************** af4c63760c432f66b1c6c8e7e7666699  gcc/tr
*** 124544,124561 ****
  c7cfce71bf4903e72ac00b08e215eb2c  gcc/tree-switch-conversion.cc
  ebb8ac3717c1bf5db4371da2f3cf6af7  gcc/tree-switch-conversion.h
  324fa6ae10c2436c091c4c968318d653  gcc/tree-tailcall.cc
! 155cba670139398bb39ea8a47610472f  gcc/tree-vect-data-refs.cc
  5d8bb0df796ceea958fd65c5aedb5bce  gcc/tree-vect-generic.cc
  e104b17ea517e15aa0e3e38e4afcabaa  gcc/tree-vect-loop-manip.cc
! abd8d798b0beb75af08557900623c4d9  gcc/tree-vect-loop.cc
! da6336ee0c69409d59d2599d74cc5717  gcc/tree-vect-patterns.cc
  c6943415b45e06de6924e0c93b06b502  gcc/tree-vect-slp-patterns.cc
! 10c687ce905eb0530a509248f0b16291  gcc/tree-vect-slp.cc
! aab033125d57b678b2bd582569b6f3dc  gcc/tree-vect-stmts.cc
  c8efeee600d612c4bae8dda4bd45ee54  gcc/tree-vector-builder.cc
  258611ff1e83cc7680e8c9f033499665  gcc/tree-vector-builder.h
! a4620080dfbf6757116ace6cfaae648f  gcc/tree-vectorizer.cc
! 2bbf23c99ea05dbd7196badfeda06af4  gcc/tree-vectorizer.h
  1bed475667cbd8dee00c3b7da964ca5b  gcc/tree-vrp.cc
  a19edad681d27130bd2a0d83768ac946  gcc/tree-vrp.h
  56e573528b356925dac2888cf34cf030  gcc/tree.cc
--- 124709,124726 ----
  c7cfce71bf4903e72ac00b08e215eb2c  gcc/tree-switch-conversion.cc
  ebb8ac3717c1bf5db4371da2f3cf6af7  gcc/tree-switch-conversion.h
  324fa6ae10c2436c091c4c968318d653  gcc/tree-tailcall.cc
! 234ed2a59f5fa6ac9537264c7d3203c4  gcc/tree-vect-data-refs.cc
  5d8bb0df796ceea958fd65c5aedb5bce  gcc/tree-vect-generic.cc
  e104b17ea517e15aa0e3e38e4afcabaa  gcc/tree-vect-loop-manip.cc
! a05111a3ad2ec66534a7602fb8de32b1  gcc/tree-vect-loop.cc
! a51ec9fc987505f532f95f6c7b239290  gcc/tree-vect-patterns.cc
  c6943415b45e06de6924e0c93b06b502  gcc/tree-vect-slp-patterns.cc
! 700a9984bcf1592249095cbb0b88dca2  gcc/tree-vect-slp.cc
! b2cf98f89435e52e85240eca617be1b9  gcc/tree-vect-stmts.cc
  c8efeee600d612c4bae8dda4bd45ee54  gcc/tree-vector-builder.cc
  258611ff1e83cc7680e8c9f033499665  gcc/tree-vector-builder.h
! 60ed88dd59c46ce64914ee924d0551f8  gcc/tree-vectorizer.cc
! e155f8f9ad28991d8f23b80614c3af5b  gcc/tree-vectorizer.h
  1bed475667cbd8dee00c3b7da964ca5b  gcc/tree-vrp.cc
  a19edad681d27130bd2a0d83768ac946  gcc/tree-vrp.h
  56e573528b356925dac2888cf34cf030  gcc/tree.cc
*************** df85736a75a28f2d961a417c6edbbeeb  gcc/va
*** 124590,124596 ****
  4fcfb97f5fdee9686317186a141f2b4b  gcc/value-relation.cc
  cd4e6196ea1c7eb134b4d7cbadb9dcb3  gcc/value-relation.h
  db99ee82ab71b58820d60f9863e62aac  gcc/var-tracking.cc
! 8c55316e80e8121cbbb962ad5aa4610e  gcc/varasm.cc
  69f8e035a8548037bc8c8f7f854253c4  gcc/varasm.h
  e96ee31ef62fd5574909f9328fb29af9  gcc/varpool.cc
  5958f38d462c8e23023f7b272b8b969c  gcc/vec-perm-indices.cc
--- 124755,124761 ----
  4fcfb97f5fdee9686317186a141f2b4b  gcc/value-relation.cc
  cd4e6196ea1c7eb134b4d7cbadb9dcb3  gcc/value-relation.h
  db99ee82ab71b58820d60f9863e62aac  gcc/var-tracking.cc
! 649503f269890ef89adc3e7151706daf  gcc/varasm.cc
  69f8e035a8548037bc8c8f7f854253c4  gcc/varasm.h
  e96ee31ef62fd5574909f9328fb29af9  gcc/varpool.cc
  5958f38d462c8e23023f7b272b8b969c  gcc/vec-perm-indices.cc
*************** c2784afc7476e44bc70100f7c350e07b  gcc/vm
*** 124604,124610 ****
  0901703123c4198bb16fc8076912bd2e  gcc/vr-values.h
  9ce284cb128dc6f9cadddec86a09bb4a  gcc/vtable-verify.cc
  cdaf5a05f59e5ac25581747f6a7b4fe9  gcc/vtable-verify.h
! e3fa3f45e512510e34655f420629cbd8  gcc/warning-control.cc
  1a7f6c34c7ef76ab65aa6ca9d5de17f3  gcc/web.cc
  1fc5fa557891d7e14764b954513b9920  gcc/wide-int-bitmask.h
  112f50026efc86aeff2023a67e87a688  gcc/wide-int-print.cc
--- 124769,124775 ----
  0901703123c4198bb16fc8076912bd2e  gcc/vr-values.h
  9ce284cb128dc6f9cadddec86a09bb4a  gcc/vtable-verify.cc
  cdaf5a05f59e5ac25581747f6a7b4fe9  gcc/vtable-verify.h
! 1d7674a2e96cbcf375e680b72b9d329e  gcc/warning-control.cc
  1a7f6c34c7ef76ab65aa6ca9d5de17f3  gcc/web.cc
  1fc5fa557891d7e14764b954513b9920  gcc/wide-int-bitmask.h
  112f50026efc86aeff2023a67e87a688  gcc/wide-int-print.cc
*************** c0fa0a593b3a9b1ffd2f84bc40a22980  libbac
*** 124836,124842 ****
  69e738d1cd72baaeda073609f133f005  libbacktrace/xztest.c
  4d7dab09ddbe953244044c8a60434ad9  libbacktrace/zstdtest.c
  08e64385c7a2a6f5a8d0e25f4c237e51  libbacktrace/ztest.c
! 283fda14c2b4a2001d2fb14bd46316b6  libcc1/ChangeLog
  e396ef427fc1a75d765f69ea2b48aef9  libcc1/Makefile.am
  0c197f689319d609a20206994cd5eb7e  libcc1/Makefile.in
  b39668f1b706dbfe7203b3cfa277b792  libcc1/aclocal.m4
--- 125001,125007 ----
  69e738d1cd72baaeda073609f133f005  libbacktrace/xztest.c
  4d7dab09ddbe953244044c8a60434ad9  libbacktrace/zstdtest.c
  08e64385c7a2a6f5a8d0e25f4c237e51  libbacktrace/ztest.c
! 30400f2d73a014121d52bf99768e01cb  libcc1/ChangeLog
  e396ef427fc1a75d765f69ea2b48aef9  libcc1/Makefile.am
  0c197f689319d609a20206994cd5eb7e  libcc1/Makefile.in
  b39668f1b706dbfe7203b3cfa277b792  libcc1/aclocal.m4
*************** fe09cc65e2242b1f5e5ec3dc3da54c20  libcc1
*** 124850,124856 ****
  a3cb3c5aa8181bef86a5a5e4e03235c3  libcc1/configure.ac
  ef80637fedf68c1802c638751df08472  libcc1/connection.cc
  5c6231697372fed74cf47657b57a1009  libcc1/connection.hh
! 0e7fbdb3c63509600d7fcbef59101160  libcc1/context.cc
  eccd51b74097f88b7988e89253257248  libcc1/context.hh
  e3f273e60cae4124a92782d281575f39  libcc1/deleter.hh
  af4444e0df5238c11d09a354f4e10fbc  libcc1/findcomp.cc
--- 125015,125021 ----
  a3cb3c5aa8181bef86a5a5e4e03235c3  libcc1/configure.ac
  ef80637fedf68c1802c638751df08472  libcc1/connection.cc
  5c6231697372fed74cf47657b57a1009  libcc1/connection.hh
! b996476d598a71592a88f2d386e6a940  libcc1/context.cc
  eccd51b74097f88b7988e89253257248  libcc1/context.hh
  e3f273e60cae4124a92782d281575f39  libcc1/deleter.hh
  af4444e0df5238c11d09a354f4e10fbc  libcc1/findcomp.cc
*************** cffdeae41b78da05839b193e90188f55  libcod
*** 124892,124902 ****
  6419dfc879387358e95288142e569914  libcody/packet.cc
  688ece05c8b9d378b3df186808162e76  libcody/resolver.cc
  b1f3850fc5ac62999d1e124aa6f76531  libcody/server.cc
! 4578e8d1e9bd348775732e4f5a79918c  libcpp/ChangeLog
  2bd831b17997584e38305782cebe6948  libcpp/ChangeLog.jit
  e80a909ca87015a009bee9588bb84a64  libcpp/Makefile.in
  b07c7863f0e7ad4e6a0915d66fc9e582  libcpp/aclocal.m4
! 093a99089e489dae84557ca917e60dd6  libcpp/charset.cc
  5b2f9d37e91d01eed5bf420a47dc8046  libcpp/combining-chars.inc
  4c25fc38f2b9d20ca1fbefba9ad34b45  libcpp/config.in
  25fc63b1c46544e2d10d49555b022624  libcpp/configure
--- 125057,125067 ----
  6419dfc879387358e95288142e569914  libcody/packet.cc
  688ece05c8b9d378b3df186808162e76  libcody/resolver.cc
  b1f3850fc5ac62999d1e124aa6f76531  libcody/server.cc
! 1a3a7e9cbba9a08bc8254532e25e2ed7  libcpp/ChangeLog
  2bd831b17997584e38305782cebe6948  libcpp/ChangeLog.jit
  e80a909ca87015a009bee9588bb84a64  libcpp/Makefile.in
  b07c7863f0e7ad4e6a0915d66fc9e582  libcpp/aclocal.m4
! 8f57460d8c70595e235ec3ec53127378  libcpp/charset.cc
  5b2f9d37e91d01eed5bf420a47dc8046  libcpp/combining-chars.inc
  4c25fc38f2b9d20ca1fbefba9ad34b45  libcpp/config.in
  25fc63b1c46544e2d10d49555b022624  libcpp/configure
*************** edcd9f141150c148f5c5c9584a446394  libcpp
*** 124907,124920 ****
  ce74c78c2cb27bcdeac8a9b0400712cd  libcpp/files.cc
  97faf9e969cb255f2a2a91e0e7ac3c32  libcpp/generated_cpp_wcwidth.h
  c496c50691c37464e0aacc985cc3ab1e  libcpp/identifiers.cc
! 625e2785c1c28cbca2c662f92d67cf2b  libcpp/include/cpplib.h
  ac88522f7fec46badcd2623d11a4b61e  libcpp/include/label-text.h
  7bab1640ddcf15772a1a51f0315a3099  libcpp/include/line-map.h
  4779aaa10e24fd2398a105e78bdd88a5  libcpp/include/mkdeps.h
! 8dc5525eef86dcf1b1ee26cd243ab3a6  libcpp/include/rich-location.h
  d516a30568fd33a5e69be4374f27812f  libcpp/include/symtab.h
  3f05e522dd9325c9807fc4f662533f7b  libcpp/init.cc
! a0d37c297f3d462529b502a4e1bd2378  libcpp/internal.h
  4e6255f45482c932e22abfa044142804  libcpp/lex.cc
  4db7eb22b48b044d4c574217d110732b  libcpp/line-map.cc
  46a07100f95f5e354c7e25cd19d26884  libcpp/location-example.txt
--- 125072,125085 ----
  ce74c78c2cb27bcdeac8a9b0400712cd  libcpp/files.cc
  97faf9e969cb255f2a2a91e0e7ac3c32  libcpp/generated_cpp_wcwidth.h
  c496c50691c37464e0aacc985cc3ab1e  libcpp/identifiers.cc
! 2e36892d11f14ea2fa11aa1028995411  libcpp/include/cpplib.h
  ac88522f7fec46badcd2623d11a4b61e  libcpp/include/label-text.h
  7bab1640ddcf15772a1a51f0315a3099  libcpp/include/line-map.h
  4779aaa10e24fd2398a105e78bdd88a5  libcpp/include/mkdeps.h
! 4425f3f8462ed9bfc4a7255738750310  libcpp/include/rich-location.h
  d516a30568fd33a5e69be4374f27812f  libcpp/include/symtab.h
  3f05e522dd9325c9807fc4f662533f7b  libcpp/init.cc
! 439e6d290e7a6d513ed80d0c1ccab538  libcpp/internal.h
  4e6255f45482c932e22abfa044142804  libcpp/lex.cc
  4db7eb22b48b044d4c574217d110732b  libcpp/line-map.cc
  46a07100f95f5e354c7e25cd19d26884  libcpp/location-example.txt
*************** f63a06d746592d67d8c161bc2461a24e  libgfo
*** 128031,128037 ****
  e90afde1ec8653f66d433a7cc5e070a7  libgfortran/runtime/select_inc.c
  fa1f81a5ee204308c775545490d24fbd  libgfortran/runtime/stop.c
  08f6570c94f64b0aaf21fb2ec9aa10e9  libgfortran/runtime/string.c
! b0e68a793ee26ebc24d12beb8406a9c9  libgm2/ChangeLog
  81dadb03add7a7278a98cd845177e76a  libgm2/Makefile.am
  38778826306c4efe1f6a33cb21cece23  libgm2/Makefile.in
  5655398e9c1e3027c587898dc4fce566  libgm2/acinclude.m4
--- 128196,128202 ----
  e90afde1ec8653f66d433a7cc5e070a7  libgfortran/runtime/select_inc.c
  fa1f81a5ee204308c775545490d24fbd  libgfortran/runtime/stop.c
  08f6570c94f64b0aaf21fb2ec9aa10e9  libgfortran/runtime/string.c
! 8964d516ca77dffa5d218ff20a35f68e  libgm2/ChangeLog
  81dadb03add7a7278a98cd845177e76a  libgm2/Makefile.am
  38778826306c4efe1f6a33cb21cece23  libgm2/Makefile.in
  5655398e9c1e3027c587898dc4fce566  libgm2/acinclude.m4
*************** f25de03fc822c5eebf7118fcf5283ebc  libgm2
*** 128045,128066 ****
  1c81daa01520f3a05da1ff4d530f5873  libgm2/libm2cor/Makefile.in
  256f893d9141ee50fb703d08f0c7ce3a  libgm2/libm2iso/ChanConsts.h
  87d5ba33acc7d56c7dd0f43a7d6660ca  libgm2/libm2iso/ErrnoCategory.cc
! 50b1ab5ac2f7313addeb89244a63e53d  libgm2/libm2iso/Makefile.am
! 06bbf355611e65199fed815c1971975a  libgm2/libm2iso/Makefile.in
  55e7456cbf4c00590b7d5c26437bf683  libgm2/libm2iso/RTco.cc
  60e20d4966763ff532153264c355ec8f  libgm2/libm2iso/m2rts.h
  9cb2d2fda0da4de1596491a1ba383634  libgm2/libm2iso/wrapclock.cc
  e3037b97506181892bc760a12d9c5f69  libgm2/libm2iso/wrapsock.c
  33246d6ec18583a1eb0fc89ca61f4fd8  libgm2/libm2iso/wraptime.cc
  eb003ee7f1b2cf1972500be967c4d5eb  libgm2/libm2log/Break.c
! 2990568f387a516f255792a1cc54039f  libgm2/libm2log/Makefile.am
! c0826ae4087216cbe3d07b7ac749be7c  libgm2/libm2log/Makefile.in
! 36f227f41f6cb4fc9bd5eaa5345378f3  libgm2/libm2min/Makefile.am
! 0508f72ba2d22517546c50f880f3cf9e  libgm2/libm2min/Makefile.in
  a9f05e5da997bab66d457b3be2773189  libgm2/libm2min/libc.c
  672db9b5f503b1b02773144313a13746  libgm2/libm2pim/CFileSysOp.cc
! e9a9fa4aa273c6c9fb72e428bbac71b3  libgm2/libm2pim/Makefile.am
! ec626ef6d1f1791a48dde69a7877a01a  libgm2/libm2pim/Makefile.in
  944531ee3e0d441b1c7209ac2c2355eb  libgm2/libm2pim/Selective.cc
  635915386732139700506c42de8b469d  libgm2/libm2pim/SysExceptions.cc
  04512543e0711f8f6f6e1fb2a995330e  libgm2/libm2pim/UnixArgs.cc
--- 128210,128231 ----
  1c81daa01520f3a05da1ff4d530f5873  libgm2/libm2cor/Makefile.in
  256f893d9141ee50fb703d08f0c7ce3a  libgm2/libm2iso/ChanConsts.h
  87d5ba33acc7d56c7dd0f43a7d6660ca  libgm2/libm2iso/ErrnoCategory.cc
! 093abbe1256afaed6cf0bf9588c74678  libgm2/libm2iso/Makefile.am
! 0ed2871eb2c8ea782bdcd9005036a7db  libgm2/libm2iso/Makefile.in
  55e7456cbf4c00590b7d5c26437bf683  libgm2/libm2iso/RTco.cc
  60e20d4966763ff532153264c355ec8f  libgm2/libm2iso/m2rts.h
  9cb2d2fda0da4de1596491a1ba383634  libgm2/libm2iso/wrapclock.cc
  e3037b97506181892bc760a12d9c5f69  libgm2/libm2iso/wrapsock.c
  33246d6ec18583a1eb0fc89ca61f4fd8  libgm2/libm2iso/wraptime.cc
  eb003ee7f1b2cf1972500be967c4d5eb  libgm2/libm2log/Break.c
! 2174db736f05842c30f16bf53515adf5  libgm2/libm2log/Makefile.am
! 03694b1aa63b0fb8ee180e8f2fed57d0  libgm2/libm2log/Makefile.in
! ba2db7fd78510ae0ff3e50d0d57c1b8d  libgm2/libm2min/Makefile.am
! 7f4aeaf0c74fa83422c651bcac4573ea  libgm2/libm2min/Makefile.in
  a9f05e5da997bab66d457b3be2773189  libgm2/libm2min/libc.c
  672db9b5f503b1b02773144313a13746  libgm2/libm2pim/CFileSysOp.cc
! f8df0461dbb353c3db40cf75cf623f56  libgm2/libm2pim/Makefile.am
! 06954b6e0bb1a5bd60026314ca71aa0d  libgm2/libm2pim/Makefile.in
  944531ee3e0d441b1c7209ac2c2355eb  libgm2/libm2pim/Selective.cc
  635915386732139700506c42de8b469d  libgm2/libm2pim/SysExceptions.cc
  04512543e0711f8f6f6e1fb2a995330e  libgm2/libm2pim/UnixArgs.cc
*************** a3a7e9ca6057da9ca42e03e41e1c73f7  libgo/
*** 133568,133574 ****
  dcdf1b680b15b372bdb64cc5107d51b6  libgo/testsuite/libgo-test-support.exp.in
  bf162aa572f7b96b25dbd2b027845d32  libgo/testsuite/libgo.testmain/testmain.exp
  cc9d2a0e34e31ba866a8caf9f46f48f3  libgomp/.gitattributes
! 9a2e134678cf9b6a1d3cd1c9654ed198  libgomp/ChangeLog
  0d55aa862aee66efdc5f8d62c94ff8fb  libgomp/ChangeLog.graphite
  883cfea6de23904b83d6bd58a729c866  libgomp/Makefile.am
  54c7bc8277669e3bf5f1a3db179ae206  libgomp/Makefile.in
--- 133733,133739 ----
  dcdf1b680b15b372bdb64cc5107d51b6  libgo/testsuite/libgo-test-support.exp.in
  bf162aa572f7b96b25dbd2b027845d32  libgo/testsuite/libgo.testmain/testmain.exp
  cc9d2a0e34e31ba866a8caf9f46f48f3  libgomp/.gitattributes
! fdbe903a8bed012c8c444334f8309f1b  libgomp/ChangeLog
  0d55aa862aee66efdc5f8d62c94ff8fb  libgomp/ChangeLog.graphite
  883cfea6de23904b83d6bd58a729c866  libgomp/Makefile.am
  54c7bc8277669e3bf5f1a3db179ae206  libgomp/Makefile.in
*************** ab3063f8b6682d372e65d063a35a406d  libgom
*** 134030,134037 ****
  131b2ab5b78c2725e33c4249f59e5799  libgomp/testsuite/libgomp.c++/target-7.C
  1a7862ad9a2af6943f9928a670bcaf16  libgomp/testsuite/libgomp.c++/target-8.C
  e8abd1a92868914a2a5307268ef4b3d8  libgomp/testsuite/libgomp.c++/target-9.C
! 9d99c4c8266b85f3e755797f45220fa2  libgomp/testsuite/libgomp.c++/target-cdtor-1.C
! 97c6a58c85759cb7153801e0d0286635  libgomp/testsuite/libgomp.c++/target-cdtor-2.C
  3d15e0d44019185d8004a4d4b87851de  libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-1.C
  64bd4e898ee85afe93f6f182b3a479fc  libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-GCN.C
  2ab3f03a68f64f25cb39af3017726c7c  libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-nvptx.C
--- 134195,134202 ----
  131b2ab5b78c2725e33c4249f59e5799  libgomp/testsuite/libgomp.c++/target-7.C
  1a7862ad9a2af6943f9928a670bcaf16  libgomp/testsuite/libgomp.c++/target-8.C
  e8abd1a92868914a2a5307268ef4b3d8  libgomp/testsuite/libgomp.c++/target-9.C
! 0c3cc98689bf759beba23798d61ce4b1  libgomp/testsuite/libgomp.c++/target-cdtor-1.C
! 457b919f3ef79b72a20a5deb55a33a8e  libgomp/testsuite/libgomp.c++/target-cdtor-2.C
  3d15e0d44019185d8004a4d4b87851de  libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-1.C
  64bd4e898ee85afe93f6f182b3a479fc  libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-GCN.C
  2ab3f03a68f64f25cb39af3017726c7c  libgomp/testsuite/libgomp.c++/target-exceptions-bad_cast-2-offload-sorry-nvptx.C
*************** d680e7307fb59fe24f8431e179191f16  libssp
*** 138623,138629 ****
  534c3fb4a88e5c1f70db35c12b7742c3  libssp/vsnprintf-chk.c
  34daeb04a522ee796098df4446d6ce61  libssp/vsprintf-chk.c
  9e2de2e1f20ab0ffa2201164de02824f  libstdc++-v3/.editorconfig
! 436966f37c15e34af8c07c07a7fdc122  libstdc++-v3/ChangeLog
  7aa6c40440a44fcf5ec94c066160c2f8  libstdc++-v3/ChangeLog-1998
  7aff86600b6a1ed3fa87305075a92db0  libstdc++-v3/ChangeLog-1999
  a6f28e8fc9bb07696a9e068b439a3a87  libstdc++-v3/ChangeLog-2000
--- 138788,138794 ----
  534c3fb4a88e5c1f70db35c12b7742c3  libssp/vsnprintf-chk.c
  34daeb04a522ee796098df4446d6ce61  libssp/vsprintf-chk.c
  9e2de2e1f20ab0ffa2201164de02824f  libstdc++-v3/.editorconfig
! 9b1b121f2107f5a5857b2f068a3b13af  libstdc++-v3/ChangeLog
  7aa6c40440a44fcf5ec94c066160c2f8  libstdc++-v3/ChangeLog-1998
  7aff86600b6a1ed3fa87305075a92db0  libstdc++-v3/ChangeLog-1999
  a6f28e8fc9bb07696a9e068b439a3a87  libstdc++-v3/ChangeLog-2000
*************** d4640a684d621320ba7676511ca49731  libstd
*** 139444,139450 ****
  e10663748871662214948efa4440ceaa  libstdc++-v3/include/bits/uniform_int_dist.h
  0d7174a622374816c75ac03f78148fc9  libstdc++-v3/include/bits/unique_lock.h
  93a78bb35b2fe9f54d8df8c4c1669ad4  libstdc++-v3/include/bits/unique_ptr.h
! 720670953bf88eec92501c1ba0c32197  libstdc++-v3/include/bits/unordered_map.h
  23e3769341c471dd17aa42c532a2e463  libstdc++-v3/include/bits/unordered_set.h
  a29de34311f884bb0a7bb8854fe4ce34  libstdc++-v3/include/bits/uses_allocator.h
  b9489856439b8ba5238cd45b2f65370a  libstdc++-v3/include/bits/uses_allocator_args.h
--- 139609,139615 ----
  e10663748871662214948efa4440ceaa  libstdc++-v3/include/bits/uniform_int_dist.h
  0d7174a622374816c75ac03f78148fc9  libstdc++-v3/include/bits/unique_lock.h
  93a78bb35b2fe9f54d8df8c4c1669ad4  libstdc++-v3/include/bits/unique_ptr.h
! cc943715f9f524c3520028821de279b9  libstdc++-v3/include/bits/unordered_map.h
  23e3769341c471dd17aa42c532a2e463  libstdc++-v3/include/bits/unordered_set.h
  a29de34311f884bb0a7bb8854fe4ce34  libstdc++-v3/include/bits/uses_allocator.h
  b9489856439b8ba5238cd45b2f65370a  libstdc++-v3/include/bits/uses_allocator_args.h
*************** e790ae6877466aa86b47f36d201e8563  libstd
*** 140027,140033 ****
  866d33497e4338e4e1a5289de701f9ba  libstdc++-v3/include/std/functional
  d472ad4b1b5c12e2f731980802d15b50  libstdc++-v3/include/std/future
  d91bc94f2a9c1ff7f642d23c27ec66ae  libstdc++-v3/include/std/generator
! 338f1c11e4505d6e69bdd1ee87244acb  libstdc++-v3/include/std/inplace_vector
  90e01b4e65cec5c0a3786580b2529edb  libstdc++-v3/include/std/iomanip
  bf5ea5fbda7bfdc1dc462f0303fc4e99  libstdc++-v3/include/std/ios
  4623e874877c5e927587c4bfe1a03c84  libstdc++-v3/include/std/iosfwd
--- 140192,140198 ----
  866d33497e4338e4e1a5289de701f9ba  libstdc++-v3/include/std/functional
  d472ad4b1b5c12e2f731980802d15b50  libstdc++-v3/include/std/future
  d91bc94f2a9c1ff7f642d23c27ec66ae  libstdc++-v3/include/std/generator
! 82613eb8615066794371a675dcd5d2f9  libstdc++-v3/include/std/inplace_vector
  90e01b4e65cec5c0a3786580b2529edb  libstdc++-v3/include/std/iomanip
  bf5ea5fbda7bfdc1dc462f0303fc4e99  libstdc++-v3/include/std/ios
  4623e874877c5e927587c4bfe1a03c84  libstdc++-v3/include/std/iosfwd
*************** a98ad6deeb1a797726968f46416f6122  libstd
*** 140039,140045 ****
  c9ef2791c2dc0d6c98a1a85c8f6aa473  libstdc++-v3/include/std/list
  f4af31191dea172207576960ad71d42d  libstdc++-v3/include/std/locale
  8b76fc7da76f0579c2fd1f22821d03be  libstdc++-v3/include/std/map
! 27e064589f9dddfae7bde158d961ff12  libstdc++-v3/include/std/mdspan
  c381426cd2710743a6530b116179d74f  libstdc++-v3/include/std/memory
  9e86c11ff29d60fddf403674e9182b36  libstdc++-v3/include/std/memory_resource
  a7b8e00d6cf56ea696ec15140b7c1d15  libstdc++-v3/include/std/mutex
--- 140204,140210 ----
  c9ef2791c2dc0d6c98a1a85c8f6aa473  libstdc++-v3/include/std/list
  f4af31191dea172207576960ad71d42d  libstdc++-v3/include/std/locale
  8b76fc7da76f0579c2fd1f22821d03be  libstdc++-v3/include/std/map
! 0a8963714f2461a7476a9b16706eb7f2  libstdc++-v3/include/std/mdspan
  c381426cd2710743a6530b116179d74f  libstdc++-v3/include/std/memory
  9e86c11ff29d60fddf403674e9182b36  libstdc++-v3/include/std/memory_resource
  a7b8e00d6cf56ea696ec15140b7c1d15  libstdc++-v3/include/std/mutex
*************** eda36ec39a3ddadcfe8e8ab16caefc48  libstd
*** 140809,140815 ****
  a7c7d3cf31b77ca51ce57296221adf6d  libstdc++-v3/testsuite/20_util/any/layout.cc
  ce98d5d9b12fec73dbcbd896bed4e992  libstdc++-v3/testsuite/20_util/any/make_any.cc
  510b58670ba5f173bf535ce0b6e3a448  libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc
! f286040b251865c06a7b926aed7002b2  libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
  6543b2cec5e0fb057721dff92b954218  libstdc++-v3/testsuite/20_util/any/misc/any_cast_no_rtti.cc
  a576256da1fd0145043529eaf7e62e7d  libstdc++-v3/testsuite/20_util/any/misc/lwg3305.cc
  64524fd415c3427160fee1e36c356aec  libstdc++-v3/testsuite/20_util/any/misc/swap.cc
--- 140974,140980 ----
  a7c7d3cf31b77ca51ce57296221adf6d  libstdc++-v3/testsuite/20_util/any/layout.cc
  ce98d5d9b12fec73dbcbd896bed4e992  libstdc++-v3/testsuite/20_util/any/make_any.cc
  510b58670ba5f173bf535ce0b6e3a448  libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc
! 9de854f35c76a982b55600d13cb5667c  libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
  6543b2cec5e0fb057721dff92b954218  libstdc++-v3/testsuite/20_util/any/misc/any_cast_no_rtti.cc
  a576256da1fd0145043529eaf7e62e7d  libstdc++-v3/testsuite/20_util/any/misc/lwg3305.cc
  64524fd415c3427160fee1e36c356aec  libstdc++-v3/testsuite/20_util/any/misc/swap.cc
*************** e8a5d4c4f0e447896dac59a5a84ec9c0  libstd
*** 141002,141008 ****
  e860269ac09079a27b177fc3da2839e7  libstdc++-v3/testsuite/20_util/expected/cons.cc
  56411bbfdf1df328a5b305222e4527ed  libstdc++-v3/testsuite/20_util/expected/equality.cc
  8bcfbe2481e180a50db20c6b10f2d6a0  libstdc++-v3/testsuite/20_util/expected/equality_constrained.cc
! f56847054b7eea85a598a3299216a456  libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc
  b6846002a3a56bb10b1621e1792c246a  libstdc++-v3/testsuite/20_util/expected/lwg3836.cc
  3f3a954cb96422e14f241df35baee8ad  libstdc++-v3/testsuite/20_util/expected/lwg3843.cc
  2fe263333a538ddd2a8cd7953725ff52  libstdc++-v3/testsuite/20_util/expected/lwg3877.cc
--- 141167,141173 ----
  e860269ac09079a27b177fc3da2839e7  libstdc++-v3/testsuite/20_util/expected/cons.cc
  56411bbfdf1df328a5b305222e4527ed  libstdc++-v3/testsuite/20_util/expected/equality.cc
  8bcfbe2481e180a50db20c6b10f2d6a0  libstdc++-v3/testsuite/20_util/expected/equality_constrained.cc
! 51122703f016055e7f753b4c20fef888  libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc
  b6846002a3a56bb10b1621e1792c246a  libstdc++-v3/testsuite/20_util/expected/lwg3836.cc
  3f3a954cb96422e14f241df35baee8ad  libstdc++-v3/testsuite/20_util/expected/lwg3843.cc
  2fe263333a538ddd2a8cd7953725ff52  libstdc++-v3/testsuite/20_util/expected/lwg3877.cc
*************** a97926deeb496a76093d2fc9bb4fd879  libstd
*** 141599,141605 ****
  711b1737b784a943fe0e18612d0dd1a2  libstdc++-v3/testsuite/20_util/optional/make_optional.cc
  9f6d73e852cf82959a57a12db48e8905  libstdc++-v3/testsuite/20_util/optional/monadic/and_then.cc
  ca862872c63399df0317190ea1f66d4b  libstdc++-v3/testsuite/20_util/optional/monadic/or_else.cc
! ee09f6b0b65aa45b2df39f550d3fa064  libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc
  72fbbba600f3e2e6599c46a0812c30bd  libstdc++-v3/testsuite/20_util/optional/monadic/pr109242.cc
  b7d8b66190edd1b5779d2e2e80d350e2  libstdc++-v3/testsuite/20_util/optional/monadic/transform.cc
  d329c4116ef0ed3bde8a1621b437e53d  libstdc++-v3/testsuite/20_util/optional/nullopt.cc
--- 141764,141770 ----
  711b1737b784a943fe0e18612d0dd1a2  libstdc++-v3/testsuite/20_util/optional/make_optional.cc
  9f6d73e852cf82959a57a12db48e8905  libstdc++-v3/testsuite/20_util/optional/monadic/and_then.cc
  ca862872c63399df0317190ea1f66d4b  libstdc++-v3/testsuite/20_util/optional/monadic/or_else.cc
! abdfe6ec8acaa93c094f5513ee2502e7  libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc
  72fbbba600f3e2e6599c46a0812c30bd  libstdc++-v3/testsuite/20_util/optional/monadic/pr109242.cc
  b7d8b66190edd1b5779d2e2e80d350e2  libstdc++-v3/testsuite/20_util/optional/monadic/transform.cc
  d329c4116ef0ed3bde8a1621b437e53d  libstdc++-v3/testsuite/20_util/optional/nullopt.cc
*************** f4cd79a32c4d00bd9817a25cef9fe909  libstd
*** 142335,142341 ****
  35c34576a3006668440e983476df9da4  libstdc++-v3/testsuite/21_strings/basic_string/cons/char/noexcept_move_construct.cc
  ca9ae628b034a9ec99cd3e60951cfecc  libstdc++-v3/testsuite/21_strings/basic_string/cons/char/nullptr.cc
  3830f2c4dcb298975cf3a65181dc6757  libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc
! f9a4ecd017de67a4a931d6102f497ce7  libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc
  9b0b0442eb5e35b3881502ae2dee1e00  libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/1.cc
  a038ee254fac0e0abf9184282e6605c7  libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc
  6b59fcbfe23000c829fa14a5b8aa9cb6  libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/2.cc
--- 142500,142506 ----
  35c34576a3006668440e983476df9da4  libstdc++-v3/testsuite/21_strings/basic_string/cons/char/noexcept_move_construct.cc
  ca9ae628b034a9ec99cd3e60951cfecc  libstdc++-v3/testsuite/21_strings/basic_string/cons/char/nullptr.cc
  3830f2c4dcb298975cf3a65181dc6757  libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc
! 316760a099fd131ab7d6075e0ef40b20  libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc
  9b0b0442eb5e35b3881502ae2dee1e00  libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/1.cc
  a038ee254fac0e0abf9184282e6605c7  libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc
  6b59fcbfe23000c829fa14a5b8aa9cb6  libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/2.cc
*************** fed3452b9fd695c2fcacf169f97f7fbc  libstd
*** 142415,142421 ****
  21fd19580e8a6912e0d8c76f04cf5107  libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc
  6a7fb5daaab33be9e1e454e0efe5a4f0  libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc
  bbf91f21f3febff3e3db164981ba2a41  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/64422.cc
! 4e4cc95e48d2bd94ad3c1a4c07001500  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc
  eed5a5683962fbcb4b5b280bc1c336a5  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/1.cc
  5e4d455700e44db51617c187a038d68b  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/2.cc
  f2236ef5628630aad4fd1655bbddb0d0  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/3.cc
--- 142580,142586 ----
  21fd19580e8a6912e0d8c76f04cf5107  libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc
  6a7fb5daaab33be9e1e454e0efe5a4f0  libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc
  bbf91f21f3febff3e3db164981ba2a41  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/64422.cc
! 89506a2ca72334b3212f4c9fb2babf18  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc
  eed5a5683962fbcb4b5b280bc1c336a5  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/1.cc
  5e4d455700e44db51617c187a038d68b  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/2.cc
  f2236ef5628630aad4fd1655bbddb0d0  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/3.cc
*************** ce7c816e1a9a7fb3459333bb0684e346  libstd
*** 142424,142430 ****
  de61dd744862e54686ec6688e808fd28  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/2.cc
  fed9da6c780fcdc59bd5781a606e6421  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/3.cc
  b6e8f45c09ff882a388994cc33c71c7c  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc
! 1bc674adbe130b9899a4e0ad5eeaf445  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc
  b4b1bb82a2d753bdac19752570cc5095  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/1.cc
  ab2a8a66cc0816b289c0a17b601a4352  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/2.cc
  6f5dabf607ff6c861ef3e1c198a2993f  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/3.cc
--- 142589,142595 ----
  de61dd744862e54686ec6688e808fd28  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/2.cc
  fed9da6c780fcdc59bd5781a606e6421  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/3.cc
  b6e8f45c09ff882a388994cc33c71c7c  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/4.cc
! 94b29218fb10d78f60975a6d63a4246b  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc
  b4b1bb82a2d753bdac19752570cc5095  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/1.cc
  ab2a8a66cc0816b289c0a17b601a4352  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/2.cc
  6f5dabf607ff6c861ef3e1c198a2993f  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/3.cc
*************** b5440b36ca04a745bfb69aecfee0f46d  libstd
*** 142445,142451 ****
  077b7632d260b62f5e1fc9228457c85a  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/2.cc
  1c7c0fb681b78944772899f010f9223c  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc
  3a9d0880cc6073c2bf9eaf974890307d  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/83328.cc
! fb7988c8a3ebdedf57c7dfd30fca0d4f  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc
  c64cf801b1910a6ed890da26a4377e52  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/1.cc
  55ef493bebf3bf1720aa45f0c27340e2  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/2.cc
  304c98866d7f4a3467a76efe0aac8c55  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc
--- 142610,142616 ----
  077b7632d260b62f5e1fc9228457c85a  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/2.cc
  1c7c0fb681b78944772899f010f9223c  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/3.cc
  3a9d0880cc6073c2bf9eaf974890307d  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/char/83328.cc
! d356f7f3fae27b3f2be158636def2395  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc
  c64cf801b1910a6ed890da26a4377e52  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/1.cc
  55ef493bebf3bf1720aa45f0c27340e2  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/2.cc
  304c98866d7f4a3467a76efe0aac8c55  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/wchar_t/3.cc
*************** ef9978cee4400b81ac57a10cf690d4a7  libstd
*** 142459,142465 ****
  140972c10d31106908a1272141cc227f  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/5.cc
  17d10d7b47c3f6fe0545251cdd36011c  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/6.cc
  17e6c7430bc930a5e8dee4672f219657  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc
! 94707a49de6995544f18f62eb7001456  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc
  57858f24253f9e4f40cc8a5859938ea0  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/1.cc
  427dbe3bf18378981dc0b85b01dff1b1  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/2.cc
  faff29c1520d6755a9fa9e565a6ffad6  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/3.cc
--- 142624,142630 ----
  140972c10d31106908a1272141cc227f  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/5.cc
  17d10d7b47c3f6fe0545251cdd36011c  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/6.cc
  17e6c7430bc930a5e8dee4672f219657  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc
! 1371a34e64b61722f5b9c384e3d5635a  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc
  57858f24253f9e4f40cc8a5859938ea0  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/1.cc
  427dbe3bf18378981dc0b85b01dff1b1  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/2.cc
  faff29c1520d6755a9fa9e565a6ffad6  libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/3.cc
*************** c0fce4eb756201fee341ec1f012adb26  libstd
*** 143400,143406 ****
  224417afded5fa24d407144744d6700e  libstdc++-v3/testsuite/23_containers/array/creation/111512.cc
  11bac09ddbd90a00219248b83c052d06  libstdc++-v3/testsuite/23_containers/array/creation/115522.cc
  39bd1870ddd8084fed6cc356d9b2d952  libstdc++-v3/testsuite/23_containers/array/creation/2.cc
! 2a0a83b8b6a2b113f23713574ba45c26  libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc
  2f5c6d72baa5aa45312df9c3d3cb6090  libstdc++-v3/testsuite/23_containers/array/debug/back1_neg.cc
  51813f6cb86cc6d68db8b7da3df64aa3  libstdc++-v3/testsuite/23_containers/array/debug/back2_neg.cc
  9e5540d125cd257a19c4a1b00e7f253a  libstdc++-v3/testsuite/23_containers/array/debug/constexpr_c++11.cc
--- 143565,143571 ----
  224417afded5fa24d407144744d6700e  libstdc++-v3/testsuite/23_containers/array/creation/111512.cc
  11bac09ddbd90a00219248b83c052d06  libstdc++-v3/testsuite/23_containers/array/creation/115522.cc
  39bd1870ddd8084fed6cc356d9b2d952  libstdc++-v3/testsuite/23_containers/array/creation/2.cc
! 4fd40f3250e655a4c88d0276076776d9  libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc
  2f5c6d72baa5aa45312df9c3d3cb6090  libstdc++-v3/testsuite/23_containers/array/debug/back1_neg.cc
  51813f6cb86cc6d68db8b7da3df64aa3  libstdc++-v3/testsuite/23_containers/array/debug/back2_neg.cc
  9e5540d125cd257a19c4a1b00e7f253a  libstdc++-v3/testsuite/23_containers/array/debug/constexpr_c++11.cc
*************** da421f8c7821a0a6d7eab3d8001476e3  libstd
*** 143696,143712 ****
  43de62af8d3c543b80596072975c9266  libstdc++-v3/testsuite/23_containers/headers/unordered_set/std_c++0x_neg.cc
  50bc010406caef63380764c8105e79c8  libstdc++-v3/testsuite/23_containers/headers/vector/synopsis.cc
  c3b72820d263829b8713079673adf2bf  libstdc++-v3/testsuite/23_containers/inplace_vector/access/capacity.cc
! 7d9575b2c875f7cc36857669232abf8e  libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc
! fdd8743e959f7d6cdaef16e857544176  libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc
  e43e9eb523468bb62b4f7889ad64b811  libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc
! 108a7ab00c7a6d8ad8a5db53efa1dca3  libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
  38e5f39346a05e51ec2a0e4cdf2586e4  libstdc++-v3/testsuite/23_containers/inplace_vector/cons/throws.cc
  273424e32898a9d53a7f2ac8a6fc355b  libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
  99d153ffeaacc6a311788e24a42c8f60  libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
! 8660cebd944df0751ee6e65f17d8a9d5  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
  5aec8512568ce2f7543d9c77e6605c2c  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc
! ac49fb17014b5bfa7544caf2bff9cc94  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
  8c4c89cbb2ba35feda988027855433ad  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
  f134ee48b3f80955503a35907623395b  libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
  5518dafa57195a13905e6083cf064ace  libstdc++-v3/testsuite/23_containers/inplace_vector/relops.cc
  2b73622f47b87d526a0d4cbbd45bd738  libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc
--- 143861,143879 ----
  43de62af8d3c543b80596072975c9266  libstdc++-v3/testsuite/23_containers/headers/unordered_set/std_c++0x_neg.cc
  50bc010406caef63380764c8105e79c8  libstdc++-v3/testsuite/23_containers/headers/vector/synopsis.cc
  c3b72820d263829b8713079673adf2bf  libstdc++-v3/testsuite/23_containers/inplace_vector/access/capacity.cc
! 0dfecfd826cd666c38084ef6cb55c9b2  libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc
! 30ab64df2eb33c78da29eab2cf8935d7  libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc
  e43e9eb523468bb62b4f7889ad64b811  libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc
! cd81d3555896e4c03e2bba3f0932ce5c  libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
  38e5f39346a05e51ec2a0e4cdf2586e4  libstdc++-v3/testsuite/23_containers/inplace_vector/cons/throws.cc
  273424e32898a9d53a7f2ac8a6fc355b  libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
  99d153ffeaacc6a311788e24a42c8f60  libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
! 25458c2942c9e5fdbe79af5a83ec4102  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
  5aec8512568ce2f7543d9c77e6605c2c  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc
! 32171ec785b1b967d1076d5da1536940  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc
! a7c24e54c62a380315141d521b8fdcef  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
  8c4c89cbb2ba35feda988027855433ad  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
+ 63a7d605a0bc39f3acfb0fa4bb289dda  libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc
  f134ee48b3f80955503a35907623395b  libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
  5518dafa57195a13905e6083cf064ace  libstdc++-v3/testsuite/23_containers/inplace_vector/relops.cc
  2b73622f47b87d526a0d4cbbd45bd738  libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc
*************** cc42abd3f12e4e2d740c196077e9dfbd  libstd
*** 143962,143987 ****
  1e719131ce8d3c52ab96fb6320a2682e  libstdc++-v3/testsuite/23_containers/map/requirements/partial_specialization/1.cc
  ef8992fce519e4aeb10d10129736a163  libstdc++-v3/testsuite/23_containers/map/requirements/typedefs.cc
  1a429dd433a9cca8518d6eeaf0db7ff4  libstdc++-v3/testsuite/23_containers/map/version.cc
- 44898fbd0da3bd306298ec2583fc7138  libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc
  c9be65e1a0cf8e0da83e4027b6ea3e64  libstdc++-v3/testsuite/23_containers/mdspan/accessors/default_neg.cc
  22e0f5f9fb4bc8a3baf9b93c86b44573  libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc
  f5bb9f936365225b61020ea9149ba6fa  libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
  58d322becec5c5e65c19f17834e2a082  libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc
  e9e5cce5f41b3fcb25e00e9b6edb9a83  libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_default.cc
! d4de13f0203d7d66539b205b64e6fdf5  libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
! 74773d6a3d965e479de89f3fe5d7058d  libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc
  56a0f5d5edaad1117cc988beafc16d5d  libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
  669e44182af41d221acecffd45681dc9  libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
  c1ed4da78be7e752025a693bb0564242  libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
  e941ac1789059834b40085a779a24d2e  libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
! d68af45366016aad6a270abcb0712c53  libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h
  09f60c1da783ed561b487e9441ae6882  libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
  bfd42a535aa33a3b5315bf669715ffb4  libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
  ea1a2f61fac46b6b55b9ff2c52289540  libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc
  dd7692786bb4cc01e8e54a11e77eef69  libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc
  a65c4b5056c3c06dc115e0ce959f26b4  libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
  3f96813b92ac712ab8210f7eb24e7158  libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
! d8070ef63040f007c8035c819313f81e  libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
  4b1a50b4d361b155b60027f1bdc566e7  libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc
  0c4d322f39233942c4ee2e211a2ea456  libstdc++-v3/testsuite/23_containers/mdspan/version.cc
  351e436ffeeb8e47804c6992b75a81cb  libstdc++-v3/testsuite/23_containers/multimap/14340.cc
--- 144129,144154 ----
  1e719131ce8d3c52ab96fb6320a2682e  libstdc++-v3/testsuite/23_containers/map/requirements/partial_specialization/1.cc
  ef8992fce519e4aeb10d10129736a163  libstdc++-v3/testsuite/23_containers/map/requirements/typedefs.cc
  1a429dd433a9cca8518d6eeaf0db7ff4  libstdc++-v3/testsuite/23_containers/map/version.cc
  c9be65e1a0cf8e0da83e4027b6ea3e64  libstdc++-v3/testsuite/23_containers/mdspan/accessors/default_neg.cc
+ de978f376d5c51d0779f6a300d80e844  libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc
  22e0f5f9fb4bc8a3baf9b93c86b44573  libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc
  f5bb9f936365225b61020ea9149ba6fa  libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
  58d322becec5c5e65c19f17834e2a082  libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc
  e9e5cce5f41b3fcb25e00e9b6edb9a83  libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_default.cc
! 66875233ba8f0cee58dceb78c0d2268d  libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
! f11430abfbf793c9117a6d498fc9e9d6  libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc
  56a0f5d5edaad1117cc988beafc16d5d  libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
  669e44182af41d221acecffd45681dc9  libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
  c1ed4da78be7e752025a693bb0564242  libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
  e941ac1789059834b40085a779a24d2e  libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
! bead52db525471c98d26137e05743c97  libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h
  09f60c1da783ed561b487e9441ae6882  libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
  bfd42a535aa33a3b5315bf669715ffb4  libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
  ea1a2f61fac46b6b55b9ff2c52289540  libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc
  dd7692786bb4cc01e8e54a11e77eef69  libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc
  a65c4b5056c3c06dc115e0ce959f26b4  libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
  3f96813b92ac712ab8210f7eb24e7158  libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
! de0ccc5f3275031f5c8109ac93a09046  libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
  4b1a50b4d361b155b60027f1bdc566e7  libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc
  0c4d322f39233942c4ee2e211a2ea456  libstdc++-v3/testsuite/23_containers/mdspan/version.cc
  351e436ffeeb8e47804c6992b75a81cb  libstdc++-v3/testsuite/23_containers/multimap/14340.cc
*************** b10e477ceb2448b2bd45fd0fdee32d8b  libstd
*** 144840,144846 ****
  c16513cc4d3631e94cfd316c6566d30a  libstdc++-v3/testsuite/23_containers/vector/bool/cons/2.cc
  ebc47e5dcba86666ba23cc0aabe3a291  libstdc++-v3/testsuite/23_containers/vector/bool/cons/87809.cc
  8d0b07e1cf5846334fc00f9f4705e3fe  libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc
! 312b72f70797bc0ed11cf6e071944149  libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc
  5ae4b10af939a0161833a11ff6188af3  libstdc++-v3/testsuite/23_containers/vector/bool/cons/lwg3778.cc
  349038f10da6c12b9247b98ba3680cb4  libstdc++-v3/testsuite/23_containers/vector/bool/cons/noexcept_move_construct.cc
  e0b11c4dbbdafef2f8d275b74b88c682  libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc
--- 145007,145013 ----
  c16513cc4d3631e94cfd316c6566d30a  libstdc++-v3/testsuite/23_containers/vector/bool/cons/2.cc
  ebc47e5dcba86666ba23cc0aabe3a291  libstdc++-v3/testsuite/23_containers/vector/bool/cons/87809.cc
  8d0b07e1cf5846334fc00f9f4705e3fe  libstdc++-v3/testsuite/23_containers/vector/bool/cons/constexpr.cc
! 943f0e119a2957746915dbdaefa190cf  libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc
  5ae4b10af939a0161833a11ff6188af3  libstdc++-v3/testsuite/23_containers/vector/bool/cons/lwg3778.cc
  349038f10da6c12b9247b98ba3680cb4  libstdc++-v3/testsuite/23_containers/vector/bool/cons/noexcept_move_construct.cc
  e0b11c4dbbdafef2f8d275b74b88c682  libstdc++-v3/testsuite/23_containers/vector/bool/element_access/1.cc
*************** f05d61ed2f2f49da266a6dd1825c57fb  libstd
*** 144852,144858 ****
  981d796e31f85b155c22e4537df612da  libstdc++-v3/testsuite/23_containers/vector/bool/hash/1.cc
  ab56a6e398445099c12ca1122424277f  libstdc++-v3/testsuite/23_containers/vector/bool/iterator_c++20.cc
  3830dcd977751429dffbc55d64b358c1  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/1.cc
! 7526dc14638b2890353c7cc93a5cf891  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc
  c2caffba87c853ac017ff0008682574f  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc
  564442c432d0e1aa5d2ed0fc5baea507  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc
  3046d906fd328453b47f6c0e97fb486f  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/erase/1.cc
--- 145019,145025 ----
  981d796e31f85b155c22e4537df612da  libstdc++-v3/testsuite/23_containers/vector/bool/hash/1.cc
  ab56a6e398445099c12ca1122424277f  libstdc++-v3/testsuite/23_containers/vector/bool/iterator_c++20.cc
  3830dcd977751429dffbc55d64b358c1  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/1.cc
! e984dec113c5693b04d00111607183f9  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc
  c2caffba87c853ac017ff0008682574f  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc
  564442c432d0e1aa5d2ed0fc5baea507  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/constexpr.cc
  3046d906fd328453b47f6c0e97fb486f  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/erase/1.cc
*************** c2caffba87c853ac017ff0008682574f  libstd
*** 144860,144868 ****
  919862c93c1c6fcafdc9459c5324dfdd  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/1.cc
  8411c535ec979be02e85103a2ce6a933  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/104559.cc
  62e93654c5187d851af4b4c264b5bfb8  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/31370.cc
! 8d6363ee67654eb1d0fdefc69076e1c6  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc
  1897e319a5208a48e633774cef003076  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/const_iterator.cc
! e235ea87a6293213703f9853b990f44f  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc
  25c099d5a4a3e08165ccddba9ddad9f5  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/1.cc
  3200035d0929245106f6c6e3567c10a4  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/2.cc
  780e46ea3d7c50d8c8512793253f488f  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc
--- 145027,145035 ----
  919862c93c1c6fcafdc9459c5324dfdd  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/1.cc
  8411c535ec979be02e85103a2ce6a933  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/104559.cc
  62e93654c5187d851af4b4c264b5bfb8  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/31370.cc
! 932298e59279e959ff893f12aab9f310  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc
  1897e319a5208a48e633774cef003076  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/const_iterator.cc
! ff9d5673f40678b2d4268d0b9a93a134  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc
  25c099d5a4a3e08165ccddba9ddad9f5  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/1.cc
  3200035d0929245106f6c6e3567c10a4  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/2.cc
  780e46ea3d7c50d8c8512793253f488f  libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc
*************** e3eb212137f2101dd4ceb83392d4f604  libstd
*** 144911,144917 ****
  7a66bf7f5aca27ddc8ca203f2f55a9b6  libstdc++-v3/testsuite/23_containers/vector/cons/destroy-adl.cc
  2694e9f5cb5094fe107333e8e893566e  libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc
  3910bbb9d09dde186eeeeb0f6fc1fbab  libstdc++-v3/testsuite/23_containers/vector/cons/destructible_neg.cc
! 833017a30b2de971981f574bdc3fd989  libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
  95343136dbd192e25dfe16b3a4eda01d  libstdc++-v3/testsuite/23_containers/vector/cons/moveable.cc
  f1d10ca32c2d09fd89ac466ce1077fce  libstdc++-v3/testsuite/23_containers/vector/cons/moveable2.cc
  7e7b7e0e0333f9178ee8f602413f5ce6  libstdc++-v3/testsuite/23_containers/vector/cons/noexcept_move_construct.cc
--- 145078,145084 ----
  7a66bf7f5aca27ddc8ca203f2f55a9b6  libstdc++-v3/testsuite/23_containers/vector/cons/destroy-adl.cc
  2694e9f5cb5094fe107333e8e893566e  libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc
  3910bbb9d09dde186eeeeb0f6fc1fbab  libstdc++-v3/testsuite/23_containers/vector/cons/destructible_neg.cc
! c76fb24cc0e3db5317766b313c4adf00  libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
  95343136dbd192e25dfe16b3a4eda01d  libstdc++-v3/testsuite/23_containers/vector/cons/moveable.cc
  f1d10ca32c2d09fd89ac466ce1077fce  libstdc++-v3/testsuite/23_containers/vector/cons/moveable2.cc
  7e7b7e0e0333f9178ee8f602413f5ce6  libstdc++-v3/testsuite/23_containers/vector/cons/noexcept_move_construct.cc
*************** d25f291816575ab3288d7ef11616c8c4  libstd
*** 144972,144980 ****
  fd4fcb831fe8650097c41c5e89dac0b9  libstdc++-v3/testsuite/23_containers/vector/init-list.cc
  c1b88d2f8969f3db574edd537b12aa9f  libstdc++-v3/testsuite/23_containers/vector/modifiers/1.cc
  1290761e41a3824f22113332e9e7e2f3  libstdc++-v3/testsuite/23_containers/vector/modifiers/2.cc
! e767eac7e8c20f96c48d462609c4d0b4  libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc
  871e71919a8ead646df53a68cf98d0ee  libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/1.cc
! 3961fb1e7e3cf628954d162eb59723e1  libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc
  953c68b9c8f36c7a72454dbf1966be8c  libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc
  000698581016741f52c8bf2bfe086a46  libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/no_realloc.cc
  a325122e6a6afa548900873f460f4121  libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc
--- 145139,145147 ----
  fd4fcb831fe8650097c41c5e89dac0b9  libstdc++-v3/testsuite/23_containers/vector/init-list.cc
  c1b88d2f8969f3db574edd537b12aa9f  libstdc++-v3/testsuite/23_containers/vector/modifiers/1.cc
  1290761e41a3824f22113332e9e7e2f3  libstdc++-v3/testsuite/23_containers/vector/modifiers/2.cc
! 51f7c2cac76acbdc14070788c567fd75  libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc
  871e71919a8ead646df53a68cf98d0ee  libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/1.cc
! 1e1490fa3302bf9a5a136fd51b977a6a  libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc
  953c68b9c8f36c7a72454dbf1966be8c  libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/constexpr.cc
  000698581016741f52c8bf2bfe086a46  libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/no_realloc.cc
  a325122e6a6afa548900873f460f4121  libstdc++-v3/testsuite/23_containers/vector/modifiers/constexpr.cc
*************** a5f7ae14b6844d43b1081a499624f525  libstd
*** 144991,144997 ****
  7d27fdbd20b83aa5340cdab8ef4c3ce8  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/58148.cc
  28a3af6e38881699bccce32dfeee9612  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/aliasing.cc
  26744f861734b6a0aa5bad87665a2ad9  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/const_iterator.cc
! be9bdc7d3330f3394771c82f96ecc66f  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc
  35e70ddc10ee243c7ae40dfd6fba7ce6  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/self_insert.cc
  8fb5c601f412e71f5977219b7d89f18d  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert_vs_emplace.cc
  2301f3312f26a25c0cecd650693c1ee6  libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc
--- 145158,145164 ----
  7d27fdbd20b83aa5340cdab8ef4c3ce8  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/58148.cc
  28a3af6e38881699bccce32dfeee9612  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/aliasing.cc
  26744f861734b6a0aa5bad87665a2ad9  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/const_iterator.cc
! c4d8593e81e1b765107c5ae168ef4f27  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc
  35e70ddc10ee243c7ae40dfd6fba7ce6  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/self_insert.cc
  8fb5c601f412e71f5977219b7d89f18d  libstdc++-v3/testsuite/23_containers/vector/modifiers/insert_vs_emplace.cc
  2301f3312f26a25c0cecd650693c1ee6  libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc
*************** e5f996fbd7c463c5cdce92d1cfeec2c1  libstd
*** 145150,145156 ****
  52d8e3f0c0e27fec1f58a5ba479d93f5  libstdc++-v3/testsuite/24_iterators/output/concept.cc
  682bd05ac09bdd08c584fcd1728f928c  libstdc++-v3/testsuite/24_iterators/output/tag.cc
  1e373c51fd12f6b0ddc4d653f0a8246a  libstdc++-v3/testsuite/24_iterators/random_access/concept.cc
! 713b6634126689a91f1d403206e3ed1f  libstdc++-v3/testsuite/24_iterators/random_access/string_vector_iterators.cc
  559c614ab19722e055aaaa325a00536b  libstdc++-v3/testsuite/24_iterators/random_access/tag.cc
  0954a0794f753047e5654d11d59f7d0e  libstdc++-v3/testsuite/24_iterators/range_access/range_access.cc
  22be42b7219401f9c6d645e2efc3d0be  libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp14.cc
--- 145317,145323 ----
  52d8e3f0c0e27fec1f58a5ba479d93f5  libstdc++-v3/testsuite/24_iterators/output/concept.cc
  682bd05ac09bdd08c584fcd1728f928c  libstdc++-v3/testsuite/24_iterators/output/tag.cc
  1e373c51fd12f6b0ddc4d653f0a8246a  libstdc++-v3/testsuite/24_iterators/random_access/concept.cc
! 54c7e60528ff78287af2e89800f59f7c  libstdc++-v3/testsuite/24_iterators/random_access/string_vector_iterators.cc
  559c614ab19722e055aaaa325a00536b  libstdc++-v3/testsuite/24_iterators/random_access/tag.cc
  0954a0794f753047e5654d11d59f7d0e  libstdc++-v3/testsuite/24_iterators/range_access/range_access.cc
  22be42b7219401f9c6d645e2efc3d0be  libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp14.cc
*************** c8a50553dd3b7126efd679c539a6fe59  libstd
*** 145165,145171 ****
  b73d317c5a2565fa5bdea7235d84b955  libstdc++-v3/testsuite/24_iterators/range_generators/except.cc
  2655d5bd5e2ec076f8bc48c4004c50de  libstdc++-v3/testsuite/24_iterators/range_generators/iter_deref_return.cc
  c0cf7a998d7a04b5d3058bd84c0a1c74  libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc
! 563b847dbbebfa4128d4c633fae82ec7  libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc
  1e1d86dc401e097273fc12a0dc17640f  libstdc++-v3/testsuite/24_iterators/range_generators/pr118022.cc
  a7fdd4ef46d148c07b2306186a300c7e  libstdc++-v3/testsuite/24_iterators/range_generators/pr118196.cc
  ccbbe51e2f862feaa3f4e717ef2f1cd6  libstdc++-v3/testsuite/24_iterators/range_generators/subrange.cc
--- 145332,145338 ----
  b73d317c5a2565fa5bdea7235d84b955  libstdc++-v3/testsuite/24_iterators/range_generators/except.cc
  2655d5bd5e2ec076f8bc48c4004c50de  libstdc++-v3/testsuite/24_iterators/range_generators/iter_deref_return.cc
  c0cf7a998d7a04b5d3058bd84c0a1c74  libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc
! 5846a6625f238913840979281e9008d5  libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc
  1e1d86dc401e097273fc12a0dc17640f  libstdc++-v3/testsuite/24_iterators/range_generators/pr118022.cc
  a7fdd4ef46d148c07b2306186a300c7e  libstdc++-v3/testsuite/24_iterators/range_generators/pr118196.cc
  ccbbe51e2f862feaa3f4e717ef2f1cd6  libstdc++-v3/testsuite/24_iterators/range_generators/subrange.cc
*************** b3d8282607956ee4826df350c5a70605  libstd
*** 147934,147940 ****
  4770655eced43833b45a7bff9815589f  libstdc++-v3/testsuite/29_atomics/atomic/requirements/compare_exchange_lowering.cc
  638a3151b6917b31577257fe25faead9  libstdc++-v3/testsuite/29_atomics/atomic/requirements/explicit_instantiation/1.cc
  f08bda434201147cbbae0882f57b6f85  libstdc++-v3/testsuite/29_atomics/atomic/requirements/typedefs.cc
! f51c048c81346d717df317430049cb80  libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc
  4ba60a21ca727b934f2ac2dcda3e7eba  libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/1.cc
  d83dbdce3ea29e2b1a8cef08ae7b805f  libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/100334.cc
  0c57c2f91f968ace2a2fc16b2f362a94  libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/102994.cc
--- 148101,148107 ----
  4770655eced43833b45a7bff9815589f  libstdc++-v3/testsuite/29_atomics/atomic/requirements/compare_exchange_lowering.cc
  638a3151b6917b31577257fe25faead9  libstdc++-v3/testsuite/29_atomics/atomic/requirements/explicit_instantiation/1.cc
  f08bda434201147cbbae0882f57b6f85  libstdc++-v3/testsuite/29_atomics/atomic/requirements/typedefs.cc
! d744fe5162c958ab77f86b1d203ca0fa  libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc
  4ba60a21ca727b934f2ac2dcda3e7eba  libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/1.cc
  d83dbdce3ea29e2b1a8cef08ae7b805f  libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/100334.cc
  0c57c2f91f968ace2a2fc16b2f362a94  libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/102994.cc
*************** a50ee762289c16f526e565c1a4a289ab  libstd
*** 148291,148298 ****
  669054b4f77b1f37c01d79ce1b681488  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/deadlock-mt.cc
  104890270a2a7c83c8d352ae82ee1200  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/deadlock.cc
  1a21d7046e422b44dade576e8c4faea5  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destroy.cc
! 225227649f89f2d61cb45eba484ff2ff  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc
! 4162f3e41a2f8c1f05ae1e77d4e026ca  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc
  a5bb4a6df861f69ede87d5ede99afcae  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invoke.cc
  e468465d90804d3f3333e522da3498fc  libstdc++-v3/testsuite/30_threads/stop_token/stop_source.cc
  97c265fb2eb60646be155e18f47b2f61  libstdc++-v3/testsuite/30_threads/stop_token/stop_source/109339.cc
--- 148458,148465 ----
  669054b4f77b1f37c01d79ce1b681488  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/deadlock-mt.cc
  104890270a2a7c83c8d352ae82ee1200  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/deadlock.cc
  1a21d7046e422b44dade576e8c4faea5  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destroy.cc
! cd8fff914990d827f381565ce41d30ef  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc
! d40c2193b2dcb037f50a3f19ca750c7e  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc
  a5bb4a6df861f69ede87d5ede99afcae  libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invoke.cc
  e468465d90804d3f3333e522da3498fc  libstdc++-v3/testsuite/30_threads/stop_token/stop_source.cc
  97c265fb2eb60646be155e18f47b2f61  libstdc++-v3/testsuite/30_threads/stop_token/stop_source/109339.cc
*************** cce32ddc9f763f73b9ecdd456f62dad8  libstd
*** 149596,149602 ****
  553fa21f46dadf88c0986882e76d0ccf  libstdc++-v3/testsuite/std/concepts/concepts.object/semiregular.cc
  576d75aaf7d2aae28e341cda63776ff9  libstdc++-v3/testsuite/std/format/arguments/112607.cc
  6aba59df6148b2c2d4a2bb0a6167d356  libstdc++-v3/testsuite/std/format/arguments/args.cc
! d52aff2e6dfd886a32da7955635ed09e  libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
  0ae0aa3194832d790df652a9ef7d17c7  libstdc++-v3/testsuite/std/format/arguments/lwg3810.cc
  088e48d84af728cffa21af00b37e3c04  libstdc++-v3/testsuite/std/format/context.cc
  8f6b20493386ac083a968add9dea93ac  libstdc++-v3/testsuite/std/format/debug.cc
--- 149763,149769 ----
  553fa21f46dadf88c0986882e76d0ccf  libstdc++-v3/testsuite/std/concepts/concepts.object/semiregular.cc
  576d75aaf7d2aae28e341cda63776ff9  libstdc++-v3/testsuite/std/format/arguments/112607.cc
  6aba59df6148b2c2d4a2bb0a6167d356  libstdc++-v3/testsuite/std/format/arguments/args.cc
! 9b395b28a17d44c9d7e0673396df4031  libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
  0ae0aa3194832d790df652a9ef7d17c7  libstdc++-v3/testsuite/std/format/arguments/lwg3810.cc
  088e48d84af728cffa21af00b37e3c04  libstdc++-v3/testsuite/std/format/context.cc
  8f6b20493386ac083a968add9dea93ac  libstdc++-v3/testsuite/std/format/debug.cc
*************** d9708c521b612f15f943a911427b169b  libstd
*** 149630,149636 ****
  fdca82ddd8e353e70075872cb27926c2  libstdc++-v3/testsuite/std/format/ranges/string.cc
  22af3c8593871c64b40b11663417f80a  libstdc++-v3/testsuite/std/format/runtime_format.cc
  c400d0d58ad702f461b28668dc629c09  libstdc++-v3/testsuite/std/format/string.cc
! 9818aa3a29f6312d9efbbdc1369fdc1f  libstdc++-v3/testsuite/std/format/string_neg.cc
  a554040cee1e3b564ea9bf0188ddf8da  libstdc++-v3/testsuite/std/format/tuple.cc
  1ee4f09d4811a5b094ebc85dd48142f9  libstdc++-v3/testsuite/std/memory/indirect/copy.cc
  2b0944a1839541995d0521288e45e718  libstdc++-v3/testsuite/std/memory/indirect/copy_alloc.cc
--- 149797,149803 ----
  fdca82ddd8e353e70075872cb27926c2  libstdc++-v3/testsuite/std/format/ranges/string.cc
  22af3c8593871c64b40b11663417f80a  libstdc++-v3/testsuite/std/format/runtime_format.cc
  c400d0d58ad702f461b28668dc629c09  libstdc++-v3/testsuite/std/format/string.cc
! 7c654edf02fc2f7793fb1f549b890993  libstdc++-v3/testsuite/std/format/string_neg.cc
  a554040cee1e3b564ea9bf0188ddf8da  libstdc++-v3/testsuite/std/format/tuple.cc
  1ee4f09d4811a5b094ebc85dd48142f9  libstdc++-v3/testsuite/std/memory/indirect/copy.cc
  2b0944a1839541995d0521288e45e718  libstdc++-v3/testsuite/std/memory/indirect/copy_alloc.cc
*************** f2b0e4d916814dffed575ea22219e282  libstd
*** 150552,150558 ****
  115aa7d14fbe6ab56dfbe3ea70aae859  libstdc++-v3/testsuite/util/testsuite_abi.h
  48ffba86c4669f3a97144b731fcff6cd  libstdc++-v3/testsuite/util/testsuite_abi_check.cc
  5181eaba4b9bb86b0b6e535b11d64fe3  libstdc++-v3/testsuite/util/testsuite_allocator.cc
! b7850d7be1e3222b160fc1f37157596c  libstdc++-v3/testsuite/util/testsuite_allocator.h
  476f839662a77a0eadd8ff8fa3c9fa2c  libstdc++-v3/testsuite/util/testsuite_api.h
  760319735b19378de98320351aac54d8  libstdc++-v3/testsuite/util/testsuite_character.cc
  ebb4d891741cf15170ea7d0b26f6ec9e  libstdc++-v3/testsuite/util/testsuite_character.h
--- 150719,150725 ----
  115aa7d14fbe6ab56dfbe3ea70aae859  libstdc++-v3/testsuite/util/testsuite_abi.h
  48ffba86c4669f3a97144b731fcff6cd  libstdc++-v3/testsuite/util/testsuite_abi_check.cc
  5181eaba4b9bb86b0b6e535b11d64fe3  libstdc++-v3/testsuite/util/testsuite_allocator.cc
! 65af11b7f290541704987aab61bae9bc  libstdc++-v3/testsuite/util/testsuite_allocator.h
  476f839662a77a0eadd8ff8fa3c9fa2c  libstdc++-v3/testsuite/util/testsuite_api.h
  760319735b19378de98320351aac54d8  libstdc++-v3/testsuite/util/testsuite_character.cc
  ebb4d891741cf15170ea7d0b26f6ec9e  libstdc++-v3/testsuite/util/testsuite_character.h
*************** aa52b04bf095d0226a1314474cb5c3c4  libstd
*** 150567,150573 ****
  3d3f95e4c126c7714834db5c046f0867  libstdc++-v3/testsuite/util/testsuite_hooks.cc
  c08d7419962b291852dd827d7d78f678  libstdc++-v3/testsuite/util/testsuite_hooks.h
  2cc9d485ece15882c52d8b6a9c1094e8  libstdc++-v3/testsuite/util/testsuite_io.h
! 6ab737f49ec07ab67b45fe38f78b1f8d  libstdc++-v3/testsuite/util/testsuite_iterators.h
  bb471f730bbdca73a1658e3b1e4295c0  libstdc++-v3/testsuite/util/testsuite_new_operators.h
  cb452b2ea9afe9f303a9f003d3d6412b  libstdc++-v3/testsuite/util/testsuite_performance.h
  9e7f7529d1423cbb841bf18d5251891d  libstdc++-v3/testsuite/util/testsuite_random.h
--- 150734,150740 ----
  3d3f95e4c126c7714834db5c046f0867  libstdc++-v3/testsuite/util/testsuite_hooks.cc
  c08d7419962b291852dd827d7d78f678  libstdc++-v3/testsuite/util/testsuite_hooks.h
  2cc9d485ece15882c52d8b6a9c1094e8  libstdc++-v3/testsuite/util/testsuite_io.h
! c6b33c1381e9c6f8ffd5e787b3480a93  libstdc++-v3/testsuite/util/testsuite_iterators.h
  bb471f730bbdca73a1658e3b1e4295c0  libstdc++-v3/testsuite/util/testsuite_new_operators.h
  cb452b2ea9afe9f303a9f003d3d6412b  libstdc++-v3/testsuite/util/testsuite_performance.h
  9e7f7529d1423cbb841bf18d5251891d  libstdc++-v3/testsuite/util/testsuite_random.h
diff -Nrcpad gcc-16-20250720/contrib/ChangeLog gcc-16-20250727/contrib/ChangeLog
*** gcc-16-20250720/contrib/ChangeLog	Sun Jul 20 22:32:07 2025
--- gcc-16-20250727/contrib/ChangeLog	Sun Jul 27 22:32:07 2025
***************
*** 1,3 ****
--- 1,17 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* filter-clang-warnings.py: Update for move of
+ 	diagnostic-path-output.cc to diagnostics/paths-output.cc.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.doxy (INPUT): Add gcc/diagnostics subdir.
+ 
+ 2025-07-23  Sam James  <sam@gentoo.org>
+ 
+ 	PR other/105404
+ 	* gcc-changelog/git_commit.py (ignored_prefixes): Add zlib/.
+ 
  2025-07-16  David Malcolm  <dmalcolm@redhat.com>
  
  	* gcc.doxy (INPUT): Add directory "gcc/text-art".
diff -Nrcpad gcc-16-20250720/contrib/filter-clang-warnings.py gcc-16-20250727/contrib/filter-clang-warnings.py
*** gcc-16-20250720/contrib/filter-clang-warnings.py	Sun Jul 20 22:32:07 2025
--- gcc-16-20250727/contrib/filter-clang-warnings.py	Sun Jul 27 22:32:07 2025
*************** def skip_warning(filename, message):
*** 46,52 ****
                   '-Wunused-function', '-Wunneeded-internal-declaration',
                   '-Wvla-cxx-extension', '-Wunused-command-line-argument'],
  
!             'diagnostic-path-output.cc': ['m_logical_loc_mgr'],
              'fold-const-call.cc': ['-Wreturn-type'],
              'gimple-match': ['-Wunused-', '-Wtautological-compare'],
              'generic-match': ['-Wunused-', '-Wtautological-compare'],
--- 46,52 ----
                   '-Wunused-function', '-Wunneeded-internal-declaration',
                   '-Wvla-cxx-extension', '-Wunused-command-line-argument'],
  
!             'diagnostics/paths-output.cc': ['m_logical_loc_mgr'],
              'fold-const-call.cc': ['-Wreturn-type'],
              'gimple-match': ['-Wunused-', '-Wtautological-compare'],
              'generic-match': ['-Wunused-', '-Wtautological-compare'],
diff -Nrcpad gcc-16-20250720/contrib/gcc-changelog/git_commit.py gcc-16-20250727/contrib/gcc-changelog/git_commit.py
*** gcc-16-20250720/contrib/gcc-changelog/git_commit.py	Sun Jul 20 22:32:07 2025
--- gcc-16-20250727/contrib/gcc-changelog/git_commit.py	Sun Jul 27 22:32:07 2025
*************** ignored_prefixes = {
*** 152,157 ****
--- 152,158 ----
      'libphobos/libdruntime/',
      'libphobos/src/',
      'libsanitizer/',
+     'zlib/',
      }
  
  wildcard_prefixes = {
diff -Nrcpad gcc-16-20250720/contrib/gcc.doxy gcc-16-20250727/contrib/gcc.doxy
*** gcc-16-20250720/contrib/gcc.doxy	Sun Jul 20 22:32:07 2025
--- gcc-16-20250727/contrib/gcc.doxy	Sun Jul 27 22:32:07 2025
*************** WARN_LOGFILE           =
*** 478,484 ****
  # directories like "/usr/src/myproject". Separate the files or directories 
  # with spaces.
  
! INPUT                  = gcc gcc/analyzer gcc/text-art
  
  # This tag can be used to specify the character encoding of the source files that 
  # doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default 
--- 478,484 ----
  # directories like "/usr/src/myproject". Separate the files or directories 
  # with spaces.
  
! INPUT                  = gcc gcc/analyzer gcc/diagnostics gcc/text-art
  
  # This tag can be used to specify the character encoding of the source files that 
  # doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default 
diff -Nrcpad gcc-16-20250720/gcc/ChangeLog gcc-16-20250727/gcc/ChangeLog
*** gcc-16-20250720/gcc/ChangeLog	Sun Jul 20 22:32:07 2025
--- gcc-16-20250727/gcc/ChangeLog	Sun Jul 27 22:32:07 2025
***************
*** 1,3 ****
--- 1,1838 ----
+ 2025-07-27  Nathaniel Shead  <nathanieloshead@gmail.com>
+ 
+ 	PR middle-end/120855
+ 	* cgraphunit.cc (symbol_table::compile): Assert a transparent
+ 	alias is not an internal identifier.
+ 	* symtab.cc (symbol_table::change_decl_assembler_name):
+ 	Likewise.
+ 	* varasm.cc (assemble_name_resolve): Check for
+ 	IDENTIFIER_TRANSPARENT_ALIAS instead of just TREE_CHAIN.
+ 
+ 2025-07-26  Thomas Schwinge  <tschwinge@baylibre.com>
+ 
+ 	* diagnostics/context.cc (context::diagnostic_impl)
+ 	(context::diagnostic_n_impl): In presence of formal parameter
+ 	'kind', explicitly state 'diagnostics::' scope for 'kind' enum.
+ 
+ 2025-07-26  Thomas Schwinge  <tschwinge@baylibre.com>
+ 
+ 	* diagnostics/option-classifier.cc
+ 	(update_effective_level_from_pragmas): In presence of local
+ 	variable 'kind', explicitly state 'diagnostics::' scope for 'kind'
+ 	enum.
+ 
+ 2025-07-26  Christoph Müllner  <christoph.muellner@vrull.eu>
+ 
+ 	* config/riscv/riscv-ext.def: Add allocated group IDs and
+ 	group bit positions.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostics/context.cc: Eliminate digraphs::lazy_digraph in
+ 	favor of lazily_created template.
+ 	* diagnostics/context.h: Likewise.
+ 	* diagnostics/digraphs.cc: Likewise, also digraphs::lazy_digraphs.
+ 	* diagnostics/digraphs.h: Likewise.
+ 	* diagnostics/html-sink.cc: Likewise.
+ 	* diagnostics/metadata.h: Likewise.
+ 	* diagnostics/sarif-sink.cc: Likewise.
+ 	* diagnostics/sink.h: Likewise.
+ 	* diagnostics/text-sink.h: Likewise.
+ 	* lazily-created.h: New file.
+ 	* libgdiagnostics.cc: Eliminate digraphs::lazy_digraph in
+ 	favor of lazily_created template.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic.h: Use TextOrHtml rather than Sink for template
+ 	params.
+ 	* diagnostics/context.h: Likewise.
+ 	* diagnostics/selftest-context.cc: Use "html_or_text" rather than
+ 	"sink".
+ 	* diagnostics/source-printing.cc: Use TextOrHtml rather than Sink
+ 	for template params.  Use "text_out" and "html_out" rather than
+ 	"sink".
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic.h (diagnostic_set_caret_max_width): Drop forward
+ 	decl.
+ 	(diagnostic_same_line): Make
+ 	diagnostics::context::m_source_printing private.
+ 	* diagnostics/context.cc (diagnostic_set_caret_max_width): Convert
+ 	to...
+ 	(diagnostics::context::set_caret_max_width): ...this.
+ 	* diagnostics/context.h
+ 	(diagnostics::context::get_source_printing_options): New
+ 	accessors.
+ 	(diagnostics::context::m_source_printing): Make private.
+ 	* diagnostics/html-sink.cc: Make
+ 	diagnostics::context::m_source_printing private.
+ 	* diagnostics/paths-output.cc: Likewise.
+ 	* diagnostics/sarif-sink.cc: Likewise.
+ 	* diagnostics/selftest-context.cc: Likewise.
+ 	* diagnostics/selftest-context.h
+ 	(diagnostics::selftest::test_context::colorize_source): New.
+ 	(diagnostics::selftest::test_context::show_labels): New.
+ 	(diagnostics::selftest::test_context::show_line_numbers): New.
+ 	(diagnostics::selftest::test_context::show_ruler): New.
+ 	(diagnostics::selftest::test_context::show_event_links): New.
+ 	(diagnostics::selftest::test_context::set_caret_char): New.
+ 	* diagnostics/source-printing.cc: Make
+ 	diagnostics::context::m_source_printing private.
+ 	* diagnostics/text-sink.h: Likewise.
+ 	* libgdiagnostics.cc: Likewise.
+ 	* opts.cc: Likewise.
+ 	* toplev.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic.h: Eliminate "diagnostic_info" typedef.
+ 	* diagnostics/context.cc: Update usage of "diagnostic_info" to
+ 	explicitly refer to "diagnostics::diagnostic_info".
+ 	* langhooks.cc: Likewise.
+ 	* libgdiagnostics.cc: Likewise.
+ 	* rtl-error.cc: Likewise.
+ 	* substring-locations.cc: Likewise.
+ 	* toplev.cc: Likewise.
+ 	* tree-diagnostic.cc: Likewise.
+ 	* tree-diagnostic.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic.h (enum diagnostics_column_unit): Move to
+ 	diagnostics/context-options.h.
+ 	(enum diagnostics_escape_format): Likewise.
+ 	(enum diagnostics_output_format): Likewise.
+ 	(enum diagnostic_path_format): Likewise.
+ 	(enum diagnostics_extra_output_kind): Likewise.
+ 	(enum diagnostic_text_art_charset): Likewise.
+ 	* diagnostics/context-options.h: New file, based on the above
+ 	material.
+ 	* diagnostics/context.h: Include it.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Add diagnostics/file-cache.o.
+ 	* diagnostics/changes.cc: Update for file_cache and char_span
+ 	moving from input.h to diagnostics/file-cache.h and into the
+ 	"diagnostics::" namespace.
+ 	* diagnostics/context.cc: Likewise.
+ 	* diagnostics/diagnostics-selftests.cc: Likewise.
+ 	* diagnostics/diagnostics-selftests.h: Likewise.
+ 	* diagnostics/file-cache.cc: New file, based on the file_cache
+ 	and file_cache_slot material in input.cc.
+ 	* diagnostics/file-cache.h: Likewise for input.h.
+ 	* diagnostics/selftest-source-printing.h: Update for file_cache
+ 	and char_span moving from input.h to diagnostics/file-cache.h and
+ 	into the "diagnostics::" namespace.
+ 	* diagnostics/source-printing.cc: Likewise.
+ 	* final.cc: Likewise.
+ 	* gcc-rich-location.cc: Likewise.
+ 	* input.cc (default_charset_callback): Move to
+ 	diagnostics/file-cache.cc.
+ 	(file_cache::initialize_input_context): Likewise.
+ 	(class file_cache_slot): Likewise.
+ 	(file_cache::tune): Likewise.
+ 	(file_cache::lookup_file): Likewise.
+ 	(file_cache::forcibly_evict_file): Likewise.
+ 	(file_cache::missing_trailing_newline_p): Likewise.
+ 	(file_cache::add_buffered_content): Likewise.
+ 	(file_cache::evicted_cache_tab_entry): Likewise.
+ 	(file_cache::add_file): Likewise.
+ 	(file_cache::file_cache): Likewise.
+ 	(file_cache::dump): Likewise.
+ 	(file_cache::dump): Likewise.
+ 	(file_cache::lookup_or_add_file): Likewise.
+ 	(find_end_of_line): Likewise.
+ 	(file_cache::get_source_line): Likewise.
+ 	(check_line): Likewise.
+ 	(test_replacement): Likewise.
+ 	(test_reading_source_line): Likewise.
+ 	(test_reading_source_buffer): Likewise.
+ 	* input.h (class char_span): Move to diagnostics/file-cache.h and
+ 	into the "diagnostics::" namespace.
+ 	(class file_cache_slot): Likewise.
+ 	(class file_cache): Likewise.
+ 	* libgdiagnostics.cc: Update for file_cache and char_span moving
+ 	from input.h to diagnostics/file-cache.h and into the
+ 	"diagnostics::" namespace.
+ 	* selftest.cc: Likewise.
+ 	* selftest.h: Likewise.
+ 	* substring-locations.h: Likewise.
+ 	* toplev.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostics/selftest-paths.cc: Don't include "demangle.h"
+ 	and "backtrace.h".
+ 	* diagnostics/source-printing.cc: Likewise.
+ 	* diagnostics/state-graphs.cc: Don't include "graphviz.h",
+ 	"xml.h", "xml-printer.h", or "intl.h".
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic.h: Move include of "unique-argv.h"
+ 	and various forward decls into...
+ 	* diagnostics/context.h: ...here.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic.h (num_digits): Move to...
+ 	(diagnostics::num_digits): ...here.
+ 	(get_cwe_url): Move to...
+ 	(diagnostics::get_cwe_url): ...here.
+ 	(maybe_line_and_column): Move to...
+ 	(diagnostics::maybe_line_and_column): ...here.
+ 	* diagnostic.cc: Move to...
+ 	* diagnostics/context.cc: ...here.
+ 	* diagnostics/diagnostics-selftests.cc
+ 	(run_diagnostics_selftests): Add comment about context_cc_tests.
+ 	* diagnostics/diagnostics-selftests.h: Add context_cc_tests decl.
+ 	* diagnostics/sarif-sink.cc: Update for file rename.
+ 	* diagnostics/source-printing.cc: Update for num_digits moving to
+ 	diagnostics::num_digits.
+ 	* errors.cc: Update for file rename.
+ 	* input.cc: Update for num_digits moving to
+ 	diagnostics::num_digits.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Replace diagnostic.o with
+ 	diagnostics/context.o.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in: Replace diagnostic.def with diagnostics/kinds.def.
+ 	* config/aarch64/aarch64.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* config/i386/i386-options.cc: Likewise.
+ 	* config/s390/s390.cc: Likewise.
+ 	* diagnostic-core.h: Replace typedef diagnostic_t with
+ 	enum class diagnostics::kind in diagnostics/kinds.h and include
+ 	it.
+ 	* diagnostic-global-context.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* diagnostic.cc: Likewise.
+ 	* diagnostic.h: Likewise.
+ 	* diagnostics/buffering.cc: Likewise.
+ 	* diagnostics/buffering.h: Likewise.
+ 	* diagnostics/context.h: Likewise.
+ 	* diagnostics/diagnostic-info.h: Likewise.
+ 	* diagnostics/html-sink.cc: Likewise.
+ 	* diagnostic.def: Move to...
+ 	* diagnostics/kinds.def: ...here and update for diagnostic_t
+ 	becoming enum class diagnostics::kind.
+ 	* diagnostics/kinds.h: New file, based on material in
+ 	diagnostic-core.h.
+ 	* diagnostics/lazy-paths.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* diagnostics/option-classifier.cc: Likewise.
+ 	* diagnostics/option-classifier.h: Likewise.
+ 	* diagnostics/output-spec.h: Likewise.
+ 	* diagnostics/paths-output.cc: Likewise.
+ 	* diagnostics/sarif-sink.cc: Likewise.
+ 	* diagnostics/selftest-context.cc: Likewise.
+ 	* diagnostics/selftest-context.h: Likewise.
+ 	* diagnostics/sink.h: Likewise.
+ 	* diagnostics/source-printing.cc: Likewise.
+ 	* diagnostics/text-sink.cc: Likewise.
+ 	* diagnostics/text-sink.h: Likewise.
+ 	* gcc.cc: Likewise.
+ 	* libgdiagnostics.cc: Likewise.
+ 	* lto-wrapper.cc: Likewise.
+ 	* opts-common.cc: Likewise.
+ 	* opts-diagnostic.h: Likewise.
+ 	* opts.cc: Likewise.
+ 	* rtl-error.cc: Likewise.
+ 	* substring-locations.cc: Likewise.
+ 	* toplev.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic-core.h: Include "diagnostics/option-id.h".
+ 	(struct diagnostic_option_id): Move there, renaming to
+ 	diagnostics::option_id.
+ 	* diagnostic-global-context.cc: Update for renaming of
+ 	diagnostic_option_id to diagnostics::option_id.
+ 	* diagnostic.cc: Likewise.
+ 	* diagnostic.h: Likewise.
+ 	* diagnostics/context.h: Likewise.
+ 	* diagnostics/diagnostic-info.h: Likewise.
+ 	* diagnostics/lazy-paths.cc: Likewise.
+ 	* diagnostics/option-classifier.cc: Likewise.
+ 	* diagnostics/option-classifier.h: Likewise.
+ 	* diagnostics/option-id.h: New file, taken from material in
+ 	diagnostic-core.h.
+ 	* diagnostics/selftest-context.cc: Update for renaming of
+ 	diagnostic_option_id to diagnostics::option_id.
+ 	* diagnostics/selftest-context.h: Likewise.
+ 	* ipa-pure-const.cc: Likewise.
+ 	* lto-wrapper.cc: Likewise.
+ 	* opts-common.cc: Likewise.
+ 	* opts-diagnostic.h: Likewise.
+ 	* opts.cc: Likewise.
+ 	* substring-locations.cc: Likewise.
+ 	* substring-locations.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Replace diagnostic-spec.o with
+ 	gcc-diagnostic-spec.o.
+ 	(GTFILES): Replace diagnostic-spec.h with gcc-diagnostic-spec.h.
+ 	* diagnostic-spec.cc: Move to...
+ 	* gcc-diagnostic-spec.cc: ...here.
+ 	* diagnostic-spec.h: Move to...
+ 	* gcc-diagnostic-spec.h: ...here.
+ 	* gengtype.cc (open_base_files): Replace diagnostic-spec.h with
+ 	gcc-diagnostic-spec.h.
+ 	* warning-control.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Replace diagnostics/changes.o with
+ 	diagnostics/edit-context.o.
+ 	* diagnostic.cc: Update for move of diagnostics/edit-context.h to
+ 	diagnostics/changes.h.
+ 	(diagnostics::context::initialize): Update for renaming of
+ 	m_edit_context_ptr to m_fixits_change_set.
+ 	(diagnostics::context::finish): Likewise.
+ 	(diagnostics::context::create_edit_context): Rename to...
+ 	(diagnostics::context::initialize_fixits_change_set): ...this and
+ 	update for other renamings.
+ 	(diagnostics::context::report_diagnostic): Update for renaming of
+ 	m_edit_context_ptr to m_fixits_change_set.
+ 	* diagnostic.h (diagnostics::edit_context): Drop forward decl
+ 	* diagnostics/edit-context.cc: Move to...
+ 	* diagnostics/changes.cc: ...here.  Update for move of
+ 	diagnostics/edit-context.h to diagnostics/changes.h.
+ 	Rename diagnostics::edit_context to
+ 	diagnostics::changes::change_set.  Rename diagnostics::edited_file
+ 	to diagnostics::changes::changed_file.  Rename
+ 	diagnostics::edited_line to diagnostics::changes::changed_line.
+ 	* diagnostics/edit-context.h: Move to...
+ 	* diagnostics/changes.h: ...here, renaming as above.
+ 	* diagnostics/context.h (diagnostics::changes::change_set): New
+ 	forward decl.
+ 	(diagnostics::context::create_edit_context): Rename to...
+ 	(diagnostics::context::initialize_fixits_change_set): ...this.
+ 	(diagnostics::context::get_edit_context): Rename to...
+ 	(diagnostics::context::get_fixits_change_set): ...this.
+ 	(diagnostics::context::m_edit_context_ptr): Rename to...
+ 	(diagnostics::context::m_fixits_change_set): ..this and update
+ 	type.
+ 	* diagnostics/diagnostics-selftests.cc: Update for renaming.
+ 	* diagnostics/diagnostics-selftests.h: Likewise.
+ 	* diagnostics/html-sink.cc: Update for above changes.
+ 	* libgdiagnostics.cc: Likewise.
+ 	* toplev.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS): Move diagnostics/lazy-paths.o to...
+ 	(OBJS-libcommon): ...here.  Add
+ 	diagnostics/diagnostics-selftests.o.
+ 	* diagnostic.cc: Update for move of
+ 	selftest::test_diagnostic_context to
+ 	diagnostics::selftest::test_context.
+ 	* diagnostics/color.cc: Move selftests from selftest:: to
+ 	diagnostics::selftest::.
+ 	* diagnostics/diagnostics-selftests.cc: New file.
+ 	* diagnostics/diagnostics-selftests.h: New file.
+ 	* diagnostics/digraphs.cc: Move selftests from selftest:: to
+ 	diagnostics::selftest::.
+ 	* diagnostics/edit-context.cc: Likewise.
+ 	* diagnostics/html-sink.cc: Likewise.
+ 	* diagnostics/lazy-paths.cc: Likewise.  Eliminate use of "tree"
+ 	by porting selftests from simple-diagnostic-path.h to
+ 	diagnostics/selftest-paths.h.
+ 	* diagnostics/output-spec.cc: Move selftests from selftest:: to
+ 	diagnostics::selftest::.
+ 	* diagnostics/paths-output.cc: Likewise.
+ 	* diagnostics/sarif-sink.cc: Likewise.
+ 	* diagnostics/selftest-context.cc: Move
+ 	selftest::test_diagnostic_context to
+ 	diagnostics::selftest::test_context.
+ 	* diagnostics/selftest-context.h: Likewise.
+ 	* diagnostics/selftest-logical-locations.cc: Move selftests from
+ 	selftest:: to diagnostics::logical_locations::selftest::.
+ 	* diagnostics/selftest-logical-locations.h: Move
+ 	selftest::logical_location_manager to
+ 	diagnostics::logical_locations::selftest::logical_location_manager.
+ 	* diagnostics/selftest-paths.cc: Move
+ 	selftest::test_diagnostic_path to
+ 	diagnostics::paths::selftest::test_path.  Move
+ 	selftest::test_diagnostic_event to
+ 	diagnostics::paths::selftest::test_event.
+ 	* diagnostics/selftest-paths.h: Likewise, and move
+ 	selftest::test_diagnostic_thread to
+ 	diagnostics::paths::selftest::test_thread.
+ 	* diagnostics/selftest-source-printing.h: Move
+ 	selftest::diagnostic_show_locus_fixture to
+ 	diagnostics::selftest::source_printing_fixture.
+ 	* diagnostics/source-printing.cc: Move selftests from selftest::
+ 	to diagnostics::selftest:: and update for renames.
+ 	* diagnostics/state-graphs.cc: Likewise.
+ 	* selftest-run-tests.cc: Include
+ 	"diagnostics/diagnostics-selftests.h".
+ 	(selftest::run_tests): Replace invocation of the various diagnostics
+ 	selftests with a call to
+ 	diagnostics::selftest::run_diagnostics_selftests.
+ 	* selftest.h: Move decls of the various per-file diagnostics
+ 	invocation functions to diagnostics/diagnostics-selftests.h,
+ 	renaming due to diagostics prefix being implied by namespace.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* common.opt: Update for move of diagnostic-url.h to
+ 	diagnostics/url.h.
+ 	* diagnostic.cc: Likewise.
+ 	* diagnostics/color.cc: Likewise.
+ 	* diagnostics/text-sink.cc: Likewise.
+ 	* diagnostic-url.h: Move to...
+ 	* diagnostics/url.h: ...here.
+ 	* libgdiagnostics.cc: Update for move of diagnostic-url.h to
+ 	diagnostics/url.h.
+ 	* pretty-print.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Replace diagnostic-color.o with
+ 	diagnostics/color.o.
+ 	(PLUGIN_HEADERS): Remove diagnostic-color.h in favor of glob.
+ 	* common.opt: Update for move of diagnostic-color.h to
+ 	diagnostics/color.h.
+ 	* diagnostic.cc: Likewise.
+ 	* diagnostic-color.cc: Move to...
+ 	* diagnostics/color.cc: ...here.
+ 	* diagnostic-color.h: Move to...
+ 	* diagnostics/color.h: ...here.
+ 	* diagnostics/edit-context.cc: Update for move of
+ 	diagnostic-color.h to diagnostics/color.h.
+ 	* diagnostics/output-spec.cc: Likewise.
+ 	* diagnostics/paths-output.cc: Likewise.
+ 	* diagnostics/source-printing.cc: Likewise.
+ 	* diagnostics/text-sink.cc: Likewise.
+ 	* libgdiagnostics.cc: Likewise.
+ 	* opts.cc: Likewise.
+ 	* pretty-print-markup.h: Likewise.
+ 	* pretty-print.cc: Likewise.
+ 	* selftest-run-tests.cc: Likewise.
+ 	* selftest.h: Likewise.
+ 	* text-art/style.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Replace selftest-diagnostic.o with
+ 	diagnostics/selftest-context.o.
+ 	* diagnostic.cc: Update for move of selftest-diagnostic.h to
+ 	diagnostics/selftest-context.h.
+ 	* diagnostics/html-sink.cc: Likewise.
+ 	* diagnostics/lazy-paths.cc: Likewise.
+ 	* diagnostics/output-spec.cc: Likewise.
+ 	* diagnostics/paths-output.cc: Likewise.
+ 	* diagnostics/sarif-sink.cc: Likewise.
+ 	* selftest-diagnostic.cc: Move to...
+ 	* diagnostics/selftest-context.cc: ...here and update for move of
+ 	header file.
+ 	* selftest-diagnostic.h: Move to...
+ 	* diagnostics/selftest-context.h: ...here.
+ 	* diagnostics/source-printing.cc: Update for move of
+ 	selftest-diagnostic.h to diagnostics/selftest-context.h.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Add diagnostics/buffering.o.
+ 	* diagnostic.cc (diagnostics::context::set_diagnostic_buffer): Move to
+ 	diagnostics/buffering.cc.
+ 	(diagnostics::context::clear_diagnostic_buffer): Likewise.
+ 	(diagnostics::context::flush_diagnostic_buffer): Likewise.
+ 	(diagnostics::buffer::buffer): Likewise.
+ 	(diagnostics::buffer::~buffer): Likewise.
+ 	(diagnostics::buffer::dump): Likewise.
+ 	(diagnostics::buffer::empty_p): Likewise.
+ 	(diagnostics::buffer::move_to): Likewise.
+ 	(diagnostics::buffer::ensure_per_sink_buffers): Likewise.
+ 	* diagnostics/buffering.cc: New file, from material in diagnostic.cc.
+ 	* diagnostics/buffering.h: Fix comment.
+ 	* diagnostics/text-sink.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Add
+ 	diagnostics/option-classifier.o.
+ 	* diagnostic.cc (diagnostics::option_classifier::init): Move to
+ 	diagnostics/option-classifier.cc.
+ 	(diagnostics::option_classifier::fini): Likewise.
+ 	(diagnostics::option_classifier::pch_save): Likewise.
+ 	(diagnostics::option_classifier::pch_restore): Likewise.
+ 	(diagnostics::option_classifier::push): Likewise.
+ 	(diagnostics::option_classifier::pop): Likewise.
+ 	(diagnostics::option_classifier::classify_diagnostic): Likewise.
+ 	(diagnostics::option_classifier::update_effective_level_from_pragmas):
+ 	Likewise.
+ 	* diagnostics/context.h: Include
+ 	"diagnostics/option-classifier.h".
+ 	(class option_classifier): Move to
+ 	diagnostics/option-classifier.h.
+ 	* diagnostics/option-classifier.cc: New file, based on material
+ 	from diagnostic.cc.
+ 	* diagnostics/option-classifier.h: New file, based on material
+ 	from diagnostics/context.h.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* coretypes.h: Update for diagnostic_context becoming
+ 	diagnostics::context.
+ 	* diagnostic-global-context.cc: Likewise.
+ 	* diagnostic.cc: Likewise.  Also for diagnostic_option_classifier
+ 	becoming diagnostics::option_classifier.
+ 	* diagnostic.h (diagnostic_text_starter_fn): Rename to...
+ 	(diagnostics::text_starter_fn): ...this, and move to
+ 	diagnostics/context.h.
+ 	(get_printer): Rename to...
+ 	(diagnostics::get_printer): ...this, and move to
+ 	diagnostics/context.h.
+ 	(class diagnostic_option_manager): Rename to...
+ 	(class diagnostics::option_manager): ...this, and move to
+ 	diagnostics/context.h.
+ 	(class diagnostic_option_classifier): Rename to...
+ 	(class diagnostics::option_classifier): ...this, and move to
+ 	diagnostics/context.h.
+ 	(struct diagnostic_source_printing_options): Rename to...
+ 	(struct diagnostics::source_printing_options): ...this, and move
+ 	to diagnostics/context.h.
+ 	(class diagnostic_column_policy): Rename to...
+ 	(class diagnostics::column_policy): ...this, and move to
+ 	diagnostics/context.h.
+ 	(class diagnostic_location_print_policy): Rename to...
+ 	(class diagnostics::location_print_policy): ...this, and move to
+ 	diagnostics/context.h.
+ 	(class html_label_writer): Rename to...
+ 	(class diagnostics::html_label_writer): ...this, and move to
+ 	diagnostics/context.h.
+ 	(class diagnostic_source_print_policy): Rename to...
+ 	(class diagnostics::source_print_policy): ...this, and move to
+ 	diagnostics/context.h.
+ 	(struct diagnostic_counters): Rename to...
+ 	(struct diagnostics::counters): ...this, and move to
+ 	diagnostics/context.h.
+ 	(class diagnostic_context): Rename to...
+ 	(class diagnostics::context): ...this, and move to
+ 	diagnostics/context.h.
+ 	(diagnostic_text_starter): Rename to...
+ 	(diagnostics::text_starter): ...this, and move to
+ 	diagnostics/context.h.
+ 	(diagnostic_start_span): Rename to...
+ 	(diagnostics::start_span): ...this, and move to
+ 	diagnostics/context.h.
+ 	(diagnostic_text_finalizer): Rename to...
+ 	(diagnostics::text_finalizer): ...this, and move to
+ 	diagnostics/context.h.
+ 	Include "diagnostics/context.h".
+ 	* diagnostics/buffering.h: Update for diagnostic_context becoming
+ 	diagnostics::context; similarly for diagnostic_counters.
+ 	* diagnostics/client-data-hooks.h: Likewise.
+ 	* diagnostics/context.h: New file, taken from material in
+ 	diagnostic.h.
+ 	* diagnostics/html-sink.cc: : Update for diagnostic_context
+ 	becoming diagnostics::context.
+ 	* diagnostics/html-sink.h: Likewise.
+ 	* diagnostics/lazy-paths.cc: Likewise for
+ 	diagnostic_option_manager.
+ 	* diagnostics/output-file.h: Likewise for diagnostic_context.
+ 	* diagnostics/output-spec.cc: Likewise.
+ 	* diagnostics/output-spec.h: Likewise.
+ 	* diagnostics/paths-output.cc: Likewise.
+ 	* diagnostics/sarif-sink.cc: Likewise.
+ 	* diagnostics/sarif-sink.h: Likewise.
+ 	* diagnostics/sink.h: Likewise.
+ 	* diagnostics/source-printing.cc: Likewise.
+ 	* diagnostics/text-sink.cc: Likewise.
+ 	* diagnostics/text-sink.h: Likewise.
+ 	* gcc-rich-location.h: Likewise.
+ 	* gcc.cc: Likewise.
+ 	* gdbinit.in: Likewise.
+ 	* langhooks-def.h: Likewise.
+ 	* langhooks.cc: Likewise.
+ 	* langhooks.h: Likewise.
+ 	* libgdiagnostics.cc: Likewise.
+ 	* optc-gen.awk: Likewise.
+ 	* opth-gen.awk: Likewise.
+ 	* opts-common.cc: Likewise.
+ 	* opts-diagnostic.cc: Likewise.
+ 	* opts-diagnostic.h: Likewise.
+ 	* opts-global.cc: Likewise.
+ 	* opts.cc: Likewise.
+ 	* opts.h: Likewise.
+ 	* selftest-diagnostic.cc: Likewise.
+ 	* selftest-diagnostic.h: Likewise.
+ 	* toplev.cc: Likewise.
+ 	* tree-diagnostic-client-data-hooks.cc: Likewise.
+ 	* tree-diagnostic.cc: Likewise.
+ 	* tree-diagnostic.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic.h (struct diagnostic_info): Move to
+ 	diagnostics/diagnostic-info.h as diagnostics::diagnostic_info.
+ 	Add typedef bringing it back into root namespace, for now.
+ 	* diagnostics/diagnostic-info.h: New file, based on the above.
+ 	* langhooks-def.h: Update for diagnostic_info moving into
+ 	namespace diagnostics.
+ 	* langhooks.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic.cc: Update to add "m_" prefix to fields of
+ 	diagnostic_info throughout.
+ 	* diagnostic.h: Likewise.
+ 	* diagnostics/html-sink.cc: Likewise.
+ 	* diagnostics/sarif-sink.cc: Likewise.
+ 	* diagnostics/text-sink.cc: Likewise.
+ 	* libgdiagnostics.cc: Likewise.
+ 	* substring-locations.cc: Likewise.
+ 	* tree-diagnostic.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS): Replace diagnostic-macro-unwinding.o with
+ 	diagnostics/macro-unwinding.o.
+ 	* diagnostic-macro-unwinding.cc: Move to...
+ 	* diagnostics/macro-unwinding.cc: ...here, moving content into
+ 	namespace diagnostics.
+ 	* diagnostic-macro-unwinding.h: Move to...
+ 	* diagnostics/macro-unwinding.h: ...here, moving content into
+ 	namespace diagnostics.
+ 	* diagnostics/paths-output.cc: Update for move of
+ 	"diagnostic-macro-unwinding.h" to "diagnostics/macro-unwinding.h".
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS): Replace diagnostic-show-locus.o with
+ 	diagnostics/source-printing.o.
+ 	* diagnostic.h (class diagnostic_source_effect_info): Replace
+ 	with...
+ 	(class diagnotics::source_effect_info): ...this.
+ 	* diagnostics/paths-output.cc: Likewise.  Update for move of
+ 	"diagnostic-label-effects.h" to
+ 	"diagnostics/source-printing-effects.h".
+ 	* diagnostics/sarif-sink.cc: Update for move of
+ 	"selftest-diagnostic-show-locus.h" to
+ 	"diagnostics/selftest-source-printing.h".
+ 	* selftest-diagnostic-show-locus.h: Move to...
+ 	* diagnostics/selftest-source-printing.h: ...here.
+ 	* diagnostic-label-effects.h: Move to...
+ 	* diagnostics/source-printing-effects.h: ...here, updating
+ 	for above changes.
+ 	* diagnostic-show-locus.cc: Move to...
+ 	* diagnostics/source-printing.cc: ...here.
+ 	* gcc-rich-location.h: Likewise.
+ 	* selftest-run-tests.cc: Likewise.
+ 	* selftest.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS): Replace diagnostic-format-html.o with
+ 	diagnostics/html-sink.o, diagnostic-format-sarif.o with
+ 	diagnostics/sarif-sink.o, and diagnostic-format-text.o with
+ 	diagnostics/text-sink.o.
+ 	* coretypes.h (class diagnostic_text_output_format): Replace
+ 	with...
+ 	(class diagnostics::text_sink): ...this.
+ 	* diagnostic-global-context.cc: Update for move of diagnostics
+ 	output formats into namespace "diagnostics", as "sinks".
+ 	* diagnostic-macro-unwinding.cc: Likewise.
+ 	* diagnostic-macro-unwinding.h: Likewise.
+ 	* diagnostic-show-locus.cc: Likewise.
+ 	* diagnostic.cc: Likewise.
+ 	* diagnostic.h: Likewise.
+ 	* diagnostic-buffer.h: Rename to...
+ 	* diagnostics/buffering.h: ...this, updating for above changes.
+ 	* diagnostics/client-data-hooks.h: Likewise.
+ 	* diagnostics/digraphs.cc: Likewise.
+ 	* diagnostic-format-html.cc: Rename to...
+ 	* diagnostics/html-sink.cc: ...this, updating for above changes.
+ 	* diagnostic-format-html.h: Rename to...
+ 	* diagnostics/html-sink.h: ...this, updating for above changes.
+ 	* diagnostics/lazy-paths.cc: Likewise.
+ 	* diagnostics/metadata.h: Likewise.
+ 	* diagnostics/output-spec.cc: Likewise.
+ 	* diagnostics/output-spec.h: Likewise.
+ 	* diagnostics/paths-output.cc: Likewise.
+ 	* diagnostics/paths.h: Likewise.
+ 	* diagnostic-format-sarif.cc: Rename to...
+ 	* diagnostics/sarif-sink.cc: ...this, updating for above changes.
+ 	* diagnostic-format-sarif.h: Rename to...
+ 	* diagnostics/sarif-sink.h: ...this, updating for above changes.
+ 	* diagnostic-format.h: Rename to...
+ 	* diagnostics/sink.h: ...this, updating for above changes.
+ 	* diagnostics/state-graphs-to-dot.cc: Likewise.
+ 	* diagnostic-format-text.cc: Rename to...
+ 	* diagnostics/text-sink.cc: ...this, updating for above changes.
+ 	* diagnostic-format-text.h: Rename to...
+ 	* diagnostics/text-sink.h: ...this, updating for above changes.
+ 	* gcc.cc: Likewise.
+ 	* langhooks-def.h: Likewise.
+ 	* langhooks.cc: Likewise.
+ 	* langhooks.h: Likewise.
+ 	* libgdiagnostics.cc: Likewise.
+ 	* opts-diagnostic.cc: Likewise.
+ 	* opts.cc: Likewise.
+ 	* selftest-diagnostic.cc: Likewise.
+ 	* selftest-run-tests.cc: Likewise.
+ 	* selftest.h: Likewise.
+ 	* tree-diagnostic-client-data-hooks.cc: Likewise.
+ 	* tree-diagnostic.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS): Replace lazy-diagnostic-path.o with
+ 	diagnostics/lazy-paths.o.
+ 	(OBJS-libcommon): Replace diagnostic-path.o with
+ 	diagnostics/paths.o, diagnostic-path-output.o with
+ 	diagnostics/paths-output.o, and selftest-diagnostic-path.o with
+ 	diagnostics/selftest-paths.o.
+ 	(EXTRA_BACKEND_OBJS): Replace lazy-diagnostic-path.o with
+ 	diagnostics/lazy-paths.o.
+ 	* diagnostic-format-html.cc: Update #include for
+ 	"diagnostic-path.h" moving to "diagnostics/paths.h",
+ 	diagnostic_thread_id_t to diagnostics::paths::thread_id_t,
+ 	diagnostic_event_id_t to diagnostics::paths::event_id_t,
+ 	diagnostic_path to diagnostics::paths::path, and
+ 	diagnostic_thread to diagnostics::paths::thread, and
+ 	diagnostic_event to diagnostics::paths::event.
+ 	* diagnostic-format-html.h: Likewise.
+ 	* diagnostic-format-sarif.cc: Likewise.  Update PROPERTY_PREFIX
+ 	for threadFlowLocations from "gcc/diagnostic_event/" to
+ 	"gcc/diagnostics/paths/event/".
+ 	* diagnostic-format-text.cc: Likewise.
+ 	* diagnostic-format-text.h: Likewise.
+ 	* diagnostic.cc: Likewise.
+ 	* diagnostic.h: Likewise.
+ 	* diagnostic-event-id.h: Move to...
+ 	* diagnostics/event-id.h: ...here, updating header guard.
+ 	(diagnostics:paths:event_id_t): New typedef.
+ 	(diagnostic_thread_id_t): Replace with...
+ 	(diagnostics:paths:thread_id_t): New typedef.
+ 	* lazy-diagnostic-path.cc: Move to...
+ 	* diagnostics/lazy-paths.cc: ...here.  Update for above changes,
+ 	lazy_diagnostic_path becomes diagnostics::paths::lazy_path.
+ 	(lazy_diagnostic_path_cc_tests): Rename to...
+ 	(diagnostics_lazy_paths_cc_tests): ...this.
+ 	* lazy-diagnostic-path.h: Move to...
+ 	* diagnostics/lazy-paths.h: ...here, updating header guard.
+ 	Update for above changes.
+ 	* diagnostic-path-output.cc: Move to...
+ 	* diagnostics/paths-output.cc: ...here.  Update for above changes.
+ 	(diagnostic_path_output_cc_tests): Rename to...
+ 	(diagnostics_paths_output_cc_tests): ...this.
+ 	* diagnostic-path.cc: Move to...
+ 	* diagnostics/paths.cc: ...here.  Update for above changes.
+ 	* diagnostic-path.h: Move to...
+ 	* diagnostics/paths.h: ...here, updating header guard.
+ 	Update #include for moving "diagnostic-event-id.h" to
+ 	"diagnostics/event-id.h".
+ 	(class diagnostic_event): Convert to...
+ 	(class diagnostics::paths::event): ...this.
+ 	(class diagnostic_thread): Convert to...
+ 	(class diagnostics::paths::thread): ...this.
+ 	(class diagnostic_path): Convert to...
+ 	(class diagnostics::paths::path): ...this.
+ 	* diagnostic-show-locus.cc: Update for above changes.
+ 	* doc/analyzer.texi: Likewise.
+ 	* selftest-diagnostic-path.cc: Move to...
+ 	* diagnostics/selftest-paths.cc: ...here.  Update for
+ 	above changes, and for "selftest-diagnostic-path.h" moving to
+ 	"diagnostics/selftest-paths.h".
+ 	* selftest-diagnostic-path.h: Move to...
+ 	* diagnostics/selftest-paths.h: ...here, updating header guard.
+ 	Update for above changes.
+ 	* libgdiagnostics.cc: Update for above changes.
+ 	* libsarifreplay.cc: Update property prefix for
+ 	threadFlowLocations from "gcc/diagnostic_event/" to
+ 	"gcc/diagnostics/paths/event/".
+ 	* pretty-print-format-impl.h: Update for above changes.
+ 	* pretty-print.cc: Likewise.
+ 	* selftest-run-tests.cc (selftest::run_tests): Update for
+ 	renaming of lazy_diagnostic_path_cc_tests to
+ 	diagnostics_lazy_paths_cc_tests, and of
+ 	diagnostic_path_output_cc_tests to
+ 	diagnostics_paths_output_cc_tests.
+ 	* selftest.h (lazy_diagnostic_path_cc_tests): Replace decl with...
+ 	(diagnostics_lazy_paths_cc_tests): ...this.
+ 	(diagnostic_path_output_cc_tests): Replace decl with...
+ 	(diagnostics_paths_output_cc_tests): ...this.
+ 	* simple-diagnostic-path.cc: Clarify that this relates to "tree"
+ 	and thus shouldn't be in "diagnostics".  Update for above changes.
+ 	* simple-diagnostic-path.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Replace diagnostic-output-spec.o
+ 	with diagnostics/output-spec.o.
+ 	* diagnostic-output-spec.cc: Move to...
+ 	* diagnostics/output-spec.cc: ...here.  Update #include for
+ 	move of diagnostic-output-spec.h to diagnostics/output-spec.h.
+ 	(namespace::diagnostics_output_spec): Replace with...
+ 	(namespace diagnostics::output_spec): ...this, removing redundant
+ 	prefixes.
+ 	(diagnostics_output_spec::gcc_spec_context): Replace with...
+ 	(diagnostics::output_spec::dc_spec_context): ...this.
+ 	(diagnostic_output_spec_cc_tests): Rename to...
+ 	(diagnostics_output_spec_cc_tests): ...this.
+ 	* diagnostic-output-spec.h: Move to...
+ 	* diagnostics/output-spec.h: ...here and update inclusion guard.
+ 	(namespace::diagnostics_output_spec): Replace with...
+ 	(namespace diagnostics::output_spec): ...this, removing redundant
+ 	prefixes.
+ 	(diagnostics_output_spec::gcc_spec_context): Replace with...
+ 	(diagnostics::output_spec::dc_spec_context): ...this.
+ 	* libgdiagnostics.cc: Update #include for move of
+ 	diagnostic-output-spec.h to diagnostics/output-spec.h.
+ 	* opts-diagnostic.cc: Likewise.  Update for namespace and name
+ 	changes.
+ 	* selftest-run-tests.cc (selftest::run_tests): Update for renaming
+ 	of diagnostic_output_spec_cc_tests to
+ 	diagnostics_output_spec_cc_tests.
+ 	* selftest.h (diagnostic_output_spec_cc_tests): Rename decl to...
+ 	(diagnostics_output_spec_cc_tests): ...this.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic-format-html.cc: Update #include for move of
+ 	diagnostic-output-file.h to diagnostics/output-file.h.  Update for
+ 	move of diagnostic_output_file to diagnostics::output_file.
+ 	* diagnostic-format-html.h: Likewise.
+ 	* diagnostic-format-sarif.cc: Likewise.
+ 	* diagnostic-format-sarif.h: Likewise.
+ 	* diagnostic-output-spec.cc: Likewise.
+ 	* diagnostic-output-spec.h (along): Likewise.
+ 	* diagnostic-output-file.h: Move to...
+ 	* diagnostics/output-file.h: ...here, updating header guard.
+ 	(class diagnostic_output_file): Move to...
+ 	(class diagnostics::output_file): ...here.
+ 	* libgdiagnostics.cc (sarif_sink::sarif_sink): Update for
+ 	move of diagnostic_output_file to diagnostics::output_file.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic-format-html.cc: Update #include for move of
+ 	diagnostic-client-data-hooks.h to diagnostics/client-data-hooks.h.
+ 	* diagnostic-format-sarif.cc: Likewise.  Update for move of
+ 	diagnostic_client_plugin_info to diagnostics::client_plugin_info.
+ 	* diagnostic-format-text.cc: Likewise.
+ 	* diagnostic.cc: Likewise.
+ 	* diagnostic.h: Likewise.
+ 	* diagnostic-client-data-hooks.h: Move to...
+ 	* diagnostics/client-data-hooks.h: ...here, updating header guard.
+ 	(class diagnostic_client_data_hooks): Move to...
+ 	(class diagnostics::client_data_hooks): ...here.  Remove redundant
+ 	"diagnostics::" prefixes.
+ 	(class diagnostic_client_plugin_info): Move to...
+ 	(class diagnostics::client_plugin_info): ...here.
+ 	* libgdiagnostics.cc: : Update #include for move of
+ 	diagnostic-client-data-hooks.h to diagnostics/client-data-hooks.h.
+ 	Update for move of diagnostic_client_data_hooks to
+ 	diagnostics::client_data_hooks, and for move of
+ 	diagnostic_client_version_info to diagnostics::client_version_info.
+ 	* tree-diagnostic-client-data-hooks.cc: Likewise.
+ 	* tree-diagnostic.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Replace edit-context.o with
+ 	diagnostics/edit-context.o.
+ 	* diagnostic-format-html.cc: Update #include for move
+ 	of edit-context.h to diagnostics subdir.
+ 	* diagnostic.cc: Likewise.  Update for move of edit_context to
+ 	diagnostics::edit_context.
+ 	* diagnostic.h: Likewise.
+ 	* edit-context.cc: Move to...
+ 	* diagnostics/edit-context.cc: ...here.  Update #include for move
+ 	of edit-context.h to diagnostics subdir.  Move all code
+ 	within namespace diagnostics.
+ 	* edit-context.h: Move to...
+ 	* diagnostics/edit-context.h: ...here, updating header guard.
+ 	Move all code within namespace diagnostics.
+ 	* libgdiagnostics.cc: Update #include for move of edit-context.h
+ 	to diagnostics subdir.  Update for move of edit_context
+ 	to diagnostics::edit_context.
+ 	* toplev.cc: Update #include for move of edit-context.h
+ 	to diagnostics subdir.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic-format-html.cc: Update for move of diagnostic_diagram
+ 	to diagnostics::diagram.
+ 	* diagnostic-format-sarif.cc: Update #include for move of
+ 	"diagnostic-diagram.h" to "diagnostics/diagram.h". Update for move
+ 	of diagnostic_diagram to diagnostics::diagram.
+ 	* diagnostic-format-text.cc: Likewise.
+ 	* diagnostic-format-text.h: Update for move of diagnostic_diagram
+ 	to diagnostics::diagram.
+ 	* diagnostic-format.h: Likewise.
+ 	* diagnostic.cc: Update #include for move of
+ 	"diagnostic-diagram.h" to "diagnostics/diagram.h". Update for move
+ 	of diagnostic_diagram to diagnostics::diagram.
+ 	* diagnostic.h: Update for move of diagnostic_diagram to
+ 	diagnostics::diagram.
+ 	* diagnostic-diagram.h: Move to...
+ 	* diagnostics/diagram.h: ...here.
+ 	(class diagnostic_diagram): Convert to...
+ 	(class diagnostics::diagram): ...this.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic-core.h: Update for move of diagnostic_metadata to
+ 	diagnostics::metadata.
+ 	* diagnostic-format-html.cc: Likewise; also, update #include for
+ 	move of "diagnostic-metadata.h" to "diagnostics/metadata.h".
+ 	* diagnostic-format-sarif.cc: Likewise.
+ 	* diagnostic-format-text.cc: Likewise.
+ 	* diagnostic-global-context.cc: Likewise.
+ 	* diagnostic.cc: Likewise.
+ 	* diagnostic.h: Likewise.
+ 	* diagnostic-metadata.h: Move to...
+ 	* diagnostics/metadata.h: ...here, updating header guard.
+ 	(class diagnostic_metadata): Move to...
+ 	(class diagnostics::metadata): ...here.  Drop redundant
+ 	"diagnostics::" qualifiers.
+ 	* libgdiagnostics.cc: : Update #include for move of
+ 	"diagnostic-metadata.h" to "diagnostics/metadata.h", and update
+ 	for move of diagnostic_metadata to diagnostics::metadata.
+ 	* selftest-diagnostic.cc: Update for move of diagnostic_metadata
+ 	to diagnostics::metadata.
+ 	* selftest-diagnostic.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Replace
+ 	selftest-logical-location.o with
+ 	diagnostics/selftest-logical-locations.o.
+ 	* diagnostic-client-data-hooks.h: Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager, and of logical_location
+ 	to diagnostics::logical_locations::key.
+ 	* diagnostic-format-html.cc: Add "using namespace diagnostics;",
+ 	and drop now-redundant "diagnostics::" prefixes.
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager, of logical_location to
+ 	diagnostics::logical_locations::key, and of
+ 	enum logical_location_kind to
+ 	enum diagnostics::logical_locations::kind.
+ 	* diagnostic-format-sarif.cc: Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".  Add
+ 	"using namespace diagnostics;", and drop now-redundant
+ 	"diagnostics::" prefixes.
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager, of logical_location to
+ 	diagnostics::logical_locations::key, and of
+ 	enum logical_location_kind to
+ 	enum diagnostics::logical_locations::kind.
+ 	* diagnostic-format-sarif.h: Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".
+ 	Update for conversion of logical_location to
+ 	diagnostics::logical_locations::key.
+ 	* diagnostic-path-output.cc: Add "using namespace diagnostics;".
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager, and
+ 	of logical_location to diagnostics::logical_locations::key,
+ 	* diagnostic-path.cc: Add "using namespace diagnostics;".
+ 	Update for conversion of logical_location to
+ 	diagnostics::logical_locations::key.
+ 	* diagnostic-path.h: Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager, and of logical_location
+ 	to diagnostics::logical_locations::key,
+ 	* diagnostic.cc: Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager and of
+ 	enum logical_location_kind to
+ 	enum diagnostics::logical_locations::kind.
+ 	* diagnostic.h: Reorganize forward decls.
+ 	(class logical_location_manager): Replace this forward decl
+ 	with...
+ 	(class diagnostics::logical_locations::manager): ...this.
+ 	(diagnostic_context::get_logical_location_manager): Update
+ 	return type.
+ 	* diagnostics/digraphs.h: : Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".
+ 	Update for conversion of logical_location to
+ 	diagnostics::logical_locations::key.
+ 	* logical-location.h: Move to...
+ 	* diagnostics/logical-locations.h: ...here.
+ 	(enum class logical_location_kind): Convert to...
+ 	(enum class diagnostics::logical_locations::kind): ... this.
+ 	(class logical_location_manager::key): Convert to...
+ 	(class diagnostics::logical_locations::key): ... this.
+ 	(class logical_location_manager): Convert to...
+ 	(class diagnostics::logical_locations::manager): ... this.
+ 	(logical_location): Drop this typedef in favor of
+ 	diagnostics::logical_locations::key.
+ 	* selftest-logical-location.cc: Move to...
+ 	* diagnostics/selftest-logical-locations.cc: ...here.
+ 	Update #include for move of "selftest-logical-location.h" to
+ 	"diagnostics/selftest-logical-locations.h".
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager, of logical_location to
+ 	diagnostics::logical_locations::key, and of
+ 	enum logical_location_kind to
+ 	enum diagnostics::logical_locations::kind.
+ 	(selftest_logical_location_cc_tests): Rename to...
+ 	(diagnostics_selftest_logical_locations_cc_tests): ...this.
+ 	* selftest-logical-location.h: Move to...
+ 	* diagnostics/selftest-logical-locations.h: ...here, updating
+ 	include guard.
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager, of logical_location to
+ 	diagnostics::logical_locations::key, and of
+ 	enum logical_location_kind to
+ 	enum diagnostics::logical_locations::kind.
+ 	* diagnostics/state-graphs-to-dot.cc: Add
+ 	"using namespace diagnostics;" and drop now-redundant
+ 	"diagnostics::" prefixes.
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager.
+ 	* diagnostics/state-graphs.h: Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager,
+ 	of logical_location to diagnostics::logical_locations::key.
+ 	* libgdiagnostics.cc: Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager, and of logical_location
+ 	to diagnostics::logical_locations::key.
+ 	* selftest-diagnostic-path.cc: Update for conversion of
+ 	logical_location to diagnostics::logical_locations::key.
+ 	* selftest-diagnostic-path.h: Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".
+ 	Update for conversion of logical_location to
+ 	diagnostics::logical_locations::key.
+ 	* selftest-run-tests.cc (selftest::run_tests): Update for
+ 	renaming of selftest_logical_location_cc_tests to
+ 	diagnostics_selftest_logical_locations_cc_tests.
+ 	* selftest.h: Likewise.
+ 	* simple-diagnostic-path.h: Update for conversion of
+ 	logical_location to diagnostics::logical_locations::key.
+ 	* tree-diagnostic-client-data-hooks.cc: Update for conversion of
+ 	logical_location_manager to
+ 	diagnostics::logical_locations::manager, and of logical_location
+ 	to diagnostics::logical_locations::key.
+ 	* tree-logical-location.cc: Update for conversions.
+ 	Update for conversion of logical_location to
+ 	diagnostics::logical_locations::key, and of
+ 	enum logical_location_kind to
+ 	enum diagnostics::logical_locations::kind.
+ 	* tree-logical-location.h: Update #include for move of
+ 	"logical-location.h" to "diagnostics/logical-locations.h".
+ 	Update for conversion of logical_location_manager to
+ 	diagnostics::logical_locations::manager, of logical_location
+ 	to diagnostics::logical_locations::key, and of
+ 	enum logical_location_kind to
+ 	enum diagnostics::logical_locations::kind.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* Makefile.in (OBJS-libcommon): Rename diagnostic-digraphs.o to
+ 	diagnostics/digraphs.o.  Rename diagnostic-state-graphs.o to
+ 	diagnostics/state-graphs.o.  Rename diagnostic-state-to-dot.o to
+ 	diagnostics/state-graphs-to-dot.o.
+ 	(PLUGIN_HEADERS): Add $(srcdir)/diagnostics/*.h.
+ 	(install-plugin:): Likewise.
+ 	* configure: Regenerate.
+ 	* configure.ac (gccdepdir): Add "diagnostics" to directories.
+ 	* diagnostic-format-html.cc: Update #includes for move of
+ 	"diagnostic-digraphs.h" to "diagnostics/digraphs.h" and of
+ 	move of "diagnostic-state-graphs.h" to
+ 	"diagnostics/state-graphs.h".
+ 	* diagnostic-format-sarif.cc: Likewise.
+ 	* diagnostic-path.cc: Likewise for state-graphs.h
+ 	* diagnostic-digraphs.cc: Move...
+ 	* diagnostics/digraphs.cc: ...to here.  Update #include
+ 	for renaming of digraphs.h.
+ 	(selftest::diagnostic_digraphs_cc_tests): Rename to...
+ 	(selftest::diagnostics_digraphs_cc_tests): ...this.
+ 	* diagnostic-digraphs.h: Move...
+ 	* diagnostics/digraphs.h: ...to here, updating header guard.
+ 	* diagnostic-state-to-dot.cc: Move...
+ 	* diagnostics/state-graphs-to-dot.cc: ...to here.  Update #include
+ 	of state-graphs.h.
+ 	* diagnostic-state-graphs.cc: Move...
+ 	* diagnostics/state-graphs.cc: ...to here.  Update #include
+ 	of state-graphs.h.
+ 	(selftest::diagnostic_state_graphs_cc_tests): Rename...
+ 	(selftest::diagnostics_state_graphs_cc_tests): ...to this.
+ 	* diagnostic-state-graphs.h: Move...
+ 	* diagnostics/state-graphs.h: ...to here, updating header guard.
+ 	* libgdiagnostics.cc: Update #includes for move of
+ 	"diagnostic-digraphs.h" to "diagnostics/digraphs.h" and of
+ 	move of "diagnostic-state-graphs.h" to
+ 	"diagnostics/state-graphs.h".
+ 	* selftest-run-tests.cc (selftest::run_tests): Update for
+ 	function renamings that reflect file renamings.
+ 	* selftest.h (selftest::diagnostic_digraphs_cc_tests): Rename
+ 	to...
+ 	(selftest::diagnostics_digraphs_cc_tests): ...this.
+ 	(selftest::diagnostic_state_graphs_cc_tests): Rename...
+ 	(selftest::diagnostics_state_graphs_cc_tests): ...to this.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (vect_get_vec_defs): Remove overload
+ 	with operand vector type.  Remove stmt_vec_info and
+ 	ncopies argument.
+ 	* tree-vect-stmts.cc (vect_get_vec_defs): Likewise.
+ 	(vectorizable_conversion): Adjust by not passing in
+ 	vector types, stmt_vec_info and ncopies.
+ 	(vectorizable_bswap): Likewise.
+ 	(vectorizable_assignment): Likewise.
+ 	(vectorizable_shift): Likewise.
+ 	(vectorizable_operation): Likewise.
+ 	(vectorizable_scan_store): Likewise.
+ 	(vectorizable_store): Likewise.
+ 	(vectorizable_condition): Likewise.
+ 	(vectorizable_comparison_1): Likewise.
+ 	* tree-vect-loop.cc (vect_transform_reduction): Likewise.
+ 	(vect_transform_lc_phi): Likewise.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (vect_is_simple_use): Remove stmt-info
+ 	with vectype output overload and remove stmt-info argument
+ 	from SLP based API.
+ 	* tree-vect-loop.cc (vectorizable_lane_reducing): Remove
+ 	unused def_stmt_info output argument to vect_is_simple_use.
+ 	Adjust.
+ 	* tree-vect-stmts.cc (get_group_load_store_type): Get
+ 	the gather/scatter offset vector type from the SLP child.
+ 	(vect_check_scalar_mask): Remove stmt_info argument.  Adjust.
+ 	(vect_check_store_rhs): Likewise.
+ 	(vectorizable_call): Likewise.
+ 	(vectorizable_simd_clone_call): Likewise.
+ 	(vectorizable_conversion): Likewise.
+ 	(vectorizable_assignment): Likewise.
+ 	(vectorizable_shift): Likewise.
+ 	(vectorizable_operation): Likewise.
+ 	(vectorizable_load): Likewise.
+ 	(vect_is_simple_cond): Remove stmt_info argument.  Adjust.
+ 	(vectorizable_condition): Likewise.
+ 	(vectorizable_comparison_1): Likewise.
+ 	(vectorizable_store): Likewise.
+ 	(vect_is_simple_use): Remove overload and non-SLP path.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vect_model_simple_cost): Removed code
+ 	when no SLP node is passed, remove then unused dt and ndts
+ 	parameters and fix the number of vector stmts calculation.
+ 	(vectorizable_call): Adjust.
+ 	(vectorizable_simd_clone_call): Likewise.
+ 	(vectorizable_conversion): Likewise.
+ 	(vectorizable_assignment): Likewise.
+ 	(vectorizable_shift): Likewise.
+ 	(vectorizable_operation): Likewise.
+ 	(vectorizable_condition): Likewise.
+ 	(vectorizable_comparison_1): Likewise.
+ 
+ 2025-07-25  Robin Dapp  <rdapp@ventanamicro.com>
+ 
+ 	* config/riscv/riscv-vector-costs.cc (get_live_range):
+ 	Move compute_local_program_points to cost class.
+ 	(variable_vectorized_p): Add slp node parameter.
+ 	(need_additional_vector_vars_p): Move from here...
+ 	(costs::need_additional_vector_vars_p): ... to here and add slp
+ 	parameter.
+ 	(compute_estimated_lmul): Move update_local_live_ranges to cost
+ 	class.
+ 	(has_unexpected_spills_p): Move from here...
+ 	(costs::has_unexpected_spills_p): ... to here.
+ 	(costs::record_lmul_spills): New function.
+ 	(costs::add_stmt_cost): Add stmt_info, slp mapping.
+ 	(costs::finish_cost): Analyze loop.
+ 	* config/riscv/riscv-vector-costs.h: Move declarations to class.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-loop.cc (vect_analyze_loop_2): Get vectype
+ 	from the SLP node.
+ 	(vectorize_fold_left_reduction): Likewise.
+ 	(vect_transform_reduction): Likewise.
+ 	(vect_transform_cycle_phi): Likewise.
+ 	(vect_transform_lc_phi): Likewise.
+ 	* tree-vect-slp.cc (vect_analyze_slp): Likewise.
+ 	* tree-vect-stmts.cc (vect_truncate_gather_scatter_offset):
+ 	Pass in vectype and use that.
+ 	(vect_use_strided_gather_scatters_p): Likewise.
+ 	(get_group_load_store_type): Adjust.
+ 	(vect_check_scalar_mask): We always have a SLP node.
+ 	Use vectype from the SLP node.
+ 	(vect_check_store_rhs): Likewise.
+ 	(vect_build_one_gather_load_call): Pass in the vector type
+ 	and use that.
+ 	(vect_get_strided_load_store_ops): Likewise.
+ 	(vectorizable_store): Adjust.
+ 	(vectorizable_load): Use the vector type from the SLP node
+ 	and adjust.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* target.h (stmt_vectype): Remove.
+ 	* tree-vect-stmts.cc (stmt_vectype): Likewise.
+ 
+ 2025-07-25  Christoph Müllner  <christoph.muellner@vrull.eu>
+ 
+ 	* config/riscv/riscv.cc (enum riscv_privilege_levels): Remove USER_MODE.
+ 	(riscv_handle_type_attribute): Remove "user" interrupts.
+ 	(riscv_expand_epilogue): Likewise.
+ 	(riscv_get_interrupt_type): Likewise.
+ 	* config/riscv/riscv.md (riscv_uret): Remove URET pattern.
+ 	* doc/extend.texi: Remove documentation of user interrupts.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (_stmt_vec_info::vec_stmts): Remove.
+ 	(STMT_VINFO_VEC_STMTS): Likewise.
+ 	* tree-vectorizer.cc (vec_info::new_stmt_vec_info): Do not
+ 	initialize it.
+ 	(vec_info::free_stmt_vec_info): Nor free it.
+ 	* tree-vect-data-refs.cc (vect_vfa_access_size): Remove
+ 	check on STMT_VINFO_VEC_STMTS.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (vect_transform_grouped_load): Remove.
+ 	(vect_record_grouped_load_vectors): Likewise.
+ 	* tree-vect-data-refs.cc (vect_permute_load_chain): Likewise.
+ 	(vect_shift_permute_load_chain): Likewise.
+ 	(vect_transform_grouped_load): Likewise.
+ 	(vect_record_grouped_load_vectors): Likewise.
+ 	* tree-vect-stmts.cc (vectorizable_load): Remove comments
+ 	about load interleaving.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (vect_permute_store_chain): Remove.
+ 	* tree-vect-data-refs.cc (vect_permute_store_chain): Likewise.
+ 	* tree-vect-stmts.cc (vectorizable_store): Remove comment
+ 	about store interleaving.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (vect_get_vec_defs_for_operand): Remove.
+ 	* tree-vect-stmts.cc (vect_get_vec_defs_for_operand): Likewise.
+ 	(vect_get_vec_defs): Remove non-SLP path.
+ 	(check_load_store_for_partial_vectors): We always have an
+ 	SLP node.
+ 	(vect_check_store_rhs): Likewise.
+ 	(vect_get_gather_scatter_ops): Likewise.
+ 	(vect_create_vectorized_demotion_stmts): Likewise.
+ 	(vectorizable_store): Adjust.
+ 	(vectorizable_load): Likewise.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (VMAT_CONTIGUOUS_PERMUTE): Remove.
+ 	* tree-vect-stmts.cc (check_load_store_for_partial_vectors):
+ 	Remove checks on VMAT_CONTIGUOUS_PERMUTE.
+ 	(vectorizable_load): Likewise.
+ 	(vectorizable_store): Likewise.  Prune dead code.
+ 
+ 2025-07-25  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vectorizable_store): Remove trivially
+ 	dead code.
+ 
+ 2025-07-25  Tobias Burnus  <tburnus@baylibre.com>
+ 
+ 	* config/gcn/gcn-opts.h (TARGET_NO_MANUAL_NOPS,
+ 	TARGET_CDNA3_NOPS): Define.
+ 	* config/gcn/gcn.md (define_attr "laneselect): Change 'yes' to
+ 	'read' and 'write'.
+ 	(define_attr "flatmemaccess"): Add with values store, storex34,
+ 	load, atomic, atomicwait, cmpswapx2, and no. Replacing ...
+ 	(define_attr "delayeduse"): Remove.
+ 	(define_attr "transop"): Add with values yes and no.
+ 	(various insns): Update 'laneselect', add flatmemaccess and transop,
+ 	remove delayeduse; fixing an issue for s_load_dwordx4 vs.
+ 	flat_store_dwordx4 related to delayeduse (now: flatmemaccess).
+ 	* config/gcn/gcn-valu.md: Update laneselect attribute and add
+ 	flatmemaccess.
+ 	* config/gcn/gcn.cc (gcn_cmpx_insn_p): New.
+ 	(gcn_md_reorg): Update for MI300 to add additional s_nop.
+ 	Skip s_nop-insertion part for RDNA{2,3}; add "VALU writes EXEC
+ 	followed by VALU DPP" unconditionally for CDNA2/CDNA3/GCN5.
+ 
+ 2025-07-25  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	PR middle-end/121214
+ 	* genpreds.cc (constraint_max_namelen): Delete.
+ 	(write_tm_preds_h): Always write insn_constraint_len() and
+ 	define CONSTRAINT_LEN to it, i.e., remove guard
+ 	constraint_max_namelen>1.  Remove outer guard
+ 	constraint_max_namelen>0 and re-indent.
+ 	(write_insn_preds_c): Remove guard
+ 	constraint_max_namelen>0 and re-indent.
+ 
+ 2025-07-25  Christoph Müllner  <christoph.muellner@vrull.eu>
+ 
+ 	* config/riscv/riscv.cc (enum riscv_privilege_levels): Add
+ 	RNMI_MODE.
+ 	(riscv_handle_type_attribute): Handle 'rnmi' interrupt attribute.
+ 	(riscv_expand_epilogue): Generate nmret for RNMI handlers.
+ 	(riscv_get_interrupt_type): Handle 'rnmi' interrupt attribute.
+ 	* config/riscv/riscv.md (riscv_rnmi): Add nmret INSN.
+ 	* doc/extend.texi: Add documentation for 'rnmi' interrupt attribute.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (vectorizable_induction): Remove
+ 	gimple **vec_stmt argument.
+ 	(vectorizable_phi): Likewise.
+ 	(vectorizable_recurr): Likewise.
+ 	(vectorizable_early_exit): Likewise.
+ 	* tree-vect-loop.cc (vectorizable_phi): Likewise and adjust.
+ 	(vectorizable_recurr): Likewise.
+ 	(vectorizable_nonlinear_induction): Likewise.
+ 	(vectorizable_induction): Likewise.
+ 	* tree-vect-stmts.cc (vectorizable_bswap): Likewise.
+ 	(vectorizable_call): Likewise.
+ 	(vectorizable_simd_clone_call): Likewise.
+ 	(vectorizable_conversion): Likewise.
+ 	(vectorizable_assignment): Likewise.
+ 	(vectorizable_shift): Likewise.
+ 	(vectorizable_operation): Likewise.
+ 	(vectorizable_store): Likewise.
+ 	(vectorizable_load): Likewise.
+ 	(vectorizable_condition): Likewise.
+ 	(vectorizable_comparison_1): Likewise.
+ 	(vectorizable_comparison): Likewise.
+ 	(vectorizable_early_exit): Likewise.
+ 	(vect_analyze_stmt): Adjust.
+ 	(vect_transform_stmt): Likewise.
+ 	* tree-vect-slp.cc (vect_slp_analyze_operations): Adjust.
+ 	(vectorize_slp_instance_root_stmt): Likewise.
+ 
+ 2025-07-24  Andrew Pinski  <quic_apinski@quicinc.com>
+ 
+ 	* doc/cpp.texi (#ifdef): Correct typo.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vectorizable_early_exit): Remove non-SLP
+ 	path.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (_stmt_vec_info::simd_clone_info): Remove.
+ 	(STMT_VINFO_SIMD_CLONE_INFO): Likewise.
+ 	* tree-vectorizer.cc (vec_info::free_stmt_vec_info): Do not
+ 	release it.
+ 	* tree-vect-stmts.cc (vectorizable_simd_clone_call): Remove
+ 	non-SLP path.
+ 
+ 2025-07-24  Robin Dapp  <rdapp@ventanamicro.com>
+ 
+ 	* internal-fn.cc (internal_fn_len_index): Adjust indices for new
+ 	alias_ptr param.
+ 	(internal_fn_else_index): Ditto.
+ 	(internal_fn_mask_index): Ditto.
+ 	(internal_fn_stored_value_index): Ditto.
+ 	(internal_fn_alias_ptr_index): Ditto.
+ 	(internal_fn_offset_index): Ditto.
+ 	(internal_fn_scale_index): Ditto.
+ 	(internal_gather_scatter_fn_supported_p): Ditto.
+ 	* internal-fn.h (internal_fn_alias_ptr_index): Ditto.
+ 	* optabs-query.cc (supports_vec_gather_load_p): Ditto.
+ 	* tree-vect-data-refs.cc (vect_check_gather_scatter): Add alias
+ 	pointer.
+ 	* tree-vect-patterns.cc (vect_recog_gather_scatter_pattern): Add
+ 	alias pointer.
+ 	* tree-vect-slp.cc (vect_get_operand_map): Adjust for alias
+ 	pointer.
+ 	* tree-vect-stmts.cc (vect_truncate_gather_scatter_offset): Add
+ 	alias pointer and misalignment handling.
+ 	(get_load_store_type): Move from here...
+ 	(get_group_load_store_type): ...To here.
+ 	(vectorizable_store): Add alias pointer.
+ 	(vectorizable_load): Ditto.
+ 	* tree-vectorizer.h (struct gather_scatter_info): Ditto.
+ 
+ 2025-07-24  Robin Dapp  <rdapp@ventanamicro.com>
+ 
+ 	* config/aarch64/aarch64.cc (aarch64_builtin_support_vector_misalignment):
+ 	Return true for gather/scatter.
+ 	* config/arm/arm.cc (arm_builtin_support_vector_misalignment):
+ 	Ditto.
+ 	* config/epiphany/epiphany.cc (epiphany_support_vector_misalignment):
+ 	Ditto.
+ 	* config/gcn/gcn.cc (gcn_vectorize_support_vector_misalignment):
+ 	Ditto.
+ 	* config/loongarch/loongarch.cc (loongarch_builtin_support_vector_misalignment):
+ 	Ditto.
+ 	* config/riscv/riscv.cc (riscv_support_vector_misalignment):
+ 	Add gather/scatter argument.
+ 	* config/rs6000/rs6000.cc (rs6000_builtin_support_vector_misalignment):
+ 	Return true for gather/scatter.
+ 	* config/s390/s390.cc (s390_support_vector_misalignment):
+ 	Ditto.
+ 	* doc/tm.texi: Add argument.
+ 	* target.def: Ditto.
+ 	* targhooks.cc (default_builtin_support_vector_misalignment):
+ 	Ditto.
+ 	* targhooks.h (default_builtin_support_vector_misalignment):
+ 	Ditto.
+ 	* tree-vect-data-refs.cc (vect_supportable_dr_alignment):
+ 	Ditto.
+ 
+ 2025-07-24  Robin Dapp  <rdapp@ventanamicro.com>
+ 
+ 	* tree-vect-slp.cc (GATHER_SCATTER_OFFSET): New define.
+ 	(vect_get_and_check_slp_defs): Use.
+ 	* tree-vectorizer.h (GATHER_SCATTER_LEGACY_P): New define.
+ 	(GATHER_SCATTER_IFN_P): Ditto.
+ 	(GATHER_SCATTER_EMULATED_P): Ditto.
+ 	* tree-vect-stmts.cc (vectorizable_store): Use.
+ 	(vectorizable_load): Use.
+ 
+ 2025-07-24  Robin Dapp  <rdapp@ventanamicro.com>
+ 
+ 	* internal-fn.cc (expand_scatter_store_optab_fn): Use new
+ 	function.
+ 	(expand_gather_load_optab_fn): Ditto.
+ 	(internal_fn_offset_index): Ditto.
+ 	(internal_fn_scale_index): Ditto.
+ 	* internal-fn.h (internal_fn_offset_index): New function.
+ 	(internal_fn_scale_index): Ditto.
+ 	* tree-vect-data-refs.cc (vect_describe_gather_scatter_call):
+ 	Use new function.
+ 
+ 2025-07-24  Alfie Richards  <alfie.richards@arm.com>
+ 
+ 	* tree-vect-data-refs.cc (vect_create_data_ref_ptr): Remove unnecessary
+ 	casts to aggr_ptr_type.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vectorizable_comparison_1): Remove
+ 	non-SLP path.
+ 	(vectorizable_comparison): Likewise.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vectorizable_condition): Remove
+ 	non-SLP paths.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vectorizable_scan_store): Remove
+ 	non-SLP path and unused parameters.
+ 	(vectorizable_store): Adjust.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vectorizable_shift): Remove non-SLP paths.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vectorizable_assignment): Remove
+ 	non-SLP paths.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vectorizable_call): Remove non-SLP path.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-stmts.cc (vectorizable_bswap): Remove non-SLP path.
+ 
+ 2025-07-24  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vect-loop.cc (vectorizable_recurr): Remove non-SLP path.
+ 
+ 2025-07-24  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* config/aarch64/aarch64-sve.md (*cond_<optab><mode>_2_relaxed):
+ 	Extend from SVE_FULL_F_B16B16 to SVE_F_B16B16.
+ 	(*cond_<optab><mode>_3_relaxed): Likewise.
+ 	(*cond_<optab><mode>_any_relaxed): Likwise.
+ 	(*cond_<optab><mode>_any_const_relaxed): Extend from SVE_FULL_F
+ 	to SVE_F.
+ 	(*cond_add<mode>_2_const_relaxed): Likewise.
+ 	(*cond_add<mode>_any_const_relaxed): Likewise.
+ 	(*cond_sub<mode>_3_const_relaxed): Likewise.
+ 	(*cond_sub<mode>_const_relaxed): Likewise.
+ 
+ 2025-07-24  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* config/aarch64/aarch64-sve.md: (@aarch64_sve_<optab><mode>):
+ 	Extend from SVE_FULL_F to SVE_F, use aarch64_predicate_operand.
+ 	(@aarch64_frecpe<mode>): Extend from SVE_FULL_F to SVE_F.
+ 	(@aarch64_frecps<mode>): Likewise.
+ 	(div<mode>3): Likewise, use aarch64_sve_fp_pred.
+ 	* config/aarch64/iterators.md: Add warnings above SVE_FP_UNARY
+ 	and SVE_FP_BINARY.
+ 
+ 2025-07-24  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* config/aarch64/aarch64-sve.md (<optab><mode>3): Extend from
+ 	SVE_FULL_F to SVE_F, use aarch64_sve_fp_pred.
+ 	(*post_ra_<sve_fp_op><mode>3): Extend from SVE_FULL_F to SVE_F.
+ 	(@aarch64_pred_<optab><mode>): Extend from SVE_FULL_F to SVE_F,
+ 	use aarch64_predicate_operand (ADD/SUB/MUL/MAX/MIN).
+ 	(split for using unpredicated insns): Move SVE_RELAXED_GP into
+ 	the pattern, rather than testing for it in the condition.
+ 	* config/aarch64/aarch64-sve2.md (@aarch64_pred_<optab><mode>):
+ 	Extend from VNx8BF_ONLY to SVE_BF.
+ 
+ 2025-07-24  Pan Li  <pan2.li@intel.com>
+ 
+ 	* config/riscv/autovec-opt.md (*uavg_floor_vx_<mode>): Rename
+ 	from...
+ 	(*<sat_op_v_vdup>_vx_<mode>): Rename to...
+ 	(*<sat_op_vdup_v>_vx_<mode>): Rename to...
+ 	* config/riscv/riscv-protos.h (enum insn_flags): Add vxrm
+ 	RNE, ROD type.
+ 	(enum insn_type): Add RNE_P, ROD_P type.
+ 	(expand_vx_binary_vxrm_vec_vec_dup): Add new func decl.
+ 	(expand_vx_binary_vxrm_vec_dup_vec): Ditto.
+ 	* config/riscv/riscv-v.cc (get_insn_type_by_vxrm_val): Add
+ 	helper to get insn type by vxrm value.
+ 	(expand_vx_binary_vxrm_vec_vec_dup): Add new func impl
+ 	to expand vec + vec_dup pattern.
+ 	(expand_vx_binary_vxrm_vec_dup_vec): Ditto but for
+ 	vec_dup + vec pattern.
+ 	* config/riscv/vector-iterators.md: Add helper iterator
+ 	for sat vx combine.
+ 
+ 2025-07-23  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* config/aarch64/aarch64-sve.md (*cond_<optab><mode>_2_relaxed):
+ 	Extend from SVE_FULL_F to SVE_F.
+ 	(*cond_<optab><mode>_any_relaxed): Likewise.
+ 
+ 2025-07-23  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* config/aarch64/aarch64-sve.md (<optab><mode>2): Replace use of
+ 	aarch64_ptrue_reg with aarch64_sve_fp_pred.
+ 	(@aarch64_pred_<optab><mode>): Extend from SVE_FULL_F to SVE_F,
+ 	and use aarch64_predicate_operand.
+ 	* config/aarch64/iterators.md: Split FABS/FNEG out of
+ 	SVE_COND_FP_UNARY (into new SVE_COND_FP_UNARY_BITWISE).
+ 
+ 2025-07-23  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* config/aarch64/aarch64-sve.md
+ 	(*cond_<optab>_nontrunc<SVE_PARTIAL_F:mode><SVE_HSDI:mode>_relaxed):
+ 	New FCVT/SEL combiner pattern.
+ 	(*cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx2SI_ONLY:mode>_relaxed):
+ 	New FCVTZ{S,U}/SEL combiner pattern.
+ 	(*cond_<optab>_nonextend<SVE_HSDI:mode><SVE_PARTIAL_F:mode>_relaxed):
+ 	New {S,U}CVTF/SEL combiner pattern.
+ 	(*cond_<optab>_trunc<SVE_SDF:mode><SVE_PARTIAL_HSF:mode>):
+ 	New FCVT/SEL combiner pattern.
+ 	(*cond_<optab>_nontrunc<SVE_PARTIAL_HSF:mode><SVE_SDF:mode>_relaxed):
+ 	New FCVTZ{S,U}/SEL combiner pattern.
+ 	* config/aarch64/iterators.md: New mode iterator for VNx2SI.
+ 
+ 2025-07-23  Robin Dapp  <rdapp@ventanamicro.com>
+ 
+ 	PR target/121073
+ 	* config/riscv/autovec-opt.md: Use new helpers.
+ 	* config/riscv/autovec.md: Ditto.
+ 	* config/riscv/predicates.md (strided_broadcast_mask_operand):
+ 	New predicate.
+ 	(strided_broadcast_operand): Ditto.
+ 	(any_broadcast_operand): Ditto.
+ 	* config/riscv/riscv-protos.h (expand_broadcast): Declare.
+ 	(expand_set_first): Ditto.
+ 	(expand_set_first_tu): Ditto.
+ 	(strided_broadcast_p): Ditto.
+ 	* config/riscv/riscv-string.cc (expand_vec_setmem): Use new
+ 	helpers.
+ 	* config/riscv/riscv-v.cc (expand_broadcast): New functionk.
+ 	(expand_set_first): Ditto.
+ 	(expand_set_first_tu): Ditto.
+ 	(expand_const_vec_duplicate): Use new helpers.
+ 	(expand_const_vector_duplicate_repeating): Ditto.
+ 	(expand_const_vector_duplicate_default): Ditto.
+ 	(sew64_scalar_helper): Ditto.
+ 	(expand_vector_init_merge_repeating_sequence): Ditto.
+ 	(expand_reduction): Ditto.
+ 	(strided_broadcast_p): New function.
+ 	(whole_reg_to_reg_move_p): Use new helpers.
+ 	* config/riscv/riscv-vector-builtins-bases.cc: Use either
+ 	broadcast or strided broadcast.
+ 	* config/riscv/riscv-vector-builtins.cc (function_expander::use_ternop_insn):
+ 	Ditto.
+ 	(function_expander::use_widen_ternop_insn): Ditto.
+ 	(function_expander::use_scalar_broadcast_insn): Ditto.
+ 	* config/riscv/riscv-vector-builtins.h: Declare scalar
+ 	broadcast.
+ 	* config/riscv/vector.md (*pred_broadcast<mode>): Split into
+ 	regular and strided broadcast.
+ 	(*pred_broadcast<mode>_zvfh): Split.
+ 	(pred_broadcast<mode>_zvfh): Ditto.
+ 	(*pred_broadcast<mode>_zvfhmin): Ditto.
+ 	(@pred_strided_broadcast<mode>): Ditto.
+ 	(*pred_strided_broadcast<mode>): Ditto.
+ 	(*pred_strided_broadcast<mode>_zvfhmin): Ditto.
+ 
+ 2025-07-23  Andrew Pinski  <quic_apinski@quicinc.com>
+ 
+ 	PR target/120119
+ 	* config/aarch64/cortex-a57-fma-steering.cc (func_fma_steering::analyze):
+ 	Skip if renaming fails.
+ 
+ 2025-07-23  Richard Biener  <rguenther@suse.de>
+ 
+ 	PR tree-optimization/121220
+ 	* tree-ssa-sink.cc (statement_sink_location): For stores
+ 	handle sinking to paths ending in a store.  Skip loads
+ 	that do not use the store.
+ 
+ 2025-07-23  Martin Jambor  <mjambor@suse.cz>
+ 
+ 	PR tree-optimization/119085
+ 	* tree-sra.cc (sort_and_splice_var_accesses): Prevent total
+ 	scalarization if two incompatible aggregates access the same place.
+ 
+ 2025-07-23  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+ 
+ 	* config.gcc <sparc*-*-solaris2*> (with_cpu): Default to ultrasparc3.
+ 
+ 2025-07-23  Richard Biener  <rguenther@suse.de>
+ 
+ 	* config/aarch64/aarch64.cc (aarch64_vector_costs::add_stmt_cost):
+ 	Check vectype is non-NULL before accessing it.
+ 
+ 2025-07-23  Richard Biener  <rguenther@suse.de>
+ 
+ 	PR middle-end/121216
+ 	* expr.cc (constant_byte_string): Check the string type
+ 	size fits an uhwi before converting to uhwi.
+ 
+ 2025-07-22  Andrew Pinski  <quic_apinski@quicinc.com>
+ 
+ 	PR middle-end/109267
+ 	* tree-cfgcleanup.cc (execute_cleanup_cfg_post_optimizing): If the first
+ 	non debug statement in the first (and only) basic block is a call
+ 	to __builtin_unreachable change it to a call to __builtin_trap or an
+ 	infinite loop.
+ 
+ 2025-07-22  Takayuki 'January June' Suwa  <jjsuwa_sys3175@yahoo.co.jp>
+ 
+ 	* config/xtensa/xtensa.cc (xtensa_is_insn_L32R_p):
+ 	Rewrite to capture insns that could be L32R machine instructions
+ 	wherever possible.
+ 	(xtensa_rtx_costs): Fix to consider that moves larger than a
+ 	natural word can take multiple L32R machine instructions.
+ 	(constantpool_address_p): Cosmetics.
+ 	* config/xtensa/xtensa.md (movdi_internal, movdf_internal):
+ 	Add missing insn attributes.
+ 
+ 2025-07-22  Takayuki 'January June' Suwa  <jjsuwa_sys3175@yahoo.co.jp>
+ 
+ 	* config/xtensa/xtensa.md
+ 	(movsi_internal, movhi_internal, movsf_internal):
+ 	Change the value of the "type" attribute from "move" to "load"
+ 	when the source operand constraint is "Y".
+ 
+ 2025-07-22  Karl Meakin  <karl.meakin@arm.com>
+ 
+ 	* tree-vect-data-refs.cc (vect_check_gather_scatter): Swap
+ 	`base` and `off` in more scenarios. Also assert at the end of
+ 	the function that `base` and `off` are loop-invariant and not
+ 	loop-invariant respectively.
+ 
+ 2025-07-22  Jeff Law  <jlaw@ventanamicro.com>
+ 
+ 	* config/riscv/generic-vector-ooo.md: Restrict insn reservations to
+ 	generic_ooo and generic tuning models.
+ 
+ 2025-07-22  Richard Biener  <rguenther@suse.de>
+ 
+ 	PR tree-optimization/121202
+ 	* tree-vect-slp.cc (vect_schedule_slp_node): Do not take
+ 	an out-of-region stmt as "last".
+ 
+ 2025-07-22  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* genpreds.cc (write_insn_constraint_len): Replace rawmemchr by
+ 	a loop.
+ 
+ 2025-07-21  Jeff Law  <jlaw@ventanamicro.com>
+ 
+ 	* config/riscv/mips-p8700.md: Add support for "ghost" insn types.
+ 	* config/riscv/xiangshan.md: Add support for "sf_vc" and "sf_vc_se"
+ 	insn types.
+ 
+ 2025-07-21  Andrew Pinski  <quic_apinski@quicinc.com>
+ 
+ 	PR tree-optimization/110949
+ 	PR tree-optimization/95906
+ 	* match.pd (cmp - 1): New pattern.
+ 
+ 2025-07-21  Andreas Schwab  <schwab@suse.de>
+ 
+ 	PR target/121121
+ 	* config/riscv/riscv.cc (riscv_allocate_and_probe_stack_space):
+ 	Use temp2 instead of temp1 for the CFA note.
+ 
+ 2025-07-21  Pan Li  <pan2.li@intel.com>
+ 
+ 	* config/riscv/vector.md: Allow VLS DImode for sat_op vx pattern.
+ 
+ 2025-07-21  Pan Li  <pan2.li@intel.com>
+ 
+ 	* config/riscv/autovec-opt.md (*uavg_floor_vx_<mode>): Add
+ 	pattern for vaaddu.vx combine.
+ 	* config/riscv/riscv.cc (get_vector_binary_rtx_cost): Add UNSPEC
+ 	handling for UNSPEC_VAADDU.
+ 	(riscv_rtx_costs): Ditto.
+ 
+ 2025-07-21  Kyrylo Tkachov  <ktkachov@nvidia.com>
+ 
+ 	* config/aarch64/aarch64-simd.md (aarch64_simd_vec_set_zero<mode>):
+ 	Enable only when optimizing for size.
+ 
+ 2025-07-21  Kyrylo Tkachov  <ktkachov@nvidia.com>
+ 
+ 	* config/aarch64/aarch64.cc (aarch64_rtx_costs): Add extra_cost values
+ 	only when speed is true for CONST_VECTOR, VEC_DUPLICATE, VEC_SELECT
+ 	cases.
+ 	* config/aarch64/aarch64-cost-tables.h (qdf24xx_extra_costs,
+ 	thunderx_extra_costs, thunderx2t99_extra_costs,
+ 	thunderx3t110_extra_costs, tsv110_extra_costs, a64fx_extra_costs,
+ 	ampere1_extra_costs, ampere1a_extra_costs, ampere1b_extra_costs):
+ 	Reduce cost of movi, dup, extract fields by COSTS_N_INSNS (1).
+ 	* config/arm/aarch-cost-tables.h (generic_extra_costs,
+ 	cortexa53_extra_costs, cortexa57_extra_costs, cortexa76_extra_costs,
+ 	exynosm1_extra_costs, xgene1_extra_costs): Likewise.
+ 
+ 2025-07-21  Richard Biener  <rguenther@suse.de>
+ 
+ 	PR tree-optimization/121194
+ 	* tree-vect-loop.cc (vectorizable_lc_phi): Verify
+ 	vector types are compatible.
+ 
+ 2025-07-21  Andrew Stubbs  <ams@baylibre.com>
+ 
+ 	* config/gcn/gcn-valu.md (gather_load<mode><vndi>): New.
+ 	(scatter_store<mode><vndi>): New.
+ 	(mask_gather_load<mode><vndi>): New.
+ 	(mask_scatter_store<mode><vndi>): New.
+ 	* config/gcn/gcn.cc (gcn_expand_scaled_offsets): Support DImode.
+ 
+ 2025-07-21  Andrew Stubbs  <ams@baylibre.com>
+ 
+ 	* config/gcn/gcn.cc (GEN_VNM_NOEXEC): Use USE_QHF.
+ 	(GEN_VNM): Likewise, and call for new ashl and mul variants.
+ 
+ 2025-07-21  Andrew Stubbs  <ams@baylibre.com>
+ 
+ 	* config/gcn/gcn-valu.md (add<mode>3_dup): New.
+ 	(add<mode>3_dup_exec): New.
+ 	(<su>mul<mode>3_highpart_dup<exec>): New.
+ 	(mul<mode>3_dup): Move the vec_duplicate to operand 1.
+ 	(mul<mode>3_dup_exec): New.
+ 	(vec_series<mode>): Adjust call to gen_mul<mode>3_dup.
+ 	* config/gcn/gcn.cc (gcn_expand_vector_init): Likewise.
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* genoutput.cc (main): Emit function
+ 	verify_reg_names_in_constraints() for run-time validation.
+ 	(mdep_constraint_len): Deal with hard register constraints.
+ 	* output.h (verify_reg_names_in_constraints): New function
+ 	declaration.
+ 	* toplev.cc (backend_init): If checking is enabled, call into
+ 	verify_reg_names_in_constraints().
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* cfgexpand.cc (n_occurrences): Move this ...
+ 	(check_operand_nalternatives): and this ...
+ 	(expand_asm_stmt): and the call to gimplify.cc.
+ 	* config/s390/s390.cc (s390_md_asm_adjust): Pass null pointer to
+ 	parse_{input,output}_constraint().
+ 	* gimple-walk.cc (walk_gimple_asm): Pass null pointer to
+ 	parse_{input,output}_constraint().
+ 	(walk_stmt_load_store_addr_ops): Ditto.
+ 	* gimplify-me.cc (gimple_regimplify_operands): Ditto.
+ 	* gimplify.cc (num_occurrences): Moved from cfgexpand.cc.
+ 	(num_alternatives): Ditto.
+ 	(gimplify_asm_expr): Deal with hard register constraints.
+ 	* stmt.cc (eliminable_regno_p): New helper.
+ 	(hardreg_ok_p): Perform a similar check as done in
+ 	make_decl_rtl().
+ 	(parse_output_constraint): Add parameter for gimplify_reg_info
+ 	and validate hard register constrained operands.
+ 	(parse_input_constraint): Ditto.
+ 	* stmt.h (class gimplify_reg_info): Forward declaration.
+ 	(parse_output_constraint): Add parameter.
+ 	(parse_input_constraint): Ditto.
+ 	* tree-ssa-operands.cc
+ 	(operands_scanner::get_asm_stmt_operands): Pass null pointer
+ 	to parse_{input,output}_constraint().
+ 	* tree-ssa-structalias.cc (find_func_aliases): Pass null pointer
+ 	to parse_{input,output}_constraint().
+ 	* varasm.cc (assemble_asm): Pass null pointer to
+ 	parse_{input,output}_constraint().
+ 	* gimplify_reg_info.h: New file.
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* config/cris/cris.cc (cris_md_asm_adjust): Deal with hard
+ 	register constraint.
+ 	* config/i386/i386.cc (map_egpr_constraints): Ditto.
+ 	* config/s390/s390.cc (f_constraint_p): Ditto.
+ 	* doc/extend.texi: Document hard register constraints.
+ 	* doc/md.texi: Ditto.
+ 	* function.cc (match_asm_constraints_2): Have a unique pseudo
+ 	for each operand with a hard register constraint.
+ 	(pass_match_asm_constraints::execute): Calling into new helper
+ 	match_asm_constraints_2().
+ 	* genoutput.cc (mdep_constraint_len): Return the length of a
+ 	hard register constraint.
+ 	* genpreds.cc (write_insn_constraint_len): Support hard register
+ 	constraints for insn_constraint_len().
+ 	* ira.cc (valid_replacement_for_asm_input_p_1): New helper.
+ 	(valid_replacement_for_asm_input_p): New helper.
+ 	(decrease_live_ranges_number): Similar to
+ 	match_asm_constraints_2() ensure that each operand has a unique
+ 	pseudo if constrained by a hard register.
+ 	* lra-constraints.cc (process_alt_operands): Install hard
+ 	register filter according to constraint.
+ 	* recog.cc (asm_operand_ok): Accept register type for hard
+ 	register constrained asm operands.
+ 	(constrain_operands): Validate hard register constraints.
+ 	* stmt.cc (decode_hard_reg_constraint): Parse a hard register
+ 	constraint into the corresponding register number or bail out.
+ 	(parse_output_constraint): Parse hard register constraint and
+ 	set *ALLOWS_REG.
+ 	(parse_input_constraint): Ditto.
+ 	* stmt.h (decode_hard_reg_constraint): Declaration of new
+ 	function.
+ 
+ 2025-07-21  Richard Biener  <rguenther@suse.de>
+ 
+ 	* tree-vectorizer.h (vect_analyze_data_refs): Remove min_vf
+ 	output.
+ 	* tree-vect-data-refs.cc (vect_analyze_data_refs): Likewise.
+ 	* tree-vect-loop.cc (vect_analyze_loop_2): Remove early
+ 	out based on bogus min_vf.
+ 	* tree-vect-slp.cc (vect_slp_analyze_bb_1): Adjust.
+ 
+ 2025-07-20  Pan Li  <pan2.li@intel.com>
+ 
+ 	* config/riscv/autovec.md: Add (const_int 1) as the op2 of
+ 	ashiftrt.
+ 
  2025-07-19  Dimitar Dimitrov  <dimitar@dinux.eu>
  
  	PR target/121124
diff -Nrcpad gcc-16-20250720/gcc/DATESTAMP gcc-16-20250727/gcc/DATESTAMP
*** gcc-16-20250720/gcc/DATESTAMP	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/DATESTAMP	Sun Jul 27 22:32:07 2025
***************
*** 1 ****
! 20250720
--- 1 ----
! 20250727
diff -Nrcpad gcc-16-20250720/gcc/Makefile.in gcc-16-20250727/gcc/Makefile.in
*** gcc-16-20250720/gcc/Makefile.in	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/Makefile.in	Sun Jul 27 22:32:07 2025
*************** TREE_SSA_H = tree-ssa.h tree-ssa-operand
*** 1069,1075 ****
  PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H) wide-int-print.h
  TREE_PRETTY_PRINT_H = tree-pretty-print.h $(PRETTY_PRINT_H)
  GIMPLE_PRETTY_PRINT_H = gimple-pretty-print.h $(TREE_PRETTY_PRINT_H)
! DIAGNOSTIC_CORE_H = diagnostic-core.h $(INPUT_H) bversion.h diagnostic.def
  DIAGNOSTIC_H = diagnostic.h $(DIAGNOSTIC_CORE_H) $(PRETTY_PRINT_H)
  C_PRETTY_PRINT_H = c-family/c-pretty-print.h $(PRETTY_PRINT_H) \
  	$(C_COMMON_H) $(TREE_H)
--- 1069,1075 ----
  PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H) wide-int-print.h
  TREE_PRETTY_PRINT_H = tree-pretty-print.h $(PRETTY_PRINT_H)
  GIMPLE_PRETTY_PRINT_H = gimple-pretty-print.h $(TREE_PRETTY_PRINT_H)
! DIAGNOSTIC_CORE_H = diagnostic-core.h $(INPUT_H) bversion.h diagnostics/kinds.def
  DIAGNOSTIC_H = diagnostic.h $(DIAGNOSTIC_CORE_H) $(PRETTY_PRINT_H)
  C_PRETTY_PRINT_H = c-family/c-pretty-print.h $(PRETTY_PRINT_H) \
  	$(C_COMMON_H) $(TREE_H)
*************** OBJS = \
*** 1595,1601 ****
  	jump.o \
  	langhooks.o \
  	late-combine.o \
- 	lazy-diagnostic-path.o \
  	lcm.o \
  	lists.o \
  	loop-doloop.o \
--- 1595,1600 ----
*************** OBJS = \
*** 1852,1881 ****
  
  # Objects in libcommon.a, potentially used by all host binaries and with
  # no target dependencies.
! OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
! 	diagnostic-format-html.o \
! 	diagnostic-format-sarif.o \
! 	diagnostic-format-text.o \
  	diagnostic-global-context.o \
! 	diagnostic-digraphs.o \
! 	diagnostic-macro-unwinding.o \
! 	diagnostic-output-spec.o \
! 	diagnostic-path.o \
! 	diagnostic-path-output.o \
! 	diagnostic-show-locus.o \
! 	diagnostic-state-graphs.o \
! 	diagnostic-state-to-dot.o \
! 	edit-context.o \
  	graphviz.o pex.o \
  	pretty-print.o intl.o \
  	json.o json-parsing.o \
  	xml.o \
  	sbitmap.o \
  	vec.o input.o hash-table.o ggc-none.o memory-block.o \
! 	selftest.o selftest-diagnostic.o sort.o \
! 	selftest-diagnostic-path.o \
  	selftest-json.o \
- 	selftest-logical-location.o \
  	text-art/box-drawing.o \
  	text-art/canvas.o \
  	text-art/ruler.o \
--- 1851,1889 ----
  
  # Objects in libcommon.a, potentially used by all host binaries and with
  # no target dependencies.
! OBJS-libcommon = \
  	diagnostic-global-context.o \
! 	diagnostics/buffering.o \
! 	diagnostics/changes.o \
! 	diagnostics/color.o \
! 	diagnostics/context.o \
! 	diagnostics/digraphs.o \
! 	diagnostics/file-cache.o \
! 	diagnostics/output-spec.o \
! 	diagnostics/html-sink.o \
! 	diagnostics/sarif-sink.o \
! 	diagnostics/text-sink.o \
! 	diagnostics/lazy-paths.o \
! 	diagnostics/macro-unwinding.o \
! 	diagnostics/option-classifier.o \
! 	diagnostics/paths.o \
! 	diagnostics/paths-output.o \
! 	diagnostics/source-printing.o \
! 	diagnostics/state-graphs.o \
! 	diagnostics/state-graphs-to-dot.o \
! 	diagnostics/selftest-context.o \
! 	diagnostics/selftest-logical-locations.o \
! 	diagnostics/selftest-paths.o \
! 	diagnostics/diagnostics-selftests.o \
! 	gcc-diagnostic-spec.o \
  	graphviz.o pex.o \
  	pretty-print.o intl.o \
  	json.o json-parsing.o \
  	xml.o \
  	sbitmap.o \
  	vec.o input.o hash-table.o ggc-none.o memory-block.o \
! 	selftest.o sort.o \
  	selftest-json.o \
  	text-art/box-drawing.o \
  	text-art/canvas.o \
  	text-art/ruler.o \
*************** endif
*** 1922,1928 ****
  
  # libbackend.a objs that might not be in some cases linked into the compiler,
  # yet they are supposed to be part of the plugin ABI.  See PR116143.
! EXTRA_BACKEND_OBJS = simple-diagnostic-path.o lazy-diagnostic-path.o
  
  BACKEND = $(EXTRA_BACKEND_OBJS) libbackend.a main.o libcommon-target.a \
  	libcommon.a $(CPPLIB) $(LIBDECNUMBER)
--- 1930,1936 ----
  
  # libbackend.a objs that might not be in some cases linked into the compiler,
  # yet they are supposed to be part of the plugin ABI.  See PR116143.
! EXTRA_BACKEND_OBJS = simple-diagnostic-path.o diagnostics/lazy-paths.o
  
  BACKEND = $(EXTRA_BACKEND_OBJS) libbackend.a main.o libcommon-target.a \
  	libcommon.a $(CPPLIB) $(LIBDECNUMBER)
*************** GTFILES = $(CPPLIB_H) $(srcdir)/input.h
*** 3039,3045 ****
    $(srcdir)/ipa-modref-tree.h \
    $(srcdir)/ipa-locality-cloning.cc \
    $(srcdir)/signop.h \
!   $(srcdir)/diagnostic-spec.h $(srcdir)/diagnostic-spec.cc \
    $(srcdir)/dwarf2out.h \
    $(srcdir)/dwarf2asm.cc \
    $(srcdir)/dwarf2cfi.cc \
--- 3047,3053 ----
    $(srcdir)/ipa-modref-tree.h \
    $(srcdir)/ipa-locality-cloning.cc \
    $(srcdir)/signop.h \
!   $(srcdir)/gcc-diagnostic-spec.h $(srcdir)/gcc-diagnostic-spec.cc \
    $(srcdir)/dwarf2out.h \
    $(srcdir)/dwarf2asm.cc \
    $(srcdir)/dwarf2cfi.cc \
*************** PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $
*** 4072,4078 ****
    fold-const.h fold-const-call.h tree-cfg.h tree-into-ssa.h tree-ssanames.h \
    print-tree.h varasm.h context.h tree-phinodes.h stor-layout.h \
    ssa-iterators.h $(RESOURCE_H) tree-cfgcleanup.h attribs.h calls.h \
!   cfgexpand.h diagnostic-color.h gcc-symtab.h gimple-builder.h gimple-low.h \
    gimple-walk.h gimplify-me.h pass_manager.h print-rtl.h stmt.h \
    tree-dfa.h tree-hasher.h tree-nested.h tree-object-size.h tree-outof-ssa.h \
    tree-parloops.h tree-ssa-address.h tree-ssa-coalesce.h tree-ssa-dom.h \
--- 4080,4086 ----
    fold-const.h fold-const-call.h tree-cfg.h tree-into-ssa.h tree-ssanames.h \
    print-tree.h varasm.h context.h tree-phinodes.h stor-layout.h \
    ssa-iterators.h $(RESOURCE_H) tree-cfgcleanup.h attribs.h calls.h \
!   cfgexpand.h gcc-symtab.h gimple-builder.h gimple-low.h \
    gimple-walk.h gimplify-me.h pass_manager.h print-rtl.h stmt.h \
    tree-dfa.h tree-hasher.h tree-nested.h tree-object-size.h tree-outof-ssa.h \
    tree-parloops.h tree-ssa-address.h tree-ssa-coalesce.h tree-ssa-dom.h \
*************** PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $
*** 4082,4088 ****
    hash-set.h dominance.h cfg.h cfgrtl.h cfganal.h cfgbuild.h cfgcleanup.h \
    lcm.h cfgloopmanip.h file-prefix-map.h builtins.def $(INSN_ATTR_H) \
    pass-instances.def params.list $(srcdir)/../include/gomp-constants.h \
!   $(EXPR_H) $(srcdir)/analyzer/*.h
  
  # generate the 'build fragment' b-header-vars
  s-header-vars: Makefile
--- 4090,4096 ----
    hash-set.h dominance.h cfg.h cfgrtl.h cfganal.h cfgbuild.h cfgcleanup.h \
    lcm.h cfgloopmanip.h file-prefix-map.h builtins.def $(INSN_ATTR_H) \
    pass-instances.def params.list $(srcdir)/../include/gomp-constants.h \
!   $(EXPR_H) $(srcdir)/analyzer/*.h $(srcdir)/diagnostics/*.h
  
  # generate the 'build fragment' b-header-vars
  s-header-vars: Makefile
*************** install-plugin: installdirs lang.install
*** 4120,4125 ****
--- 4128,4134 ----
  	  fi; \
  	  case $$path in \
  	  "$(srcdir)"/analyzer/* \
+ 	  | "$(srcdir)"/diagnostics/* \
  	  | "$(srcdir)"/config/* | "$(srcdir)"/common/config/* \
  	  | "$(srcdir)"/c-family/* | "$(srcdir)"/*.def ) \
  	    base=`echo "$$path" | sed -e "s|$$srcdirstrip/||"`;; \
diff -Nrcpad gcc-16-20250720/gcc/ada/ChangeLog gcc-16-20250727/gcc/ada/ChangeLog
*** gcc-16-20250720/gcc/ada/ChangeLog	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/ChangeLog	Sun Jul 27 22:32:07 2025
***************
*** 1,3 ****
--- 1,373 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc-interface/misc.cc: Make
+ 	diagnostics::context::m_source_printing private.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc-interface/trans.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc-interface/misc.cc: Update for diagnostic_context becoming
+ 	diagnostics::context.
+ 
+ 2025-07-25  Marc Poulhiès  <poulhies@adacore.com>
+ 
+ 	* gcc-interface/utils.cc (update_pointer_to): Renamed ptr/old_ptr, ref/old_ref.
+ 
+ 2025-07-25  Alexandre Oliva  <oliva@adacore.com>
+ 
+ 	* s-oscons-tmplt.c (CLOCK_RT_Ada) [__vxworks]: Define to
+ 	CLOCK_REALTIME on VxWorks6.
+ 	* gsocket.h [__vxworks]: Include strings.h if available.
+ 	* sysdep.c [__vxworks]: Likewise.
+ 
+ 2025-07-25  Steve Baird  <baird@adacore.com>
+ 
+ 	* exp_ch6.adb (Apply_Access_Discrims_Accessibility_Check): Do
+ 	nothing and simply return if either Ada_Version <= Ada_95 or if
+ 	the function being returned from lacks the extra formal parameter
+ 	needed to perform the check (typically because the result is
+ 	tagged).
+ 
+ 2025-07-25  Bob Duff  <duff@adacore.com>
+ 
+ 	* sem_ch12.adb (Check_Formal_Package_Instance):
+ 	Do nothing in case of E_Subprogram_Body.
+ 
+ 2025-07-25  Ronan Desplanques  <desplanques@adacore.com>
+ 
+ 	* sem_ch3.adb (Process_Discriminants): Update comments
+ 
+ 2025-07-25  Ronan Desplanques  <desplanques@adacore.com>
+ 
+ 	* sem_ch3.adb (Build_Derived_Record_Type): Set flag appropriately.
+ 
+ 2025-07-25  Eric Botcazou  <ebotcazou@adacore.com>
+ 
+ 	* libgnat/a-calend.adb (To_Struct_Timespec_64): Deal with negative
+ 	Duration values and truncate the nanoseconds too.
+ 	* libgnat/g-calend.adb (timeval_to_duration): Unsuppress overflow
+ 	checks.
+ 	(duration_to_timeval): Likewise.  Deal with negative Duration values
+ 	as well as integral Duration values.
+ 	* libgnat/g-socket.adb (To_Timeval): Simplify the implementation.
+ 
+ 2025-07-24  Steve Baird  <baird@adacore.com>
+ 
+ 	* exp_aggr.adb (Convert_To_Assignments): Add calls to Ensure_Defined
+ 	before generating assignments to components that could be
+ 	associated with a not-yet-defined itype.
+ 
+ 2025-07-24  Steve Baird  <baird@adacore.com>
+ 
+ 	* accessibility.adb (Function_Call_Or_Allocator_Level): Handle the
+ 	case where a function that has an Extra_Accessibility_Of_Result
+ 	parameter returns as its result a call to another such function.
+ 	In that case, the extra parameter should be passed along.
+ 	(Check_Return_Construct_Accessibility): Replace a warning about an
+ 	inevitable failure of a dynamic check with a legality-rule-violation
+ 	error message; adjust the text of the message accordingly.
+ 	* exp_ch6.ads (Apply_Access_Discrims_Accessibility_Check): New
+ 	procedure, following example of the existing
+ 	Apply_CW_Accessibility procedure.
+ 	* exp_ch6.adb (Apply_Access_Discrims_Accessibility_Check): body
+ 	for new procedure.
+ 	(Expand_Simple_Function_Return): Add call to new
+ 	Apply_Access_Discrims_Accessibility_Check procedure.
+ 	* exp_ch3.adb (Make_Allocator_For_Return): Add call to new
+ 	Apply_Access_Discrims_Accessibility_Check procedure.
+ 
+ 2025-07-24  Tonu Naks  <naks@adacore.com>
+ 
+ 	* doc/gnat_rm/standard_and_implementation_defined_restrictions.rst:
+ 	clarify parameter description.
+ 	* gnat_rm.texi: Regenerate.
+ 
+ 2025-07-22  Gary Dismukes  <dismukes@adacore.com>
+ 
+ 	* sem_ch8.adb (End_Use_Type): Add a test for there not being an earlier
+ 	use_type_clause for the same type as an additional criterion for turning
+ 	off In_Use and Current_Use_Clause.
+ 
+ 2025-07-22  Piotr Trojanek  <trojanek@adacore.com>
+ 
+ 	* sem_attr.adb (Eval_Attribute): Only fold array attributes when prefix
+ 	is static or at least safe to evaluate
+ 
+ 2025-07-22  Ronan Desplanques  <desplanques@adacore.com>
+ 
+ 	* einfo.ads (Is_Controlled_Active): Fix pasto in comment.
+ 	* sem_util.ads (Propagate_Controlled_Flags): Update comment for
+ 	Destructor aspect.
+ 
+ 2025-07-22  Ronan Desplanques  <desplanques@adacore.com>
+ 
+ 	* doc/gnat_rm/gnat_language_extensions.rst: Document new extension.
+ 	* snames.ads-tmpl: Add name for new aspect.
+ 	* gen_il-fields.ads (Has_Destructor, Is_Destructor): Add new fields.
+ 	* gen_il-gen-gen_entities.adb (E_Procedure, Type_Kind): Add new fields.
+ 	* einfo.ads (Has_Destructor, Is_Destructor): Document new fields.
+ 	* aspects.ads: Add new aspect.
+ 	* sem_ch13.adb (Analyze_Aspect_Specifications,
+ 	Check_Aspect_At_Freeze_Point, Check_Aspect_At_End_Of_Declarations):
+ 	Add semantic analysis for new aspect.
+ 	(Resolve_Finalization_Procedure): New function.
+ 	(Resolve_Finalizable_Argument): Use new function above.
+ 	* sem_util.adb (Propagate_Controlled_Flags): Extend for new field.
+ 	* freeze.adb (Freeze_Entity): Add legality check for new aspect.
+ 	* exp_ch3.adb (Expand_Freeze_Record_Type, Predefined_Primitive_Bodies):
+ 	Use new field.
+ 	* exp_ch7.adb (Build_Finalize_Statements): Add expansion for
+ 	destructors.
+ 	(Make_Final_Call, Build_Record_Deep_Procs): Adapt to new Has_Destructor
+ 	field.
+ 	(Build_Adjust_Statements): Tweak to handle cases of empty lists.
+ 	* gnat_rm.texi: Regenerate.
+ 
+ 2025-07-22  Denis Mazzucato  <mazzucato@adacore.com>
+ 
+ 	* sem_ch6.adb (Might_Need_BIP_Task_Actuals): Before retrieving the original corresponding
+ 	operation we retrieve first the root of the aliased chain.
+ 
+ 2025-07-22  Ronan Desplanques  <desplanques@adacore.com>
+ 
+ 	* gen_il-fields.ads (Is_Implicit_Full_View): New field.
+ 	* gen_il-gen-gen_entities.adb (Type_Kind): Use new field.
+ 	* einfo.ads (Is_Implicit_Full_View): Document new field.
+ 	* exp_ch7.adb (Make_Adjust_Call, Make_Init_Call, Make_Final_Call): Use
+ 	new field.
+ 	* exp_util.adb (Finalize_Address): Likewise.
+ 	* sem_ch3.adb (Copy_And_Build): Set new field.
+ 
+ 2025-07-22  Eric Botcazou  <ebotcazou@adacore.com>
+ 
+ 	* exp_util.ads (May_Generate_Large_Temp): Delete.
+ 	* exp_util.adb (May_Generate_Large_Temp): Likewise.
+ 	(Safe_Unchecked_Type_Conversion): Do not take stack checking into
+ 	account to compute the result.
+ 
+ 2025-07-22  Javier Miranda  <miranda@adacore.com>
+ 
+ 	* sinfo.ads (Is_Expanded_Dispatching_Call): New flag.
+ 	(Tag_Propagated): New flag.
+ 	* exp_ch6.adb (Expand_Call_Helper): Propagate the tag when
+ 	the dispatching call is placed in conditionl expressions or
+ 	case-expressions.
+ 	* sem_ch5.adb (Analyze_Assignment): For assignment of tag-
+ 	indeterminate expression, do not propagate the tag if
+ 	previously done.
+ 	* sem_disp.adb (Is_Tag_Indeterminate): Add missing support
+ 	for conditional expression and case expression.
+ 	* exp_disp.ads (Is_Expanded_Dispatching_Call): Removed. Function
+ 	replaced by a new flag in the nodes.
+ 	* exp_disp.adb (Expand_Dispatching_Call): Set a flag in the
+ 	call node to remember that the call has been expanded.
+ 	(Is_Expanded_Dispatching_Call): Function removed.
+ 	* gen_il-fields.ads (Tag_Propagated): New flag.
+ 	(Is_Expanded_Dispatching_Call): New flag.
+ 	* gen_il-gen-gen_nodes.adb (Tag_Propagated): New flag.
+ 	(Is_Expanded_Dispatching_Call): New flag.
+ 
+ 2025-07-22  Gary Dismukes  <dismukes@adacore.com>
+ 
+ 	* libgnat/a-cbhama.ads (Empty): Add missing default to Capacity formal.
+ 	* libgnat/a-cbhama.adb (Empty): Add missing default to Capacity formal.
+ 	* exp_aggr.adb (Build_Size_Expr): Test for presence of Capacity
+ 	discriminant as additional criterion for generating the call to
+ 	the Length function. Update comments.
+ 
+ 2025-07-22  Eric Botcazou  <ebotcazou@adacore.com>
+ 
+ 	* exp_util.adb (Safe_Unchecked_Type_Conversion): Always return True
+ 	if the expression is the prefix of an N_Selected_Component.
+ 
+ 2025-07-22  Denis Mazzucato  <mazzucato@adacore.com>
+ 
+ 	* sem_ch6.adb (Might_Need_BIP_Task_Actuals): Check whether No_Task_Parts is enabled in any
+ 	of the derived types, or interfaces, from the user-defined primitive return type.
+ 	* sem_ch13.adb (Analyze_Aspect_Specifications): Add No_Task_Parts and No_Controlled_Parts to
+ 	the representation chain to be visible in the full view of private types.
+ 	* aspects.ads (Nonoverridable_Aspect_Id): As per GNAT RM, No_Task_Parts is nonoverridable.
+ 	* sem_util.adb (Check_Inherited_Nonoverridable_Aspects): Likewise.
+ 	* sem_util.ads: Fix typo and style.
+ 	* sem_disp.adb: Missing comment.
+ 
+ 2025-07-22  Javier Miranda  <miranda@adacore.com>
+ 
+ 	* einfo.ads (Extra_Formals): Complete documentation.
+ 	(Has_First_Controlling_Parameter_Aspect): Place it in alphabetical order.
+ 	(Has_Frozen_Extra_Formals): New attribute.
+ 	* gen_il-fields.ads (Has_Frozen_Extra_Formals): New entity field.
+ 	* gen_il-gen-gen_entities.adb (Has_Frozen_Extra_Formals): Adding new
+ 	entity flag to subprograms, subprogram types, and and entries.
+ 	* gen_il-internals.adb (Image): Adding Has_Frozen_Extra_Formals.
+ 	* exp_ch3.adb (Build_Array_Init_Proc): Freeze its extra formals.
+ 	(Build_Init_Procedure): Freeze its extra formals.
+ 	(Expand_Freeze_Record_Type): For tagged types with foreign convention
+ 	create the extra formals of primitives with convention Ada.
+ 	* exp_ch6.ads (Create_Extra_Actuals): New subprogram.
+ 	* exp_ch6.adb (Check_BIP_Actuals): Adding assertions.
+ 	(Create_Extra_Actuals): New subprogram that factorizes code from
+ 	Expand_Call_Helper.
+ 	(Expand_Call_Helper): Adding support to defer the addition of extra
+ 	actuals. Move the code that adds the extra actuals to a new subprogram.
+ 	(Is_Unchecked_Union_Equality): Renamed as Is_Unchecked_Union_Predefined_
+ 	Equality_Call.
+ 	* exp_ch7.adb (Create_Finalizer): Freeze its extra formals.
+ 	(Wrap_Transient_Expression): Link the temporary with its relocated
+ 	expression to facilitate locating the expression in the expanded code.
+ 	* exp_ch9.ads (Expand_N_Entry_Declaration): Adding one formal.
+ 	* exp_ch9.adb (Expand_N_Entry_Declaration): Defer the expansion of
+ 	the entry if the extra formals are not available; analyze the built
+ 	declarations for the record type that holds all the parameters if
+ 	the expansion of the entry declaration was deferred.
+ 	* exp_disp.adb (Expand_Dispatching_Call): Handle deferred extra formals.
+ 	(Set_CPP_Constructors): Freeze its extra formals.
+ 	* freeze.adb (Freeze_Entity): Create the extra actuals of acccess to
+ 	subprograms whose designated type is a subprogram type.
+ 	(Freeze_Subprogram): Adjust assertion to support deferred extra formals,
+ 	and freeze extra formals of non-dispatching subprograms with foreign
+ 	convention. Added assertion to check matching of formals in thunks.
+ 	* sem_aux.adb (Get_Called_Entity): Adding documentation.
+ 	* sem_ch3.adb (Analyze_Full_Type_Declaration): Create the extra formals
+ 	of deferred subprograms, subprogram types and entries; create also the
+ 	extra actuals of deferred calls.
+ 	* sem_ch6.ads (Freeze_Extra_Formals): New subprogram.
+ 	(Deferred_Extra_Formals_Support): New package.
+ 	* sem_ch6.adb (Analyze_Subprogram_Body_Helper): Create the extra formals
+ 	of subprograms without separate spec.
+ 	(Add_Extra_Formal): Add documentation.
+ 	(Has_Extra_Formals): Removed.
+ 	(Parent_Subprogram): Adding documentation.
+ 	(Create_Extra_Formals): Defer adding extra formals if the underlying_type
+ 	of some formal type or return type is not available.
+ 	(Extra_Formals_Match_OK): Add missing check on the extra formals of
+ 	unchecked unions.
+ 	(Freeze_Extra_Formals): New subprogram.
+ 	(Deferred_Extra_Formals_Support): New package.
+ 	* sem_ch9.adb (Analyze_Entry_Declaration): Freeze its extra formals.
+ 	* sem_ch13.adb (New_Put_Image_Subprogram): ditto.
+ 	* sem_util.ads (Is_Unchecked_Union_Equality): New subprogram.
+ 	* sem_util.adb (Is_Unchecked_Union_Equality): ditto.
+ 
+ 2025-07-22  Piotr Trojanek  <trojanek@adacore.com>
+ 
+ 	* sem_util.adb (Get_Actual_Subtype): Do the same for GCC and GNATprove
+ 	backends.
+ 
+ 2025-07-22  Martin Clochard  <clochard@adacore.com>
+ 
+ 	* exp_spark.adb (Expand_SPARK): Add expansion of continue statements.
+ 	(Expand_SPARK_N_Continue_Statement): Expand continue statements resolved
+ 	as procedure calls into said procedure calls.
+ 
+ 2025-07-22  Piotr Trojanek  <trojanek@adacore.com>
+ 
+ 	* sem_res.adb (Resolve_Call): Look at the base type of actual parameter
+ 	when checking call to Set_Handler.
+ 
+ 2025-07-22  Eric Botcazou  <ebotcazou@adacore.com>
+ 
+ 	* sem_util.adb (Get_Actual_Subtype): Only create a new subtype when
+ 	the expander is active.  Remove a useless test of type inequality,
+ 	as well as a useless call to Set_Has_Delayed_Freeze on the subtype.
+ 
+ 2025-07-22  Gary Dismukes  <dismukes@adacore.com>
+ 
+ 	* exp_aggr.adb (Build_Size_Expr): Change test of "not Present (...)"
+ 	to "No (...)".
+ 
+ 2025-07-22  Gary Dismukes  <dismukes@adacore.com>
+ 
+ 	* exp_aggr.adb (Build_Size_Expr): Determine the length of a container
+ 	aggregate association in the case where it's an iteration over an
+ 	object of a container type coming from an instantiation of a predefined
+ 	container generic. Minor updates to existing comments.
+ 
+ 2025-07-22  Ghjuvan Lacambre  <lacambre@adacore.com>
+ 
+ 	* exp_util.adb (Finalize_Address): Prevent infinite loop
+ 
+ 2025-07-22  Steve Baird  <baird@adacore.com>
+ 
+ 	* sem_aux.ads: Declare new function Unique_Component_Name.
+ 	* sem_aux.adb: Implement new function Unique_Component_Name.
+ 
+ 2025-07-22  Viljar Indus  <indus@adacore.com>
+ 
+ 	* sem_ch13.adb (Check_Aspect_At_End_Of_Declarations):
+ 	Ensure the Expression_Copy always has a parent before
+ 	calling any analyze.
+ 
+ 2025-07-22  Steve Baird  <baird@adacore.com>
+ 
+ 	* exp_aggr.adb (Build_Record_Aggr_Code.Gen_Assign): In the case of
+ 	an aggregate component where the component type is mutably tagged
+ 	and the component value is provided by a qualified aggregate (and
+ 	qualified with a specific type), avoid incorrectly rejecting the
+ 	inner aggregate for violating the rule that the type of an
+ 	aggregate shall not be class-wide.
+ 	* exp_attr.adb: For a predefined streaming operation (i.e., Read,
+ 	Write, Input, or Output) of a class-wide type, the external name
+ 	of the tag of the value is normally written out by Output and read
+ 	in by Input. In the case of a mutably tagged type, this is instead
+ 	done in Write and Read.
+ 	* exp_ch4.adb (Expand_Composite_Equality): In the case of an
+ 	equality comparison for a type having a mutably tagged component,
+ 	we want the component comparison to compare two values of the
+ 	mutably tagged type, not two values of the corresponding
+ 	array-of-bytes-ish representation type. Even if there are no
+ 	user-defined equality functions anywhere in sight, comparing the
+ 	array values still doesn't work because undefined bits may end up
+ 	participating in the comparison (resulting in an incorrect result
+ 	of False).
+ 	* exp_put_image.adb: In the case of a class-wide type, the
+ 	predefined Image attribute includes the name of the specific type
+ 	(and a "'" character, to follow qualified expression syntax) to
+ 	indicate the tag of the value. With the introduction of mutably
+ 	tagged types, this case can now arise in the case of a component
+ 	(of either an enclosing array or an enclosing record), not just
+ 	for a top-level object. So we factor the code to do this into a
+ 	new procedure, Put_Specific_Type_Name_Qualifier, so that it can be
+ 	called from more than one place. This reorganization also involves
+ 	replacing the procedure Put_String_Exp with a new procedure,
+ 	Put_String_Exp_To_Buffer, declared in a less nested scope. For
+ 	mutably tagged components (at the source level) the component type
+ 	(at the GNAT tree level) is an array of bytes (actually a two
+ 	field record containing an array of bytes, but that's a detail).
+ 	Appropriate conversions need to be generated so that we don't end
+ 	up generating an image for an array of bytes; this is done at the
+ 	same places where Put_Specific_Type_Name_Qualifier is called
+ 	(for components) by calling Make_Mutably_Tagged_Conversion.
+ 	* exp_strm.adb (Make_Field_Attribute): Add
+ 	Make_Mutably_Tagged_Conversion call where we construct a
+ 	Selected_Component node and the corresponding component type is
+ 	the internal representation type for a mutably tagged type.
+ 	(Stream_Base_Type): Return the mutably
+ 	tagged type if given the corresponding internal representation type.
+ 	* sem_ch3.adb (Array_Type_Declaration): In the case where the
+ 	source-level component type of an array type is mutably tagged,
+ 	set the Component_Type field of the base type of the declared
+ 	array type (as opposed to that of the first subtype of the array
+ 	type) to the corresponding internal representation type.
+ 	* sem_ch4.adb (Analyze_Selected_Component): In the case of a
+ 	selected component name which references a component whose type is
+ 	the internal representation type of a mutably tagged type,
+ 	generate a conversion to the mutably tagged type.
+ 
+ 2025-07-21  Eric Botcazou  <ebotcazou@gcc.gnu.org>
+ 
+ 	PR ada/121184
+ 	* styleg.adb (Check_Comment): Use consistent warning message.
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* gcc-interface/trans.cc (gnat_to_gnu): Pass null pointer to
+ 	parse_{input,output}_constraint().
+ 
  2025-07-18  Steve Baird  <baird@adacore.com>
  
  	* sem_ch12.adb (Validate_Derived_Type_Instance): Cope with the case
diff -Nrcpad gcc-16-20250720/gcc/ada/accessibility.adb gcc-16-20250727/gcc/ada/accessibility.adb
*** gcc-16-20250720/gcc/ada/accessibility.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/accessibility.adb	Sun Jul 27 22:32:07 2025
*************** package body Accessibility is
*** 327,334 ****
                 if In_Return_Value (N)
                   or else In_Return_Context
                 then
!                   return Make_Level_Literal
!                            (Subprogram_Access_Level (Current_Subprogram));
                 end if;
              end if;
  
--- 327,349 ----
                 if In_Return_Value (N)
                   or else In_Return_Context
                 then
!                   if Present (Extra_Accessibility_Of_Result
!                                 (Current_Subprogram))
!                   then
!                      --  If a function is passed an extra "level of the
!                      --  master of the call" parameter and that function
!                      --  returns a call to another such function (or
!                      --  possibly to the same function, in the case of a
!                      --  recursive call), then that parameter should be
!                      --  "passed along".
! 
!                      return New_Occurrence_Of
!                               (Extra_Accessibility_Of_Result
!                                 (Current_Subprogram), Loc);
!                   else
!                      return Make_Level_Literal
!                               (Subprogram_Access_Level (Current_Subprogram));
!                   end if;
                 end if;
              end if;
  
*************** package body Accessibility is
*** 1683,1698 ****
                  Condition => Check_Cond,
                  Reason    => PE_Accessibility_Check_Failed));
  
!             --  If constant folding has happened on the condition for the
!             --  generated error, then warn about it being unconditional when
!             --  we know an error will be raised.
  
              if Nkind (Check_Cond) = N_Identifier
                and then Entity (Check_Cond) = Standard_True
              then
                 Error_Msg_N
!                  ("access discriminant in return object could be a dangling"
!                   & " reference??", Return_Stmt);
              end if;
           end if;
  
--- 1698,1711 ----
                  Condition => Check_Cond,
                  Reason    => PE_Accessibility_Check_Failed));
  
!             --  ??? Is this how we want to detect RM 6.5(5.9) violations?
  
              if Nkind (Check_Cond) = N_Identifier
                and then Entity (Check_Cond) = Standard_True
              then
                 Error_Msg_N
!                  ("level of type of access discriminant value of return object"
!                     & " is statically too deep", Return_Stmt);
              end if;
           end if;
  
diff -Nrcpad gcc-16-20250720/gcc/ada/aspects.ads gcc-16-20250727/gcc/ada/aspects.ads
*** gcc-16-20250720/gcc/ada/aspects.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/aspects.ads	Sun Jul 27 22:32:07 2025
*************** package Aspects is
*** 92,97 ****
--- 92,98 ----
        Aspect_Default_Value,
        Aspect_Depends,                       -- GNAT
        Aspect_Designated_Storage_Model,      -- GNAT
+       Aspect_Destructor,                    -- GNAT
        Aspect_Dimension,                     -- GNAT
        Aspect_Dimension_System,              -- GNAT
        Aspect_Dispatching_Domain,
*************** package Aspects is
*** 259,264 ****
--- 260,266 ----
                                   | Aspect_Iterator_Element
                                   | Aspect_Max_Entry_Queue_Length
                                   | Aspect_No_Controlled_Parts
+                                  | Aspect_No_Task_Parts
                                   | Aspect_Real_Literal
                                   | Aspect_String_Literal
                                   | Aspect_Variable_Indexing;
*************** package Aspects is
*** 293,298 ****
--- 295,301 ----
        Aspect_CUDA_Global                => True,
        Aspect_Depends                    => True,
        Aspect_Designated_Storage_Model   => True,
+       Aspect_Destructor                 => True,
        Aspect_Dimension                  => True,
        Aspect_Dimension_System           => True,
        Aspect_Disable_Controlled         => True,
*************** package Aspects is
*** 447,452 ****
--- 450,456 ----
        Aspect_Default_Value              => Expression,
        Aspect_Depends                    => Expression,
        Aspect_Designated_Storage_Model   => Name,
+       Aspect_Destructor                 => Name,
        Aspect_Dimension                  => Expression,
        Aspect_Dimension_System           => Expression,
        Aspect_Dispatching_Domain         => Expression,
*************** package Aspects is
*** 551,556 ****
--- 555,561 ----
        Aspect_Default_Value                => True,
        Aspect_Depends                      => False,
        Aspect_Designated_Storage_Model     => True,
+       Aspect_Destructor                   => False,
        Aspect_Dimension                    => False,
        Aspect_Dimension_System             => False,
        Aspect_Dispatching_Domain           => False,
*************** package Aspects is
*** 726,731 ****
--- 731,737 ----
        Aspect_Default_Value                => Name_Default_Value,
        Aspect_Depends                      => Name_Depends,
        Aspect_Designated_Storage_Model     => Name_Designated_Storage_Model,
+       Aspect_Destructor                   => Name_Destructor,
        Aspect_Dimension                    => Name_Dimension,
        Aspect_Dimension_System             => Name_Dimension_System,
        Aspect_Disable_Controlled           => Name_Disable_Controlled,
*************** package Aspects is
*** 994,999 ****
--- 1000,1006 ----
        Aspect_Default_Value                => Always_Delay,
        Aspect_Default_Component_Value      => Always_Delay,
        Aspect_Designated_Storage_Model     => Always_Delay,
+       Aspect_Destructor                   => Always_Delay,
        Aspect_Discard_Names                => Always_Delay,
        Aspect_Dispatching_Domain           => Always_Delay,
        Aspect_Dynamic_Predicate            => Always_Delay,
diff -Nrcpad gcc-16-20250720/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst gcc-16-20250727/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst
*** gcc-16-20250720/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst	Sun Jul 27 22:32:07 2025
*************** statement in the sequence of statements
*** 1793,1795 ****
--- 1793,1863 ----
  
  Note that ``continue`` is a keyword but it is not a reserved word. This is a
  configuration that does not exist in standard Ada.
+ 
+ Destructors
+ -----------
+ 
+ The ``Destructor`` aspect can be applied to any record type, tagged or not.
+ It must denote a primitive of the type that is a procedure with one parameter
+ of the type and of mode ``in out``:
+ 
+ .. code-block:: ada
+ 
+    type T is record
+       ...
+    end record with Destructor => Foo;
+ 
+    procedure Foo (X : in out T);
+ 
+ This is equivalent to the following code that uses ``Finalizable``:
+ 
+ .. code-block:: ada
+ 
+    type T is record
+       ...
+    end record with Finalizable => (Finalize => Foo);
+ 
+    procedure Foo (X : in out T);
+ 
+ Unlike ``Finalizable``, however, ``Destructor`` can be specified on a derived
+ type. And when it is, the effect of the aspect combines with the destructors of
+ the parent type. Take, for example:
+ 
+ .. code-block:: ada
+ 
+    type T1 is record
+       ...
+    end record with Destructor => Foo;
+ 
+    procedure Foo (X : in out T1);
+ 
+    type T2 is new T1 with Destructor => Bar;
+ 
+    procedure Bar (X : in out T2);
+ 
+ Here, when an object of type ``T2`` is finalized, a call to ``Bar``
+ will be performed and it will be followed by a call to ``Foo``.
+ 
+ The ``Destructor`` aspect comes with a legality rule: if a primitive procedure
+ of a type is denoted by a ``Destructor`` aspect specification, it is illegal to
+ override this procedure in a derived type. For example, the following is illegal:
+ 
+ .. code-block:: ada
+ 
+    type T1 is record
+       ...
+    end record with Destructor => Foo;
+ 
+    procedure Foo (X : in out T1);
+ 
+    type T2 is new T1;
+ 
+    overriding
+    procedure Foo (X : in out T2); -- Error here
+ 
+ It is possible to specify ``Destructor`` on the completion of a private type,
+ but there is one more restriction in that case: the denoted primitive must
+ be private to the enclosing package. This is necessary due to the previously
+ mentioned legality rule, to prevent breaking the privacy of the type when
+ imposing that rule on outside types that derive from the private view of the
+ type.
diff -Nrcpad gcc-16-20250720/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst gcc-16-20250727/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
*** gcc-16-20250720/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst	Sun Jul 27 22:32:07 2025
*************** must define with the following profile:
*** 333,341 ****
                   "__gnat_last_chance_handler");
  
  
! The parameter is a C null-terminated string representing a message to be
! associated with the exception (typically the source location of the raise
! statement generated by the compiler). The Line parameter when nonzero
  represents the line number in the source program where the raise occurs.
  
  No_Exception_Propagation
--- 333,341 ----
                   "__gnat_last_chance_handler");
  
  
! The ``Source_Location`` parameter is a C null-terminated string representing a
! message to be associated with the exception (typically the source location of
! the raise statement generated by the compiler). The Line parameter when nonzero
  represents the line number in the source program where the raise occurs.
  
  No_Exception_Propagation
diff -Nrcpad gcc-16-20250720/gcc/ada/einfo.ads gcc-16-20250727/gcc/ada/einfo.ads
*** gcc-16-20250720/gcc/ada/einfo.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/einfo.ads	Sun Jul 27 22:32:07 2025
*************** package Einfo is
*** 1279,1287 ****
  --       that represents an activation record pointer is an extra formal.
  
  --    Extra_Formals
! --       Applies to subprograms, subprogram types, entries, and entry
! --       families. Returns first extra formal of the subprogram or entry.
! --       Returns Empty if there are no extra formals.
  
  --    Finalization_Collection [root type only]
  --       Defined in access-to-controlled or access-to-class-wide types. The
--- 1279,1288 ----
  --       that represents an activation record pointer is an extra formal.
  
  --    Extra_Formals
! --       Applies to subprograms, subprogram types, entries, and entry families.
! --       Returns the first extra formal of the subprogram or entry. An entity
! --       has no extra formals when this attribute is Empty, and its attribute
! --       Extra_Formals_Known is True.
  
  --    Finalization_Collection [root type only]
  --       Defined in access-to-controlled or access-to-class-wide types. The
*************** package Einfo is
*** 1594,1599 ****
--- 1595,1605 ----
  --       set, signalling that Freeze.Inherit_Delayed_Rep_Aspects must be called
  --       at the freeze point of the derived type.
  
+ --    Has_Destructor
+ --       Defined in all type and subtype entities. Set only for record type
+ --       entities for which at least one ancestor has the Destructor aspect
+ --       specified.
+ 
  --    Has_DIC (synthesized)
  --       Defined in all type entities. Set for a private type and its full view
  --       when the type is subject to pragma Default_Initial_Condition (DIC), or
*************** package Einfo is
*** 1640,1650 ****
  --       that this does not imply a representation with holes, since the rep
  --       clause may merely confirm the default 0..N representation.
  
- --    Has_First_Controlling_Parameter_Aspect
- --       Defined in tagged types, concurrent types and concurrent record types.
- --       Set to indicate that the type has a First_Controlling_Parameter of
- --       True (whether by an aspect_specification, a pragma, or inheritance).
- 
  --    Has_Exit
  --       Defined in loop entities. Set if the loop contains an exit statement.
  
--- 1646,1651 ----
*************** package Einfo is
*** 1654,1659 ****
--- 1655,1666 ----
  --       flag prevents double expansion of a contract when a construct is
  --       rewritten into something else and subsequently reanalyzed/expanded.
  
+ --    Has_First_Controlling_Parameter_Aspect
+ --       Defined in tagged types, concurrent types, and concurrent record
+ --       types. Set to indicate that the type has a First_Controlling_Parameter
+ --       of True (whether by an aspect_specification, a pragma, or
+ --       inheritance).
+ 
  --    Has_Foreign_Convention (synthesized)
  --       Applies to all entities. Determines if the Convention for the entity
  --       is a foreign convention, i.e. non-native: other than Convention_Ada,
*************** package Einfo is
*** 1668,1673 ****
--- 1675,1686 ----
  --       the instance will conflict with the linear elaboration of front-end
  --       inlining.
  
+ --    Extra_Formals_Known
+ --       Defined in subprograms, subprogram types, entries, and entry families.
+ --       Set when the extra formals have been determined. An entity has no
+ --       extra formals when this attribute is True, and its attribute
+ --       Extra_Formals is Empty.
+ 
  --    Has_Fully_Qualified_Name
  --       Defined in all entities. Set if the name in the Chars field has been
  --       replaced by the fully qualified name, as used for debug output. See
*************** package Einfo is
*** 2515,2525 ****
  
  --    Is_Controlled_Active [base type only]
  --       Defined in all type entities. Indicates that the type is controlled,
! --       i.e. has been declared with the Finalizable aspect or has inherited
! --       the Finalizable aspect from an ancestor. Can only be set for record
! --       types, tagged or untagged. System.Finalization_Root.Root_Controlled
! --       is an example of the former case while Ada.Finalization.Controlled
! --       and Ada.Finalization.Limited_Controlled are examples of the latter.
  
  --    Is_Controlled (synth) [base type only]
  --       Defined in all type entities. Set if Is_Controlled_Active is set for
--- 2528,2539 ----
  
  --    Is_Controlled_Active [base type only]
  --       Defined in all type entities. Indicates that the type is controlled,
! --       i.e. has been declared with the Finalizable or the Destructor aspect
! --       or has inherited the aspect from an ancestor. Can only be set for
! --       record types, tagged or untagged.
! --       System.Finalization_Root.Root_Controlled is an example of the former
! --       case while Ada.Finalization.Controlled and
! --       Ada.Finalization.Limited_Controlled are examples of the latter.
  
  --    Is_Controlled (synth) [base type only]
  --       Defined in all type entities. Set if Is_Controlled_Active is set for
*************** package Einfo is
*** 2545,2550 ****
--- 2559,2568 ----
  --       Defined in all entities. True if the entity is type System.Address,
  --       or (recursively) a subtype or derived type of System.Address.
  
+ --    Is_Destructor
+ --       Defined in procedure entities. True if the procedure is denoted by the
+ --       Destructor aspect on some type.
+ 
  --    Is_DIC_Procedure
  --       Defined in functions and procedures. Set for a generated procedure
  --       which verifies the assumption of pragma Default_Initial_Condition at
*************** package Einfo is
*** 2779,2784 ****
--- 2797,2806 ----
  --       identifiers in standard library packages, and to implement the
  --       restriction No_Implementation_Identifiers.
  
+ --    Is_Implicit_Full_View
+ --       Defined in types. Set on types that the compiler generates to act as
+ --       full views of types that are derivations of private types.
+ 
  --    Is_Imported
  --       Defined in all entities. Set if the entity is imported. For now we
  --       only allow the import of exceptions, functions, procedures, packages,
*************** package Einfo is
*** 5393,5403 ****
     --    Scope_Depth_Value
     --    Protection_Object                    (protected kind)
     --    Contract_Wrapper
-    --    Extra_Formals
     --    Contract
     --    SPARK_Pragma                         (protected kind)
     --    Default_Expressions_Processed
     --    Entry_Accepted
     --    Has_Yield_Aspect
     --    Has_Expanded_Contract
     --    Ignore_SPARK_Mode_Pragmas
--- 5415,5426 ----
     --    Scope_Depth_Value
     --    Protection_Object                    (protected kind)
     --    Contract_Wrapper
     --    Contract
     --    SPARK_Pragma                         (protected kind)
     --    Default_Expressions_Processed
     --    Entry_Accepted
+    --    Extra_Formals
+    --    Extra_Formals_Known
     --    Has_Yield_Aspect
     --    Has_Expanded_Contract
     --    Ignore_SPARK_Mode_Pragmas
*************** package Einfo is
*** 5519,5524 ****
--- 5542,5548 ----
     --    Overridden_Operation
     --    Wrapped_Entity                       (non-generic case only)
     --    Extra_Formals
+    --    Extra_Formals_Known                  (non-generic case only)
     --    Anonymous_Collections                (non-generic case only)
     --    Corresponding_Equality               (implicit /= only)
     --    Thunk_Entity                         (thunk case only)
*************** package Einfo is
*** 5723,5728 ****
--- 5747,5754 ----
     --    Overridden_Operation
     --    Linker_Section_Pragma
     --    Contract
+    --    Extra_Formals
+    --    Extra_Formals_Known
     --    Import_Pragma
     --    LSP_Subprogram
     --    SPARK_Pragma
*************** package Einfo is
*** 5877,5882 ****
--- 5903,5909 ----
     --    Overridden_Operation                 (never for init proc)
     --    Wrapped_Entity                       (non-generic case only)
     --    Extra_Formals
+    --    Extra_Formals_Known                  (non-generic case only)
     --    Anonymous_Collections                (non-generic case only)
     --    Static_Initialization                (init_proc only)
     --    Thunk_Entity                         (thunk case only)
*************** package Einfo is
*** 5915,5920 ****
--- 5942,5948 ----
     --    Is_Class_Wide_Wrapper
     --    Is_Constructor
     --    Is_CUDA_Kernel
+    --    Is_Destructor                        (non-generic case only)
     --    Is_DIC_Procedure                     (non-generic case only)
     --    Is_Elaboration_Checks_OK_Id
     --    Is_Elaboration_Warnings_OK_Id
*************** package Einfo is
*** 6104,6109 ****
--- 6132,6138 ----
     --    Last_Entity
     --    Scope_Depth_Value
     --    Extra_Formals
+    --    Extra_Formals_Known
     --    Anonymous_Collections
     --    Contract
     --    SPARK_Pragma
*************** package Einfo is
*** 6117,6122 ****
--- 6146,6152 ----
     --    Extra_Accessibility_Of_Result
     --    Directly_Designated_Type
     --    Extra_Formals
+    --    Extra_Formals_Known
     --    Access_Subprogram_Wrapper
     --    First_Formal                         (synth)
     --    First_Formal_With_Extras             (synth)
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_aggr.adb gcc-16-20250727/gcc/ada/exp_aggr.adb
*** gcc-16-20250720/gcc/ada/exp_aggr.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_aggr.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_Aggr is
*** 1422,1429 ****
                 elsif Is_Mutably_Tagged_Type (Comp_Typ)
                   and then Nkind (Expr) = N_Qualified_Expression
                 then
!                   Analyze_And_Resolve (Expr_Q, Etype (Expr));
  
                 else
                    Analyze_And_Resolve (Expr_Q, Comp_Typ);
                 end if;
--- 1422,1432 ----
                 elsif Is_Mutably_Tagged_Type (Comp_Typ)
                   and then Nkind (Expr) = N_Qualified_Expression
                 then
!                   --  Avoid class-wide expected type for aggregate
!                   --  (which would be rejected as illegal)
!                   --  if the aggregate is explicitly qualified.
  
+                   Analyze_And_Resolve (Expr_Q, Etype (Expr));
                 else
                    Analyze_And_Resolve (Expr_Q, Comp_Typ);
                 end if;
*************** package body Exp_Aggr is
*** 4346,4351 ****
--- 4349,4355 ----
          and then Is_Limited_Type (Typ)
        then
           Target_Expr := New_Copy_Tree (Name (Parent_Node));
+          Ensure_Defined (Typ, Parent_Node);
           Insert_Actions (Parent_Node,
             Build_Record_Aggr_Code (N, Typ, Target_Expr));
           Rewrite (Parent_Node, Make_Null_Statement (Loc));
*************** package body Exp_Aggr is
*** 4371,4376 ****
--- 4375,4381 ----
  
              if Nkind (N) in N_Aggregate | N_Extension_Aggregate then
                 Target_Expr := New_Copy_Tree (Lhs);
+                Ensure_Defined (Typ, Parent_Node);
                 Insert_Actions (Parent_Node,
                   Build_Record_Aggr_Code (N, Typ, Target_Expr));
                 Rewrite (Parent_Node, Make_Null_Statement (Loc));
*************** package body Exp_Aggr is
*** 6729,6734 ****
--- 6734,6740 ----
        function Build_Size_Expr (Comp : Node_Id) return Node_Id is
           Lo, Hi       : Node_Id;
           It           : Node_Id;
+          It_Subt      : Entity_Id;
           Siz_Exp      : Node_Id := Empty;
           Choice       : Node_Id;
           Temp_Siz_Exp : Node_Id;
*************** package body Exp_Aggr is
*** 6803,6822 ****
           elsif Nkind (Comp) = N_Iterated_Component_Association then
              if Present (Iterator_Specification (Comp)) then
  
!                --  If the static size of the iterable object is known,
                 --  attempt to return it.
  
                 It := Name (Iterator_Specification (Comp));
                 Preanalyze (It);
  
!                --  Handle the simplest cases for now where It denotes an array
!                --  object.
  
                 if Nkind (It) in N_Identifier
!                  and then Ekind (Etype (It)) = E_Array_Subtype
                 then
                    declare
!                      Idx_N : Node_Id := First_Index (Etype (It));
                       Siz_Exp : Node_Id := Empty;
                    begin
                       while Present (Idx_N) loop
--- 6809,6830 ----
           elsif Nkind (Comp) = N_Iterated_Component_Association then
              if Present (Iterator_Specification (Comp)) then
  
!                --  If the size of the iterable object can be determined,
                 --  attempt to return it.
  
                 It := Name (Iterator_Specification (Comp));
                 Preanalyze (It);
  
!                It_Subt := Etype (It);
! 
!                --  Handle the simplest cases for now, where It denotes an array
!                --  object or a container object.
  
                 if Nkind (It) in N_Identifier
!                  and then Ekind (It_Subt) = E_Array_Subtype
                 then
                    declare
!                      Idx_N : Node_Id := First_Index (It_Subt);
                       Siz_Exp : Node_Id := Empty;
                    begin
                       while Present (Idx_N) loop
*************** package body Exp_Aggr is
*** 6850,6855 ****
--- 6858,6953 ----
  
                       return Siz_Exp;
                    end;
+ 
+                --  Case of iterating over a container object. Note that this
+                --  must be a simple object, and not something like a function
+                --  call (which might have side effects, and we wouldn't want
+                --  it to be evaluated more than once). We take advantage of
+                --  RM22 4.3.5(40/5), which allows implementation-defined
+                --  behavior for the parameter passed to the Empty function,
+                --  and here use the container Length function when available.
+                --  Class-wide objects are also excluded, since those would
+                --  lead to dispatching, which could call a user-defined
+                --  overriding of Length that might have arbitrary effects.
+ 
+                elsif Is_Entity_Name (It)
+                  and then Is_Object (Entity (It))
+                  and then Ekind (It_Subt) in Record_Kind
+                  and then not Is_Class_Wide_Type (It_Subt)
+                then
+                   declare
+                      Aggr_Base    : constant Entity_Id := Base_Type (Typ);
+                      It_Base      : constant Entity_Id := Base_Type (It_Subt);
+                      Empty_Formal : constant Entity_Id :=
+                                       First_Formal (Entity (Empty_Subp));
+                      Length_Subp  : Entity_Id;
+                      Param_List   : List_Id;
+ 
+                   begin
+                      --  We only determine a nondefault capacity in the case
+                      --  of containers of predefined container types, which
+                      --  generally have a Length function. User-defined
+                      --  containers don't necessarily have such a function,
+                      --  or it may be named differently, or it may have
+                      --  the wrong semantics. The base subtypes are tested,
+                      --  since their Sloc will refer to the original container
+                      --  generics in the predefined library, even though the
+                      --  types are declared in a package instantiation in some
+                      --  other unit. Also, this is only done when Empty_Subp
+                      --  has a formal parameter (generally named Capacity),
+                      --  and not in the case of a parameterless Empty function.
+                      --  Finally, we test for the container aggregate's type
+                      --  having a first discriminant with the name Capacity,
+                      --  since determining capacity via Length is only sensible
+                      --  for container types with that discriminant (bounded
+                      --  containers).
+ 
+                      if Present (Empty_Formal)
+                        and then In_Predefined_Unit (It_Base)
+                        and then In_Predefined_Unit (Aggr_Base)
+                        and then Has_Discriminants (Aggr_Base)
+                        and then
+                          Get_Name_String
+                            (Chars (First_Discriminant (Aggr_Base)))
+                            = "capacity"
+                      then
+                         --  Look for the container type's Length function in
+                         --  the package where it's defined.
+ 
+                         Push_Scope (Scope (It_Base));
+ 
+                         Length_Subp := Current_Entity_In_Scope (Name_Length);
+ 
+                         Pop_Scope;
+ 
+                         --  If we found a Length function that has a single
+                         --  parameter of the iterator object's container type,
+                         --  then expand a call to that, passing the object,
+                         --  and return that call, which will be used as the
+                         --  "size" of the current element association of the
+                         --  bounded container aggregate.
+ 
+                         if Present (Length_Subp)
+                           and then Ekind (Length_Subp) = E_Function
+                           and then
+                             Present (First_Entity (Length_Subp))
+                           and then
+                             No (Next_Entity (First_Entity (Length_Subp)))
+                           and then
+                             Base_Type
+                               (Etype (First_Entity (Length_Subp))) = It_Base
+                         then
+                            Param_List :=
+                              New_List (New_Occurrence_Of (Entity (It), Loc));
+ 
+                            return
+                              Make_Function_Call (Loc,
+                                Name =>
+                                  New_Occurrence_Of (Length_Subp, Loc),
+                                Parameter_Associations => Param_List);
+                         end if;
+                      end if;
+                   end;
                 end if;
  
                 return Empty;
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_attr.adb gcc-16-20250727/gcc/ada/exp_attr.adb
*** gcc-16-20250720/gcc/ada/exp_attr.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_attr.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_Attr is
*** 1915,1920 ****
--- 1915,1929 ----
        --  call to the appropriate TSS procedure. Pname is the entity for the
        --  procedure to call.
  
+       procedure Read_Controlling_Tag
+         (P_Type : Entity_Id; Cntrl : out Node_Id);
+       --  Read the external tag from the stream and use it to construct the
+       --  controlling operand for a dispatching call.
+ 
+       procedure Write_Controlling_Tag (P_Type : Entity_Id);
+       --  Write the external tag of the given attribute prefix type to
+       --  the stream. Also perform the accompanying accessibility check.
+ 
        -------------------------------------
        -- Build_And_Insert_Type_Attr_Subp --
        -------------------------------------
*************** package body Exp_Attr is
*** 2175,2180 ****
--- 2184,2336 ----
           Analyze (N);
        end Rewrite_Attribute_Proc_Call;
  
+       --------------------------
+       -- Read_Controlling_Tag --
+       --------------------------
+ 
+       procedure Read_Controlling_Tag
+         (P_Type : Entity_Id; Cntrl : out Node_Id)
+       is
+          Strm    : constant Node_Id := First (Exprs);
+          Expr    : Node_Id; -- call to Descendant_Tag
+          Get_Tag : Node_Id; -- expression to read the 'Tag
+ 
+       begin
+          --  Read the internal tag (RM 13.13.2(34)) and use it to
+          --  initialize a dummy tag value. We used to unconditionally
+          --  generate:
+          --
+          --     Descendant_Tag (String'Input (Strm), P_Type);
+          --
+          --  which turns into a call to String_Input_Blk_IO. However,
+          --  if the input is malformed, that could try to read an
+          --  enormous String, causing chaos. So instead we call
+          --  String_Input_Tag, which does the same thing as
+          --  String_Input_Blk_IO, except that if the String is
+          --  absurdly long, it raises an exception.
+          --
+          --  However, if the No_Stream_Optimizations restriction
+          --  is active, we disable this unnecessary attempt at
+          --  robustness; we really need to read the string
+          --  character-by-character.
+          --
+          --  This value is used only to provide a controlling
+          --  argument for the eventual _Input call. Descendant_Tag is
+          --  called rather than Internal_Tag to ensure that we have a
+          --  tag for a type that is descended from the prefix type and
+          --  declared at the same accessibility level (the exception
+          --  Tag_Error will be raised otherwise). The level check is
+          --  required for Ada 2005 because tagged types can be
+          --  extended in nested scopes (AI-344).
+ 
+          --  Note: we used to generate an explicit declaration of a
+          --  constant Ada.Tags.Tag object, and use an occurrence of
+          --  this constant in Cntrl, but this caused a secondary stack
+          --  leak.
+ 
+          if Restriction_Active (No_Stream_Optimizations) then
+             Get_Tag :=
+               Make_Attribute_Reference (Loc,
+                 Prefix         =>
+                   New_Occurrence_Of (Standard_String, Loc),
+                 Attribute_Name => Name_Input,
+                 Expressions    => New_List (
+                   Relocate_Node (Duplicate_Subexpr (Strm))));
+          else
+             Get_Tag :=
+               Make_Function_Call (Loc,
+                 Name                   =>
+                   New_Occurrence_Of
+                     (RTE (RE_String_Input_Tag), Loc),
+                 Parameter_Associations => New_List (
+                   Relocate_Node (Duplicate_Subexpr (Strm))));
+          end if;
+ 
+          Expr :=
+            Make_Function_Call (Loc,
+              Name                   =>
+                New_Occurrence_Of (RTE (RE_Descendant_Tag), Loc),
+              Parameter_Associations => New_List (
+                Get_Tag,
+                Make_Attribute_Reference (Loc,
+                  Prefix         => New_Occurrence_Of (P_Type, Loc),
+                  Attribute_Name => Name_Tag)));
+ 
+          Set_Etype (Expr, RTE (RE_Tag));
+ 
+          --  Construct a controlling operand for a dispatching call.
+ 
+          Cntrl := Unchecked_Convert_To (P_Type, Expr);
+          Set_Etype (Cntrl, P_Type);
+          Set_Parent (Cntrl, N);
+       end Read_Controlling_Tag;
+ 
+       ----------------------------
+       --  Write_Controlling_Tag --
+       ----------------------------
+ 
+       procedure Write_Controlling_Tag (P_Type : Entity_Id) is
+          Strm : constant Node_Id := First (Exprs);
+          Item : constant Node_Id := Next (Strm);
+       begin
+          --  Ada 2005 (AI-344): Check that the accessibility level
+          --  of the type of the output object is not deeper than
+          --  that of the attribute's prefix type.
+ 
+          --  if Get_Access_Level (Item'Tag)
+          --       /= Get_Access_Level (P_Type'Tag)
+          --  then
+          --     raise Tag_Error;
+          --  end if;
+ 
+          --  String'Output (Strm, External_Tag (Item'Tag));
+ 
+          --  We cannot figure out a practical way to implement this
+          --  accessibility check on virtual machines, so we omit it.
+ 
+          if Ada_Version >= Ada_2005
+            and then Tagged_Type_Expansion
+          then
+             Insert_Action (N,
+               Make_Implicit_If_Statement (N,
+                 Condition =>
+                   Make_Op_Ne (Loc,
+                     Left_Opnd  =>
+                       Build_Get_Access_Level (Loc,
+                         Make_Attribute_Reference (Loc,
+                           Prefix         =>
+                             Relocate_Node (
+                               Duplicate_Subexpr (Item,
+                                 Name_Req => True)),
+                           Attribute_Name => Name_Tag)),
+ 
+                     Right_Opnd =>
+                       Make_Integer_Literal (Loc,
+                         Type_Access_Level (P_Type))),
+ 
+                 Then_Statements =>
+                   New_List (Make_Raise_Statement (Loc,
+                               New_Occurrence_Of (
+                                 RTE (RE_Tag_Error), Loc)))));
+          end if;
+ 
+          Insert_Action (N,
+            Make_Attribute_Reference (Loc,
+              Prefix => New_Occurrence_Of (Standard_String, Loc),
+              Attribute_Name => Name_Output,
+              Expressions => New_List (
+                Relocate_Node (Duplicate_Subexpr (Strm)),
+                Make_Function_Call (Loc,
+                  Name =>
+                    New_Occurrence_Of (RTE (RE_External_Tag), Loc),
+                  Parameter_Associations => New_List (
+                   Make_Attribute_Reference (Loc,
+                     Prefix =>
+                       Relocate_Node
+                         (Duplicate_Subexpr (Item, Name_Req => True)),
+                     Attribute_Name => Name_Tag))))));
+       end Write_Controlling_Tag;
+ 
        Typ  : constant Entity_Id    := Etype (N);
        Btyp : constant Entity_Id    := Base_Type (Typ);
        Ptyp : constant Entity_Id    := Etype (Pref);
*************** package body Exp_Attr is
*** 4487,4580 ****
  
              elsif Is_Class_Wide_Type (P_Type) then
  
!                --  No need to do anything else compiling under restriction
!                --  No_Dispatching_Calls. During the semantic analysis we
!                --  already notified such violation.
! 
!                if Restriction_Active (No_Dispatching_Calls) then
!                   return;
!                end if;
  
!                declare
!                   Rtyp : constant Entity_Id := Root_Type (P_Type);
  
!                   Expr    : Node_Id; -- call to Descendant_Tag
!                   Get_Tag : Node_Id; -- expression to read the 'Tag
  
!                begin
!                   --  Read the internal tag (RM 13.13.2(34)) and use it to
!                   --  initialize a dummy tag value. We used to unconditionally
!                   --  generate:
!                   --
!                   --     Descendant_Tag (String'Input (Strm), P_Type);
!                   --
!                   --  which turns into a call to String_Input_Blk_IO. However,
!                   --  if the input is malformed, that could try to read an
!                   --  enormous String, causing chaos. So instead we call
!                   --  String_Input_Tag, which does the same thing as
!                   --  String_Input_Blk_IO, except that if the String is
!                   --  absurdly long, it raises an exception.
!                   --
!                   --  However, if the No_Stream_Optimizations restriction
!                   --  is active, we disable this unnecessary attempt at
!                   --  robustness; we really need to read the string
!                   --  character-by-character.
!                   --
!                   --  This value is used only to provide a controlling
!                   --  argument for the eventual _Input call. Descendant_Tag is
!                   --  called rather than Internal_Tag to ensure that we have a
!                   --  tag for a type that is descended from the prefix type and
!                   --  declared at the same accessibility level (the exception
!                   --  Tag_Error will be raised otherwise). The level check is
!                   --  required for Ada 2005 because tagged types can be
!                   --  extended in nested scopes (AI-344).
  
!                   --  Note: we used to generate an explicit declaration of a
!                   --  constant Ada.Tags.Tag object, and use an occurrence of
!                   --  this constant in Cntrl, but this caused a secondary stack
!                   --  leak.
  
!                   if Restriction_Active (No_Stream_Optimizations) then
!                      Get_Tag :=
                         Make_Attribute_Reference (Loc,
!                          Prefix         =>
!                            New_Occurrence_Of (Standard_String, Loc),
!                          Attribute_Name => Name_Input,
!                          Expressions    => New_List (
!                            Relocate_Node (Duplicate_Subexpr (Strm))));
!                   else
!                      Get_Tag :=
!                        Make_Function_Call (Loc,
!                          Name                   =>
!                            New_Occurrence_Of
!                              (RTE (RE_String_Input_Tag), Loc),
!                          Parameter_Associations => New_List (
!                            Relocate_Node (Duplicate_Subexpr (Strm))));
!                   end if;
! 
!                   Expr :=
!                     Make_Function_Call (Loc,
!                       Name                   =>
!                         New_Occurrence_Of (RTE (RE_Descendant_Tag), Loc),
!                       Parameter_Associations => New_List (
!                         Get_Tag,
!                         Make_Attribute_Reference (Loc,
!                           Prefix         => New_Occurrence_Of (P_Type, Loc),
!                           Attribute_Name => Name_Tag)));
  
!                   Set_Etype (Expr, RTE (RE_Tag));
  
!                   --  Now we need to get the entity for the call, and construct
!                   --  a function call node, where we preset a reference to Dnn
!                   --  as the controlling argument (doing an unchecked convert
!                   --  to the class-wide tagged type to make it look like a real
!                   --  tagged object).
  
!                   Fname := Find_Prim_Op (Rtyp, TSS_Stream_Input);
!                   Cntrl := Unchecked_Convert_To (P_Type, Expr);
!                   Set_Etype (Cntrl, P_Type);
!                   Set_Parent (Cntrl, N);
!                end;
  
              --  For tagged types, use the primitive Input function
  
--- 4643,4699 ----
  
              elsif Is_Class_Wide_Type (P_Type) then
  
!                if Is_Mutably_Tagged_Type (P_Type) then
  
!                   --  In mutably tagged case, rewrite
!                   --    T'Class'Input (Strm)
!                   --  as (roughly)
!                   --    declare
!                   --       Result : T'Class;
!                   --       T'Class'Read (Strm, Result);
!                   --    begin
!                   --      Result;
!                   --    end;
  
!                   declare
!                      Result_Temp : constant Entity_Id :=
!                        Make_Temporary (Loc, 'I');
  
!                      --  Gets default initialization
!                      Result_Temp_Decl : constant Node_Id :=
!                        Make_Object_Declaration (Loc,
!                          Defining_Identifier => Result_Temp,
!                          Object_Definition =>
!                            New_Occurrence_Of (P_Type, Loc));
  
!                      function Result_Temp_Name return Node_Id is
!                        (New_Occurrence_Of (Result_Temp, Loc));
  
!                      Actions : constant List_Id := New_List (
!                        Result_Temp_Decl,
                         Make_Attribute_Reference (Loc,
!                          Prefix => New_Occurrence_Of (P_Type, Loc),
!                          Attribute_Name => Name_Read,
!                          Expressions => New_List (
!                            Relocate_Node (Strm), Result_Temp_Name)));
!                   begin
!                      Rewrite (N, Make_Expression_With_Actions (Loc,
!                                    Actions, Result_Temp_Name));
!                      Analyze_And_Resolve (N, P_Type);
!                      return;
!                   end;
!                end if;
  
!                --  No need to do anything else compiling under restriction
!                --  No_Dispatching_Calls. During the semantic analysis we
!                --  already notified such violation.
  
!                if Restriction_Active (No_Dispatching_Calls) then
!                   return;
!                end if;
  
!                Read_Controlling_Tag (P_Type, Cntrl);
!                Fname := Find_Prim_Op (Root_Type (P_Type), TSS_Stream_Input);
  
              --  For tagged types, use the primitive Input function
  
*************** package body Exp_Attr is
*** 5957,5962 ****
--- 6076,6089 ----
                       Attr_Ref => N);
                 end;
  
+             --  In the mutably tagged case, T'Class'Output calls T'Class'Write;
+             --  T'Write will take care of writing out the external tag.
+ 
+             elsif Is_Mutably_Tagged_Type (P_Type) then
+                Set_Attribute_Name (N, Name_Write);
+                Analyze (N);
+                return;
+ 
              --  Class-wide case, first output external tag, then dispatch
              --  to the appropriate primitive Output function (RM 13.13.2(31)).
  
*************** package body Exp_Attr is
*** 5970,6037 ****
                    return;
                 end if;
  
!                Tag_Write : declare
!                   Strm : constant Node_Id := First (Exprs);
!                   Item : constant Node_Id := Next (Strm);
! 
!                begin
!                   --  Ada 2005 (AI-344): Check that the accessibility level
!                   --  of the type of the output object is not deeper than
!                   --  that of the attribute's prefix type.
! 
!                   --  if Get_Access_Level (Item'Tag)
!                   --       /= Get_Access_Level (P_Type'Tag)
!                   --  then
!                   --     raise Tag_Error;
!                   --  end if;
! 
!                   --  String'Output (Strm, External_Tag (Item'Tag));
! 
!                   --  We cannot figure out a practical way to implement this
!                   --  accessibility check on virtual machines, so we omit it.
! 
!                   if Ada_Version >= Ada_2005
!                     and then Tagged_Type_Expansion
!                   then
!                      Insert_Action (N,
!                        Make_Implicit_If_Statement (N,
!                          Condition =>
!                            Make_Op_Ne (Loc,
!                              Left_Opnd  =>
!                                Build_Get_Access_Level (Loc,
!                                  Make_Attribute_Reference (Loc,
!                                    Prefix         =>
!                                      Relocate_Node (
!                                        Duplicate_Subexpr (Item,
!                                          Name_Req => True)),
!                                    Attribute_Name => Name_Tag)),
! 
!                              Right_Opnd =>
!                                Make_Integer_Literal (Loc,
!                                  Type_Access_Level (P_Type))),
! 
!                          Then_Statements =>
!                            New_List (Make_Raise_Statement (Loc,
!                                        New_Occurrence_Of (
!                                          RTE (RE_Tag_Error), Loc)))));
!                   end if;
! 
!                   Insert_Action (N,
!                     Make_Attribute_Reference (Loc,
!                       Prefix => New_Occurrence_Of (Standard_String, Loc),
!                       Attribute_Name => Name_Output,
!                       Expressions => New_List (
!                         Relocate_Node (Duplicate_Subexpr (Strm)),
!                         Make_Function_Call (Loc,
!                           Name =>
!                             New_Occurrence_Of (RTE (RE_External_Tag), Loc),
!                           Parameter_Associations => New_List (
!                            Make_Attribute_Reference (Loc,
!                              Prefix =>
!                                Relocate_Node
!                                  (Duplicate_Subexpr (Item, Name_Req => True)),
!                              Attribute_Name => Name_Tag))))));
!                end Tag_Write;
  
                 Pname := Find_Prim_Op (U_Type, TSS_Stream_Output);
  
--- 6097,6103 ----
                    return;
                 end if;
  
!                Write_Controlling_Tag (P_Type);
  
                 Pname := Find_Prim_Op (U_Type, TSS_Stream_Output);
  
*************** package body Exp_Attr is
*** 6793,6798 ****
--- 6859,6865 ----
           P_Type  : constant Entity_Id := Entity (Pref);
           B_Type  : constant Entity_Id := Base_Type (P_Type);
           U_Type  : constant Entity_Id := Underlying_Type (P_Type);
+          Cntrl   : Node_Id := Empty; -- nonempty only if P_Type mutably tagged
           Pname   : Entity_Id;
           Decl    : Node_Id;
           Prag    : Node_Id;
*************** package body Exp_Attr is
*** 6941,6946 ****
--- 7008,7018 ----
              --  this will dispatch in the class-wide case which is what we want
  
              elsif Is_Tagged_Type (U_Type) then
+ 
+                if Is_Mutably_Tagged_Type (U_Type) then
+                   Read_Controlling_Tag (P_Type, Cntrl);
+                end if;
+ 
                 Pname := Find_Prim_Op (U_Type, TSS_Stream_Read);
  
              --  All other record type cases, including protected records. The
*************** package body Exp_Attr is
*** 7001,7006 ****
--- 7073,7118 ----
  
           Rewrite_Attribute_Proc_Call (Pname);
  
+          if Present (Cntrl) then
+             pragma Assert (Is_Mutably_Tagged_Type (U_Type));
+             pragma Assert (Nkind (N) = N_Procedure_Call_Statement);
+ 
+             --  Assign the Tag value that was read from the stream
+             --  to the tag of the out-mode actual parameter so that
+             --  we dispatch correctly. This isn't quite right.
+             --  We should assign a complete object (not just
+             --  the tag), but that would require a dispatching call to
+             --  perform default initialization of the source object and
+             --  dispatching default init calls are currently not supported.
+ 
+             declare
+                function Select_Tag (Prefix : Node_Id) return Node_Id is
+                  (Make_Selected_Component (Loc,
+                     Prefix => Prefix,
+                     Selector_Name =>
+                       New_Occurrence_Of (First_Tag_Component
+                                            (Etype (Prefix)), Loc)));
+ 
+                Controlling_Actual : constant Node_Id :=
+                  Next (First (Parameter_Associations (N)));
+ 
+                pragma Assert (Is_Controlling_Actual (Controlling_Actual));
+ 
+                Assign_Tag : Node_Id;
+             begin
+                Remove_Side_Effects (Controlling_Actual, Name_Req => True);
+ 
+                Assign_Tag :=
+                  Make_Assignment_Statement (Loc,
+                    Name =>
+                      Select_Tag (New_Copy_Tree (Controlling_Actual)),
+                    Expression => Select_Tag (Cntrl));
+ 
+                Insert_Before (Before => N, Node => Assign_Tag);
+                Analyze (Assign_Tag);
+             end;
+          end if;
+ 
           if not Is_Tagged_Type (P_Type) then
              Cached_Attribute_Ops.Read_Map.Set (U_Type, Pname);
           end if;
*************** package body Exp_Attr is
*** 8611,8616 ****
--- 8723,8736 ----
              --  this will dispatch in the class-wide case which is what we want
  
              elsif Is_Tagged_Type (U_Type) then
+ 
+                --  If T'Class is mutably tagged, then the external tag
+                --  is written out by T'Class'Write, not by T'Class'Output.
+ 
+                if Is_Mutably_Tagged_Type (U_Type) then
+                   Write_Controlling_Tag (P_Type);
+                end if;
+ 
                 Pname := Find_Prim_Op (U_Type, TSS_Stream_Write);
  
              --  All other record type cases, including protected records.
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_ch3.adb gcc-16-20250727/gcc/ada/exp_ch3.adb
*** gcc-16-20250720/gcc/ada/exp_ch3.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_ch3.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_Ch3 is
*** 942,951 ****
                 Make_Handled_Sequence_Of_Statements (Loc,
                   Statements => Body_Stmts)));
  
!          Mutate_Ekind       (Proc_Id, E_Procedure);
!          Set_Is_Public      (Proc_Id, Is_Public (A_Type));
!          Set_Is_Internal    (Proc_Id);
!          Set_Has_Completion (Proc_Id);
  
           if not Debug_Generated_Code then
              Set_Debug_Info_Off (Proc_Id);
--- 942,952 ----
                 Make_Handled_Sequence_Of_Statements (Loc,
                   Statements => Body_Stmts)));
  
!          Mutate_Ekind         (Proc_Id, E_Procedure);
!          Set_Is_Public        (Proc_Id, Is_Public (A_Type));
!          Set_Is_Internal      (Proc_Id);
!          Set_Has_Completion   (Proc_Id);
!          Freeze_Extra_Formals (Proc_Id);
  
           if not Debug_Generated_Code then
              Set_Debug_Info_Off (Proc_Id);
*************** package body Exp_Ch3 is
*** 3204,3209 ****
--- 3205,3211 ----
           end if;
  
           Set_Parameter_Specifications (Proc_Spec_Node, Parameters);
+          Freeze_Extra_Formals (Proc_Id);
           Set_Specification (Body_Node, Proc_Spec_Node);
           Set_Declarations (Body_Node, Decls);
  
*************** package body Exp_Ch3 is
*** 6496,6502 ****
           end;
        end if;
  
!       if Has_Controlled_Component (Typ) then
           Build_Controlling_Procs (Typ);
        end if;
  
--- 6498,6504 ----
           end;
        end if;
  
!       if Has_Controlled_Component (Typ) or else Has_Destructor (Typ) then
           Build_Controlling_Procs (Typ);
        end if;
  
*************** package body Exp_Ch3 is
*** 6570,6586 ****
        --  procedure, because a self-referential type might call one of these
        --  primitives in the body of the init_proc itself.
        --
!       --  This is not needed:
!       --    1) If expansion is disabled, because extra formals are only added
!       --       when we are generating code.
        --
!       --    2) For types with foreign convention since primitives with foreign
!       --       convention don't have extra formals and AI95-117 requires that
!       --       all primitives of a tagged type inherit the convention.
  
        if Expander_Active
          and then Is_Tagged_Type (Typ)
-         and then not Has_Foreign_Convention (Typ)
        then
           declare
              Elmt : Elmt_Id;
--- 6572,6587 ----
        --  procedure, because a self-referential type might call one of these
        --  primitives in the body of the init_proc itself.
        --
!       --  This is not needed when expansion is disabled, because extra formals
!       --  are only added when we are generating code.
        --
!       --  Notice that for tagged types with foreign convention this is also
!       --  required because (although primitives with foreign convention don't
!       --  have extra formals), a tagged type with foreign convention may have
!       --  primitives with convention Ada.
  
        if Expander_Active
          and then Is_Tagged_Type (Typ)
        then
           declare
              Elmt : Elmt_Id;
*************** package body Exp_Ch3 is
*** 7500,7505 ****
--- 7501,7512 ----
                 Apply_CW_Accessibility_Check (Expr, Func_Id);
              end if;
  
+             if Has_Anonymous_Access_Discriminant (Etype (Expr)) then
+                --  Check that access discrims do not designate entities
+                --  that the function result could outlive.
+                Apply_Access_Discrims_Accessibility_Check (Expr, Func_Id);
+             end if;
+ 
              Alloc_Expr := New_Copy_Tree (Expr);
  
              if Etype (Alloc_Expr) /= Alloc_Typ then
*************** package body Exp_Ch3 is
*** 9058,9063 ****
--- 9065,9074 ----
                 if Is_Class_Wide_Type (Etype (Func_Id)) then
                    Apply_CW_Accessibility_Check (Expr_Q, Func_Id);
                 end if;
+ 
+                --  ??? Usually calls to Apply_CW_Accessibility_Check and to
+                --  Apply_Access_Discrims_Accessibility_Check come in pairs.
+                --  Do we need a (conditional) call here to A_A_D_A_C ?
              end;
           end if;
  
*************** package body Exp_Ch3 is
*** 12845,12869 ****
              Append_To (Res, Decl);
           end if;
  
!          Fin_Call := Empty;
!          Decl     := Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Finalize, True);
  
!          if Is_Controlled (Tag_Typ) then
!             Fin_Call :=
!               Make_Final_Call
!                 (Obj_Ref => Make_Identifier (Loc, Name_V),
!                  Typ     => Tag_Typ);
!          end if;
  
!          if No (Fin_Call) then
!             Fin_Call := Make_Null_Statement (Loc);
!          end if;
  
!          Set_Handled_Statement_Sequence (Decl,
!            Make_Handled_Sequence_Of_Statements (Loc,
!              Statements => New_List (Fin_Call)));
  
!          Append_To (Res, Decl);
        end if;
  
        return Res;
--- 12856,12882 ----
              Append_To (Res, Decl);
           end if;
  
!          if not Has_Destructor (Tag_Typ) then
!             Fin_Call := Empty;
!             Decl := Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Finalize, True);
  
!             if Is_Controlled (Tag_Typ) then
!                Fin_Call :=
!                  Make_Final_Call
!                    (Obj_Ref => Make_Identifier (Loc, Name_V), Typ => Tag_Typ);
!             end if;
  
!             if No (Fin_Call) then
!                Fin_Call := Make_Null_Statement (Loc);
!             end if;
  
!             Set_Handled_Statement_Sequence
!               (Decl,
!                Make_Handled_Sequence_Of_Statements
!                  (Loc, Statements => New_List (Fin_Call)));
  
!             Append_To (Res, Decl);
!          end if;
        end if;
  
        return Res;
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_ch4.adb gcc-16-20250727/gcc/ada/exp_ch4.adb
*** gcc-16-20250720/gcc/ada/exp_ch4.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_ch4.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_Ch4 is
*** 2354,2359 ****
--- 2354,2360 ----
        Rhs        : Node_Id) return Node_Id
     is
        Loc       : constant Source_Ptr := Sloc (Nod);
+       CW_Comp   : Boolean := False;
        Full_Type : Entity_Id;
        Eq_Op     : Entity_Id;
  
*************** package body Exp_Ch4 is
*** 2383,2392 ****
           Full_Type := Underlying_Type (Full_Type);
        end if;
  
        --  Case of tagged record types
  
        if Is_Tagged_Type (Full_Type) then
!          Eq_Op := Find_Primitive_Eq (Comp_Type);
           pragma Assert (Present (Eq_Op));
  
           return
--- 2384,2400 ----
           Full_Type := Underlying_Type (Full_Type);
        end if;
  
+       if Is_Class_Wide_Equivalent_Type (Full_Type) then
+          CW_Comp := True;
+          Full_Type :=
+            Get_Corresponding_Mutably_Tagged_Type_If_Present (Full_Type);
+          pragma Assert (Is_Tagged_Type (Full_Type));
+       end if;
+ 
        --  Case of tagged record types
  
        if Is_Tagged_Type (Full_Type) then
!          Eq_Op := Find_Primitive_Eq (if CW_Comp then Full_Type else Comp_Type);
           pragma Assert (Present (Eq_Op));
  
           return
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_ch6.adb gcc-16-20250727/gcc/ada/exp_ch6.adb
*** gcc-16-20250720/gcc/ada/exp_ch6.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_ch6.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_Ch6 is
*** 734,739 ****
--- 734,991 ----
        Add_Extra_Actual_To_Call (Function_Call, Chain_Formal, Chain_Actual);
     end Add_Task_Actuals_To_Build_In_Place_Call;
  
+    ----------------------------------------------
+    -- Apply_Access_Discrims_Accesibility_Check --
+    ----------------------------------------------
+ 
+    procedure Apply_Access_Discrims_Accessibility_Check
+      (Exp : Node_Id; Func : Entity_Id)
+    is
+       Loc : constant Source_Ptr := Sloc (Exp);
+ 
+       --  Some of the code here in this procedure may need to be factored
+       --  out at some point because it seems like some of the same
+       --  functionality would be needed for accessibility checking of a
+       --  return statement when the function result type is an anonymous
+       --  access type (as opposed to a type that has an anonymous access
+       --  discriminant).
+       --
+       --  Another case that is not addressed today is the case where
+       --  we need to check an access discriminant subcomponent of the
+       --  function result other than a discriminant of the function result.
+       --  This can only happen if the function result type has an unconstrained
+       --  subcomponent subtype that has an access discriminant (which implies
+       --  that the function result type must be limited).
+       --
+       --  A further corner case of that corner case arises if the limited
+       --  function result type is class-wide and it is not known statically
+       --  that this access-discriminant-bearing subcomponent exists. The
+       --  easiest way to address this properly would probably involve adding
+       --  a new compiler-generated dispatching procedure; a dispatching call
+       --  could then be used to perform the check in a context where we know
+       --  statically the specific type of the function result. Finding a
+       --  less important unimplemented case would be challenging.
+ 
+       function Constraint_Bearing_Subtype_If_Any
+         (Exp : Node_Id) return Node_Id;
+       --  If we can locate a constrained subtype whose constraint applies
+       --  to Exp, then return that. Otherwise, return Etype (Exp).
+ 
+       function Discr_Expression
+         (Typ : Entity_Id; Discr_Index : Positive) return Node_Id;
+       --  Typ is a constrained discriminated subtype.
+       --  Return the constraint expression for the indexed discriminant.
+ 
+       function Has_Level_Tied_To_Explicitly_Aliased_Param
+         (Constraint_Exp : Node_Id) return Boolean;
+       --  Constraint_Exp is the value given for an access discriminant
+       --  in a discriminant constraint for Exp. Return True iff the
+       --  accessibility of the type of that discriminant of Exp is the level
+       --  of an explicitly aliased parameter of Func. If true, this indicates
+       --  that no check should be performed for this discriminant.
+ 
+       ---------------------------------------
+       -- Constraint_Bearing_Subtype_If_Any --
+       ---------------------------------------
+ 
+       function Constraint_Bearing_Subtype_If_Any
+         (Exp : Node_Id) return Entity_Id
+       is
+          Result : Entity_Id := Etype (Exp);
+       begin
+          if Is_Constrained (Result) then
+             return Result;
+          end if;
+ 
+          --  Look through expansion-generated levels of indirection
+          --  to find a constrained subtype. Yuck. This comes up in
+          --  some cases when the unexpanded source returns an aggregate.
+ 
+          if Nkind (Exp) = N_Explicit_Dereference
+            and then Nkind (Prefix (Exp)) = N_Identifier
+            and then Ekind (Entity (Prefix (Exp))) = E_Constant
+          then
+             declare
+                Acc_Const       : Entity_Id := Entity (Prefix (Exp));
+                Acc_Const_Value : Node_Id := Empty;
+             begin
+                --  look through constants initialized to constants
+                loop
+                   exit when Nkind (Parent (Acc_Const)) /= N_Object_Declaration;
+ 
+                   Acc_Const_Value := Expression (Parent (Acc_Const));
+ 
+                   if Nkind (Acc_Const_Value) = N_Identifier
+                     and then Ekind (Entity (Acc_Const_Value)) = E_Constant
+                   then
+                      Acc_Const := Entity (Acc_Const_Value);
+                   else
+                      exit;
+                   end if;
+                end loop;
+ 
+                if Nkind (Acc_Const_Value) = N_Allocator
+                  and then Nkind (Expression (Acc_Const_Value))
+                              = N_Qualified_Expression
+                then
+                   Result :=
+                     Etype (Expression (Acc_Const_Value));
+                end if;
+             end;
+          end if;
+ 
+          if Is_Constrained (Result) then
+             return Result;
+          end if;
+ 
+          --  no constrained subtype found
+          return Etype (Exp);
+       end Constraint_Bearing_Subtype_If_Any;
+ 
+       ----------------------
+       -- Discr_Expression --
+       ----------------------
+ 
+       function Discr_Expression
+         (Typ : Entity_Id; Discr_Index : Positive) return Node_Id
+       is
+          Constraint_Elmt : Elmt_Id :=
+            First_Elmt (Discriminant_Constraint (Typ));
+       begin
+          for Skip in 1 .. Discr_Index - 1 loop
+             Next_Elmt (Constraint_Elmt);
+          end loop;
+          return Node (Constraint_Elmt);
+       end Discr_Expression;
+ 
+       -------------------------------------------------
+       --  Has_Level_Tied_To_Explicitly_Aliased_Param --
+       -------------------------------------------------
+ 
+       function Has_Level_Tied_To_Explicitly_Aliased_Param
+         (Constraint_Exp : Node_Id) return Boolean
+       is
+          Discr_Exp   : Node_Id := Constraint_Exp;
+          Attr_Prefix : Node_Id;
+       begin
+          --  look through constants
+          while Nkind (Discr_Exp) = N_Identifier
+            and then Ekind (Entity (Discr_Exp)) = E_Constant
+            and then Nkind (Parent (Entity (Discr_Exp))) = N_Object_Declaration
+          loop
+             Discr_Exp := Expression (Parent (Entity (Discr_Exp)));
+          end loop;
+ 
+          if Nkind (Discr_Exp) = N_Attribute_Reference
+            and then Get_Attribute_Id
+                       (Attribute_Name (Discr_Exp)) = Attribute_Access
+          then
+             Attr_Prefix := Ultimate_Prefix (Prefix (Discr_Exp));
+             if Is_Entity_Name (Attr_Prefix)
+               and then Is_Explicitly_Aliased (Entity (Attr_Prefix))
+               and then Scope (Entity (Attr_Prefix)) = Func
+             then
+                return True;
+             end if;
+          end if;
+ 
+          return False;
+       end Has_Level_Tied_To_Explicitly_Aliased_Param;
+ 
+       Discr       : Entity_Id := First_Discriminant (Etype (Exp));
+       Discr_Index : Positive  := 1;
+       Discr_Exp   : Node_Id;
+ 
+       Constrained_Subtype : constant Entity_Id :=
+         Constraint_Bearing_Subtype_If_Any (Exp);
+    begin
+       --  ??? Do not generate a check if version is Ada 95 (or earlier).
+       --  It is unclear whether this is really correct, or is just a stopgap
+       --  measure. Investigation is needed to decide how post-Ada-95 binding
+       --  interpretation changes in RM 3.10.2 should interact with Ada 95's
+       --  return-by-reference model for functions with limited result types
+       --  (which was abandoned in Ada 2005).
+ 
+       if Ada_Version <= Ada_95 then
+          return;
+       end if;
+ 
+       --  If we are returning a function call then that function will
+       --  perform the needed check.
+ 
+       if Nkind (Unqualify (Exp)) = N_Function_Call then
+          return;
+       end if;
+ 
+      --  ??? Cope with the consequences of the Disable_Tagged_Cases flag
+      --  in accessibility.adb (which can cause the extra formal parameter
+      --  needed for the check(s) generated here to be missing in the case
+      --  of a tagged result type); this is a workaround and can
+      --  prevent generation of a required check.
+ 
+       if No (Extra_Accessibility_Of_Result (Func)) then
+          return;
+       end if;
+ 
+       Remove_Side_Effects (Exp);
+ 
+       while Present (Discr) loop
+          if Is_Anonymous_Access_Type (Etype (Discr)) then
+             if Is_Constrained (Constrained_Subtype) then
+                Discr_Exp :=
+                  New_Copy_Tree
+                    (Discr_Expression (Constrained_Subtype, Discr_Index));
+             else
+                Discr_Exp :=
+                  Make_Selected_Component (Loc,
+                    Prefix => New_Copy_Tree (Exp),
+                    Selector_Name => New_Occurrence_Of (Discr, Loc));
+             end if;
+ 
+             if not Has_Level_Tied_To_Explicitly_Aliased_Param (Discr_Exp) then
+                declare
+                   --  We could do this min operation earlier, as is done
+                   --  for other implicit level parameters. Motivation for
+                   --  doing this min operation (earlier or not) is as for
+                   --  Generate_Minimum_Accessibility (see sem_ch6.adb):
+                   --  if a level value is too big, then the caller and the
+                   --  callee disagree about what it means.
+ 
+                   Level_Of_Master_Of_Call : constant Node_Id :=
+                     Make_Attribute_Reference (Loc,
+                       Prefix => New_Occurrence_Of (Standard_Natural, Loc),
+                       Attribute_Name => Name_Min,
+                       Expressions => New_List (
+                         Make_Integer_Literal (Loc, Scope_Depth (Func)),
+                         New_Occurrence_Of
+                           (Extra_Accessibility_Of_Result (Func), Loc)));
+ 
+                   Discrim_Level : Node_Id;
+                begin
+                   Analyze (Level_Of_Master_Of_Call);
+                   Analyze (Discr_Exp);
+ 
+                   Discrim_Level :=
+                     Accessibility_Level (Discr_Exp, Level => Dynamic_Level);
+                   Analyze (Discrim_Level);
+ 
+                   Insert_Action (Exp,
+                     Make_Raise_Program_Error (Loc,
+                       Condition =>
+                         Make_Op_Gt (Loc,
+                           Left_Opnd  => Discrim_Level,
+                           Right_Opnd => Level_Of_Master_Of_Call),
+                       Reason    => PE_Accessibility_Check_Failed),
+                     Suppress => Access_Check);
+                end;
+             end if;
+          end if;
+ 
+          Next_Discriminant (Discr);
+          Discr_Index := Discr_Index + 1;
+       end loop;
+    end Apply_Access_Discrims_Accessibility_Check;
+ 
     ----------------------------------
     -- Apply_CW_Accessibility_Check --
     ----------------------------------
*************** package body Exp_Ch6 is
*** 1155,1167 ****
       (Subp_Call : Node_Id;
        Subp_Id   : Entity_Id) return Boolean
     is
!       Formal : Entity_Id;
        Actual : Node_Id;
  
     begin
        pragma Assert (Nkind (Subp_Call) in N_Entry_Call_Statement
                                          | N_Function_Call
                                          | N_Procedure_Call_Statement);
  
        --  In CodePeer_Mode, the tree for `'Elab_Spec` procedures will be
        --  malformed because GNAT does not perform the usual expansion that
--- 1407,1424 ----
       (Subp_Call : Node_Id;
        Subp_Id   : Entity_Id) return Boolean
     is
!       use Deferred_Extra_Formals_Support;
! 
        Actual : Node_Id;
+       Formal : Entity_Id;
  
     begin
        pragma Assert (Nkind (Subp_Call) in N_Entry_Call_Statement
                                          | N_Function_Call
                                          | N_Procedure_Call_Statement);
+       pragma Assert (Extra_Formals_Known (Subp_Id)
+         or else not Expander_Active
+         or else Is_Unsupported_Extra_Actuals_Call (Subp_Call, Subp_Id));
  
        --  In CodePeer_Mode, the tree for `'Elab_Spec` procedures will be
        --  malformed because GNAT does not perform the usual expansion that
*************** package body Exp_Ch6 is
*** 2866,2880 ****
     -----------------
  
     procedure Expand_Call (N : Node_Id) is
!       function Is_Unchecked_Union_Equality (N : Node_Id) return Boolean;
        --  Return True if N is a call to the predefined equality operator of an
        --  unchecked union type, or a renaming thereof.
  
!       ---------------------------------
!       -- Is_Unchecked_Union_Equality --
!       ---------------------------------
  
!       function Is_Unchecked_Union_Equality (N : Node_Id) return Boolean is
        begin
           if Is_Entity_Name (Name (N))
             and then Ekind (Entity (Name (N))) = E_Function
--- 3123,3139 ----
     -----------------
  
     procedure Expand_Call (N : Node_Id) is
!       function Is_Unchecked_Union_Predefined_Equality_Call
!         (N : Node_Id) return Boolean;
        --  Return True if N is a call to the predefined equality operator of an
        --  unchecked union type, or a renaming thereof.
  
!       -------------------------------------------------
!       -- Is_Unchecked_Union_Predefined_Equality_Call --
!       -------------------------------------------------
  
!       function Is_Unchecked_Union_Predefined_Equality_Call
!         (N : Node_Id) return Boolean is
        begin
           if Is_Entity_Name (Name (N))
             and then Ekind (Entity (Name (N))) = E_Function
*************** package body Exp_Ch6 is
*** 2899,2905 ****
           else
              return False;
           end if;
!       end Is_Unchecked_Union_Equality;
  
        --  If this is an indirect call through an Access_To_Subprogram
        --  with contract specifications, it is rewritten as a call to
--- 3158,3164 ----
           else
              return False;
           end if;
!       end Is_Unchecked_Union_Predefined_Equality_Call;
  
        --  If this is an indirect call through an Access_To_Subprogram
        --  with contract specifications, it is rewritten as a call to
*************** package body Exp_Ch6 is
*** 2996,3002 ****
        --  Case of a call to the predefined equality operator of an unchecked
        --  union type, which requires specific processing.
  
!       elsif Is_Unchecked_Union_Equality (N) then
           declare
              Eq : constant Entity_Id := Entity (Name (N));
  
--- 3255,3261 ----
        --  Case of a call to the predefined equality operator of an unchecked
        --  union type, which requires specific processing.
  
!       elsif Is_Unchecked_Union_Predefined_Equality_Call (N) then
           declare
              Eq : constant Entity_Id := Entity (Name (N));
  
*************** package body Exp_Ch6 is
*** 3020,3048 ****
        end if;
     end Expand_Call;
  
!    ------------------------
!    -- Expand_Call_Helper --
!    ------------------------
! 
!    --  This procedure handles expansion of function calls and procedure call
!    --  statements (i.e. it serves as the body for Expand_N_Function_Call and
!    --  Expand_N_Procedure_Call_Statement). Processing for calls includes:
! 
!    --    Replace call to Raise_Exception by Raise_Exception_Always if possible
!    --    Provide values of actuals for all formals in Extra_Formals list
!    --    Replace "call" to enumeration literal function by literal itself
!    --    Rewrite call to predefined operator as operator
!    --    Replace actuals to in-out parameters that are numeric conversions,
!    --     with explicit assignment to temporaries before and after the call.
! 
!    --   Note that the list of actuals has been filled with default expressions
!    --   during semantic analysis of the call. Only the extra actuals required
!    --   for the 'Constrained attribute and for accessibility checks are added
!    --   at this point.
  
!    procedure Expand_Call_Helper (N : Node_Id; Post_Call : out List_Id) is
!       Loc           : constant Source_Ptr := Sloc (N);
!       Call_Node     : Node_Id := N;
        Extra_Actuals : List_Id := No_List;
        Prev          : Node_Id := Empty;
  
--- 3279,3290 ----
        end if;
     end Expand_Call;
  
!    --------------------------
!    -- Create_Extra_Actuals --
!    --------------------------
  
!    procedure Create_Extra_Actuals (Call_Node : Node_Id) is
!       Loc           : constant Source_Ptr := Sloc (Call_Node);
        Extra_Actuals : List_Id := No_List;
        Prev          : Node_Id := Empty;
  
*************** package body Exp_Ch6 is
*** 3072,3159 ****
        --  expression for the value of the actual, EF is the entity for the
        --  extra formal.
  
-       procedure Add_View_Conversion_Invariants
-         (Formal : Entity_Id;
-          Actual : Node_Id);
-       --  Adds invariant checks for every intermediate type between the range
-       --  of a view converted argument to its ancestor (from parent to child).
- 
-       function Can_Fold_Predicate_Call (P : Entity_Id) return Boolean;
-       --  Try to constant-fold a predicate check, which often enough is a
-       --  simple arithmetic expression that can be computed statically if
-       --  its argument is static. This cleans up the output of CCG, even
-       --  though useless predicate checks will be generally removed by
-       --  back-end optimizations.
- 
-       procedure Check_Subprogram_Variant;
-       --  Emit a call to the internally generated procedure with checks for
-       --  aspect Subprogram_Variant, if present and enabled.
- 
-       function Inherited_From_Formal (S : Entity_Id) return Entity_Id;
-       --  Within an instance, a type derived from an untagged formal derived
-       --  type inherits from the original parent, not from the actual. The
-       --  current derivation mechanism has the derived type inherit from the
-       --  actual, which is only correct outside of the instance. If the
-       --  subprogram is inherited, we test for this particular case through a
-       --  convoluted tree traversal before setting the proper subprogram to be
-       --  called.
- 
-       function In_Unfrozen_Instance (E : Entity_Id) return Boolean;
-       --  Return true if E comes from an instance that is not yet frozen
- 
-       function Is_Class_Wide_Interface_Type (E : Entity_Id) return Boolean;
-       --  Return True when E is a class-wide interface type or an access to
-       --  a class-wide interface type.
- 
-       function Is_Direct_Deep_Call (Subp : Entity_Id) return Boolean;
-       --  Determine if Subp denotes a non-dispatching call to a Deep routine
- 
-       function New_Value (From : Node_Id) return Node_Id;
-       --  From is the original Expression. New_Value is equivalent to a call
-       --  to Duplicate_Subexpr with an explicit dereference when From is an
-       --  access parameter.
- 
-       --------------------------
-       -- Add_Actual_Parameter --
-       --------------------------
- 
-       procedure Add_Actual_Parameter (Insert_Param : Node_Id) is
-          Actual_Expr : constant Node_Id :=
-                          Explicit_Actual_Parameter (Insert_Param);
- 
-       begin
-          --  Case of insertion is first named actual
- 
-          if No (Prev) or else
-             Nkind (Parent (Prev)) /= N_Parameter_Association
-          then
-             Set_Next_Named_Actual
-               (Insert_Param, First_Named_Actual (Call_Node));
-             Set_First_Named_Actual (Call_Node, Actual_Expr);
- 
-             if No (Prev) then
-                if No (Parameter_Associations (Call_Node)) then
-                   Set_Parameter_Associations (Call_Node, New_List);
-                end if;
- 
-                Append (Insert_Param, Parameter_Associations (Call_Node));
- 
-             else
-                Insert_After (Prev, Insert_Param);
-             end if;
- 
-          --  Case of insertion is not first named actual
- 
-          else
-             Set_Next_Named_Actual
-               (Insert_Param, Next_Named_Actual (Parent (Prev)));
-             Set_Next_Named_Actual (Parent (Prev), Actual_Expr);
-             Append (Insert_Param, Parameter_Associations (Call_Node));
-          end if;
- 
-          Prev := Actual_Expr;
-       end Add_Actual_Parameter;
- 
        --------------------------------------
        -- Add_Cond_Expression_Extra_Actual --
        --------------------------------------
--- 3314,3319 ----
*************** package body Exp_Ch6 is
*** 3368,3381 ****
              if Etype (Formal) = Standard_Natural then
                 Actual := Make_Integer_Literal (Loc, Uint_0);
                 Analyze_And_Resolve (Actual, Standard_Natural);
!                Add_Extra_Actual_To_Call (N, Formal, Actual);
  
              --  BIPtaskmaster
  
              elsif Etype (Formal) = Standard_Integer then
                 Actual := Make_Integer_Literal (Loc, Uint_0);
                 Analyze_And_Resolve (Actual, Standard_Integer);
!                Add_Extra_Actual_To_Call (N, Formal, Actual);
  
              --  BIPstoragepool, BIPcollection, BIPactivationchain,
              --  and BIPaccess.
--- 3528,3541 ----
              if Etype (Formal) = Standard_Natural then
                 Actual := Make_Integer_Literal (Loc, Uint_0);
                 Analyze_And_Resolve (Actual, Standard_Natural);
!                Add_Extra_Actual_To_Call (Call_Node, Formal, Actual);
  
              --  BIPtaskmaster
  
              elsif Etype (Formal) = Standard_Integer then
                 Actual := Make_Integer_Literal (Loc, Uint_0);
                 Analyze_And_Resolve (Actual, Standard_Integer);
!                Add_Extra_Actual_To_Call (Call_Node, Formal, Actual);
  
              --  BIPstoragepool, BIPcollection, BIPactivationchain,
              --  and BIPaccess.
*************** package body Exp_Ch6 is
*** 3383,3389 ****
              elsif Is_Access_Type (Etype (Formal)) then
                 Actual := Make_Null (Loc);
                 Analyze_And_Resolve (Actual, Etype (Formal));
!                Add_Extra_Actual_To_Call (N, Formal, Actual);
  
              else
                 pragma Assert (False);
--- 3543,3549 ----
              elsif Is_Access_Type (Etype (Formal)) then
                 Actual := Make_Null (Loc);
                 Analyze_And_Resolve (Actual, Etype (Formal));
!                Add_Extra_Actual_To_Call (Call_Node, Formal, Actual);
  
              else
                 pragma Assert (False);
*************** package body Exp_Ch6 is
*** 3402,3407 ****
--- 3562,3608 ----
           pragma Assert (Check_BIP_Actuals (Call_Node, Function_Id));
        end Add_Dummy_Build_In_Place_Actuals;
  
+       --------------------------
+       -- Add_Actual_Parameter --
+       --------------------------
+ 
+       procedure Add_Actual_Parameter (Insert_Param : Node_Id) is
+          Actual_Expr : constant Node_Id :=
+                          Explicit_Actual_Parameter (Insert_Param);
+ 
+       begin
+          --  Case of insertion is first named actual
+ 
+          if No (Prev)
+            or else Nkind (Parent (Prev)) /= N_Parameter_Association
+          then
+             Set_Next_Named_Actual
+               (Insert_Param, First_Named_Actual (Call_Node));
+             Set_First_Named_Actual (Call_Node, Actual_Expr);
+ 
+             if No (Prev) then
+                if No (Parameter_Associations (Call_Node)) then
+                   Set_Parameter_Associations (Call_Node, New_List);
+                end if;
+ 
+                Append (Insert_Param, Parameter_Associations (Call_Node));
+ 
+             else
+                Insert_After (Prev, Insert_Param);
+             end if;
+ 
+          --  Case of insertion is not first named actual
+ 
+          else
+             Set_Next_Named_Actual
+               (Insert_Param, Next_Named_Actual (Parent (Prev)));
+             Set_Next_Named_Actual (Parent (Prev), Actual_Expr);
+             Append (Insert_Param, Parameter_Associations (Call_Node));
+          end if;
+ 
+          Prev := Actual_Expr;
+       end Add_Actual_Parameter;
+ 
        ----------------------
        -- Add_Extra_Actual --
        ----------------------
*************** package body Exp_Ch6 is
*** 3427,3432 ****
--- 3628,4048 ----
           end if;
        end Add_Extra_Actual;
  
+       --  Local variables
+ 
+       use Deferred_Extra_Formals_Support;
+ 
+       Actual        : Node_Id;
+       Formal        : Entity_Id;
+       Param_Count   : Positive;
+       Subp          : constant Entity_Id := Get_Called_Entity (Call_Node);
+ 
+    --  Start of processing for Create_Extra_Actuals
+ 
+    begin
+       --  Special case: Thunks must not compute the extra actuals; they must
+       --  just propagate their extra actuals to the target primitive.
+ 
+       if Is_Thunk (Current_Scope)
+         and then Thunk_Entity (Current_Scope) = Subp
+       then
+          declare
+             Target_Formal : Entity_Id;
+             Thunk_Formal  : Entity_Id;
+ 
+          begin
+             pragma Assert (Extra_Formals_Known (Subp)
+               and then Extra_Formals_Match_OK (Current_Scope, Subp));
+ 
+             Target_Formal := Extra_Formals (Subp);
+             Thunk_Formal  := Extra_Formals (Current_Scope);
+             while Present (Target_Formal) loop
+                Add_Extra_Actual
+                   (Expr => New_Occurrence_Of (Thunk_Formal, Loc),
+                    EF   => Thunk_Formal);
+ 
+                Target_Formal := Extra_Formal (Target_Formal);
+                Thunk_Formal  := Extra_Formal (Thunk_Formal);
+             end loop;
+ 
+             while Is_Non_Empty_List (Extra_Actuals) loop
+                Add_Actual_Parameter (Remove_Head (Extra_Actuals));
+             end loop;
+ 
+             return;
+          end;
+       end if;
+ 
+       pragma Assert (Extra_Formals_Known (Subp)
+         or else Is_Unsupported_Extra_Formals_Entity (Subp));
+ 
+       --  First step, compute extra actuals, corresponding to any Extra_Formals
+       --  present. Note that we do not access Extra_Formals directly; instead
+       --  we generate and collect the corresponding actuals in Extra_Actuals.
+ 
+       Formal := First_Formal (Subp);
+       Actual := First_Actual (Call_Node);
+       Param_Count := 1;
+       while Present (Formal) loop
+          --  Prepare to examine current entry
+ 
+          Prev := Actual;
+ 
+          --  Create possible extra actual for constrained case. Usually, the
+          --  extra actual is of the form actual'constrained, but since this
+          --  attribute is only available for unconstrained records, TRUE is
+          --  expanded if the type of the formal happens to be constrained (for
+          --  instance when this procedure is inherited from an unconstrained
+          --  record to a constrained one) or if the actual has no discriminant
+          --  (its type is constrained). An exception to this is the case of a
+          --  private type without discriminants. In this case we pass FALSE
+          --  because the object has underlying discriminants with defaults.
+ 
+          if Present (Extra_Constrained (Formal)) then
+             if Is_Mutably_Tagged_Type (Etype (Actual))
+               or else (Is_Private_Type (Etype (Prev))
+                         and then not Has_Discriminants
+                                        (Base_Type (Etype (Prev))))
+             then
+                Add_Extra_Actual
+                  (Expr => New_Occurrence_Of (Standard_False, Loc),
+                   EF   => Extra_Constrained (Formal));
+ 
+             elsif Is_Constrained (Etype (Formal))
+               or else not Has_Discriminants (Etype (Prev))
+             then
+                Add_Extra_Actual
+                  (Expr => New_Occurrence_Of (Standard_True, Loc),
+                   EF   => Extra_Constrained (Formal));
+ 
+             --  Do not produce extra actuals for Unchecked_Union parameters.
+             --  Jump directly to the end of the loop.
+ 
+             elsif Is_Unchecked_Union (Base_Type (Etype (Actual))) then
+                goto Skip_Extra_Actual_Generation;
+ 
+             else
+                --  If the actual is a type conversion, then the constrained
+                --  test applies to the actual, not the target type.
+ 
+                declare
+                   Act_Prev : Node_Id;
+ 
+                begin
+                   --  Test for unchecked conversions as well, which can occur
+                   --  as out parameter actuals on calls to stream procedures.
+ 
+                   Act_Prev := Prev;
+                   while Nkind (Act_Prev) in N_Type_Conversion
+                                           | N_Unchecked_Type_Conversion
+                   loop
+                      Act_Prev := Expression (Act_Prev);
+                   end loop;
+ 
+                   --  If the expression is a conversion of a dereference, this
+                   --  is internally generated code that manipulates addresses,
+                   --  e.g. when building interface tables. No check should
+                   --  occur in this case, and the discriminated object is not
+                   --  directly at hand.
+ 
+                   if not Comes_From_Source (Actual)
+                     and then Nkind (Actual) = N_Unchecked_Type_Conversion
+                     and then Nkind (Act_Prev) = N_Explicit_Dereference
+                   then
+                      Add_Extra_Actual
+                        (Expr => New_Occurrence_Of (Standard_False, Loc),
+                         EF   => Extra_Constrained (Formal));
+ 
+                   else
+                      Add_Extra_Actual
+                        (Expr =>
+                           Make_Attribute_Reference (Sloc (Prev),
+                             Prefix         =>
+                               Duplicate_Subexpr_No_Checks
+                                 (Act_Prev, Name_Req => True),
+                             Attribute_Name => Name_Constrained),
+                         EF   => Extra_Constrained (Formal));
+                   end if;
+                end;
+             end if;
+          end if;
+ 
+          --  Create possible extra actual for accessibility level
+ 
+          if Present (Extra_Accessibility (Formal)) then
+ 
+             --  Ada 2005 (AI-251): Thunks must propagate the extra actuals of
+             --  accessibility levels.
+ 
+             if Is_Thunk (Current_Scope) then
+                declare
+                   Parm_Ent : Entity_Id;
+ 
+                begin
+                   if Is_Controlling_Actual (Actual) then
+ 
+                      --  Find the corresponding actual of the thunk
+ 
+                      Parm_Ent := First_Entity (Current_Scope);
+                      for J in 2 .. Param_Count loop
+                         Next_Entity (Parm_Ent);
+                      end loop;
+ 
+                   --  Handle unchecked conversion of access types generated
+                   --  in thunks (cf. Expand_Interface_Thunk).
+ 
+                   elsif Is_Access_Type (Etype (Actual))
+                     and then Nkind (Actual) = N_Unchecked_Type_Conversion
+                   then
+                      Parm_Ent := Entity (Expression (Actual));
+ 
+                   else pragma Assert (Is_Entity_Name (Actual));
+                      Parm_Ent := Entity (Actual);
+                   end if;
+ 
+                   Add_Extra_Actual
+                     (Expr => Accessibility_Level
+                                (Expr            => Parm_Ent,
+                                 Level           => Dynamic_Level,
+                                 Allow_Alt_Model => False),
+                      EF   => Extra_Accessibility (Formal));
+                end;
+ 
+             --  Conditional expressions
+ 
+             elsif Nkind (Prev) = N_Expression_With_Actions
+               and then Nkind (Original_Node (Prev)) in
+                          N_If_Expression | N_Case_Expression
+             then
+                Add_Cond_Expression_Extra_Actual (Formal);
+ 
+             --  Internal constant generated to remove side effects (normally
+             --  from the expansion of dispatching calls).
+ 
+             --  First verify the actual is internal
+ 
+             elsif not Comes_From_Source (Prev)
+               and then not Is_Rewrite_Substitution (Prev)
+ 
+               --  Next check that the actual is a constant
+ 
+               and then Nkind (Prev) = N_Identifier
+               and then Ekind (Entity (Prev)) = E_Constant
+               and then Nkind (Parent (Entity (Prev))) = N_Object_Declaration
+             then
+                --  Generate the accessibility level based on the expression in
+                --  the constant's declaration.
+ 
+                declare
+                   Ent : Entity_Id := Entity (Prev);
+ 
+                begin
+                   --  Handle deferred constants
+ 
+                   if Present (Full_View (Ent)) then
+                      Ent := Full_View (Ent);
+                   end if;
+ 
+                   Add_Extra_Actual
+                     (Expr => Accessibility_Level
+                                (Expr            => Expression (Parent (Ent)),
+                                 Level           => Dynamic_Level,
+                                 Allow_Alt_Model => False),
+                      EF   => Extra_Accessibility (Formal));
+                end;
+ 
+             --  Normal case
+ 
+             else
+                Add_Extra_Actual
+                  (Expr => Accessibility_Level
+                             (Expr            => Prev,
+                              Level           => Dynamic_Level,
+                              Allow_Alt_Model => False),
+                   EF   => Extra_Accessibility (Formal));
+             end if;
+          end if;
+ 
+          --  This label is required when skipping extra actual generation for
+          --  Unchecked_Union parameters.
+ 
+          <<Skip_Extra_Actual_Generation>>
+ 
+          Param_Count := Param_Count + 1;
+          Next_Actual (Actual);
+          Next_Formal (Formal);
+       end loop;
+ 
+       --  If we are calling an Ada 2012 function which needs to have the
+       --  "accessibility level determined by the point of call" (AI05-0234)
+       --  passed in to it, then pass it in.
+ 
+       if Ekind (Subp) in E_Function | E_Operator | E_Subprogram_Type
+         and then
+           Present (Extra_Accessibility_Of_Result (Ultimate_Alias (Subp)))
+       then
+          declare
+             Extra_Form : Node_Id := Empty;
+             Level      : Node_Id := Empty;
+ 
+          begin
+             --  Detect cases where the function call has been internally
+             --  generated by examining the original node and return library
+             --  level - taking care to avoid ignoring function calls expanded
+             --  in prefix notation.
+ 
+             if Nkind (Original_Node (Call_Node)) not in N_Function_Call
+                                                       | N_Selected_Component
+                                                       | N_Indexed_Component
+             then
+                Level := Make_Integer_Literal
+                           (Loc, Scope_Depth (Standard_Standard));
+ 
+             --  Otherwise get the level normally based on the call node
+ 
+             else
+                Level := Accessibility_Level
+                           (Expr            => Call_Node,
+                            Level           => Dynamic_Level,
+                            Allow_Alt_Model => False);
+             end if;
+ 
+             --  It may be possible that we are re-expanding an already
+             --  expanded call when are are dealing with dispatching ???
+ 
+             if No (Parameter_Associations (Call_Node))
+               or else Nkind (Last (Parameter_Associations (Call_Node)))
+                         /= N_Parameter_Association
+               or else not Is_Accessibility_Actual
+                               (Last (Parameter_Associations (Call_Node)))
+             then
+                Extra_Form := Extra_Accessibility_Of_Result
+                                (Ultimate_Alias (Subp));
+ 
+                Add_Extra_Actual
+                  (Expr => Level,
+                   EF   => Extra_Form);
+             end if;
+          end;
+       end if;
+ 
+       --  Second step: In the previous loop we gathered the extra actuals (the
+       --  ones that correspond to Extra_Formals), so now they can be appended.
+ 
+       if Is_Non_Empty_List (Extra_Actuals) then
+          declare
+             Num_Extra_Actuals : constant Nat := List_Length (Extra_Actuals);
+ 
+          begin
+             while Is_Non_Empty_List (Extra_Actuals) loop
+                Add_Actual_Parameter (Remove_Head (Extra_Actuals));
+             end loop;
+ 
+             --  Add dummy extra BIP actuals if we are calling a function that
+             --  inherited the BIP extra actuals but does not require them.
+ 
+             if Nkind (Call_Node) = N_Function_Call
+               and then Is_Function_Call_With_BIP_Formals (Call_Node)
+               and then not Is_Build_In_Place_Function_Call (Call_Node)
+             then
+                Add_Dummy_Build_In_Place_Actuals (Subp,
+                  Num_Added_Extra_Actuals => Num_Extra_Actuals);
+             end if;
+          end;
+ 
+       --  Add dummy extra BIP actuals if we are calling a function that
+       --  inherited the BIP extra actuals but does not require them.
+ 
+       elsif Nkind (Call_Node) = N_Function_Call
+         and then Is_Function_Call_With_BIP_Formals (Call_Node)
+         and then not Is_Build_In_Place_Function_Call (Call_Node)
+       then
+          Add_Dummy_Build_In_Place_Actuals (Subp);
+       end if;
+ 
+       --  For non build-in-place calls formals and actuals must match;
+       --  for build-in-place function calls, the pending bip actuals are
+       --  added by the following subprograms as part of the bottom-up
+       --  expansion of the call (and this check will be performed there):
+       --    Make_Build_In_Place_Call_In_Allocator
+       --    Make_Build_In_Place_Call_In_Anonymous_Context
+       --    Make_Build_In_Place_Call_In_Assignment
+       --    Make_Build_In_Place_Call_In_Object_Declaration
+       --    Make_Build_In_Place_Iface_Call_In_Allocator
+       --    Make_Build_In_Place_Iface_Call_In_Anonymous_Context
+       --    Make_Build_In_Place_Iface_Call_In_Object_Declaration
+ 
+       pragma Assert (Is_Build_In_Place_Function_Call (Call_Node)
+         or else (Check_Number_Of_Actuals (Call_Node, Subp)
+                    and then Check_BIP_Actuals (Call_Node, Subp)));
+    end Create_Extra_Actuals;
+ 
+    ------------------------
+    -- Expand_Call_Helper --
+    ------------------------
+ 
+    --  This procedure handles expansion of function calls and procedure call
+    --  statements (i.e. it serves as the body for Expand_N_Function_Call and
+    --  Expand_N_Procedure_Call_Statement). Processing for calls includes:
+ 
+    --    Replace call to Raise_Exception by Raise_Exception_Always if possible
+    --    Provide values of actuals for all formals in Extra_Formals list
+    --    Replace "call" to enumeration literal function by literal itself
+    --    Rewrite call to predefined operator as operator
+    --    Replace actuals to in-out parameters that are numeric conversions,
+    --     with explicit assignment to temporaries before and after the call.
+ 
+    --   Note that the list of actuals has been filled with default expressions
+    --   during semantic analysis of the call. Only the extra actuals required
+    --   for the 'Constrained attribute and for accessibility checks are added
+    --   at this point.
+ 
+    procedure Expand_Call_Helper (N : Node_Id; Post_Call : out List_Id) is
+       Loc       : constant Source_Ptr := Sloc (N);
+       Call_Node : Node_Id := N;
+       Prev      : Node_Id := Empty;
+ 
+       procedure Add_View_Conversion_Invariants
+         (Formal : Entity_Id;
+          Actual : Node_Id);
+       --  Adds invariant checks for every intermediate type between the range
+       --  of a view converted argument to its ancestor (from parent to child).
+ 
+       function Can_Fold_Predicate_Call (P : Entity_Id) return Boolean;
+       --  Try to constant-fold a predicate check, which often enough is a
+       --  simple arithmetic expression that can be computed statically if
+       --  its argument is static. This cleans up the output of CCG, even
+       --  though useless predicate checks will be generally removed by
+       --  back-end optimizations.
+ 
+       procedure Check_Subprogram_Variant;
+       --  Emit a call to the internally generated procedure with checks for
+       --  aspect Subprogram_Variant, if present and enabled.
+ 
+       function Inherited_From_Formal (S : Entity_Id) return Entity_Id;
+       --  Within an instance, a type derived from an untagged formal derived
+       --  type inherits from the original parent, not from the actual. The
+       --  current derivation mechanism has the derived type inherit from the
+       --  actual, which is only correct outside of the instance. If the
+       --  subprogram is inherited, we test for this particular case through a
+       --  convoluted tree traversal before setting the proper subprogram to be
+       --  called.
+ 
+       function In_Unfrozen_Instance (E : Entity_Id) return Boolean;
+       --  Return true if E comes from an instance that is not yet frozen
+ 
+       function Is_Class_Wide_Interface_Type (E : Entity_Id) return Boolean;
+       --  Return True when E is a class-wide interface type or an access to
+       --  a class-wide interface type.
+ 
+       function Is_Direct_Deep_Call (Subp : Entity_Id) return Boolean;
+       --  Determine if Subp denotes a non-dispatching call to a Deep routine
+ 
+       function New_Value (From : Node_Id) return Node_Id;
+       --  From is the original Expression. New_Value is equivalent to a call
+       --  to Duplicate_Subexpr with an explicit dereference when From is an
+       --  access parameter.
+ 
        ------------------------------------
        -- Add_View_Conversion_Invariants --
        ------------------------------------
*************** package body Exp_Ch6 is
*** 3943,3948 ****
--- 4559,4567 ----
        Subp          : Entity_Id;
  
        CW_Interface_Formals_Present : Boolean := False;
+       Defer_Extra_Actuals          : Boolean := False;
+ 
+       use Deferred_Extra_Formals_Support;
  
     --  Start of processing for Expand_Call_Helper
  
*************** package body Exp_Ch6 is
*** 4029,4040 ****
           end if;
        end if;
  
-       --  Ensure that the called subprogram has all its formals
- 
-       if not Is_Frozen (Subp) then
-          Create_Extra_Formals (Subp);
-       end if;
- 
        --  Ada 2005 (AI-345): We have a procedure call as a triggering
        --  alternative in an asynchronous select or as an entry call in
        --  a conditional or timed select. Check whether the procedure call
--- 4648,4653 ----
*************** package body Exp_Ch6 is
*** 4080,4085 ****
--- 4693,4742 ----
           end;
        end if;
  
+       --  Ensure that the called subprogram has all its formals; extra formals
+       --  of init procs were added when they were built.
+ 
+       if not Extra_Formals_Known (Subp) then
+          Create_Extra_Formals (Subp);
+ 
+          --  If the previous call to Create_Extra_Formals could not add the
+          --  extra formals, then we must defer adding the extra actuals of
+          --  this call until we know the underlying type of all the formals
+          --  and return type of the called subprogram or entry. Deferral of
+          --  extra actuals occurs in two cases:
+          --  1) In the body of internally built dynamic call helpers of
+          --     class-wide preconditions.
+          --  2) In the body of expanded expression functions.
+ 
+          if not Extra_Formals_Known (Subp) then
+             declare
+                Scop_Id : Entity_Id := Current_Scope;
+ 
+             begin
+                --  Locate the enclosing subprogram or entry since it is
+                --  required to register this deferred call.
+ 
+                Scop_Id := Current_Scope;
+                while Present (Scop_Id)
+                  and then Scop_Id /= Standard_Standard
+                  and then not Is_Subprogram_Or_Entry (Scop_Id)
+                loop
+                   Scop_Id := Scope (Scop_Id);
+                end loop;
+ 
+                pragma Assert (Is_Subprogram_Or_Entry (Scop_Id));
+                pragma Assert (Is_Deferred_Extra_Formals_Entity (Subp));
+                Register_Deferred_Extra_Formals_Call (Call_Node, Scop_Id);
+ 
+                Defer_Extra_Actuals := True;
+             end;
+          end if;
+       end if;
+ 
+       pragma Assert (Extra_Formals_Known (Subp)
+         or else Is_Deferred_Extra_Formals_Entity (Subp)
+         or else Is_Unsupported_Extra_Formals_Entity (Subp));
+ 
        --  If this is a call to a predicate function, try to constant fold it
  
        if Nkind (Call_Node) = N_Function_Call
*************** package body Exp_Ch6 is
*** 4091,4146 ****
        end if;
  
        --  First step, compute extra actuals, corresponding to any Extra_Formals
!       --  present. Note that we do not access Extra_Formals directly, instead
        --  we simply note the presence of the extra formals as we process the
        --  regular formals collecting corresponding actuals in Extra_Actuals.
  
!       --  We also generate any required range checks for actuals for in formals
!       --  as we go through the loop, since this is a convenient place to do it.
!       --  (Though it seems that this would be better done in Expand_Actuals???)
  
        --  Special case: Thunks must not compute the extra actuals; they must
!       --  just propagate to the target primitive their extra actuals.
  
        if Is_Thunk (Current_Scope)
          and then Thunk_Entity (Current_Scope) = Subp
          and then Present (Extra_Formals (Subp))
        then
!          pragma Assert (Extra_Formals_Match_OK (Current_Scope, Subp));
! 
!          declare
!             Target_Formal : Entity_Id;
!             Thunk_Formal  : Entity_Id;
! 
!          begin
!             Target_Formal := Extra_Formals (Subp);
!             Thunk_Formal  := Extra_Formals (Current_Scope);
!             while Present (Target_Formal) loop
!                Add_Extra_Actual
!                  (Expr => New_Occurrence_Of (Thunk_Formal, Loc),
!                   EF   => Thunk_Formal);
! 
!                Target_Formal := Extra_Formal (Target_Formal);
!                Thunk_Formal  := Extra_Formal (Thunk_Formal);
!             end loop;
  
!             while Is_Non_Empty_List (Extra_Actuals) loop
!                Add_Actual_Parameter (Remove_Head (Extra_Actuals));
!             end loop;
  
!             --  Mark the call as processed build-in-place call; required
!             --  to avoid adding the extra formals twice.
  
!             if Nkind (Call_Node) = N_Function_Call then
!                Set_Is_Expanded_Build_In_Place_Call (Call_Node);
!             end if;
  
!             Expand_Actuals (Call_Node, Subp, Post_Call);
!             pragma Assert (Is_Empty_List (Post_Call));
!             pragma Assert (Check_Number_Of_Actuals (Call_Node, Subp));
!             pragma Assert (Check_BIP_Actuals (Call_Node, Subp));
!             return;
!          end;
        end if;
  
        Formal := First_Formal (Subp);
--- 4748,4786 ----
        end if;
  
        --  First step, compute extra actuals, corresponding to any Extra_Formals
!       --  present. Note that we do not access Extra_Formals directly; instead
        --  we simply note the presence of the extra formals as we process the
        --  regular formals collecting corresponding actuals in Extra_Actuals.
  
!       --  We also generate any required range checks for actuals for in-mode
!       --  formals as we go through the loop, since this is a convenient place
!       --  to do it. (Though it seems that this would be better done in
!       --  Expand_Actuals???)
  
        --  Special case: Thunks must not compute the extra actuals; they must
!       --  just propagate their extra actuals to the target primitive (this
!       --  propagation is performed by Create_Extra_Actuals).
  
        if Is_Thunk (Current_Scope)
          and then Thunk_Entity (Current_Scope) = Subp
+         and then Extra_Formals_Known (Subp)
          and then Present (Extra_Formals (Subp))
        then
!          Create_Extra_Actuals (N);
  
!          --  Mark the call as an expanded build-in-place call; required
!          --  to avoid adding the extra formals twice.
  
!          if Nkind (Call_Node) = N_Function_Call then
!             Set_Is_Expanded_Build_In_Place_Call (Call_Node);
!          end if;
  
!          Expand_Actuals (Call_Node, Subp, Post_Call);
  
!          pragma Assert (Is_Empty_List (Post_Call));
!          pragma Assert (Check_Number_Of_Actuals (Call_Node, Subp));
!          pragma Assert (Check_BIP_Actuals (Call_Node, Subp));
!          return;
        end if;
  
        Formal := First_Formal (Subp);
*************** package body Exp_Ch6 is
*** 4158,4337 ****
             CW_Interface_Formals_Present
               or else Is_Class_Wide_Interface_Type (Etype (Formal));
  
-          --  Create possible extra actual for constrained case. Usually, the
-          --  extra actual is of the form actual'constrained, but since this
-          --  attribute is only available for unconstrained records, TRUE is
-          --  expanded if the type of the formal happens to be constrained (for
-          --  instance when this procedure is inherited from an unconstrained
-          --  record to a constrained one) or if the actual has no discriminant
-          --  (its type is constrained). An exception to this is the case of a
-          --  private type without discriminants. In this case we pass FALSE
-          --  because the object has underlying discriminants with defaults.
- 
-          if Present (Extra_Constrained (Formal)) then
-             if Is_Mutably_Tagged_Type (Etype (Actual))
-               or else (Is_Private_Type (Etype (Prev))
-                         and then not Has_Discriminants
-                                        (Base_Type (Etype (Prev))))
-             then
-                Add_Extra_Actual
-                  (Expr => New_Occurrence_Of (Standard_False, Loc),
-                   EF   => Extra_Constrained (Formal));
- 
-             elsif Is_Constrained (Etype (Formal))
-               or else not Has_Discriminants (Etype (Prev))
-             then
-                Add_Extra_Actual
-                  (Expr => New_Occurrence_Of (Standard_True, Loc),
-                   EF   => Extra_Constrained (Formal));
- 
-             --  Do not produce extra actuals for Unchecked_Union parameters.
-             --  Jump directly to the end of the loop.
- 
-             elsif Is_Unchecked_Union (Base_Type (Etype (Actual))) then
-                goto Skip_Extra_Actual_Generation;
- 
-             else
-                --  If the actual is a type conversion, then the constrained
-                --  test applies to the actual, not the target type.
- 
-                declare
-                   Act_Prev : Node_Id;
- 
-                begin
-                   --  Test for unchecked conversions as well, which can occur
-                   --  as out parameter actuals on calls to stream procedures.
- 
-                   Act_Prev := Prev;
-                   while Nkind (Act_Prev) in N_Type_Conversion
-                                           | N_Unchecked_Type_Conversion
-                   loop
-                      Act_Prev := Expression (Act_Prev);
-                   end loop;
- 
-                   --  If the expression is a conversion of a dereference, this
-                   --  is internally generated code that manipulates addresses,
-                   --  e.g. when building interface tables. No check should
-                   --  occur in this case, and the discriminated object is not
-                   --  directly at hand.
- 
-                   if not Comes_From_Source (Actual)
-                     and then Nkind (Actual) = N_Unchecked_Type_Conversion
-                     and then Nkind (Act_Prev) = N_Explicit_Dereference
-                   then
-                      Add_Extra_Actual
-                        (Expr => New_Occurrence_Of (Standard_False, Loc),
-                         EF   => Extra_Constrained (Formal));
- 
-                   else
-                      Add_Extra_Actual
-                        (Expr =>
-                           Make_Attribute_Reference (Sloc (Prev),
-                             Prefix         =>
-                               Duplicate_Subexpr_No_Checks
-                                 (Act_Prev, Name_Req => True),
-                             Attribute_Name => Name_Constrained),
-                         EF   => Extra_Constrained (Formal));
-                   end if;
-                end;
-             end if;
-          end if;
- 
-          --  Create possible extra actual for accessibility level
- 
-          if Present (Extra_Accessibility (Formal)) then
-             --  Ada 2005 (AI-251): Thunks must propagate the extra actuals of
-             --  accessibility levels.
- 
-             if Is_Thunk (Current_Scope) then
-                declare
-                   Parm_Ent : Entity_Id;
- 
-                begin
-                   if Is_Controlling_Actual (Actual) then
- 
-                      --  Find the corresponding actual of the thunk
- 
-                      Parm_Ent := First_Entity (Current_Scope);
-                      for J in 2 .. Param_Count loop
-                         Next_Entity (Parm_Ent);
-                      end loop;
- 
-                   --  Handle unchecked conversion of access types generated
-                   --  in thunks (cf. Expand_Interface_Thunk).
- 
-                   elsif Is_Access_Type (Etype (Actual))
-                     and then Nkind (Actual) = N_Unchecked_Type_Conversion
-                   then
-                      Parm_Ent := Entity (Expression (Actual));
- 
-                   else pragma Assert (Is_Entity_Name (Actual));
-                      Parm_Ent := Entity (Actual);
-                   end if;
- 
-                   Add_Extra_Actual
-                     (Expr => Accessibility_Level
-                                (Expr            => Parm_Ent,
-                                 Level           => Dynamic_Level,
-                                 Allow_Alt_Model => False),
-                      EF   => Extra_Accessibility (Formal));
-                end;
- 
-             --  Conditional expressions
- 
-             elsif Nkind (Prev) = N_Expression_With_Actions
-               and then Nkind (Original_Node (Prev)) in
-                          N_If_Expression | N_Case_Expression
-             then
-                Add_Cond_Expression_Extra_Actual (Formal);
- 
-             --  Internal constant generated to remove side effects (normally
-             --  from the expansion of dispatching calls).
- 
-             --  First verify the actual is internal
- 
-             elsif not Comes_From_Source (Prev)
-               and then not Is_Rewrite_Substitution (Prev)
- 
-               --  Next check that the actual is a constant
- 
-               and then Nkind (Prev) = N_Identifier
-               and then Ekind (Entity (Prev)) = E_Constant
-               and then Nkind (Parent (Entity (Prev))) = N_Object_Declaration
-             then
-                --  Generate the accessibility level based on the expression in
-                --  the constant's declaration.
- 
-                declare
-                   Ent : Entity_Id := Entity (Prev);
- 
-                begin
-                   --  Handle deferred constants
- 
-                   if Present (Full_View (Ent)) then
-                      Ent := Full_View (Ent);
-                   end if;
- 
-                   Add_Extra_Actual
-                     (Expr => Accessibility_Level
-                                (Expr            => Expression (Parent (Ent)),
-                                 Level           => Dynamic_Level,
-                                 Allow_Alt_Model => False),
-                      EF   => Extra_Accessibility (Formal));
-                end;
- 
-             --  Normal case
- 
-             else
-                Add_Extra_Actual
-                  (Expr => Accessibility_Level
-                             (Expr            => Prev,
-                              Level           => Dynamic_Level,
-                              Allow_Alt_Model => False),
-                   EF   => Extra_Accessibility (Formal));
-             end if;
-          end if;
- 
           --  Perform the check of 4.6(49) that prevents a null value from being
           --  passed as an actual to an access parameter. Note that the check
           --  is elided in the common cases of passing an access attribute or
--- 4798,4803 ----
*************** package body Exp_Ch6 is
*** 4525,4590 ****
           --  This label is required when skipping extra actual generation for
           --  Unchecked_Union parameters.
  
-          <<Skip_Extra_Actual_Generation>>
- 
           Param_Count := Param_Count + 1;
           Next_Actual (Actual);
           Next_Formal (Formal);
        end loop;
  
-       --  If we are calling an Ada 2012 function which needs to have the
-       --  "accessibility level determined by the point of call" (AI05-0234)
-       --  passed in to it, then pass it in.
- 
-       if Ekind (Subp) in E_Function | E_Operator | E_Subprogram_Type
-         and then
-           Present (Extra_Accessibility_Of_Result (Ultimate_Alias (Subp)))
-       then
-          declare
-             Extra_Form : Node_Id := Empty;
-             Level      : Node_Id := Empty;
- 
-          begin
-             --  Detect cases where the function call has been internally
-             --  generated by examining the original node and return library
-             --  level - taking care to avoid ignoring function calls expanded
-             --  in prefix notation.
- 
-             if Nkind (Original_Node (Call_Node)) not in N_Function_Call
-                                                       | N_Selected_Component
-                                                       | N_Indexed_Component
-             then
-                Level := Make_Integer_Literal
-                           (Loc, Scope_Depth (Standard_Standard));
- 
-             --  Otherwise get the level normally based on the call node
- 
-             else
-                Level := Accessibility_Level
-                           (Expr            => Call_Node,
-                            Level           => Dynamic_Level,
-                            Allow_Alt_Model => False);
-             end if;
- 
-             --  It may be possible that we are re-expanding an already
-             --  expanded call when are are dealing with dispatching ???
- 
-             if No (Parameter_Associations (Call_Node))
-               or else Nkind (Last (Parameter_Associations (Call_Node)))
-                         /= N_Parameter_Association
-               or else not Is_Accessibility_Actual
-                               (Last (Parameter_Associations (Call_Node)))
-             then
-                Extra_Form := Extra_Accessibility_Of_Result
-                                (Ultimate_Alias (Subp));
- 
-                Add_Extra_Actual
-                  (Expr => Level,
-                   EF   => Extra_Form);
-             end if;
-          end;
-       end if;
- 
        --  If we are expanding the RHS of an assignment we need to check if tag
        --  propagation is needed. You might expect this processing to be in
        --  Analyze_Assignment but has to be done earlier (bottom-up) because the
--- 4991,5001 ----
*************** package body Exp_Ch6 is
*** 4597,4623 ****
        then
           declare
              Ass : Node_Id := Empty;
  
           begin
!             if Nkind (Parent (Call_Node)) = N_Assignment_Statement then
!                Ass := Parent (Call_Node);
  
!             elsif Nkind (Parent (Call_Node)) = N_Qualified_Expression
!               and then Nkind (Parent (Parent (Call_Node))) =
!                                                   N_Assignment_Statement
!             then
!                Ass := Parent (Parent (Call_Node));
  
!             elsif Nkind (Parent (Call_Node)) = N_Explicit_Dereference
!               and then Nkind (Parent (Parent (Call_Node))) =
!                                                   N_Assignment_Statement
!             then
!                Ass := Parent (Parent (Call_Node));
!             end if;
  
!             if Present (Ass)
!               and then Is_Class_Wide_Type (Etype (Name (Ass)))
              then
                 --  Move the error messages below to sem???
  
                 if Is_Access_Type (Etype (Call_Node)) then
--- 5008,5041 ----
        then
           declare
              Ass : Node_Id := Empty;
+             Par : Node_Id := Parent (Call_Node);
  
           begin
!             --  Search for the LHS of an enclosing assignment statement to a
!             --  classwide type object (if present) and propagate the tag to
!             --  this function call.
  
!             while Nkind (Par) in N_Case_Expression
!                                | N_Case_Expression_Alternative
!                                | N_Explicit_Dereference
!                                | N_If_Expression
!                                | N_Qualified_Expression
!                                | N_Unchecked_Type_Conversion
!             loop
!                if Nkind (Par) = N_Case_Expression_Alternative then
!                   Par := Parent (Par);
!                end if;
  
!                exit when not Is_Tag_Indeterminate (Par);
  
!                Par := Parent (Par);
!             end loop;
! 
!             if Nkind (Par) = N_Assignment_Statement
!               and then Is_Class_Wide_Type (Etype (Name (Par)))
              then
+                Ass := Par;
+ 
                 --  Move the error messages below to sem???
  
                 if Is_Access_Type (Etype (Call_Node)) then
*************** package body Exp_Ch6 is
*** 4630,4635 ****
--- 5048,5059 ----
                           Call_Node, Root_Type (Etype (Name (Ass))));
                    else
                       Propagate_Tag (Name (Ass), Call_Node);
+ 
+                      --  Remember that the tag has been propagated to avoid
+                      --  propagating it again, as part of the (bottom-up)
+                      --  analysis of the enclosing assignment.
+ 
+                      Set_Tag_Propagated (Name (Ass));
                    end if;
  
                 elsif Etype (Call_Node) /= Root_Type (Etype (Name (Ass))) then
*************** package body Exp_Ch6 is
*** 4640,4645 ****
--- 5064,5075 ----
  
                 else
                    Propagate_Tag (Name (Ass), Call_Node);
+ 
+                   --  Remember that the tag has been propagated to avoid
+                   --  propagating it again, as part of the (bottom-up)
+                   --  analysis of the enclosing assignment.
+ 
+                   Set_Tag_Propagated (Name (Ass));
                 end if;
  
                 --  The call will be rewritten as a dispatching call, and
*************** package body Exp_Ch6 is
*** 4778,4815 ****
        then
           null;
  
!       --  During that loop we gathered the extra actuals (the ones that
!       --  correspond to Extra_Formals), so now they can be appended.
! 
!       elsif Is_Non_Empty_List (Extra_Actuals) then
!          declare
!             Num_Extra_Actuals : constant Nat := List_Length (Extra_Actuals);
! 
!          begin
!             while Is_Non_Empty_List (Extra_Actuals) loop
!                Add_Actual_Parameter (Remove_Head (Extra_Actuals));
!             end loop;
! 
!             --  Add dummy extra BIP actuals if we are calling a function that
!             --  inherited the BIP extra actuals but does not require them.
! 
!             if Nkind (Call_Node) = N_Function_Call
!               and then Is_Function_Call_With_BIP_Formals (Call_Node)
!               and then not Is_Build_In_Place_Function_Call (Call_Node)
!             then
!                Add_Dummy_Build_In_Place_Actuals (Subp,
!                  Num_Added_Extra_Actuals => Num_Extra_Actuals);
!             end if;
!          end;
! 
!       --  Add dummy extra BIP actuals if we are calling a function that
!       --  inherited the BIP extra actuals but does not require them.
  
!       elsif Nkind (Call_Node) = N_Function_Call
!         and then Is_Function_Call_With_BIP_Formals (Call_Node)
!         and then not Is_Build_In_Place_Function_Call (Call_Node)
!       then
!          Add_Dummy_Build_In_Place_Actuals (Subp);
        end if;
  
        --  At this point we have all the actuals, so this is the point at which
--- 5208,5219 ----
        then
           null;
  
!       elsif not Defer_Extra_Actuals then
!          Create_Extra_Formals (Subp);
  
!          if Extra_Formals_Known (Subp) then
!             Create_Extra_Actuals (N);
!          end if;
        end if;
  
        --  At this point we have all the actuals, so this is the point at which
*************** package body Exp_Ch6 is
*** 7165,7170 ****
--- 7569,7584 ----
        then
           Apply_CW_Accessibility_Check (Exp, Scope_Id);
  
+       --  Check that result's access discrims (if any) do not designate
+       --  entities that the function result could outlive. See preceding
+       --  comment about extended return statements and thunks.
+ 
+       elsif Has_Anonymous_Access_Discriminant (Exp_Typ)
+         and then not Comes_From_Extended_Return_Statement (N)
+         and then not Is_Thunk (Scope_Id)
+       then
+          Apply_Access_Discrims_Accessibility_Check (Exp, Scope_Id);
+ 
        --  Ada 2012 (AI05-0073): If the result subtype of the function is
        --  defined by an access_definition designating a specific tagged
        --  type T, a check is made that the result value is null or the tag
*************** package body Exp_Ch6 is
*** 8563,8568 ****
--- 8977,8984 ----
        Rewrite (Allocator, New_Occurrence_Of (Return_Obj_Access, Loc));
  
        Analyze_And_Resolve (Allocator, Acc_Type);
+ 
+       pragma Assert (Returns_By_Ref (Function_Id));
        pragma Assert (Check_Number_Of_Actuals (Func_Call, Function_Id));
        pragma Assert (Check_BIP_Actuals (Func_Call, Function_Id));
     end Make_Build_In_Place_Call_In_Allocator;
*************** package body Exp_Ch6 is
*** 8668,8673 ****
--- 9084,9090 ----
  
           Set_Is_Expanded_Build_In_Place_Call (Func_Call);
  
+          pragma Assert (Returns_By_Ref (Function_Id));
           pragma Assert (Check_Number_Of_Actuals (Func_Call, Function_Id));
           pragma Assert (Check_BIP_Actuals (Func_Call, Function_Id));
        end if;
*************** package body Exp_Ch6 is
*** 8769,8774 ****
--- 9186,9193 ----
        Insert_After_And_Analyze (Ptr_Typ_Decl, Obj_Decl);
  
        Rewrite (Assign, Make_Null_Statement (Loc));
+ 
+       pragma Assert (Returns_By_Ref (Func_Id));
        pragma Assert (Check_Number_Of_Actuals (Func_Call, Func_Id));
        pragma Assert (Check_BIP_Actuals (Func_Call, Func_Id));
     end Make_Build_In_Place_Call_In_Assignment;
*************** package body Exp_Ch6 is
*** 9193,9198 ****
--- 9612,9618 ----
           end if;
        end if;
  
+       pragma Assert (Returns_By_Ref (Function_Id));
        pragma Assert (Check_Number_Of_Actuals (Func_Call, Function_Id));
        pragma Assert (Check_BIP_Actuals (Func_Call, Function_Id));
     end Make_Build_In_Place_Call_In_Object_Declaration;
*************** package body Exp_Ch6 is
*** 9830,9864 ****
              =>
                 declare
                    Call_Node : Node_Id renames Nod;
!                   Subp      : Entity_Id;
  
                 begin
!                   --  Call using access to subprogram with explicit dereference
! 
!                   if Nkind (Name (Call_Node)) = N_Explicit_Dereference then
!                      Subp := Etype (Name (Call_Node));
! 
!                   --  Prefix notation calls
! 
!                   elsif Nkind (Name (Call_Node)) = N_Selected_Component then
!                      Subp := Entity (Selector_Name (Name (Call_Node)));
! 
!                   --  Call to member of entry family, where Name is an indexed
!                   --  component, with the prefix being a selected component
!                   --  giving the task and entry family name, and the index
!                   --  being the entry index.
! 
!                   elsif Nkind (Name (Call_Node)) = N_Indexed_Component then
!                      Subp :=
!                        Entity (Selector_Name (Prefix (Name (Call_Node))));
! 
!                   --  Normal case
  
!                   else
!                      Subp := Entity (Name (Call_Node));
!                   end if;
  
!                   pragma Assert (Check_BIP_Actuals (Call_Node, Subp));
                 end;
  
              --  Skip generic bodies
--- 10250,10265 ----
              =>
                 declare
                    Call_Node : Node_Id renames Nod;
!                   Subp      : constant Entity_Id := Get_Called_Entity (Nod);
  
                 begin
!                   pragma Assert (Check_BIP_Actuals (Call_Node, Subp));
  
!                   --  Build-in-place function calls return their result by
!                   --  reference.
  
!                   pragma Assert (not Is_Build_In_Place_Function (Subp)
!                     or else Returns_By_Ref (Subp));
                 end;
  
              --  Skip generic bodies
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_ch6.ads gcc-16-20250727/gcc/ada/exp_ch6.ads
*** gcc-16-20250720/gcc/ada/exp_ch6.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_ch6.ads	Sun Jul 27 22:32:07 2025
*************** package Exp_Ch6 is
*** 101,107 ****
--- 101,120 ----
     --  Adds Extra_Actual as a named parameter association for the formal
     --  Extra_Formal in Subprogram_Call.
  
+    procedure Create_Extra_Actuals (Call_Node : Node_Id);
+    --  Create the extra actuals of the given call and add them to its
+    --  actual parameters list.
+ 
+    procedure Apply_Access_Discrims_Accessibility_Check
+      (Exp : Node_Id; Func : Entity_Id);
+    --  Exp is an expression being returned from a function Func.
+    --  If the result type of the function has access discriminants, insert
+    --  checks that the accessibility level of each entity designated by an
+    --  access discriminant of the result is not deeper than the level of the
+    --  master of the call.
+ 
     procedure Apply_CW_Accessibility_Check (Exp : Node_Id; Func : Entity_Id);
+    --  Exp is an expression being returned from a function Func.
     --  Ada 2005 (AI95-344): If the result type is class-wide, insert a check
     --  that the level of the return expression's underlying type is not deeper
     --  than the level of the master enclosing the function. Always generate the
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_ch7.adb gcc-16-20250727/gcc/ada/exp_ch7.adb
*** gcc-16-20250720/gcc/ada/exp_ch7.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_ch7.adb	Sun Jul 27 22:32:07 2025
*************** with Sinfo.Nodes;    use Sinfo.Nodes;
*** 59,64 ****
--- 59,65 ----
  with Sinfo.Utils;    use Sinfo.Utils;
  with Sem;            use Sem;
  with Sem_Aux;        use Sem_Aux;
+ with Sem_Ch6;        use Sem_Ch6;
  with Sem_Ch7;        use Sem_Ch7;
  with Sem_Ch8;        use Sem_Ch8;
  with Sem_Res;        use Sem_Res;
*************** package body Exp_Ch7 is
*** 2331,2336 ****
--- 2332,2339 ----
  
                 Ensure_Freeze_Node (Fin_Id);
                 Insert_After (Fin_Spec, Freeze_Node (Fin_Id));
+                Mutate_Ekind (Fin_Id, E_Procedure);
+                Freeze_Extra_Formals (Fin_Id);
                 Set_Is_Frozen (Fin_Id);
  
                 Append_To (Stmts, Fin_Body);
*************** package body Exp_Ch7 is
*** 3586,3603 ****
  
     procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
     begin
!       Set_TSS (Typ,
!         Make_Deep_Proc
!           (Prim  => Initialize_Case,
!            Typ   => Typ,
!            Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
  
!       if not Is_Inherently_Limited_Type (Typ) then
!          Set_TSS (Typ,
!            Make_Deep_Proc
!              (Prim  => Adjust_Case,
!               Typ   => Typ,
!               Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
        end if;
  
        --  Do not generate Deep_Finalize and Finalize_Address if finalization is
--- 3589,3610 ----
  
     procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
     begin
!       if Has_Controlled_Component (Typ) then
!          Set_TSS
!            (Typ,
!             Make_Deep_Proc
!               (Prim  => Initialize_Case,
!                Typ   => Typ,
!                Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
  
!          if not Is_Inherently_Limited_Type (Typ) then
!             Set_TSS
!               (Typ,
!                Make_Deep_Proc
!                  (Prim  => Adjust_Case,
!                   Typ   => Typ,
!                   Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
!          end if;
        end if;
  
        --  Do not generate Deep_Finalize and Finalize_Address if finalization is
*************** package body Exp_Ch7 is
*** 5598,5604 ****
  
        --  Deal with untagged derivation of private views
  
!       if Present (Utyp) and then Is_Untagged_Derivation (Typ) then
           Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
           Ref  := Unchecked_Convert_To (Utyp, Ref);
           Set_Assignment_OK (Ref);
--- 5605,5614 ----
  
        --  Deal with untagged derivation of private views
  
!       if Present (Utyp)
!         and then Is_Untagged_Derivation (Typ)
!         and then Is_Implicit_Full_View (Utyp)
!       then
           Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
           Ref  := Unchecked_Convert_To (Utyp, Ref);
           Set_Assignment_OK (Ref);
*************** package body Exp_Ch7 is
*** 6635,6640 ****
--- 6645,6660 ----
        --       Raised : Boolean := False;
        --
        --    begin
+       --       begin
+       --          <Destructor_Proc> (V);  --  If applicable
+       --       exception
+       --          when others =>
+       --             if not Raised then
+       --                Raised := True;
+       --                Save_Occurrence (E, Get_Current_Excep.all.all);
+       --             end if;
+       --       end;
+       --
        --       if F then
        --          begin
        --             Finalize (V);  --  If applicable
*************** package body Exp_Ch7 is
*** 6690,6695 ****
--- 6710,6717 ----
        --
        --       begin
        --          Deep_Finalize (V._parent, False);  --  If applicable
+       --  or
+       --          Deep_Finalize (Parent_Type (V), False); -- Untagged case
        --       exception
        --          when Id : others =>
        --             if not Raised then
*************** package body Exp_Ch7 is
*** 7094,7100 ****
           --  or the type is not controlled.
  
           if Is_Empty_List (Bod_Stmts) then
!             Append_To (Bod_Stmts, Make_Null_Statement (Loc));
  
              return Bod_Stmts;
  
--- 7116,7122 ----
           --  or the type is not controlled.
  
           if Is_Empty_List (Bod_Stmts) then
!             Append_New_To (Bod_Stmts, Make_Null_Statement (Loc));
  
              return Bod_Stmts;
  
*************** package body Exp_Ch7 is
*** 7581,7589 ****
  
           --    Deep_Finalize (Obj._parent, False);
  
!          if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
              declare
!                Par_Typ  : constant Entity_Id := Parent_Field_Type (Typ);
                 Call     : Node_Id;
                 Fin_Stmt : Node_Id;
  
--- 7603,7615 ----
  
           --    Deep_Finalize (Obj._parent, False);
  
!          if Is_Derived_Type (Typ) then
              declare
!                Tagd     : constant Boolean := Is_Tagged_Type (Typ);
!                Par_Typ  : constant Entity_Id :=
!                  (if Tagd
!                   then Parent_Field_Type (Typ)
!                   else Etype (Base_Type (Typ)));
                 Call     : Node_Id;
                 Fin_Stmt : Node_Id;
  
*************** package body Exp_Ch7 is
*** 7592,7601 ****
                    Call :=
                      Make_Final_Call
                        (Obj_Ref   =>
!                          Make_Selected_Component (Loc,
!                            Prefix        => Make_Identifier (Loc, Name_V),
!                            Selector_Name =>
!                              Make_Identifier (Loc, Name_uParent)),
                         Typ       => Par_Typ,
                         Skip_Self => True);
  
--- 7618,7633 ----
                    Call :=
                      Make_Final_Call
                        (Obj_Ref   =>
!                          (if Tagd
!                           then
!                             Make_Selected_Component
!                               (Loc,
!                                Prefix        => Make_Identifier (Loc, Name_V),
!                                Selector_Name =>
!                                  Make_Identifier (Loc, Name_uParent))
!                           else
!                             Convert_To
!                               (Par_Typ, Make_Identifier (Loc, Name_V))),
                         Typ       => Par_Typ,
                         Skip_Self => True);
  
*************** package body Exp_Ch7 is
*** 7611,7616 ****
--- 7643,7663 ----
                    --               Get_Current_Excep.all.all);
                    --          end if;
                    --    end;
+                   --
+                   --  in the tagged case. In the untagged case, which arises
+                   --  with the Destructor aspect, generate:
+                   --
+                   --    begin
+                   --       Deep_Finalize (Parent_Type (V), False);
+ 
+                   --    exception
+                   --       when Id : others =>
+                   --          if not Raised then
+                   --             Raised := True;
+                   --             Save_Occurrence (E,
+                   --               Get_Current_Excep.all.all);
+                   --          end if;
+                   --    end;
  
                    if Present (Call) then
                       Fin_Stmt := Call;
*************** package body Exp_Ch7 is
*** 7656,7662 ****
                          --  than before, the extension components. That might
                          --  be more intuitive (as discussed in preceding
                          --  comment), but it is not required.
!                         Prepend_To (Bod_Stmts, Fin_Stmt);
                       end if;
                    end if;
                 end if;
--- 7703,7709 ----
                          --  than before, the extension components. That might
                          --  be more intuitive (as discussed in preceding
                          --  comment), but it is not required.
!                         Prepend_New_To (Bod_Stmts, Fin_Stmt);
                       end if;
                    end if;
                 end if;
*************** package body Exp_Ch7 is
*** 7707,7718 ****
                                   (Finalizer_Data))));
                    end if;
  
!                   Prepend_To (Bod_Stmts,
                      Make_If_Statement (Loc,
                        Condition       => Make_Identifier (Loc, Name_F),
                        Then_Statements => New_List (Fin_Stmt)));
                 end if;
              end;
           end if;
  
           --  At this point either all finalization statements have been
--- 7754,7811 ----
                                   (Finalizer_Data))));
                    end if;
  
!                   Prepend_New_To (Bod_Stmts,
                      Make_If_Statement (Loc,
                        Condition       => Make_Identifier (Loc, Name_F),
                        Then_Statements => New_List (Fin_Stmt)));
                 end if;
              end;
+ 
+             declare
+                ASN : constant Opt_N_Aspect_Specification_Id :=
+                  Get_Rep_Item (Typ, Name_Destructor, False);
+ 
+                Stmt : Node_Id;
+                Proc : Entity_Id;
+             begin
+                if Present (ASN) then
+                   --  Generate:
+                   --    begin
+                   --       <Destructor_Proc> (V);
+ 
+                   --    exception
+                   --       when others =>
+                   --          if not Raised then
+                   --             Raised := True;
+                   --             Save_Occurrence (E,
+                   --               Get_Current_Excep.all.all);
+                   --          end if;
+                   --    end;
+ 
+                   Proc := Entity (Expression (ASN));
+                   Stmt :=
+                     Make_Procedure_Call_Statement
+                       (Loc,
+                        Name                   => New_Occurrence_Of (Proc, Loc),
+                        Parameter_Associations =>
+                          New_List (Make_Identifier (Loc, Name_V)));
+                   if Exceptions_OK then
+                      Stmt :=
+                        Make_Block_Statement
+                          (Loc,
+                           Handled_Statement_Sequence =>
+                             Make_Handled_Sequence_Of_Statements
+                               (Loc,
+                                Statements         => New_List (Stmt),
+                                Exception_Handlers =>
+                                  New_List
+                                    (Build_Exception_Handler
+                                       (Finalizer_Data))));
+                   end if;
+ 
+                   Prepend_New_To (Bod_Stmts, Stmt);
+                end if;
+             end;
           end if;
  
           --  At this point either all finalization statements have been
*************** package body Exp_Ch7 is
*** 7906,7921 ****
        if Is_Untagged_Derivation (Typ) then
           if Is_Protected_Type (Typ) then
              Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
  
!          else
!             declare
!                Root : constant Entity_Id :=
!                  Underlying_Type (Root_Type (Base_Type (Typ)));
!             begin
!                if Is_Protected_Type (Root) then
!                   Utyp := Corresponding_Record_Type (Root);
!                end if;
!             end;
           end if;
  
           Ref := Unchecked_Convert_To (Utyp, Ref);
--- 7999,8010 ----
        if Is_Untagged_Derivation (Typ) then
           if Is_Protected_Type (Typ) then
              Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
+          elsif Is_Implicit_Full_View (Utyp) then
+             Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
  
!             if Is_Protected_Type (Utyp) then
!                Utyp := Corresponding_Record_Type (Utyp);
!             end if;
           end if;
  
           Ref := Unchecked_Convert_To (Utyp, Ref);
*************** package body Exp_Ch7 is
*** 7970,7976 ****
           return Empty;
  
        elsif Skip_Self then
!          if Has_Controlled_Component (Utyp) then
              if Is_Tagged_Type (Utyp) then
                 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
              else
--- 8059,8065 ----
           return Empty;
  
        elsif Skip_Self then
!          if Has_Controlled_Component (Utyp) or else Has_Destructor (Utyp) then
              if Is_Tagged_Type (Utyp) then
                 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
              else
*************** package body Exp_Ch7 is
*** 7983,7988 ****
--- 8072,8078 ----
        elsif Is_Class_Wide_Type (Typ)
          or else Is_Interface (Typ)
          or else Has_Controlled_Component (Utyp)
+         or else Has_Destructor (Utyp)
        then
           if Is_Tagged_Type (Utyp) then
              Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
*************** package body Exp_Ch7 is
*** 8480,8486 ****
  
        --  Deal with untagged derivation of private views
  
!       if Is_Untagged_Derivation (Typ) and then not Is_Conc then
           Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
           Ref  := Unchecked_Convert_To (Utyp, Ref);
  
--- 8570,8579 ----
  
        --  Deal with untagged derivation of private views
  
!       if Is_Untagged_Derivation (Typ)
!         and then not Is_Conc
!         and then Is_Implicit_Full_View (Utyp)
!       then
           Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
           Ref  := Unchecked_Convert_To (Utyp, Ref);
  
*************** package body Exp_Ch7 is
*** 9448,9456 ****
     procedure Wrap_Transient_Expression (N : Node_Id) is
        Loc  : constant Source_Ptr := Sloc (N);
        Expr : Node_Id             := Relocate_Node (N);
-       Temp : constant Entity_Id  := Make_Temporary (Loc, 'E', N);
        Typ  : constant Entity_Id  := Etype (N);
  
     begin
        --  Generate:
  
--- 9541,9556 ----
     procedure Wrap_Transient_Expression (N : Node_Id) is
        Loc  : constant Source_Ptr := Sloc (N);
        Expr : Node_Id             := Relocate_Node (N);
        Typ  : constant Entity_Id  := Etype (N);
  
+       Temp : constant Entity_Id  := Make_Temporary (Loc, 'E',
+                                       Related_Node => Expr);
+       --  We link the temporary with its relocated expression to facilitate
+       --  locating the expression in the expanded code; this simplifies the
+       --  implementation of the function that searchs in the expanded code
+       --  for a function call that has been wrapped in a transient block
+       --  (see Get_Relocated_Function_Call).
+ 
     begin
        --  Generate:
  
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_ch9.adb gcc-16-20250727/gcc/ada/exp_ch9.adb
*** gcc-16-20250720/gcc/ada/exp_ch9.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_ch9.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_Ch9 is
*** 4691,4701 ****
  
        --  The availability of the activation chain entity does not ensure
        --  that we have tasks to activate because it may have been declared
!       --  by the frontend to pass a required extra formal to a build-in-place
        --  subprogram call. If we are within the scope of a protected type and
        --  pragma Detect_Blocking is active we can assume that no tasks will be
        --  activated; if tasks are created in a protected object and this pragma
!       --  is active then the frontend emits a warning and Program_Error is
        --  raised at runtime.
  
        elsif Detect_Blocking and then Within_Protected_Type (Current_Scope) then
--- 4691,4701 ----
  
        --  The availability of the activation chain entity does not ensure
        --  that we have tasks to activate because it may have been declared
!       --  by the front end to pass a required extra formal to a build-in-place
        --  subprogram call. If we are within the scope of a protected type and
        --  pragma Detect_Blocking is active we can assume that no tasks will be
        --  activated; if tasks are created in a protected object and this pragma
!       --  is active then the front end emits a warning and Program_Error is
        --  raised at runtime.
  
        elsif Detect_Blocking and then Within_Protected_Type (Current_Scope) then
*************** package body Exp_Ch9 is
*** 8094,8105 ****
     --  access type. Finally the Entry_Component of each formal is set to
     --  reference the corresponding record component.
  
!    procedure Expand_N_Entry_Declaration (N : Node_Id) is
        Loc        : constant Source_Ptr := Sloc (N);
        Entry_Ent  : constant Entity_Id  := Defining_Identifier (N);
        Components : List_Id;
        Formal     : Node_Id;
        Ftype      : Entity_Id;
        Last_Decl  : Node_Id;
        Component  : Entity_Id;
        Ctype      : Entity_Id;
--- 8094,8111 ----
     --  access type. Finally the Entry_Component of each formal is set to
     --  reference the corresponding record component.
  
!    procedure Expand_N_Entry_Declaration
!      (N            : Node_Id;
!       Was_Deferred : Boolean := False)
!    is
!       use Deferred_Extra_Formals_Support;
! 
        Loc        : constant Source_Ptr := Sloc (N);
        Entry_Ent  : constant Entity_Id  := Defining_Identifier (N);
        Components : List_Id;
        Formal     : Node_Id;
        Ftype      : Entity_Id;
+       First_Decl : Node_Id;
        Last_Decl  : Node_Id;
        Component  : Entity_Id;
        Ctype      : Entity_Id;
*************** package body Exp_Ch9 is
*** 8108,8114 ****
--- 8114,8134 ----
        Acc_Ent    : Entity_Id;
  
     begin
+       --  No action if the addition of the extra formals was deferred,
+       --  since it means that the underlying type of some formal is not
+       --  available, and hence we cannot build the record type that will
+       --  hold all the parameter values.
+ 
+       if Present (First_Formal (Entry_Ent))
+         and then not Extra_Formals_Known (Entry_Ent)
+         and then not Is_Unsupported_Extra_Formals_Entity (Entry_Ent)
+       then
+          pragma Assert (Is_Deferred_Extra_Formals_Entity (Entry_Ent));
+          return;
+       end if;
+ 
        Formal := First_Formal (Entry_Ent);
+       First_Decl := N;
        Last_Decl := N;
  
        --  Most processing is done only if parameters are present
*************** package body Exp_Ch9 is
*** 8184,8189 ****
--- 8204,8227 ----
                   Subtype_Indication => New_Occurrence_Of (Rec_Ent, Loc)));
  
           Insert_After (Last_Decl, Decl);
+          Last_Decl := Decl;
+ 
+          --  Analyze all the inserted declarations. This is required when
+          --  the entry has formals and the addition of its extra formals
+          --  was deferred; otherwise their analysis will be performed as
+          --  as part of the regular flow of the front end at the end of
+          --  analysis of the enclosing task/protected type declaration.
+ 
+          if Was_Deferred then
+             Push_Scope (Scope (Entry_Ent));
+ 
+             while First_Decl /= Last_Decl loop
+                Next (First_Decl);
+                Analyze (First_Decl);
+             end loop;
+ 
+             End_Scope;
+          end if;
        end if;
     end Expand_N_Entry_Declaration;
  
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_ch9.ads gcc-16-20250727/gcc/ada/exp_ch9.ads
*** gcc-16-20250720/gcc/ada/exp_ch9.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_ch9.ads	Sun Jul 27 22:32:07 2025
*************** package Exp_Ch9 is
*** 227,235 ****
     procedure Expand_N_Delay_Until_Statement      (N : Node_Id);
     procedure Expand_N_Entry_Body                 (N : Node_Id);
     procedure Expand_N_Entry_Call_Statement       (N : Node_Id);
-    procedure Expand_N_Entry_Declaration          (N : Node_Id);
     procedure Expand_N_Protected_Body             (N : Node_Id);
  
     procedure Expand_N_Protected_Type_Declaration (N : Node_Id);
     --  Expands protected type declarations. This results, among other things,
     --  in the declaration of a record type for the representation of protected
--- 227,242 ----
     procedure Expand_N_Delay_Until_Statement      (N : Node_Id);
     procedure Expand_N_Entry_Body                 (N : Node_Id);
     procedure Expand_N_Entry_Call_Statement       (N : Node_Id);
     procedure Expand_N_Protected_Body             (N : Node_Id);
  
+    procedure Expand_N_Entry_Declaration
+      (N            : Node_Id;
+       Was_Deferred : Boolean := False);
+    --  Expands an entry declaration, building a record type to hold all the
+    --  parameter values. Was_Deferred is True when this expansion was deferred
+    --  because the underlying type of some formal was not available to build
+    --  the record.
+ 
     procedure Expand_N_Protected_Type_Declaration (N : Node_Id);
     --  Expands protected type declarations. This results, among other things,
     --  in the declaration of a record type for the representation of protected
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_disp.adb gcc-16-20250727/gcc/ada/exp_disp.adb
*** gcc-16-20250720/gcc/ada/exp_disp.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_disp.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_Disp is
*** 801,807 ****
  
          --  No action needed if the dispatching call has been already expanded
  
!         or else Is_Expanded_Dispatching_Call (Name (Call_Node))
        then
           return;
        end if;
--- 801,807 ----
  
          --  No action needed if the dispatching call has been already expanded
  
!         or else Is_Expanded_Dispatching_Call (Call_Node)
        then
           return;
        end if;
*************** package body Exp_Disp is
*** 926,931 ****
--- 926,933 ----
           New_Formal  : Entity_Id;
           Last_Formal : Entity_Id := Empty;
  
+          use Deferred_Extra_Formals_Support;
+ 
        begin
           if Present (Old_Formal) then
              New_Formal := New_Copy (Old_Formal);
*************** package body Exp_Disp is
*** 962,1012 ****
           end if;
  
           --  Now that the explicit formals have been duplicated, any extra
!          --  formals needed by the subprogram must be duplicated; we know
!          --  that extra formals are available because they were added when
!          --  the tagged type was frozen (see Expand_Freeze_Record_Type).
  
           pragma Assert (Is_Frozen (Typ));
  
!          --  Warning: The addition of the extra formals cannot be performed
!          --  here invoking Create_Extra_Formals since we must ensure that all
!          --  the extra formals of the pointer type and the target subprogram
!          --  match (and for functions that return a tagged type the profile of
!          --  the built subprogram type always returns a class-wide type, which
!          --  may affect the addition of some extra formals).
! 
!          if Present (Last_Formal)
!            and then Present (Extra_Formal (Last_Formal))
!          then
!             Old_Formal := Extra_Formal (Last_Formal);
!             New_Formal := New_Copy (Old_Formal);
!             Set_Scope (New_Formal, Subp_Typ);
! 
!             Set_Extra_Formal (Last_Formal, New_Formal);
!             Set_Extra_Formals (Subp_Typ, New_Formal);
! 
!             if Ekind (Subp) = E_Function
!               and then Present (Extra_Accessibility_Of_Result (Subp))
!               and then Extra_Accessibility_Of_Result (Subp) = Old_Formal
!             then
!                Set_Extra_Accessibility_Of_Result (Subp_Typ, New_Formal);
!             end if;
! 
!             Old_Formal := Extra_Formal (Old_Formal);
!             while Present (Old_Formal) loop
!                Set_Extra_Formal (New_Formal, New_Copy (Old_Formal));
!                New_Formal := Extra_Formal (New_Formal);
!                Set_Scope (New_Formal, Subp_Typ);
  
!                if Ekind (Subp) = E_Function
!                  and then Present (Extra_Accessibility_Of_Result (Subp))
!                  and then Extra_Accessibility_Of_Result (Subp) = Old_Formal
!                then
!                   Set_Extra_Accessibility_Of_Result (Subp_Typ, New_Formal);
!                end if;
  
!                Old_Formal := Extra_Formal (Old_Formal);
!             end loop;
           end if;
        end;
  
--- 964,984 ----
           end if;
  
           --  Now that the explicit formals have been duplicated, any extra
!          --  formals needed by the subprogram must be added; we know that
!          --  extra formals are available because they were added when the
!          --  tagged type was frozen (see Expand_Freeze_Record_Type).
  
           pragma Assert (Is_Frozen (Typ));
  
!          if Extra_Formals_Known (Subp) then
!             Create_Extra_Formals (Subp_Typ);
  
!          --  Extra formals were previously deferred
  
!          else
!             pragma Assert (Is_Deferred_Extra_Formals_Entity (Subp));
!             Register_Deferred_Extra_Formals_Entity (Subp_Typ);
!             Register_Deferred_Extra_Formals_Call (Call_Node, Current_Scope);
           end if;
        end;
  
*************** package body Exp_Disp is
*** 1237,1242 ****
--- 1209,1216 ----
        --  the generation of spurious warnings under ZFP run-time.
  
        Analyze_And_Resolve (Call_Node, Call_Typ, Suppress => All_Checks);
+ 
+       Set_Is_Expanded_Dispatching_Call (Call_Node);
     end Expand_Dispatching_Call;
  
     ---------------------------------
*************** package body Exp_Disp is
*** 2378,2394 ****
          and then not Restriction_Active (No_Dispatching_Calls);
     end Has_DT;
  
-    ----------------------------------
-    -- Is_Expanded_Dispatching_Call --
-    ----------------------------------
- 
-    function Is_Expanded_Dispatching_Call (N : Node_Id) return Boolean is
-    begin
-       return Nkind (N) in N_Subprogram_Call
-         and then Nkind (Name (N)) = N_Explicit_Dereference
-         and then Is_Dispatch_Table_Entity (Etype (Name (N)));
-    end Is_Expanded_Dispatching_Call;
- 
     -------------------------------------
     -- Is_Predefined_Dispatching_Alias --
     -------------------------------------
--- 2352,2357 ----
*************** package body Exp_Disp is
*** 8345,8357 ****
                          Defining_Unit_Name       => IP,
                          Parameter_Specifications => Parms)));
  
!                Set_Init_Proc (Typ, IP);
!                Set_Is_Imported    (IP);
!                Set_Is_Constructor (IP);
!                Set_Interface_Name (IP, Interface_Name (E));
!                Set_Convention     (IP, Convention_CPP);
!                Set_Is_Public      (IP);
!                Set_Has_Completion (IP);
  
              --  Case 2: Constructor of a tagged type
  
--- 8308,8322 ----
                          Defining_Unit_Name       => IP,
                          Parameter_Specifications => Parms)));
  
!                Set_Init_Proc   (Typ, IP);
!                Set_Is_Imported      (IP);
!                Set_Is_Constructor   (IP);
!                Set_Interface_Name   (IP, Interface_Name (E));
!                Set_Convention       (IP, Convention_CPP);
!                Set_Is_Public        (IP);
!                Set_Has_Completion   (IP);
!                Mutate_Ekind         (IP, E_Procedure);
!                Freeze_Extra_Formals (IP);
  
              --  Case 2: Constructor of a tagged type
  
*************** package body Exp_Disp is
*** 8484,8489 ****
--- 8449,8456 ----
  
                    Discard_Node (IP_Body);
                    Set_Init_Proc (Typ, IP);
+                   Mutate_Ekind (IP, E_Procedure);
+                   Freeze_Extra_Formals (IP);
                 end;
              end if;
  
*************** package body Exp_Disp is
*** 8549,8554 ****
--- 8516,8523 ----
  
              Discard_Node (IP_Body);
              Set_Init_Proc (Typ, IP);
+             Mutate_Ekind (IP, E_Procedure);
+             Freeze_Extra_Formals (IP);
           end;
        end if;
  
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_disp.ads gcc-16-20250727/gcc/ada/exp_disp.ads
*** gcc-16-20250720/gcc/ada/exp_disp.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_disp.ads	Sun Jul 27 22:32:07 2025
*************** package Exp_Disp is
*** 236,244 ****
     function Has_CPP_Constructors (Typ : Entity_Id) return Boolean;
     --  Returns true if the type has CPP constructors
  
-    function Is_Expanded_Dispatching_Call (N : Node_Id) return Boolean;
-    --  Returns true if N is the expanded code of a dispatching call
- 
     function Make_DT (Typ : Entity_Id) return List_Id;
     --  Expand the declarations for the Dispatch Table of Typ
  
--- 236,241 ----
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_put_image.adb gcc-16-20250727/gcc/ada/exp_put_image.adb
*** gcc-16-20250720/gcc/ada/exp_put_image.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_put_image.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_Put_Image is
*** 77,84 ****
     --  reference). The Loc parameter is used as the Sloc of the created entity.
  
     function Put_Image_Base_Type (E : Entity_Id) return Entity_Id;
!    --  Returns the base type, except for an array type whose whose first
!    --  subtype is constrained, in which case it returns the first subtype.
  
     -------------------------------------
     -- Build_Array_Put_Image_Procedure --
--- 77,104 ----
     --  reference). The Loc parameter is used as the Sloc of the created entity.
  
     function Put_Image_Base_Type (E : Entity_Id) return Entity_Id;
!    --  For an array type whose whose first subtype is constrained, return
!    --  the first subtype. For the internal representation type corresponding
!    --  to a mutably tagged type, return the mutably tagged type. Otherwise,
!    --  return the base type. Similar to Exp_Strm.Stream_Base_Type.
! 
!    procedure Put_Specific_Type_Name_Qualifier
!               (Loc               : Source_Ptr;
!                Stms              : List_Id;
!                Tagged_Obj        : Node_Id;
!                Buffer_Name       : Node_Id;
!                Is_Interface_Type : Boolean);
!    --  Append to the given statement list calls to add into the
!    --  buffer the name of the given object's tag and then a "'".
! 
!    function Put_String_Exp_To_Buffer
!      (Loc         : Source_Ptr;
!       String_Exp  : Node_Id;
!       Buffer_Name : Node_Id;
!       Wide_Wide   : Boolean := False) return Node_Id;
!    --  Generate a call to evaluate a String (or Wide_Wide_String, depending
!    --  on the Wide_Wide Boolean parameter) expression and output it into
!    --  the buffer.
  
     -------------------------------------
     -- Build_Array_Put_Image_Procedure --
*************** package body Exp_Put_Image is
*** 189,195 ****
        Ndim : constant Pos        := Number_Dimensions (Typ);
        Ctyp : constant Entity_Id  := Component_Type (Typ);
  
!       Stm         : Node_Id;
        Exl         : constant List_Id := New_List;
        PI_Entity   : Entity_Id;
  
--- 209,215 ----
        Ndim : constant Pos        := Number_Dimensions (Typ);
        Ctyp : constant Entity_Id  := Component_Type (Typ);
  
!       Stms        : List_Id := New_List;
        Exl         : constant List_Id := New_List;
        PI_Entity   : Entity_Id;
  
*************** package body Exp_Put_Image is
*** 220,234 ****
           Append_To (Exl, Make_Identifier (Loc, New_External_Name ('L', Dim)));
        end loop;
  
!       Stm :=
!         Make_Attribute_Reference (Loc,
!           Prefix => New_Occurrence_Of (Put_Image_Base_Type (Ctyp), Loc),
!           Attribute_Name => Name_Put_Image,
!           Expressions => New_List (
!             Make_Identifier (Loc, Name_S),
!             Make_Indexed_Component (Loc,
!               Prefix      => Make_Identifier (Loc, Name_V),
!               Expressions => Exl)));
  
        --  The corresponding attribute for the component type of the array might
        --  be user-defined, and frozen after the array type. In that case,
--- 240,275 ----
           Append_To (Exl, Make_Identifier (Loc, New_External_Name ('L', Dim)));
        end loop;
  
!       declare
!          Ctype_For_Call : constant Entity_Id := Put_Image_Base_Type (Ctyp);
!          Indexed_Comp   : constant Node_Id :=
!            Make_Indexed_Component (Loc,
!              Prefix      => Make_Identifier (Loc, Name_V),
!              Expressions => Exl);
!       begin
!          if Is_Mutably_Tagged_Type (Ctype_For_Call) then
!             pragma Assert (not Is_Mutably_Tagged_Type (Component_Type (Typ)));
! 
!             Make_Mutably_Tagged_Conversion (Indexed_Comp,
!                                             Typ => Ctype_For_Call);
! 
!             pragma Assert (Is_Mutably_Tagged_Type (Etype (Indexed_Comp)));
! 
!             Put_Specific_Type_Name_Qualifier (Loc,
!                Stms              => Stms,
!                Tagged_Obj        => Indexed_Comp,
!                Buffer_Name       => Make_Identifier (Loc, Name_S),
!                Is_Interface_Type => False);
!          end if;
! 
!          Append_To (Stms,
!            Make_Attribute_Reference (Loc,
!              Prefix => New_Occurrence_Of (Ctype_For_Call, Loc),
!              Attribute_Name => Name_Put_Image,
!              Expressions => New_List (
!                Make_Identifier (Loc, Name_S),
!                Indexed_Comp)));
!       end;
  
        --  The corresponding attribute for the component type of the array might
        --  be user-defined, and frozen after the array type. In that case,
*************** package body Exp_Put_Image is
*** 245,290 ****
        --  Loop through the dimensions, innermost first, generating a loop for
        --  each dimension.
  
!       declare
!          Stms : List_Id := New_List (Stm);
!       begin
!          for Dim in reverse 1 .. Ndim loop
!             declare
!                New_Stms : constant List_Id := New_List;
!                Between_Proc : RE_Id;
!             begin
!                --  For a one-dimensional array of elementary type, use
!                --  RE_Simple_Array_Between. The same applies to the last
!                --  dimension of a multidimensional array.
  
!                if Is_Elementary_Type (Ctyp) and then Dim = Ndim then
!                   Between_Proc := RE_Simple_Array_Between;
!                else
!                   Between_Proc := RE_Array_Between;
!                end if;
  
!                Append_To (New_Stms,
!                  Make_Procedure_Call_Statement (Loc,
!                    Name => New_Occurrence_Of (RTE (RE_Array_Before), Loc),
!                    Parameter_Associations => New_List
!                      (Make_Identifier (Loc, Name_S))));
  
!                Append_To
!                  (New_Stms,
!                   Wrap_In_Loop (Stms, Dim, Indices (Dim), Between_Proc));
  
!                Append_To (New_Stms,
!                  Make_Procedure_Call_Statement (Loc,
!                    Name => New_Occurrence_Of (RTE (RE_Array_After), Loc),
!                    Parameter_Associations => New_List
!                      (Make_Identifier (Loc, Name_S))));
  
!                Stms := New_Stms;
!             end;
!          end loop;
  
!          Build_Put_Image_Proc (Loc, Typ, Decl, Pnam, Stms);
!       end;
     end Build_Array_Put_Image_Procedure;
  
     -------------------------------------
--- 286,327 ----
        --  Loop through the dimensions, innermost first, generating a loop for
        --  each dimension.
  
!       for Dim in reverse 1 .. Ndim loop
!          declare
!             New_Stms : constant List_Id := New_List;
!             Between_Proc : RE_Id;
!          begin
!             --  For a one-dimensional array of elementary type, use
!             --  RE_Simple_Array_Between. The same applies to the last
!             --  dimension of a multidimensional array.
  
!             if Is_Elementary_Type (Ctyp) and then Dim = Ndim then
!                Between_Proc := RE_Simple_Array_Between;
!             else
!                Between_Proc := RE_Array_Between;
!             end if;
  
!             Append_To (New_Stms,
!               Make_Procedure_Call_Statement (Loc,
!                 Name => New_Occurrence_Of (RTE (RE_Array_Before), Loc),
!                 Parameter_Associations => New_List
!                   (Make_Identifier (Loc, Name_S))));
  
!             Append_To
!               (New_Stms,
!                Wrap_In_Loop (Stms, Dim, Indices (Dim), Between_Proc));
  
!             Append_To (New_Stms,
!               Make_Procedure_Call_Statement (Loc,
!                 Name => New_Occurrence_Of (RTE (RE_Array_After), Loc),
!                 Parameter_Associations => New_List
!                   (Make_Identifier (Loc, Name_S))));
  
!             Stms := New_Stms;
!          end;
!       end loop;
  
!       Build_Put_Image_Proc (Loc, Typ, Decl, Pnam, Stms);
     end Build_Array_Put_Image_Procedure;
  
     -------------------------------------
*************** package body Exp_Put_Image is
*** 379,385 ****
           begin
              --  We have built a dispatching call to handle calls to
              --  descendants (since they are not available through rtsfind).
!             --  Further details available in the body of Put_String_Exp.
  
              return Put_Call;
           end;
--- 416,423 ----
           begin
              --  We have built a dispatching call to handle calls to
              --  descendants (since they are not available through rtsfind).
!             --  Further details available in the body of
!             --  Put_String_Exp_To_Buffer.
  
              return Put_Call;
           end;
*************** package body Exp_Put_Image is
*** 691,709 ****
        ---------------------------
  
        procedure Append_Component_Attr (Clist : List_Id; C : Entity_Id) is
!          Component_Typ : constant Entity_Id :=
!            Put_Image_Base_Type
!              (Get_Corresponding_Mutably_Tagged_Type_If_Present (Etype (C)));
        begin
           Append_To (Clist,
             Make_Attribute_Reference (Loc,
               Prefix         => New_Occurrence_Of (Component_Typ, Loc),
               Attribute_Name => Name_Put_Image,
!              Expressions    => New_List (
!                Make_Identifier (Loc, Name_S),
!                Make_Selected_Component (Loc,
!                  Prefix        => Make_Identifier (Loc, Name_V),
!                  Selector_Name => New_Occurrence_Of (C, Loc)))));
        end Append_Component_Attr;
  
        -------------------------------
--- 729,761 ----
        ---------------------------
  
        procedure Append_Component_Attr (Clist : List_Id; C : Entity_Id) is
!          Component_Typ : constant Entity_Id := Put_Image_Base_Type (Etype (C));
!          Selected_Comp : constant Node_Id :=
!            Make_Selected_Component (Loc,
!              Prefix        => Make_Identifier (Loc, Name_V),
!              Selector_Name => New_Occurrence_Of (C, Loc));
        begin
+          if Is_Mutably_Tagged_Type (Component_Typ) then
+             pragma Assert (not Is_Mutably_Tagged_Type (Etype (C)));
+ 
+             Make_Mutably_Tagged_Conversion (Selected_Comp,
+                                             Typ => Component_Typ);
+ 
+             pragma Assert (Is_Mutably_Tagged_Type (Etype (Selected_Comp)));
+ 
+             Put_Specific_Type_Name_Qualifier (Loc,
+                Stms              => Clist,
+                Tagged_Obj        => Selected_Comp,
+                Buffer_Name       => Make_Identifier (Loc, Name_S),
+                Is_Interface_Type => False);
+          end if;
+ 
           Append_To (Clist,
             Make_Attribute_Reference (Loc,
               Prefix         => New_Occurrence_Of (Component_Typ, Loc),
               Attribute_Name => Name_Put_Image,
!              Expressions    => New_List (Make_Identifier (Loc, Name_S),
!                                          Selected_Comp)));
        end Append_Component_Attr;
  
        -------------------------------
*************** package body Exp_Put_Image is
*** 1303,1407 ****
                  New_Occurrence_Of (Sink_Entity, Loc))));
        Actions : List_Id;
  
-       function Put_String_Exp (String_Exp : Node_Id;
-                                Wide_Wide  : Boolean := False) return Node_Id;
-       --  Generate a call to evaluate a String (or Wide_Wide_String, depending
-       --  on the Wide_Wide Boolean parameter) expression and output it into
-       --  the buffer.
- 
-       --------------------
-       -- Put_String_Exp --
-       --------------------
- 
-       function Put_String_Exp (String_Exp : Node_Id;
-                                Wide_Wide  : Boolean := False) return Node_Id is
-          Put_Id : constant RE_Id :=
-            (if Wide_Wide then RE_Wide_Wide_Put else RE_Put_UTF_8);
- 
-          --  We could build a nondispatching call here, but to make
-          --  that work we'd have to change Rtsfind spec to make available
-          --  corresponding callees out of Ada.Strings.Text_Buffers.Unbounded
-          --  (as opposed to from Ada.Strings.Text_Buffers). Seems simpler to
-          --  introduce a type conversion and leave it to the optimizer to
-          --  eliminate the dispatching. This does not *introduce* any problems
-          --  if a no-dispatching-allowed restriction is in effect, since we
-          --  are already in the middle of generating a call to T'Class'Image.
- 
-          Sink_Exp : constant Node_Id :=
-            Make_Type_Conversion (Loc,
-              Subtype_Mark =>
-                New_Occurrence_Of
-                  (Class_Wide_Type (RTE (RE_Root_Buffer_Type)), Loc),
-              Expression   => New_Occurrence_Of (Sink_Entity, Loc));
-       begin
-          return
-            Make_Procedure_Call_Statement (Loc,
-              Name => New_Occurrence_Of (RTE (Put_Id), Loc),
-              Parameter_Associations => New_List (Sink_Exp, String_Exp));
-       end Put_String_Exp;
- 
-       --  Local variables
- 
-       Tag_Node : Node_Id;
- 
     --  Start of processing for Build_Image_Call
  
     begin
        if Is_Class_Wide_Type (U_Type) then
  
!          --  For interface types we must generate code to displace the pointer
!          --  to the object to reference the base of the underlying object.
! 
!          --  Generate:
!          --    To_Tag_Ptr (Image_Prefix'Address).all
! 
!          --  Note that Image_Prefix'Address is recursively expanded into a
!          --  call to Ada.Tags.Base_Address (Image_Prefix'Address).
! 
!          if Is_Interface (U_Type) then
!             Tag_Node :=
!               Make_Explicit_Dereference (Loc,
!                 Unchecked_Convert_To (RTE (RE_Tag_Ptr),
!                   Make_Attribute_Reference (Loc,
!                     Prefix => Duplicate_Subexpr (Image_Prefix),
!                     Attribute_Name => Name_Address)));
! 
!          --  Common case
! 
!          else
!             Tag_Node :=
!               Make_Attribute_Reference (Loc,
!                 Prefix         => Duplicate_Subexpr (Image_Prefix),
!                 Attribute_Name => Name_Tag);
!          end if;
! 
!          --  Generate qualified-expression syntax; qualification name comes
!          --  from calling Ada.Tags.Wide_Wide_Expanded_Name.
! 
!          declare
!             --  The copy of Image_Prefix will be evaluated before the
!             --  original, which is ok if no side effects are involved.
! 
!             pragma Assert (Side_Effect_Free (Image_Prefix));
! 
!             Specific_Type_Name : constant Node_Id :=
!               Put_String_Exp
!                 (Make_Function_Call (Loc,
!                    Name => New_Occurrence_Of
!                              (RTE (RE_Wide_Wide_Expanded_Name), Loc),
!                    Parameter_Associations => New_List (Tag_Node)),
!                  Wide_Wide => True);
  
!             Qualification : constant Node_Id :=
!               Put_String_Exp (Make_String_Literal (Loc, "'"));
!          begin
!             Actions := New_List
!                          (Sink_Decl,
!                           Specific_Type_Name,
!                           Qualification,
!                           Put_Im,
!                           Result_Decl);
!          end;
        else
           Actions := New_List (Sink_Decl, Put_Im, Result_Decl);
        end if;
--- 1355,1374 ----
                  New_Occurrence_Of (Sink_Entity, Loc))));
        Actions : List_Id;
  
     --  Start of processing for Build_Image_Call
  
     begin
        if Is_Class_Wide_Type (U_Type) then
+          Actions := New_List (Sink_Decl);
  
!          Put_Specific_Type_Name_Qualifier (Loc,
!            Stms              => Actions,
!            Tagged_Obj        => Image_Prefix,
!            Buffer_Name       => New_Occurrence_Of (Sink_Entity, Loc),
!            Is_Interface_Type => Is_Interface (U_Type));
  
!          Append_To (Actions, Put_Im);
!          Append_To (Actions, Result_Decl);
        else
           Actions := New_List (Sink_Decl, Put_Im, Result_Decl);
        end if;
*************** package body Exp_Put_Image is
*** 1485,1493 ****
--- 1452,1540 ----
           return E;
        elsif Is_Private_Type (Base_Type (E)) and not Is_Private_Type (E) then
           return Implementation_Base_Type (E);
+       elsif Is_Mutably_Tagged_CW_Equivalent_Type (E) then
+          return Get_Corresponding_Mutably_Tagged_Type_If_Present (E);
        else
           return Base_Type (E);
        end if;
     end Put_Image_Base_Type;
  
+    --------------------------------------
+    -- Put_Specific_Type_Name_Qualifier --
+    --------------------------------------
+ 
+    procedure Put_Specific_Type_Name_Qualifier
+      (Loc               : Source_Ptr;
+       Stms              : List_Id;
+       Tagged_Obj        : Node_Id;
+       Buffer_Name       : Node_Id;
+       Is_Interface_Type : Boolean)
+    is
+       Tag_Node : Node_Id;
+    begin
+       if Is_Interface_Type then
+          Tag_Node :=
+            Make_Explicit_Dereference (Loc,
+              Unchecked_Convert_To (RTE (RE_Tag_Ptr),
+                Make_Attribute_Reference (Loc,
+                  Prefix => New_Copy_Tree (Tagged_Obj),
+                  Attribute_Name => Name_Address)));
+       else
+          Tag_Node :=
+            Make_Attribute_Reference (Loc,
+              Prefix         => New_Copy_Tree (Tagged_Obj),
+              Attribute_Name => Name_Tag);
+       end if;
+ 
+       Append_To (Stms,
+                  Put_String_Exp_To_Buffer (Loc,
+                    String_Exp =>
+                      Make_Function_Call (Loc,
+                        Name => New_Occurrence_Of
+                                  (RTE (RE_Wide_Wide_Expanded_Name), Loc),
+                        Parameter_Associations => New_List (Tag_Node)),
+                    Buffer_Name => Buffer_Name,
+                    Wide_Wide => True));
+ 
+       Append_To (Stms,
+                  Put_String_Exp_To_Buffer (Loc,
+                    String_Exp  => Make_String_Literal (Loc, "'"),
+                    Buffer_Name => New_Copy_Tree (Buffer_Name)));
+    end Put_Specific_Type_Name_Qualifier;
+ 
+    ------------------------------
+    -- Put_String_Exp_To_Buffer --
+    ------------------------------
+ 
+    function Put_String_Exp_To_Buffer
+      (Loc         : Source_Ptr;
+       String_Exp  : Node_Id;
+       Buffer_Name : Node_Id;
+       Wide_Wide   : Boolean := False) return Node_Id
+    is
+       Put_Id : constant RE_Id :=
+         (if Wide_Wide then RE_Wide_Wide_Put else RE_Put_UTF_8);
+ 
+       --  We could build a nondispatching call here, but to make
+       --  that work we'd have to change Rtsfind spec to make available
+       --  corresponding callees out of Ada.Strings.Text_Buffers.Unbounded
+       --  (as opposed to from Ada.Strings.Text_Buffers). Seems simpler to
+       --  introduce a type conversion and leave it to the optimizer to
+       --  eliminate the dispatching. This does not *introduce* any problems
+       --  if a no-dispatching-allowed restriction is in effect, since we
+       --  are already in the middle of generating a call to T'Class'Image.
+ 
+       Sink_Exp : constant Node_Id :=
+         Make_Type_Conversion (Loc,
+           Subtype_Mark =>
+             New_Occurrence_Of
+               (Class_Wide_Type (RTE (RE_Root_Buffer_Type)), Loc),
+           Expression   => Buffer_Name);
+    begin
+       return
+         Make_Procedure_Call_Statement (Loc,
+           Name => New_Occurrence_Of (RTE (Put_Id), Loc),
+           Parameter_Associations => New_List (Sink_Exp, String_Exp));
+    end Put_String_Exp_To_Buffer;
+ 
  end Exp_Put_Image;
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_spark.adb gcc-16-20250727/gcc/ada/exp_spark.adb
*** gcc-16-20250720/gcc/ada/exp_spark.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_spark.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_SPARK is
*** 73,78 ****
--- 73,82 ----
     procedure Expand_SPARK_N_Attribute_Reference (N : Node_Id);
     --  Perform attribute-reference-specific expansion
  
+    procedure Expand_SPARK_N_Continue_Statement (N : Node_Id);
+    --  Expand continue statements which are resolved as procedure calls, into
+    --  said procedure calls. Real continue statements are left as-is.
+ 
     procedure Expand_SPARK_N_Delta_Aggregate (N : Node_Id);
     --  Perform delta-aggregate-specific expansion
  
*************** package body Exp_SPARK is
*** 191,196 ****
--- 195,203 ----
  
           --  In SPARK mode, no other constructs require expansion
  
+          when N_Continue_Statement =>
+             Expand_SPARK_N_Continue_Statement (N);
+ 
           when others =>
              null;
        end case;
*************** package body Exp_SPARK is
*** 435,440 ****
--- 442,464 ----
        end if;
     end Expand_SPARK_Delta_Or_Update;
  
+    ---------------------------------------
+    -- Expand_SPARK_N_Continue_Statement --
+    ---------------------------------------
+ 
+    procedure Expand_SPARK_N_Continue_Statement (N : Node_Id) is
+       X : constant Node_Id := Call_Or_Target_Loop (N);
+    begin
+       if No (X) then
+          return;
+       end if;
+ 
+       if Nkind (X) = N_Procedure_Call_Statement then
+          Replace (N, X);
+          Analyze (N);
+       end if;
+    end Expand_SPARK_N_Continue_Statement;
+ 
     ------------------------------
     -- Expand_SPARK_N_Aggregate --
     ------------------------------
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_strm.adb gcc-16-20250727/gcc/ada/exp_strm.adb
*** gcc-16-20250720/gcc/ada/exp_strm.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_strm.adb	Sun Jul 27 22:32:07 2025
*************** with Einfo.Entities; use Einfo.Entities;
*** 29,34 ****
--- 29,35 ----
  with Einfo.Utils;    use Einfo.Utils;
  with Elists;         use Elists;
  with Exp_Util;       use Exp_Util;
+ with Mutably_Tagged; use Mutably_Tagged;
  with Namet;          use Namet;
  with Nlists;         use Nlists;
  with Nmake;          use Nmake;
*************** package body Exp_Strm is
*** 101,113 ****
     --  Loc parameter is used as the Sloc of the created entity.
  
     function Stream_Base_Type (E : Entity_Id) return Entity_Id;
!    --  Stream attributes work on the basis of the base type except for the
!    --  array case. For the array case, we do not go to the base type, but
!    --  to the first subtype if it is constrained. This avoids problems with
!    --  incorrect conversions in the packed array case. Stream_Base_Type is
!    --  exactly this function (returns the base type, unless we have an array
!    --  type whose first subtype is constrained, in which case it returns the
!    --  first subtype).
  
     --------------------------------
     -- Build_Array_Input_Function --
--- 102,111 ----
     --  Loc parameter is used as the Sloc of the created entity.
  
     function Stream_Base_Type (E : Entity_Id) return Entity_Id;
!    --  For an array type whose whose first subtype is constrained, return
!    --  the first subtype. For the internal representation type corresponding
!    --  to a mutably tagged type, return the mutably tagged type. Otherwise,
!    --  return the base type. Similar to Exp_Put_Image.Put_Image_Base_Type.
  
     --------------------------------
     -- Build_Array_Input_Function --
*************** package body Exp_Strm is
*** 1502,1507 ****
--- 1500,1506 ----
  
        function Make_Field_Attribute (C : Entity_Id) return Node_Id is
           Field_Typ : constant Entity_Id := Stream_Base_Type (Etype (C));
+          Selected  : Node_Id;
  
           TSS_Names : constant array (Name_Input .. Name_Write) of
                         TSS_Name_Type :=
*************** package body Exp_Strm is
*** 1524,1538 ****
              return Make_Null_Statement (Loc);
           end if;
  
           return
             Make_Attribute_Reference (Loc,
               Prefix         => New_Occurrence_Of (Field_Typ, Loc),
               Attribute_Name => Nam,
!              Expressions    => New_List (
!                Make_Identifier (Loc, Name_S),
!                Make_Selected_Component (Loc,
!                  Prefix        => Make_Identifier (Loc, Name_V),
!                  Selector_Name => New_Occurrence_Of (C, Loc))));
        end Make_Field_Attribute;
  
        ---------------------------
--- 1523,1545 ----
              return Make_Null_Statement (Loc);
           end if;
  
+          Selected := Make_Selected_Component (Loc,
+                        Prefix        => Make_Identifier (Loc, Name_V),
+                        Selector_Name => New_Occurrence_Of (C, Loc));
+ 
+          if Is_Mutably_Tagged_CW_Equivalent_Type (Etype (C)) then
+             Make_Mutably_Tagged_Conversion
+               (Selected,
+                Typ => Get_Corresponding_Mutably_Tagged_Type_If_Present
+                         (Etype (C)));
+          end if;
+ 
           return
             Make_Attribute_Reference (Loc,
               Prefix         => New_Occurrence_Of (Field_Typ, Loc),
               Attribute_Name => Nam,
!              Expressions    => New_List (Make_Identifier (Loc, Name_S),
!                                          Selected));
        end Make_Field_Attribute;
  
        ---------------------------
*************** package body Exp_Strm is
*** 1808,1813 ****
--- 1815,1824 ----
  
     function Stream_Base_Type (E : Entity_Id) return Entity_Id is
     begin
+       if Is_Class_Wide_Equivalent_Type (E) then
+          return Corresponding_Mutably_Tagged_Type (E);
+       end if;
+ 
        if Is_Array_Type (E)
          and then Is_First_Subtype (E)
        then
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_util.adb gcc-16-20250727/gcc/ada/exp_util.adb
*** gcc-16-20250720/gcc/ada/exp_util.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_util.adb	Sun Jul 27 22:32:07 2025
*************** package body Exp_Util is
*** 6189,6206 ****
           if Is_Protected_Type (Btyp) then
              Utyp := Corresponding_Record_Type (Root_Type (Btyp));
  
!          else
!             declare
!                Root : constant Entity_Id := Underlying_Type (Root_Type (Btyp));
!             begin
!                if Is_Protected_Type (Root) then
!                   Utyp := Corresponding_Record_Type (Root);
!                else
!                   while No (TSS (Utyp, TSS_Finalize_Address)) loop
!                      Utyp := Underlying_Type (Base_Type (Etype (Utyp)));
!                   end loop;
!                end if;
!             end;
           end if;
        end if;
  
--- 6189,6200 ----
           if Is_Protected_Type (Btyp) then
              Utyp := Corresponding_Record_Type (Root_Type (Btyp));
  
!          elsif Is_Implicit_Full_View (Utyp) then
!             Utyp := Underlying_Type (Root_Type (Btyp));
! 
!             if Is_Protected_Type (Utyp) then
!                Utyp := Corresponding_Record_Type (Utyp);
!             end if;
           end if;
        end if;
  
*************** package body Exp_Util is
*** 11736,11769 ****
        end if;
     end Matching_Standard_Type;
  
-    -----------------------------
-    -- May_Generate_Large_Temp --
-    -----------------------------
- 
-    --  At the current time, the only types that we return False for (i.e. where
-    --  we decide we know they cannot generate large temps) are ones where we
-    --  know the size is 256 bits or less at compile time, and we are still not
-    --  doing a thorough job on arrays and records.
- 
-    function May_Generate_Large_Temp (Typ : Entity_Id) return Boolean is
-    begin
-       if not Size_Known_At_Compile_Time (Typ) then
-          return False;
-       end if;
- 
-       if Known_Esize (Typ) and then Esize (Typ) <= 256 then
-          return False;
-       end if;
- 
-       if Is_Array_Type (Typ)
-         and then Present (Packed_Array_Impl_Type (Typ))
-       then
-          return May_Generate_Large_Temp (Packed_Array_Impl_Type (Typ));
-       end if;
- 
-       return True;
-    end May_Generate_Large_Temp;
- 
     ---------------------------------------
     -- Move_To_Initialization_Statements --
     ---------------------------------------
--- 11730,11735 ----
*************** package body Exp_Util is
*** 13766,13776 ****
     --  The above requirements should be documented in Sinfo ???
  
     function Safe_Unchecked_Type_Conversion (Exp : Node_Id) return Boolean is
        Otyp   : Entity_Id;
        Ityp   : Entity_Id;
        Oalign : Uint;
        Ialign : Uint;
-       Pexp   : constant Node_Id := Parent (Exp);
  
     begin
        --  If the expression is the RHS of an assignment or object declaration
--- 13732,13743 ----
     --  The above requirements should be documented in Sinfo ???
  
     function Safe_Unchecked_Type_Conversion (Exp : Node_Id) return Boolean is
+       Pexp : constant Node_Id := Parent (Exp);
+ 
        Otyp   : Entity_Id;
        Ityp   : Entity_Id;
        Oalign : Uint;
        Ialign : Uint;
  
     begin
        --  If the expression is the RHS of an assignment or object declaration
*************** package body Exp_Util is
*** 13788,13805 ****
           return True;
  
        --  If the expression is the prefix of an N_Selected_Component we should
!       --  also be OK because GCC knows to look inside the conversion except if
!       --  the type is discriminated. We assume that we are OK anyway if the
!       --  type is not set yet or if it is controlled since we can't afford to
!       --  introduce a temporary in this case.
  
        elsif Nkind (Pexp) = N_Selected_Component
          and then Prefix (Pexp) = Exp
        then
!          return No (Etype (Pexp))
!            or else not Is_Type (Etype (Pexp))
!            or else not Has_Discriminants (Etype (Pexp))
!            or else Is_Constrained (Etype (Pexp));
        end if;
  
        --  Set the output type, this comes from Etype if it is set, otherwise we
--- 13755,13766 ----
           return True;
  
        --  If the expression is the prefix of an N_Selected_Component we should
!       --  also be OK because GCC knows to look inside the conversion.
  
        elsif Nkind (Pexp) = N_Selected_Component
          and then Prefix (Pexp) = Exp
        then
!          return True;
        end if;
  
        --  Set the output type, this comes from Etype if it is set, otherwise we
*************** package body Exp_Util is
*** 13872,13885 ****
        --  known size, but we can't consider them that way here, because we are
        --  talking about the actual size of the object.
  
-       --  We also make sure that in addition to the size being known, we do not
-       --  have a case which might generate an embarrassingly large temp in
-       --  stack checking mode.
- 
        elsif Size_Known_At_Compile_Time (Otyp)
-         and then
-           (not Stack_Checking_Enabled
-             or else not May_Generate_Large_Temp (Otyp))
          and then not (Is_Record_Type (Otyp) and then not Is_Constrained (Otyp))
        then
           return True;
--- 13833,13839 ----
diff -Nrcpad gcc-16-20250720/gcc/ada/exp_util.ads gcc-16-20250727/gcc/ada/exp_util.ads
*** gcc-16-20250720/gcc/ada/exp_util.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/exp_util.ads	Sun Jul 27 22:32:07 2025
*************** package Exp_Util is
*** 1064,1079 ****
     --  typically return Standard_Short_Integer. For fixed-point types, this
     --  will return integer types of the corresponding size.
  
-    function May_Generate_Large_Temp (Typ : Entity_Id) return Boolean;
-    --  Determines if the given type, Typ, may require a large temporary of the
-    --  kind that causes back-end trouble if stack checking is enabled. The
-    --  result is True only the size of the type is known at compile time and
-    --  large, where large is defined heuristically by the body of this routine.
-    --  The purpose of this routine is to help avoid generating troublesome
-    --  temporaries that interfere with stack checking mechanism. Note that the
-    --  caller has to check whether stack checking is actually enabled in order
-    --  to guide the expansion (typically of a function call).
- 
     procedure Move_To_Initialization_Statements (Decl, Stop : Node_Id);
     --  Decl is an N_Object_Declaration node and Stop is a node past Decl in
     --  the same list. Move all the nodes on the list between Decl and Stop
--- 1064,1069 ----
diff -Nrcpad gcc-16-20250720/gcc/ada/freeze.adb gcc-16-20250727/gcc/ada/freeze.adb
*** gcc-16-20250720/gcc/ada/freeze.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/freeze.adb	Sun Jul 27 22:32:07 2025
*************** package body Freeze is
*** 7231,7236 ****
--- 7231,7265 ----
              end if;
  
              Inherit_Aspects_At_Freeze_Point (E);
+ 
+             --  Destructor legality check
+ 
+             if Present (Primitive_Operations (E)) then
+                declare
+                   Subp             : Entity_Id;
+                   Parent_Operation : Entity_Id;
+ 
+                   Elmt : Elmt_Id := First_Elmt (Primitive_Operations (E));
+ 
+                begin
+                   while Present (Elmt) loop
+                      Subp := Node (Elmt);
+ 
+                      if Present (Overridden_Operation (Subp)) then
+                         Parent_Operation := Overridden_Operation (Subp);
+ 
+                         if Ekind (Parent_Operation) = E_Procedure
+                           and then Is_Destructor (Parent_Operation)
+                         then
+                            Error_Msg_N ("cannot override destructor", Subp);
+                         end if;
+                      end if;
+ 
+                      Next_Elmt (Elmt);
+                   end loop;
+                end;
+             end if;
+ 
           end if;
  
           --  Case of array type
*************** package body Freeze is
*** 8130,8135 ****
--- 8159,8165 ----
           if Ekind (E) = E_Anonymous_Access_Subprogram_Type
             and then Ekind (Designated_Type (E)) = E_Subprogram_Type
           then
+             Create_Extra_Formals (Designated_Type (E));
              Layout_Type (Etype (Designated_Type (E)));
           end if;
  
*************** package body Freeze is
*** 10393,10398 ****
--- 10423,10430 ----
  
        --  Local variables
  
+       use Deferred_Extra_Formals_Support;
+ 
        F      : Entity_Id;
        Retype : Entity_Id;
  
*************** package body Freeze is
*** 10493,10500 ****
              Create_Extra_Formals (E);
  
              pragma Assert
!               ((Ekind (E) = E_Subprogram_Type
!                   and then Extra_Formals_OK (E))
                 or else
                   (Is_Subprogram (E)
                     and then Extra_Formals_OK (E)
--- 10525,10535 ----
              Create_Extra_Formals (E);
  
              pragma Assert
!               ((Extra_Formals_Known (E)
!                  or else Is_Deferred_Extra_Formals_Entity (E))
!                or else
!                  (Ekind (E) = E_Subprogram_Type
!                    and then Extra_Formals_OK (E))
                 or else
                   (Is_Subprogram (E)
                     and then Extra_Formals_OK (E)
*************** package body Freeze is
*** 10523,10528 ****
--- 10558,10567 ----
        else
           Set_Mechanisms (E);
  
+          if not Extra_Formals_Known (E) then
+             Freeze_Extra_Formals (E);
+          end if;
+ 
           --  For foreign conventions, warn about return of unconstrained array
  
           if Ekind (E) = E_Function then
*************** package body Freeze is
*** 10578,10583 ****
--- 10617,10627 ----
           end if;
        end if;
  
+       --  Check formals matching in thunks
+ 
+       pragma Assert (not Is_Thunk (E)
+         or else Extra_Formals_Match_OK (Thunk_Entity (E), E));
+ 
        --  Pragma Inline_Always is disallowed for dispatching subprograms
        --  because the address of such subprograms is saved in the dispatch
        --  table to support dispatching calls, and dispatching calls cannot
diff -Nrcpad gcc-16-20250720/gcc/ada/gcc-interface/misc.cc gcc-16-20250727/gcc/ada/gcc-interface/misc.cc
*** gcc-16-20250720/gcc/ada/gcc-interface/misc.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/gcc-interface/misc.cc	Sun Jul 27 22:32:07 2025
*************** gnat_post_options (const char **pfilenam
*** 271,277 ****
  
    /* No caret by default for Ada.  */
    if (!OPTION_SET_P (flag_diagnostics_show_caret))
!     global_dc->m_source_printing.enabled = false;
  
    /* Copy global settings to local versions.  */
    gnat_encodings = global_options.x_gnat_encodings;
--- 271,277 ----
  
    /* No caret by default for Ada.  */
    if (!OPTION_SET_P (flag_diagnostics_show_caret))
!     global_dc->get_source_printing_options ().enabled = false;
  
    /* Copy global settings to local versions.  */
    gnat_encodings = global_options.x_gnat_encodings;
*************** gnat_post_options (const char **pfilenam
*** 292,298 ****
  /* Here is the function to handle the compiler error processing in GCC.  */
  
  static void
! internal_error_function (diagnostic_context *context, const char *msgid,
  			 va_list *ap)
  {
    char *buffer, *p, *loc;
--- 292,298 ----
  /* Here is the function to handle the compiler error processing in GCC.  */
  
  static void
! internal_error_function (diagnostics::context *context, const char *msgid,
  			 va_list *ap)
  {
    char *buffer, *p, *loc;
diff -Nrcpad gcc-16-20250720/gcc/ada/gcc-interface/trans.cc gcc-16-20250727/gcc/ada/gcc-interface/trans.cc
*** gcc-16-20250720/gcc/ada/gcc-interface/trans.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/gcc-interface/trans.cc	Sun Jul 27 22:32:07 2025
*************** Pragma_to_gnu (Node_Id gnat_node)
*** 1510,1516 ****
  	const location_t location = input_location;
  	struct cl_option_handlers handlers;
  	unsigned int option_index;
! 	diagnostic_t kind;
  	bool imply;
  
  	gnat_temp = First (Pragma_Argument_Associations (gnat_node));
--- 1510,1516 ----
  	const location_t location = input_location;
  	struct cl_option_handlers handlers;
  	unsigned int option_index;
! 	enum diagnostics::kind kind;
  	bool imply;
  
  	gnat_temp = First (Pragma_Argument_Associations (gnat_node));
*************** Pragma_to_gnu (Node_Id gnat_node)
*** 1521,1532 ****
  	    switch (id)
  	      {
  	      case Pragma_Warning_As_Error:
! 		kind = DK_ERROR;
  		imply = false;
  		break;
  
  	      case Pragma_Warnings:
! 		kind = DK_WARNING;
  		imply = true;
  		break;
  
--- 1521,1532 ----
  	    switch (id)
  	      {
  	      case Pragma_Warning_As_Error:
! 		kind = diagnostics::kind::error;
  		imply = false;
  		break;
  
  	      case Pragma_Warnings:
! 		kind = diagnostics::kind::warning;
  		imply = true;
  		break;
  
*************** Pragma_to_gnu (Node_Id gnat_node)
*** 1543,1553 ****
  	    switch (Chars (Expression (gnat_temp)))
  	      {
  		case Name_Off:
! 		  kind = DK_IGNORED;
  		  break;
  
  		case Name_On:
! 		  kind = DK_WARNING;
  		  break;
  
  		default:
--- 1543,1553 ----
  	    switch (Chars (Expression (gnat_temp)))
  	      {
  		case Name_Off:
! 		  kind = diagnostics::kind::ignored;
  		  break;
  
  		case Name_On:
! 		  kind = diagnostics::kind::warning;
  		  break;
  
  		default:
*************** Pragma_to_gnu (Node_Id gnat_node)
*** 1569,1575 ****
  		gnat_expr = Empty;
  
  		/* For pragma Warnings (Off), we save the current state...  */
! 		if (kind == DK_IGNORED)
  		  diagnostic_push_diagnostics (global_dc, location);
  
  		/* ...so that, for pragma Warnings (On), we do not enable all
--- 1569,1575 ----
  		gnat_expr = Empty;
  
  		/* For pragma Warnings (Off), we save the current state...  */
! 		if (kind == diagnostics::kind::ignored)
  		  diagnostic_push_diagnostics (global_dc, location);
  
  		/* ...so that, for pragma Warnings (On), we do not enable all
*************** gnat_to_gnu (Node_Id gnat_node)
*** 8476,8482 ****
  	      oconstraints[i] = constraint;
  
  	      if (parse_output_constraint (&constraint, i, ninputs, noutputs,
! 					   &allows_mem, &allows_reg, &fake))
  		{
  		  /* If the operand is going to end up in memory,
  		     mark it addressable.  Note that we don't test
--- 8476,8483 ----
  	      oconstraints[i] = constraint;
  
  	      if (parse_output_constraint (&constraint, i, ninputs, noutputs,
! 					   &allows_mem, &allows_reg, &fake,
! 					   nullptr))
  		{
  		  /* If the operand is going to end up in memory,
  		     mark it addressable.  Note that we don't test
*************** gnat_to_gnu (Node_Id gnat_node)
*** 8504,8512 ****
  	      constraint
  		= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
  
! 	      if (parse_input_constraint (&constraint, i, ninputs, noutputs,
! 					  0, oconstraints,
! 					  &allows_mem, &allows_reg))
  		{
  		  /* If the operand is going to end up in memory,
  		     mark it addressable.  */
--- 8505,8513 ----
  	      constraint
  		= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
  
! 	      if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 					  oconstraints, &allows_mem,
! 					  &allows_reg, nullptr))
  		{
  		  /* If the operand is going to end up in memory,
  		     mark it addressable.  */
diff -Nrcpad gcc-16-20250720/gcc/ada/gcc-interface/utils.cc gcc-16-20250727/gcc/ada/gcc-interface/utils.cc
*** gcc-16-20250720/gcc/ada/gcc-interface/utils.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/gcc-interface/utils.cc	Sun Jul 27 22:32:07 2025
*************** build_unc_object_type_from_ptr (tree thi
*** 4510,4517 ****
  void
  update_pointer_to (tree old_type, tree new_type)
  {
!   tree ptr = TYPE_POINTER_TO (old_type);
!   tree ref = TYPE_REFERENCE_TO (old_type);
    tree t;
  
    /* If this is the main variant, process all the other variants first.  */
--- 4510,4517 ----
  void
  update_pointer_to (tree old_type, tree new_type)
  {
!   const tree old_ptr = TYPE_POINTER_TO (old_type);
!   const tree old_ref = TYPE_REFERENCE_TO (old_type);
    tree t;
  
    /* If this is the main variant, process all the other variants first.  */
*************** update_pointer_to (tree old_type, tree n
*** 4520,4526 ****
        update_pointer_to (t, new_type);
  
    /* If no pointers and no references, we are done.  */
!   if (!ptr && !ref)
      return;
  
    /* Merge the old type qualifiers in the new type.
--- 4520,4526 ----
        update_pointer_to (t, new_type);
  
    /* If no pointers and no references, we are done.  */
!   if (!old_ptr && !old_ref)
      return;
  
    /* Merge the old type qualifiers in the new type.
*************** update_pointer_to (tree old_type, tree n
*** 4554,4565 ****
    if (TREE_CODE (new_type) != UNCONSTRAINED_ARRAY_TYPE)
      {
        tree new_ptr, new_ref;
  
        /* If pointer or reference already points to new type, nothing to do.
  	 This can happen as update_pointer_to can be invoked multiple times
  	 on the same couple of types because of the type variants.  */
!       if ((ptr && TREE_TYPE (ptr) == new_type)
! 	  || (ref && TREE_TYPE (ref) == new_type))
  	return;
  
        /* Chain PTR and its variants at the end.  */
--- 4554,4566 ----
    if (TREE_CODE (new_type) != UNCONSTRAINED_ARRAY_TYPE)
      {
        tree new_ptr, new_ref;
+       tree ptr, ref;
  
        /* If pointer or reference already points to new type, nothing to do.
  	 This can happen as update_pointer_to can be invoked multiple times
  	 on the same couple of types because of the type variants.  */
!       if ((old_ptr && TREE_TYPE (old_ptr) == new_type)
! 	  || (old_ref && TREE_TYPE (old_ref) == new_type))
  	return;
  
        /* Chain PTR and its variants at the end.  */
*************** update_pointer_to (tree old_type, tree n
*** 4568,4580 ****
  	{
  	  while (TYPE_NEXT_PTR_TO (new_ptr))
  	    new_ptr = TYPE_NEXT_PTR_TO (new_ptr);
! 	  TYPE_NEXT_PTR_TO (new_ptr) = ptr;
  	}
        else
! 	TYPE_POINTER_TO (new_type) = ptr;
  
        /* Now adjust them.  */
!       for (; ptr; ptr = TYPE_NEXT_PTR_TO (ptr))
  	for (t = TYPE_MAIN_VARIANT (ptr); t; t = TYPE_NEXT_VARIANT (t))
  	  {
  	    TREE_TYPE (t) = new_type;
--- 4569,4581 ----
  	{
  	  while (TYPE_NEXT_PTR_TO (new_ptr))
  	    new_ptr = TYPE_NEXT_PTR_TO (new_ptr);
! 	  TYPE_NEXT_PTR_TO (new_ptr) = old_ptr;
  	}
        else
! 	TYPE_POINTER_TO (new_type) = old_ptr;
  
        /* Now adjust them.  */
!       for (ptr = old_ptr; ptr; ptr = TYPE_NEXT_PTR_TO (ptr))
  	for (t = TYPE_MAIN_VARIANT (ptr); t; t = TYPE_NEXT_VARIANT (t))
  	  {
  	    TREE_TYPE (t) = new_type;
*************** update_pointer_to (tree old_type, tree n
*** 4589,4601 ****
  	{
  	  while (TYPE_NEXT_REF_TO (new_ref))
  	    new_ref = TYPE_NEXT_REF_TO (new_ref);
! 	  TYPE_NEXT_REF_TO (new_ref) = ref;
  	}
        else
! 	TYPE_REFERENCE_TO (new_type) = ref;
  
        /* Now adjust them.  */
!       for (; ref; ref = TYPE_NEXT_REF_TO (ref))
  	for (t = TYPE_MAIN_VARIANT (ref); t; t = TYPE_NEXT_VARIANT (t))
  	  {
  	    TREE_TYPE (t) = new_type;
--- 4590,4602 ----
  	{
  	  while (TYPE_NEXT_REF_TO (new_ref))
  	    new_ref = TYPE_NEXT_REF_TO (new_ref);
! 	  TYPE_NEXT_REF_TO (new_ref) = old_ref;
  	}
        else
! 	TYPE_REFERENCE_TO (new_type) = old_ref;
  
        /* Now adjust them.  */
!       for (ref = old_ref; ref; ref = TYPE_NEXT_REF_TO (ref))
  	for (t = TYPE_MAIN_VARIANT (ref); t; t = TYPE_NEXT_VARIANT (t))
  	  {
  	    TREE_TYPE (t) = new_type;
*************** update_pointer_to (tree old_type, tree n
*** 4614,4633 ****
      {
        tree new_ptr = TYPE_POINTER_TO (new_type);
  
!       gcc_assert (TYPE_IS_FAT_POINTER_P (ptr));
  
        /* If PTR already points to NEW_TYPE, nothing to do.  This can happen
  	 since update_pointer_to can be invoked multiple times on the same
  	 couple of types because of the type variants.  */
!       if (TYPE_UNCONSTRAINED_ARRAY (ptr) == new_type)
  	return;
  
        update_pointer_to
! 	(TREE_TYPE (TREE_TYPE (TYPE_FIELDS (ptr))),
  	 TREE_TYPE (TREE_TYPE (TYPE_FIELDS (new_ptr))));
  
        update_pointer_to
! 	(TREE_TYPE (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (ptr)))),
  	 TREE_TYPE (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (new_ptr)))));
  
        update_pointer_to (TYPE_OBJECT_RECORD_TYPE (old_type),
--- 4615,4634 ----
      {
        tree new_ptr = TYPE_POINTER_TO (new_type);
  
!       gcc_assert (TYPE_IS_FAT_POINTER_P (old_ptr));
  
        /* If PTR already points to NEW_TYPE, nothing to do.  This can happen
  	 since update_pointer_to can be invoked multiple times on the same
  	 couple of types because of the type variants.  */
!       if (TYPE_UNCONSTRAINED_ARRAY (old_ptr) == new_type)
  	return;
  
        update_pointer_to
! 	(TREE_TYPE (TREE_TYPE (TYPE_FIELDS (old_ptr))),
  	 TREE_TYPE (TREE_TYPE (TYPE_FIELDS (new_ptr))));
  
        update_pointer_to
! 	(TREE_TYPE (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (old_ptr)))),
  	 TREE_TYPE (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (new_ptr)))));
  
        update_pointer_to (TYPE_OBJECT_RECORD_TYPE (old_type),
diff -Nrcpad gcc-16-20250720/gcc/ada/gen_il-fields.ads gcc-16-20250727/gcc/ada/gen_il-fields.ads
*** gcc-16-20250720/gcc/ada/gen_il-fields.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/gen_il-fields.ads	Sun Jul 27 22:32:07 2025
*************** package Gen_IL.Fields is
*** 255,260 ****
--- 255,261 ----
        Is_Entry_Barrier_Function,
        Is_Expanded_Build_In_Place_Call,
        Is_Expanded_Constructor_Call,
+       Is_Expanded_Dispatching_Call,
        Is_Expanded_Prefixed_Call,
        Is_Folded_In_Parser,
        Is_Generic_Contract_Pragma,
*************** package Gen_IL.Fields is
*** 400,405 ****
--- 401,407 ----
        Suppress_Loop_Warnings,
        Synchronized_Present,
        Tagged_Present,
+       Tag_Propagated,
        Target,
        Call_Or_Target_Loop,
        Target_Type,
*************** package Gen_IL.Fields is
*** 539,544 ****
--- 541,547 ----
        Extra_Constrained,
        Extra_Formal,
        Extra_Formals,
+       Extra_Formals_Known,
        Finalization_Collection,
        Finalization_Master_Node,
        Finalize_Storage_Only,
*************** package Gen_IL.Fields is
*** 572,577 ****
--- 575,581 ----
        Has_Delayed_Aspects,
        Has_Delayed_Freeze,
        Has_Delayed_Rep_Aspects,
+       Has_Destructor,
        Has_Discriminants,
        Has_Dispatch_Table,
        Has_Dynamic_Predicate_Aspect,
*************** package Gen_IL.Fields is
*** 699,704 ****
--- 703,709 ----
        Is_CPP_Class,
        Is_CUDA_Kernel,
        Is_Descendant_Of_Address,
+       Is_Destructor,
        Is_DIC_Procedure,
        Is_Discrim_SO_Function,
        Is_Discriminant_Check_Function,
*************** package Gen_IL.Fields is
*** 730,735 ****
--- 735,741 ----
        Is_Ignored_Ghost_Entity,
        Is_Immediately_Visible,
        Is_Implementation_Defined,
+       Is_Implicit_Full_View,
        Is_Imported,
        Is_Independent,
        Is_Initial_Condition_Procedure,
diff -Nrcpad gcc-16-20250720/gcc/ada/gen_il-gen-gen_entities.adb gcc-16-20250727/gcc/ada/gen_il-gen-gen_entities.adb
*** gcc-16-20250720/gcc/ada/gen_il-gen-gen_entities.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/gen_il-gen-gen_entities.adb	Sun Jul 27 22:32:07 2025
*************** begin -- Gen_IL.Gen.Gen_Entities
*** 467,472 ****
--- 467,473 ----
          Sm (Full_View, Node_Id),
          Sm (Has_Completion_In_Body, Flag),
          Sm (Has_Constrained_Partial_View, Flag, Base_Type_Only),
+         Sm (Has_Destructor, Flag, Base_Type_Only),
          Sm (Has_Discriminants, Flag),
          Sm (Has_Dispatch_Table, Flag,
              Pre => "Is_Tagged_Type (N)"),
*************** begin -- Gen_IL.Gen.Gen_Entities
*** 502,507 ****
--- 503,509 ----
          Sm (Is_Fixed_Lower_Bound_Array_Subtype, Flag),
          Sm (Is_Fixed_Lower_Bound_Index_Subtype, Flag),
          Sm (Is_Generic_Actual_Type, Flag),
+         Sm (Is_Implicit_Full_View, Flag),
          Sm (Is_Mutably_Tagged_Type, Flag),
          Sm (Is_Non_Static_Subtype, Flag),
          Sm (Is_Private_Composite, Flag),
*************** begin -- Gen_IL.Gen.Gen_Entities
*** 935,945 ****
--- 937,949 ----
         (Sm (Access_Subprogram_Wrapper, Node_Id),
          Sm (Extra_Accessibility_Of_Result, Node_Id),
          Sm (Extra_Formals, Node_Id),
+         Sm (Extra_Formals_Known, Flag),
          Sm (Needs_No_Actuals, Flag)));
  
     Ab (Overloadable_Kind, Entity_Kind,
         (Sm (Renamed_Or_Alias, Node_Id),
          Sm (Extra_Formals, Node_Id),
+         Sm (Extra_Formals_Known, Flag),
          Sm (Is_Abstract_Subprogram, Flag),
          Sm (Is_Primitive, Flag),
          Sm (Needs_No_Actuals, Flag),
*************** begin -- Gen_IL.Gen.Gen_Entities
*** 1052,1057 ****
--- 1056,1062 ----
          Sm (Is_Asynchronous, Flag),
          Sm (Is_Called, Flag),
          Sm (Is_CUDA_Kernel, Flag),
+         Sm (Is_Destructor, Flag),
          Sm (Is_DIC_Procedure, Flag),
          Sm (Is_Generic_Actual_Subprogram, Flag),
          Sm (Is_Initial_Condition_Procedure, Flag),
*************** begin -- Gen_IL.Gen.Gen_Entities
*** 1127,1132 ****
--- 1132,1138 ----
          Sm (Entry_Accepted, Flag),
          Sm (Entry_Parameters_Type, Node_Id),
          Sm (Extra_Formals, Node_Id),
+         Sm (Extra_Formals_Known, Flag),
          Sm (First_Entity, Node_Id),
          Sm (Has_Out_Or_In_Out_Parameter, Flag),
          Sm (Ignore_SPARK_Mode_Pragmas, Flag),
*************** begin -- Gen_IL.Gen.Gen_Entities
*** 1328,1333 ****
--- 1334,1340 ----
         (Sm (Anonymous_Collections, Elist_Id),
          Sm (Contract, Node_Id),
          Sm (Extra_Formals, Node_Id),
+         Sm (Extra_Formals_Known, Flag),
          Sm (First_Entity, Node_Id),
          Sm (Ignore_SPARK_Mode_Pragmas, Flag),
          Sm (Interface_Name, Node_Id),
diff -Nrcpad gcc-16-20250720/gcc/ada/gen_il-gen-gen_nodes.adb gcc-16-20250727/gcc/ada/gen_il-gen-gen_nodes.adb
*** gcc-16-20250720/gcc/ada/gen_il-gen-gen_nodes.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/gen_il-gen-gen_nodes.adb	Sun Jul 27 22:32:07 2025
*************** begin -- Gen_IL.Gen.Gen_Nodes
*** 149,154 ****
--- 149,155 ----
          Sm (Is_Controlling_Actual, Flag),
          Sm (Is_Overloaded, Flag),
          Sm (Is_Static_Expression, Flag),
+         Sm (Is_Expanded_Dispatching_Call, Flag),
          Sm (Must_Not_Freeze, Flag),
          Sm (Raises_Constraint_Error, Flag)));
  
*************** begin -- Gen_IL.Gen.Gen_Nodes
*** 181,187 ****
          Sm (Is_Elaboration_Warnings_OK_Node, Flag),
          Sm (Is_SPARK_Mode_On_Node, Flag),
          Sm (Original_Discriminant, Node_Id),
!         Sm (Redundant_Use, Flag)));
  
     Cc (N_Operator_Symbol, N_Direct_Name,
         (Sy (Strval, String_Id)));
--- 182,189 ----
          Sm (Is_Elaboration_Warnings_OK_Node, Flag),
          Sm (Is_SPARK_Mode_On_Node, Flag),
          Sm (Original_Discriminant, Node_Id),
!         Sm (Redundant_Use, Flag),
!         Sm (Tag_Propagated, Flag)));
  
     Cc (N_Operator_Symbol, N_Direct_Name,
         (Sy (Strval, String_Id)));
*************** begin -- Gen_IL.Gen.Gen_Nodes
*** 346,352 ****
         (Sy (Prefix, Node_Id),
          Sm (Actual_Designated_Subtype, Node_Id),
          Sm (Atomic_Sync_Required, Flag),
!         Sm (Has_Dereference_Action, Flag)));
  
     Cc (N_Expression_With_Actions, N_Subexpr,
         (Sy (Actions, List_Id, Default_No_List),
--- 348,355 ----
         (Sy (Prefix, Node_Id),
          Sm (Actual_Designated_Subtype, Node_Id),
          Sm (Atomic_Sync_Required, Flag),
!         Sm (Has_Dereference_Action, Flag),
!         Sm (Tag_Propagated, Flag)));
  
     Cc (N_Expression_With_Actions, N_Subexpr,
         (Sy (Actions, List_Id, Default_No_List),
*************** begin -- Gen_IL.Gen.Gen_Nodes
*** 463,468 ****
--- 466,472 ----
          Sm (Do_Length_Check, Flag),
          Sm (Do_Overflow_Check, Flag),
          Sm (Float_Truncate, Flag),
+         Sm (Tag_Propagated, Flag),
          Sm (Rounded_Result, Flag)));
  
     Cc (N_Unchecked_Type_Conversion, N_Subexpr,
*************** begin -- Gen_IL.Gen.Gen_Nodes
*** 905,910 ****
--- 909,915 ----
          Sm (Cleanup_Actions, List_Id),
          Sm (Exception_Junk, Flag),
          Sm (Is_Abort_Block, Flag),
+         Sm (Is_Expanded_Dispatching_Call, Flag),
          Sm (Is_Initialization_Block, Flag),
          Sm (Is_Task_Master, Flag)));
  
diff -Nrcpad gcc-16-20250720/gcc/ada/gen_il-internals.adb gcc-16-20250727/gcc/ada/gen_il-internals.adb
*** gcc-16-20250720/gcc/ada/gen_il-internals.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/gen_il-internals.adb	Sun Jul 27 22:32:07 2025
*************** package body Gen_IL.Internals is
*** 277,282 ****
--- 277,284 ----
              return "DT_Offset_To_Top_Func";
           when DT_Position =>
              return "DT_Position";
+          when Extra_Formals_Known =>
+             return "Extra_Formals_Known";
           when Forwards_OK =>
              return "Forwards_OK";
           when Has_First_Controlling_Parameter_Aspect =>
diff -Nrcpad gcc-16-20250720/gcc/ada/gnat_rm.texi gcc-16-20250727/gcc/ada/gnat_rm.texi
*** gcc-16-20250720/gcc/ada/gnat_rm.texi	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/gnat_rm.texi	Sun Jul 27 22:32:07 2025
***************
*** 19,25 ****
  
  @copying
  @quotation
! GNAT Reference Manual , Jul 03, 2025
  
  AdaCore
  
--- 19,25 ----
  
  @copying
  @quotation
! GNAT Reference Manual , Jul 24, 2025
  
  AdaCore
  
*************** Experimental Language Extensions
*** 931,936 ****
--- 931,937 ----
  * External_Initialization Aspect:: 
  * Finally construct:: 
  * Continue statement:: 
+ * Destructors:: 
  
  Storage Model
  
*************** pragma Export (C, Last_Chance_Handler,
*** 13071,13079 ****
                 "__gnat_last_chance_handler");
  @end example
  
! The parameter is a C null-terminated string representing a message to be
! associated with the exception (typically the source location of the raise
! statement generated by the compiler). The Line parameter when nonzero
  represents the line number in the source program where the raise occurs.
  
  @node No_Exception_Propagation,No_Exception_Registration,No_Exception_Handlers,Partition-Wide Restrictions
--- 13072,13080 ----
                 "__gnat_last_chance_handler");
  @end example
  
! The @code{Source_Location} parameter is a C null-terminated string representing a
! message to be associated with the exception (typically the source location of
! the raise statement generated by the compiler). The Line parameter when nonzero
  represents the line number in the source program where the raise occurs.
  
  @node No_Exception_Propagation,No_Exception_Registration,No_Exception_Handlers,Partition-Wide Restrictions
*************** Features activated via @code{-gnatX0} or
*** 31236,31241 ****
--- 31237,31243 ----
  * External_Initialization Aspect:: 
  * Finally construct:: 
  * Continue statement:: 
+ * Destructors:: 
  
  @end menu
  
*************** Abort/ATC (asynchronous transfer of cont
*** 32588,32594 ****
  execution, that is the finally block must be executed in full even if the containing task is
  aborted, or if the control is transferred out of the block.
  
! @node Continue statement,,Finally construct,Experimental Language Extensions
  @anchor{gnat_rm/gnat_language_extensions continue-statement}@anchor{472}
  @subsection Continue statement
  
--- 32590,32596 ----
  execution, that is the finally block must be executed in full even if the containing task is
  aborted, or if the control is transferred out of the block.
  
! @node Continue statement,Destructors,Finally construct,Experimental Language Extensions
  @anchor{gnat_rm/gnat_language_extensions continue-statement}@anchor{472}
  @subsection Continue statement
  
*************** statement in the sequence of statements
*** 32606,32613 ****
  Note that @code{continue} is a keyword but it is not a reserved word. This is a
  configuration that does not exist in standard Ada.
  
  @node Security Hardening Features,Obsolescent Features,GNAT language extensions,Top
! @anchor{gnat_rm/security_hardening_features doc}@anchor{473}@anchor{gnat_rm/security_hardening_features id1}@anchor{474}@anchor{gnat_rm/security_hardening_features security-hardening-features}@anchor{15}
  @chapter Security Hardening Features
  
  
--- 32608,32685 ----
  Note that @code{continue} is a keyword but it is not a reserved word. This is a
  configuration that does not exist in standard Ada.
  
+ @node Destructors,,Continue statement,Experimental Language Extensions
+ @anchor{gnat_rm/gnat_language_extensions destructors}@anchor{473}
+ @subsection Destructors
+ 
+ 
+ The @code{Destructor} aspect can be applied to any record type, tagged or not.
+ It must denote a primitive of the type that is a procedure with one parameter
+ of the type and of mode @code{in out}:
+ 
+ @example
+ type T is record
+    ...
+ end record with Destructor => Foo;
+ 
+ procedure Foo (X : in out T);
+ @end example
+ 
+ This is equivalent to the following code that uses @code{Finalizable}:
+ 
+ @example
+ type T is record
+    ...
+ end record with Finalizable => (Finalize => Foo);
+ 
+ procedure Foo (X : in out T);
+ @end example
+ 
+ Unlike @code{Finalizable}, however, @code{Destructor} can be specified on a derived
+ type. And when it is, the effect of the aspect combines with the destructors of
+ the parent type. Take, for example:
+ 
+ @example
+ type T1 is record
+    ...
+ end record with Destructor => Foo;
+ 
+ procedure Foo (X : in out T1);
+ 
+ type T2 is new T1 with Destructor => Bar;
+ 
+ procedure Bar (X : in out T2);
+ @end example
+ 
+ Here, when an object of type @code{T2} is finalized, a call to @code{Bar}
+ will be performed and it will be followed by a call to @code{Foo}.
+ 
+ The @code{Destructor} aspect comes with a legality rule: if a primitive procedure
+ of a type is denoted by a @code{Destructor} aspect specification, it is illegal to
+ override this procedure in a derived type. For example, the following is illegal:
+ 
+ @example
+ type T1 is record
+    ...
+ end record with Destructor => Foo;
+ 
+ procedure Foo (X : in out T1);
+ 
+ type T2 is new T1;
+ 
+ overriding
+ procedure Foo (X : in out T2); -- Error here
+ @end example
+ 
+ It is possible to specify @code{Destructor} on the completion of a private type,
+ but there is one more restriction in that case: the denoted primitive must
+ be private to the enclosing package. This is necessary due to the previously
+ mentioned legality rule, to prevent breaking the privacy of the type when
+ imposing that rule on outside types that derive from the private view of the
+ type.
+ 
  @node Security Hardening Features,Obsolescent Features,GNAT language extensions,Top
! @anchor{gnat_rm/security_hardening_features doc}@anchor{474}@anchor{gnat_rm/security_hardening_features id1}@anchor{475}@anchor{gnat_rm/security_hardening_features security-hardening-features}@anchor{15}
  @chapter Security Hardening Features
  
  
*************** change.
*** 32629,32635 ****
  @end menu
  
  @node Register Scrubbing,Stack Scrubbing,,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features register-scrubbing}@anchor{475}
  @section Register Scrubbing
  
  
--- 32701,32707 ----
  @end menu
  
  @node Register Scrubbing,Stack Scrubbing,,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features register-scrubbing}@anchor{476}
  @section Register Scrubbing
  
  
*************** programming languages, see @cite{Using t
*** 32665,32671 ****
  @c Stack Scrubbing:
  
  @node Stack Scrubbing,Hardened Conditionals,Register Scrubbing,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features stack-scrubbing}@anchor{476}
  @section Stack Scrubbing
  
  
--- 32737,32743 ----
  @c Stack Scrubbing:
  
  @node Stack Scrubbing,Hardened Conditionals,Register Scrubbing,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features stack-scrubbing}@anchor{477}
  @section Stack Scrubbing
  
  
*************** Bar_Callable_Ptr.
*** 32809,32815 ****
  @c Hardened Conditionals:
  
  @node Hardened Conditionals,Hardened Booleans,Stack Scrubbing,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features hardened-conditionals}@anchor{477}
  @section Hardened Conditionals
  
  
--- 32881,32887 ----
  @c Hardened Conditionals:
  
  @node Hardened Conditionals,Hardened Booleans,Stack Scrubbing,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features hardened-conditionals}@anchor{478}
  @section Hardened Conditionals
  
  
*************** be used with other programming languages
*** 32899,32905 ****
  @c Hardened Booleans:
  
  @node Hardened Booleans,Control Flow Redundancy,Hardened Conditionals,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features hardened-booleans}@anchor{478}
  @section Hardened Booleans
  
  
--- 32971,32977 ----
  @c Hardened Booleans:
  
  @node Hardened Booleans,Control Flow Redundancy,Hardened Conditionals,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features hardened-booleans}@anchor{479}
  @section Hardened Booleans
  
  
*************** and more details on that attribute, see
*** 32960,32966 ****
  @c Control Flow Redundancy:
  
  @node Control Flow Redundancy,,Hardened Booleans,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features control-flow-redundancy}@anchor{479}
  @section Control Flow Redundancy
  
  
--- 33032,33038 ----
  @c Control Flow Redundancy:
  
  @node Control Flow Redundancy,,Hardened Booleans,Security Hardening Features
! @anchor{gnat_rm/security_hardening_features control-flow-redundancy}@anchor{47a}
  @section Control Flow Redundancy
  
  
*************** see @cite{Using the GNU Compiler Collect
*** 33128,33134 ****
  can be used with other programming languages supported by GCC.
  
  @node Obsolescent Features,Compatibility and Porting Guide,Security Hardening Features,Top
! @anchor{gnat_rm/obsolescent_features doc}@anchor{47a}@anchor{gnat_rm/obsolescent_features id1}@anchor{47b}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{16}
  @chapter Obsolescent Features
  
  
--- 33200,33206 ----
  can be used with other programming languages supported by GCC.
  
  @node Obsolescent Features,Compatibility and Porting Guide,Security Hardening Features,Top
! @anchor{gnat_rm/obsolescent_features doc}@anchor{47b}@anchor{gnat_rm/obsolescent_features id1}@anchor{47c}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{16}
  @chapter Obsolescent Features
  
  
*************** compatibility purposes.
*** 33147,33153 ****
  @end menu
  
  @node pragma No_Run_Time,pragma Ravenscar,,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features id2}@anchor{47c}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{47d}
  @section pragma No_Run_Time
  
  
--- 33219,33225 ----
  @end menu
  
  @node pragma No_Run_Time,pragma Ravenscar,,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features id2}@anchor{47d}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{47e}
  @section pragma No_Run_Time
  
  
*************** preferred usage is to use an appropriate
*** 33160,33166 ****
  includes just those features that are to be made accessible.
  
  @node pragma Ravenscar,pragma Restricted_Run_Time,pragma No_Run_Time,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features id3}@anchor{47e}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{47f}
  @section pragma Ravenscar
  
  
--- 33232,33238 ----
  includes just those features that are to be made accessible.
  
  @node pragma Ravenscar,pragma Restricted_Run_Time,pragma No_Run_Time,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features id3}@anchor{47f}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{480}
  @section pragma Ravenscar
  
  
*************** The pragma @code{Ravenscar} has exactly
*** 33169,33175 ****
  is part of the new Ada 2005 standard.
  
  @node pragma Restricted_Run_Time,pragma Task_Info,pragma Ravenscar,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features id4}@anchor{480}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{481}
  @section pragma Restricted_Run_Time
  
  
--- 33241,33247 ----
  is part of the new Ada 2005 standard.
  
  @node pragma Restricted_Run_Time,pragma Task_Info,pragma Ravenscar,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features id4}@anchor{481}@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{482}
  @section pragma Restricted_Run_Time
  
  
*************** preferred since the Ada 2005 pragma @cod
*** 33179,33185 ****
  this kind of implementation dependent addition.
  
  @node pragma Task_Info,package System Task_Info s-tasinf ads,pragma Restricted_Run_Time,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features id5}@anchor{482}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{483}
  @section pragma Task_Info
  
  
--- 33251,33257 ----
  this kind of implementation dependent addition.
  
  @node pragma Task_Info,package System Task_Info s-tasinf ads,pragma Restricted_Run_Time,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features id5}@anchor{483}@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{484}
  @section pragma Task_Info
  
  
*************** in the spec of package System.Task_Info
*** 33205,33211 ****
  library.
  
  @node package System Task_Info s-tasinf ads,,pragma Task_Info,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{484}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{485}
  @section package System.Task_Info (@code{s-tasinf.ads})
  
  
--- 33277,33283 ----
  library.
  
  @node package System Task_Info s-tasinf ads,,pragma Task_Info,Obsolescent Features
! @anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{485}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{486}
  @section package System.Task_Info (@code{s-tasinf.ads})
  
  
*************** to support the @code{Task_Info} pragma.
*** 33215,33221 ****
  standard replacement for GNAT’s @code{Task_Info} functionality.
  
  @node Compatibility and Porting Guide,GNU Free Documentation License,Obsolescent Features,Top
! @anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{486}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{17}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{487}
  @chapter Compatibility and Porting Guide
  
  
--- 33287,33293 ----
  standard replacement for GNAT’s @code{Task_Info} functionality.
  
  @node Compatibility and Porting Guide,GNU Free Documentation License,Obsolescent Features,Top
! @anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{487}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{17}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{488}
  @chapter Compatibility and Porting Guide
  
  
*************** applications developed in other Ada envi
*** 33237,33243 ****
  @end menu
  
  @node Writing Portable Fixed-Point Declarations,Compatibility with Ada 83,,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{488}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{489}
  @section Writing Portable Fixed-Point Declarations
  
  
--- 33309,33315 ----
  @end menu
  
  @node Writing Portable Fixed-Point Declarations,Compatibility with Ada 83,,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{489}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{48a}
  @section Writing Portable Fixed-Point Declarations
  
  
*************** If you follow this scheme you will be gu
*** 33359,33365 ****
  types will be portable.
  
  @node Compatibility with Ada 83,Compatibility between Ada 95 and Ada 2005,Writing Portable Fixed-Point Declarations,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{48a}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{48b}
  @section Compatibility with Ada 83
  
  
--- 33431,33437 ----
  types will be portable.
  
  @node Compatibility with Ada 83,Compatibility between Ada 95 and Ada 2005,Writing Portable Fixed-Point Declarations,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{48b}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{48c}
  @section Compatibility with Ada 83
  
  
*************** following subsections treat the most lik
*** 33387,33393 ****
  @end menu
  
  @node Legal Ada 83 programs that are illegal in Ada 95,More deterministic semantics,,Compatibility with Ada 83
! @anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{48c}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{48d}
  @subsection Legal Ada 83 programs that are illegal in Ada 95
  
  
--- 33459,33465 ----
  @end menu
  
  @node Legal Ada 83 programs that are illegal in Ada 95,More deterministic semantics,,Compatibility with Ada 83
! @anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{48d}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{48e}
  @subsection Legal Ada 83 programs that are illegal in Ada 95
  
  
*************** the fix is usually simply to add the @co
*** 33487,33493 ****
  @end itemize
  
  @node More deterministic semantics,Changed semantics,Legal Ada 83 programs that are illegal in Ada 95,Compatibility with Ada 83
! @anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{48e}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{48f}
  @subsection More deterministic semantics
  
  
--- 33559,33565 ----
  @end itemize
  
  @node More deterministic semantics,Changed semantics,Legal Ada 83 programs that are illegal in Ada 95,Compatibility with Ada 83
! @anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{48f}@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{490}
  @subsection More deterministic semantics
  
  
*************** which open select branches are executed.
*** 33515,33521 ****
  @end itemize
  
  @node Changed semantics,Other language compatibility issues,More deterministic semantics,Compatibility with Ada 83
! @anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{490}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{491}
  @subsection Changed semantics
  
  
--- 33587,33593 ----
  @end itemize
  
  @node Changed semantics,Other language compatibility issues,More deterministic semantics,Compatibility with Ada 83
! @anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{491}@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{492}
  @subsection Changed semantics
  
  
*************** covers only the restricted range.
*** 33557,33563 ****
  @end itemize
  
  @node Other language compatibility issues,,Changed semantics,Compatibility with Ada 83
! @anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{492}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{493}
  @subsection Other language compatibility issues
  
  
--- 33629,33635 ----
  @end itemize
  
  @node Other language compatibility issues,,Changed semantics,Compatibility with Ada 83
! @anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{493}@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{494}
  @subsection Other language compatibility issues
  
  
*************** include @code{pragma Interface} and the
*** 33590,33596 ****
  @end itemize
  
  @node Compatibility between Ada 95 and Ada 2005,Implementation-dependent characteristics,Compatibility with Ada 83,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{494}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{495}
  @section Compatibility between Ada 95 and Ada 2005
  
  
--- 33662,33668 ----
  @end itemize
  
  @node Compatibility between Ada 95 and Ada 2005,Implementation-dependent characteristics,Compatibility with Ada 83,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{495}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{496}
  @section Compatibility between Ada 95 and Ada 2005
  
  
*************** can declare a function returning a value
*** 33662,33668 ****
  @end itemize
  
  @node Implementation-dependent characteristics,Compatibility with Other Ada Systems,Compatibility between Ada 95 and Ada 2005,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{496}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{497}
  @section Implementation-dependent characteristics
  
  
--- 33734,33740 ----
  @end itemize
  
  @node Implementation-dependent characteristics,Compatibility with Other Ada Systems,Compatibility between Ada 95 and Ada 2005,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{497}@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{498}
  @section Implementation-dependent characteristics
  
  
*************** transition from certain Ada 83 compilers
*** 33685,33691 ****
  @end menu
  
  @node Implementation-defined pragmas,Implementation-defined attributes,,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{498}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{499}
  @subsection Implementation-defined pragmas
  
  
--- 33757,33763 ----
  @end menu
  
  @node Implementation-defined pragmas,Implementation-defined attributes,,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{499}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{49a}
  @subsection Implementation-defined pragmas
  
  
*************** avoiding compiler rejection of units tha
*** 33707,33713 ****
  relevant in a GNAT context and hence are not otherwise implemented.
  
  @node Implementation-defined attributes,Libraries,Implementation-defined pragmas,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{49a}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{49b}
  @subsection Implementation-defined attributes
  
  
--- 33779,33785 ----
  relevant in a GNAT context and hence are not otherwise implemented.
  
  @node Implementation-defined attributes,Libraries,Implementation-defined pragmas,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{49b}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{49c}
  @subsection Implementation-defined attributes
  
  
*************** Ada 83, GNAT supplies the attributes @co
*** 33721,33727 ****
  @code{Type_Class}.
  
  @node Libraries,Elaboration order,Implementation-defined attributes,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{49c}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{49d}
  @subsection Libraries
  
  
--- 33793,33799 ----
  @code{Type_Class}.
  
  @node Libraries,Elaboration order,Implementation-defined attributes,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{49d}@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{49e}
  @subsection Libraries
  
  
*************** be preferable to retrofit the applicatio
*** 33750,33756 ****
  @end itemize
  
  @node Elaboration order,Target-specific aspects,Libraries,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{49e}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{49f}
  @subsection Elaboration order
  
  
--- 33822,33828 ----
  @end itemize
  
  @node Elaboration order,Target-specific aspects,Libraries,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{49f}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{4a0}
  @subsection Elaboration order
  
  
*************** pragmas either globally (as an effect of
*** 33786,33792 ****
  @end itemize
  
  @node Target-specific aspects,,Elaboration order,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{4a0}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{4a1}
  @subsection Target-specific aspects
  
  
--- 33858,33864 ----
  @end itemize
  
  @node Target-specific aspects,,Elaboration order,Implementation-dependent characteristics
! @anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{4a1}@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{4a2}
  @subsection Target-specific aspects
  
  
*************** on the robustness of the original design
*** 33799,33808 ****
  Ada 2005, Ada 2012, and Ada 2022) are sometimes
  incompatible with typical Ada 83 compiler practices regarding implicit
  packing, the meaning of the Size attribute, and the size of access values.
! GNAT’s approach to these issues is described in @ref{4a2,,Representation Clauses}.
  
  @node Compatibility with Other Ada Systems,Representation Clauses,Implementation-dependent characteristics,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{4a3}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{4a4}
  @section Compatibility with Other Ada Systems
  
  
--- 33871,33880 ----
  Ada 2005, Ada 2012, and Ada 2022) are sometimes
  incompatible with typical Ada 83 compiler practices regarding implicit
  packing, the meaning of the Size attribute, and the size of access values.
! GNAT’s approach to these issues is described in @ref{4a3,,Representation Clauses}.
  
  @node Compatibility with Other Ada Systems,Representation Clauses,Implementation-dependent characteristics,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{4a4}@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{4a5}
  @section Compatibility with Other Ada Systems
  
  
*************** far beyond this minimal set, as describe
*** 33845,33851 ****
  @end itemize
  
  @node Representation Clauses,Compatibility with HP Ada 83,Compatibility with Other Ada Systems,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{4a5}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{4a2}
  @section Representation Clauses
  
  
--- 33917,33923 ----
  @end itemize
  
  @node Representation Clauses,Compatibility with HP Ada 83,Compatibility with Other Ada Systems,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{4a6}@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{4a3}
  @section Representation Clauses
  
  
*************** with thin pointers.
*** 33938,33944 ****
  @end itemize
  
  @node Compatibility with HP Ada 83,,Representation Clauses,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{4a6}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{4a7}
  @section Compatibility with HP Ada 83
  
  
--- 34010,34016 ----
  @end itemize
  
  @node Compatibility with HP Ada 83,,Representation Clauses,Compatibility and Porting Guide
! @anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{4a7}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{4a8}
  @section Compatibility with HP Ada 83
  
  
*************** extension of package System.
*** 33968,33974 ****
  @end itemize
  
  @node GNU Free Documentation License,Index,Compatibility and Porting Guide,Top
! @anchor{share/gnu_free_documentation_license doc}@anchor{4a8}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{4a9}
  @chapter GNU Free Documentation License
  
  
--- 34040,34046 ----
  @end itemize
  
  @node GNU Free Documentation License,Index,Compatibility and Porting Guide,Top
! @anchor{share/gnu_free_documentation_license doc}@anchor{4a9}@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{4aa}
  @chapter GNU Free Documentation License
  
  
diff -Nrcpad gcc-16-20250720/gcc/ada/gsocket.h gcc-16-20250727/gcc/ada/gsocket.h
*** gcc-16-20250720/gcc/ada/gsocket.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/gsocket.h	Sun Jul 27 22:32:07 2025
***************
*** 64,69 ****
--- 64,75 ----
  #include <ioLib.h>
  #include <hostLib.h>
  
+ #if __has_include ("strings.h")
+ /* On VxWorks6, FD_ZERO uses bzero, but since it's not a standard header, don't
+    require it.  */
+ #include "strings.h"
+ #endif
+ 
  #define SHUT_RD		0
  #define SHUT_WR		1
  #define SHUT_RDWR	2
diff -Nrcpad gcc-16-20250720/gcc/ada/libgnat/a-calend.adb gcc-16-20250727/gcc/ada/libgnat/a-calend.adb
*** gcc-16-20250720/gcc/ada/libgnat/a-calend.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/libgnat/a-calend.adb	Sun Jul 27 22:32:07 2025
*************** is
*** 1068,1086 ****
           tv_nsec : out Long_Integer)
        is
           pragma Unsuppress (Overflow_Check);
-          Secs      : Duration;
-          Nano_Secs : Duration;
  
        begin
!          --  Seconds extraction, avoid potential rounding errors
! 
!          Secs   := D - 0.5;
!          tv_sec := Long_Long_Integer (Secs);
  
!          --  Nanoseconds extraction
  
!          Nano_Secs := D - Duration (tv_sec);
!          tv_nsec := Long_Integer (Nano_Secs * Nano);
        end To_Struct_Timespec_64;
  
        ------------------
--- 1068,1095 ----
           tv_nsec : out Long_Integer)
        is
           pragma Unsuppress (Overflow_Check);
  
        begin
!          if D = 0.0 then
!             tv_sec  := 0;
!             tv_nsec := 0;
  
!          elsif D < 0.0 then
!             tv_sec := Long_Long_Integer (D + 0.5);
!             if D = Duration (tv_sec) then
!                tv_nsec := 0;
!             else
!                tv_nsec := Long_Integer ((D - Duration (tv_sec)) * Nano + 0.5);
!             end if;
  
!          else
!             tv_sec := Long_Long_Integer (D - 0.5);
!             if D = Duration (tv_sec) then
!                tv_nsec := 0;
!             else
!                tv_nsec := Long_Integer ((D - Duration (tv_sec)) * Nano - 0.5);
!             end if;
!          end if;
        end To_Struct_Timespec_64;
  
        ------------------
diff -Nrcpad gcc-16-20250720/gcc/ada/libgnat/a-cbhama.adb gcc-16-20250727/gcc/ada/libgnat/a-cbhama.adb
*** gcc-16-20250720/gcc/ada/libgnat/a-cbhama.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/libgnat/a-cbhama.adb	Sun Jul 27 22:32:07 2025
*************** is
*** 368,374 ****
     -- Empty --
     -----------
  
!    function Empty (Capacity : Count_Type) return Map is
     begin
        return Result : Map (Capacity, 0) do
           null;
--- 368,374 ----
     -- Empty --
     -----------
  
!    function Empty (Capacity : Count_Type := 10) return Map is
     begin
        return Result : Map (Capacity, 0) do
           null;
diff -Nrcpad gcc-16-20250720/gcc/ada/libgnat/a-cbhama.ads gcc-16-20250727/gcc/ada/libgnat/a-cbhama.ads
*** gcc-16-20250720/gcc/ada/libgnat/a-cbhama.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/libgnat/a-cbhama.ads	Sun Jul 27 22:32:07 2025
*************** is
*** 71,77 ****
     --  Map objects declared without an initialization expression are
     --  initialized to the value Empty_Map.
  
!    function Empty (Capacity : Count_Type) return Map;
  
     No_Element : constant Cursor;
     --  Cursor objects declared without an initialization expression are
--- 71,77 ----
     --  Map objects declared without an initialization expression are
     --  initialized to the value Empty_Map.
  
!    function Empty (Capacity : Count_Type := 10) return Map;
  
     No_Element : constant Cursor;
     --  Cursor objects declared without an initialization expression are
diff -Nrcpad gcc-16-20250720/gcc/ada/libgnat/g-calend.adb gcc-16-20250727/gcc/ada/libgnat/g-calend.adb
*** gcc-16-20250720/gcc/ada/libgnat/g-calend.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/libgnat/g-calend.adb	Sun Jul 27 22:32:07 2025
*************** package body GNAT.Calendar is
*** 344,349 ****
--- 344,351 ----
        sec   : aliased C.Extensions.long_long;
        usec  : aliased C.long;
  
+       pragma Unsuppress (Overflow_Check);
+ 
     begin
        timeval_to_duration (T, sec'Access, usec'Access);
        pragma Annotate (CodePeer, Modified, sec);
*************** package body GNAT.Calendar is
*** 369,381 ****
        sec    : C.Extensions.long_long;
        usec   : C.long;
  
     begin
        if D = 0.0 then
           sec  := 0;
           usec := 0;
        else
!          sec  := C.Extensions.long_long (D - 0.5);
!          usec := C.long ((D - Duration (sec)) * Micro - 0.5);
        end if;
  
        duration_to_timeval (sec, usec, Result'Access);
--- 371,398 ----
        sec    : C.Extensions.long_long;
        usec   : C.long;
  
+       pragma Unsuppress (Overflow_Check);
+ 
     begin
        if D = 0.0 then
           sec  := 0;
           usec := 0;
+ 
+       elsif D < 0.0 then
+          sec := C.Extensions.long_long (D + 0.5);
+          if D = Duration (sec) then
+             usec := 0;
+          else
+             usec := C.long ((D - Duration (sec)) * Micro + 0.5);
+          end if;
+ 
        else
!          sec := C.Extensions.long_long (D - 0.5);
!          if D = Duration (sec) then
!             usec := 0;
!          else
!             usec := C.long ((D - Duration (sec)) * Micro - 0.5);
!          end if;
        end if;
  
        duration_to_timeval (sec, usec, Result'Access);
diff -Nrcpad gcc-16-20250720/gcc/ada/libgnat/g-socket.adb gcc-16-20250727/gcc/ada/libgnat/g-socket.adb
*** gcc-16-20250720/gcc/ada/libgnat/g-socket.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/libgnat/g-socket.adb	Sun Jul 27 22:32:07 2025
*************** package body GNAT.Sockets is
*** 3059,3070 ****
        --  Normal case where we do round down
  
        else
!          S  := time_t (Val - 0.5);
!          uS := suseconds_t (1_000_000 * (Val - Selector_Duration (S)) - 0.5);
! 
!          if uS = -1 then
!             --  It happen on integer duration
              uS := 0;
           end if;
        end if;
  
--- 3059,3069 ----
        --  Normal case where we do round down
  
        else
!          S := time_t (Val - 0.5);
!          if Val = Timeval_Duration (S) then
              uS := 0;
+          else
+             uS := suseconds_t ((Val - Timeval_Duration (S)) * 1_000_000 - 0.5);
           end if;
        end if;
  
diff -Nrcpad gcc-16-20250720/gcc/ada/s-oscons-tmplt.c gcc-16-20250727/gcc/ada/s-oscons-tmplt.c
*** gcc-16-20250720/gcc/ada/s-oscons-tmplt.c	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/s-oscons-tmplt.c	Sun Jul 27 22:32:08 2025
*************** CND(CLOCK_THREAD_CPUTIME_ID, "Thread CPU
*** 1976,1982 ****
  #if defined(__linux__) || defined(__FreeBSD__) \
   || (defined(_AIX) && defined(_AIXVERSION_530)) \
   || defined(__DragonFly__) || defined(__QNX__) \
!  || defined (__vxworks)
  /** On these platforms use system provided monotonic clock instead of
   ** the default CLOCK_REALTIME. We then need to set up cond var attributes
   ** appropriately (see thread.c).
--- 1976,1982 ----
  #if defined(__linux__) || defined(__FreeBSD__) \
   || (defined(_AIX) && defined(_AIXVERSION_530)) \
   || defined(__DragonFly__) || defined(__QNX__) \
!  || (defined (__vxworks) && /* VxWorks7 */ defined (_VSB_CONFIG_FILE))
  /** On these platforms use system provided monotonic clock instead of
   ** the default CLOCK_REALTIME. We then need to set up cond var attributes
   ** appropriately (see thread.c).
*************** CND(CLOCK_THREAD_CPUTIME_ID, "Thread CPU
*** 1985,1990 ****
--- 1985,1994 ----
   ** pthread_cond_timedwait (and does not have pthread_condattr_setclock),
   ** hence the conditionalization on AIX version above). _AIXVERSION_530
   ** is defined in AIX 5.3 and more recent versions.
+  **
+  ** VxWorks6 lacks pthread_condattr_setclock, so define CLOCK_RT_Ada to
+  ** CLOCK_REALTIME to get the dummy definition of __gnat_pthread_condattr_setup
+  ** in libgnarl/thread.c.
   **/
  # define CLOCK_RT_Ada "CLOCK_MONOTONIC"
  
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_attr.adb gcc-16-20250727/gcc/ada/sem_attr.adb
*** gcc-16-20250720/gcc/ada/sem_attr.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_attr.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Attr is
*** 9359,9364 ****
--- 9359,9378 ----
        when Attribute_First =>
           Set_Bounds;
  
+          --  In GNATprove mode we only fold array attributes when prefix is
+          --  static (because that's required by the Ada rules) or at least can
+          --  be evaluated without checks (because GNATprove would miss them).
+ 
+          if GNATprove_Mode
+             and then
+               not (Static
+                    or else (Is_Entity_Name (P) and then Is_Type (Entity (P)))
+                    or else Statically_Names_Object (P)
+                    or else Ekind (P_Type) = E_String_Literal_Subtype)
+          then
+             return;
+          end if;
+ 
           if Compile_Time_Known_Value (Lo_Bound) then
              if Is_Real_Type (P_Type) then
                 Fold_Ureal (N, Expr_Value_R (Lo_Bound), Static);
*************** package body Sem_Attr is
*** 9572,9577 ****
--- 9586,9605 ----
        when Attribute_Last =>
           Set_Bounds;
  
+          --  In GNATprove mode we only fold array attributes when prefix is
+          --  static (because that's required by the Ada rules) or at least can
+          --  be evaluated without checks (because GNATprove would miss them).
+ 
+          if GNATprove_Mode
+             and then
+               not (Static
+                    or else (Is_Entity_Name (P) and then Is_Type (Entity (P)))
+                    or else Statically_Names_Object (P)
+                    or else Ekind (P_Type) = E_String_Literal_Subtype)
+          then
+             return;
+          end if;
+ 
           if Compile_Time_Known_Value (Hi_Bound) then
              if Is_Real_Type (P_Type) then
                 Fold_Ureal (N, Expr_Value_R (Hi_Bound), Static);
*************** package body Sem_Attr is
*** 9655,9660 ****
--- 9683,9702 ----
  
           Set_Bounds;
  
+          --  In GNATprove mode we only fold array attributes when prefix is
+          --  static (because that's required by the Ada rules) or at least can
+          --  be evaluated without checks (because GNATprove would miss them).
+ 
+          if GNATprove_Mode
+             and then
+               not (Static
+                    or else (Is_Entity_Name (P) and then Is_Type (Entity (P)))
+                    or else Statically_Names_Object (P)
+                    or else Ekind (P_Type) = E_String_Literal_Subtype)
+          then
+             return;
+          end if;
+ 
           --  For two compile time values, we can compute length
  
           if Compile_Time_Known_Value (Lo_Bound)
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_aux.adb gcc-16-20250727/gcc/ada/sem_aux.adb
*** gcc-16-20250720/gcc/ada/sem_aux.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_aux.adb	Sun Jul 27 22:32:08 2025
***************
*** 25,31 ****
  
  with Atree;          use Atree;
  with Einfo;          use Einfo;
- with Einfo.Entities; use Einfo.Entities;
  with Einfo.Utils;    use Einfo.Utils;
  with Nlists;         use Nlists;
  with Sinfo;          use Sinfo;
--- 25,30 ----
*************** package body Sem_Aux is
*** 454,469 ****
--- 453,480 ----
        Id  : Entity_Id;
  
     begin
+       --  Call using access to subprogram with explicit dereference
+ 
        if Nkind (Nam) = N_Explicit_Dereference then
           Id := Etype (Nam);
           pragma Assert (Ekind (Id) = E_Subprogram_Type);
  
+       --  Case of call to simple entry, where the Name is a selected component
+       --  whose prefix is the task or protected record, and whose selector name
+       --  is the entry name.
+ 
        elsif Nkind (Nam) = N_Selected_Component then
           Id := Entity (Selector_Name (Nam));
  
+       --  Case of call to member of entry family, where Name is an indexed
+       --  component, with the prefix being a selected component giving the
+       --  task and entry family name, and the index being the entry index.
+ 
        elsif Nkind (Nam) = N_Indexed_Component then
           Id := Entity (Selector_Name (Prefix (Nam)));
  
+       --  Normal case
+ 
        else
           Id := Entity (Nam);
        end if;
*************** package body Sem_Aux is
*** 1546,1551 ****
--- 1557,1637 ----
        return E;
     end Ultimate_Alias;
  
+    ---------------------------
+    -- Unique_Component_Name --
+    ---------------------------
+ 
+    function Unique_Component_Name
+      (Component : Record_Field_Kind_Id) return Name_Id
+    is
+       Homographic_Component_Count : Pos := 1;
+       Hcc                         : Pos renames Homographic_Component_Count;
+       Enclosing_Type              : Entity_Id :=
+         Underlying_Type (Base_Type (Scope (Component)));
+    begin
+       if Ekind (Enclosing_Type) = E_Record_Type
+         and then Is_Tagged_Type (Enclosing_Type)
+         and then Has_Private_Ancestor (Enclosing_Type)
+       then
+          --  traverse ancestors to determine Hcc value
+          loop
+             declare
+                Type_Decl : constant Node_Id :=
+                  Parent (Underlying_Type (Base_Type (Enclosing_Type)));
+                Type_Def : constant Node_Id := Type_Definition (Type_Decl);
+             begin
+                exit when Nkind (Type_Def) /= N_Derived_Type_Definition;
+                Enclosing_Type :=
+                  Underlying_Type (Base_Type (Etype (Enclosing_Type)));
+ 
+                declare
+                   Ancestor_Comp : Opt_Record_Field_Kind_Id :=
+                     First_Component_Or_Discriminant (Enclosing_Type);
+                begin
+                   while Present (Ancestor_Comp) loop
+                      if Chars (Ancestor_Comp) = Chars (Component) then
+                         Hcc := Hcc + 1;
+                         exit; -- exit not required, but might as well
+                      end if;
+                      Next_Component_Or_Discriminant (Ancestor_Comp);
+                   end loop;
+                end;
+             end;
+          end loop;
+       end if;
+ 
+       if Hcc = 1 then
+          --  the usual case
+          return Chars (Component);
+       else
+          declare
+             Buff : Bounded_String;
+          begin
+             Append (Buff, Chars (Component));
+ 
+             Append (Buff, "__");
+             --  A double underscore in an identifier is legal in C, not in Ada.
+             --  Returning a result that is not a legal Ada identifier
+             --  ensures that we won't have problems with collisions.
+             --  If we have a component named Foo and we just append a
+             --  number (without any underscores), that new name might match
+             --  the name of another component (which would be bad).
+             --  The result of this function is intended for use as an
+             --  identifier in generated C code, so it needs to be a
+             --  legal C identifer.
+ 
+             Append (Buff, Hcc);
+             --  Should we instead append Hcc - 1 here? This is a human
+             --  readability question. If parent type and extension each
+             --  have a Foo component, do we want the name returned for the
+             --  second Foo to be "foo__2" or "foo__1" ? Does it matter?
+             --  Either way, the name returned for the first Foo will be "foo".
+ 
+             return Name_Find (Buff);
+          end;
+       end if;
+    end Unique_Component_Name;
+ 
     --------------------------
     -- Unit_Declaration_Node --
     --------------------------
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_aux.ads gcc-16-20250727/gcc/ada/sem_aux.ads
*** gcc-16-20250720/gcc/ada/sem_aux.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_aux.ads	Sun Jul 27 22:32:08 2025
***************
*** 31,36 ****
--- 31,37 ----
  --  require more than minimal semantic knowledge.
  
  with Alloc;
+ with Einfo.Entities; use Einfo.Entities;
  with Namet; use Namet;
  with Table;
  with Types; use Types;
*************** package Sem_Aux is
*** 405,410 ****
--- 406,424 ----
     --  Return the last entity in the chain of aliased entities of Prim. If Prim
     --  has no alias return Prim.
  
+    function Unique_Component_Name
+      (Component : Record_Field_Kind_Id) return Name_Id;
+    --  Usually, a record type cannot have two components with the same name.
+    --  But in the case of a component declared in an extension of a tagged
+    --  private (or private extension) parent type, it is possible that some
+    --  ancestor type also has a (non-visible) component with the same name.
+    --  In the common case, this function simply returns the Chars attribute
+    --  of its argument.
+    --  But in the multiple-components-with-the-same-name case, it appends
+    --  a uniquifying suffix. The result in this case will not be a
+    --  syntactically valid Ada identifier, but it will be a syntactically
+    --  valid C identifier.
+ 
     function Unit_Declaration_Node (Unit_Id : Entity_Id) return Node_Id;
     --  Unit_Id is the simple name of a program unit, this function returns the
     --  corresponding xxx_Declaration node for the entity. Also applies to the
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_ch12.adb gcc-16-20250727/gcc/ada/sem_ch12.adb
*** gcc-16-20250720/gcc/ada/sem_ch12.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_ch12.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Ch12 is
*** 7574,7579 ****
--- 7574,7585 ----
                      or else not Same_Instantiated_Function (E1, E2));
              end if;
  
+          --  No check is needed if this is the body of a subprogram that is
+          --  implicitly created in the case of class-wide predefined functions.
+ 
+          elsif Ekind (E1) = E_Subprogram_Body then
+             null;
+ 
           else
              raise Program_Error;
           end if;
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_ch13.adb gcc-16-20250727/gcc/ada/sem_ch13.adb
*** gcc-16-20250720/gcc/ada/sem_ch13.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_ch13.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Ch13 is
*** 337,342 ****
--- 337,349 ----
     --  Resolve each one of the arguments specified in the specification of
     --  aspect Finalizable.
  
+    function Resolve_Finalization_Procedure
+      (N   : Node_Id;
+       Typ : Entity_Id) return Boolean;
+    --  Resolve a procedure argument specified in the specification of one of
+    --  the finalization aspects, i.e. Finalizable and Destructor. Returns True
+    --  if successful, False otherwise.
+ 
     procedure Resolve_Iterable_Operation
       (N      : Node_Id;
        Cursor : Entity_Id;
*************** package body Sem_Ch13 is
*** 4647,4652 ****
--- 4654,4673 ----
                       goto Continue;
                    end if;
  
+                when Aspect_Destructor =>
+                   if not All_Extensions_Allowed then
+                      Error_Msg_Name_1 := Nam;
+                      Error_Msg_GNAT_Extension ("aspect %", Loc);
+                      goto Continue;
+ 
+                   elsif not Is_Type (E) then
+                      Error_Msg_N ("can only be specified for a type", Aspect);
+                      goto Continue;
+                   end if;
+ 
+                   Set_Has_Destructor (E);
+                   Set_Is_Controlled_Active (E);
+ 
                 when Aspect_Storage_Model_Type =>
                    if not All_Extensions_Allowed then
                       Error_Msg_Name_1 := Nam;
*************** package body Sem_Ch13 is
*** 5064,5069 ****
--- 5085,5098 ----
                          Check_Expr_Is_OK_Static_Expression (Expr, Any_Boolean);
                       end if;
  
+                      --  Record the No_Task_Parts aspects as a rep item so it
+                      --  can be consistently looked up on the full view of the
+                      --  type.
+ 
+                      if Is_Private_Type (E) then
+                         Record_Rep_Item (E, Aspect);
+                      end if;
+ 
                       goto Continue;
  
                    --  Ada 2022 (AI12-0075): static expression functions
*************** package body Sem_Ch13 is
*** 11241,11246 ****
--- 11270,11282 ----
     --  Start of processing for Check_Aspect_At_End_Of_Declarations
  
     begin
+       --  Indicate that the expression comes from an aspect specification,
+       --  which is used in subsequent analysis even if expansion is off.
+ 
+       if Present (End_Decl_Expr) then
+          Set_Parent (End_Decl_Expr, ASN);
+       end if;
+ 
        --  In an instance we do not perform the consistency check between freeze
        --  point and end of declarations, because it was done already in the
        --  analysis of the generic. Furthermore, the delayed analysis of an
*************** package body Sem_Ch13 is
*** 11270,11275 ****
--- 11306,11312 ----
        --  the one available at at the freeze point.
  
        elsif A_Id in Aspect_Constructor
+                   | Aspect_Destructor
                    | Aspect_Input
                    | Aspect_Output
                    | Aspect_Read
*************** package body Sem_Ch13 is
*** 11332,11344 ****
              end if;
           end if;
  
-          --  Indicate that the expression comes from an aspect specification,
-          --  which is used in subsequent analysis even if expansion is off.
- 
-          if Present (End_Decl_Expr) then
-             Set_Parent (End_Decl_Expr, ASN);
-          end if;
- 
           --  In a generic context the original aspect expressions have not
           --  been preanalyzed, so do it now. There are no conformance checks
           --  to perform in this case. As before, we have to make components
--- 11369,11374 ----
*************** package body Sem_Ch13 is
*** 11734,11739 ****
--- 11764,11830 ----
              Analyze (Expression (ASN));
              return;
  
+          when Aspect_Destructor =>
+             if not Is_Record_Type (Entity (ASN)) then
+                Error_Msg_N
+                  ("aspect Destructor can only be specified for a "
+                   & "record type",
+                   ASN);
+                return;
+             end if;
+ 
+             Set_Has_Destructor (Entity (ASN));
+             Set_Is_Controlled_Active (Entity (ASN));
+ 
+             Analyze (Expression (ASN));
+ 
+             if not Resolve_Finalization_Procedure
+                      (Expression (ASN), Entity (ASN))
+             then
+                Error_Msg_N
+                  ("destructor must be local procedure whose only formal "
+                   & "parameter has mode `IN OUT` and is of the type the "
+                   & "destructor is for",
+                   Expression (ASN));
+             end if;
+ 
+             Set_Is_Destructor (Entity (Expression (ASN)));
+ 
+             declare
+                Proc  : constant Entity_Id := Entity (Expression (ASN));
+                Overr : constant Opt_N_Entity_Id :=
+                  Overridden_Inherited_Operation (Proc);
+                Orig  : constant Entity_Id :=
+                  (if Present (Overr) then Overr else Proc);
+ 
+                Decl : constant Node_Id :=
+                  Parent
+                    (if Nkind (Parent (Orig)) = N_Procedure_Specification
+                     then Parent (Orig)
+                     else Orig);
+ 
+                Encl : constant Node_Id := Parent (Decl);
+ 
+                Is_Private : constant Boolean :=
+                  Nkind (Encl) = N_Package_Specification
+                  and then Is_List_Member (Decl)
+                  and then List_Containing (Decl) = Private_Declarations (Encl);
+ 
+             begin
+ 
+                if Has_Private_Declaration (Entity (ASN))
+                  and then not Aspect_On_Partial_View (ASN)
+                  and then not Is_Private
+                then
+                   Error_Msg_N
+                     ("aspect Destructor on full view cannot denote public "
+                      & "primitive",
+                      ASN);
+                end if;
+             end;
+ 
+             return;
+ 
           when Aspect_Storage_Model_Type =>
  
              --  The aggregate argument of Storage_Model_Type is optional, and
*************** package body Sem_Ch13 is
*** 15887,15892 ****
--- 15978,15985 ----
           --  We may freeze Subp_Id immediately since Ent has just been frozen.
           --  This will help to shield us from potential late freezing issues.
  
+          Mutate_Ekind (Subp_Id, E_Procedure);
+          Freeze_Extra_Formals (Subp_Id);
           Set_Is_Frozen (Subp_Id);
  
        else
*************** package body Sem_Ch13 is
*** 17334,17339 ****
--- 17427,17461 ----
        Typ : Entity_Id;
        Nam : Name_Id)
     is
+    begin
+       if Nam = Name_Relaxed_Finalization then
+          Resolve (N, Any_Boolean);
+ 
+          if Is_OK_Static_Expression (N) then
+             Set_Has_Relaxed_Finalization (Typ, Is_True (Static_Boolean (N)));
+ 
+          else
+             Flag_Non_Static_Expr
+               ("expression of aspect Finalizable must be static!", N);
+          end if;
+ 
+          return;
+       end if;
+ 
+       if Resolve_Finalization_Procedure (N, Typ) then
+          return;
+       end if;
+ 
+       Error_Msg_N
+         ("finalizable primitive must be local procedure whose only formal " &
+          "parameter has mode `IN OUT` and is of the finalizable type", N);
+    end Resolve_Finalizable_Argument;
+ 
+    function Resolve_Finalization_Procedure
+      (N   : Node_Id;
+       Typ : Entity_Id)
+       return Boolean
+    is
        function Is_Finalizable_Primitive (E : Entity_Id) return Boolean;
        --  Check whether E is a finalizable primitive for Typ
  
*************** package body Sem_Ch13 is
*** 17351,17379 ****
             and then No (Next_Formal (First_Formal (E)));
        end Is_Finalizable_Primitive;
  
!    --  Start of processing for Resolve_Finalizable_Argument
  
     begin
-       if Nam = Name_Relaxed_Finalization then
-          Resolve (N, Any_Boolean);
- 
-          if Is_OK_Static_Expression (N) then
-             Set_Has_Relaxed_Finalization (Typ, Is_True (Static_Boolean (N)));
- 
-          else
-             Flag_Non_Static_Expr
-               ("expression of aspect Finalizable must be static!", N);
-          end if;
- 
-          return;
-       end if;
- 
        if not Is_Entity_Name (N) then
           null;
  
        elsif not Is_Overloaded (N) then
           if Is_Finalizable_Primitive (Entity (N)) then
!             return;
           end if;
  
        else
--- 17473,17487 ----
             and then No (Next_Formal (First_Formal (E)));
        end Is_Finalizable_Primitive;
  
!    --  Start of processing for Resolve_Finalization_Procedure
  
     begin
        if not Is_Entity_Name (N) then
           null;
  
        elsif not Is_Overloaded (N) then
           if Is_Finalizable_Primitive (Entity (N)) then
!             return True;
           end if;
  
        else
*************** package body Sem_Ch13 is
*** 17389,17395 ****
              while Present (It.Typ) loop
                 if Is_Finalizable_Primitive (It.Nam) then
                    Set_Entity (N, It.Nam);
!                   return;
                 end if;
  
                 Get_Next_Interp (I, It);
--- 17497,17503 ----
              while Present (It.Typ) loop
                 if Is_Finalizable_Primitive (It.Nam) then
                    Set_Entity (N, It.Nam);
!                   return True;
                 end if;
  
                 Get_Next_Interp (I, It);
*************** package body Sem_Ch13 is
*** 17397,17406 ****
           end;
        end if;
  
!       Error_Msg_N
!         ("finalizable primitive must be local procedure whose only formal " &
!          "parameter has mode `IN OUT` and is of the finalizable type", N);
!    end Resolve_Finalizable_Argument;
  
     --------------------------------
     -- Resolve_Iterable_Operation --
--- 17505,17512 ----
           end;
        end if;
  
!       return False;
!    end Resolve_Finalization_Procedure;
  
     --------------------------------
     -- Resolve_Iterable_Operation --
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_ch3.adb gcc-16-20250727/gcc/ada/sem_ch3.adb
*** gcc-16-20250720/gcc/ada/sem_ch3.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_ch3.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Ch3 is
*** 3020,3025 ****
--- 3020,3027 ----
     -----------------------------------
  
     procedure Analyze_Full_Type_Declaration (N : Node_Id) is
+       use Deferred_Extra_Formals_Support;
+ 
        Def    : constant Node_Id   := Type_Definition (N);
        Def_Id : constant Entity_Id := Defining_Identifier (N);
        T      : Entity_Id;
*************** package body Sem_Ch3 is
*** 3558,3563 ****
--- 3560,3575 ----
           end if;
        end if;
  
+       --  If we have some subprogram, subprogram type, or entry, with deferred
+       --  addition of its extra formals (because the underlying type of this
+       --  type was not previously available), then try creating now its extra
+       --  formals. Create also the extra actuals of deferred calls to entities
+       --  with deferred extra formals.
+ 
+       if Has_Deferred_Extra_Formals (T) then
+          Add_Deferred_Extra_Params (T);
+       end if;
+ 
        if Ekind (T) = E_Record_Type
          and then Is_Large_Unconstrained_Definite (T)
          and then not Is_Limited_Type (T)
*************** package body Sem_Ch3 is
*** 6819,6825 ****
        --  that the element type is constrained.
  
        if Is_Mutably_Tagged_Type (Element_Type) then
!          Set_Component_Type (T,
             Class_Wide_Equivalent_Type (Element_Type));
  
        elsif not Is_Definite_Subtype (Element_Type) then
--- 6831,6837 ----
        --  that the element type is constrained.
  
        if Is_Mutably_Tagged_Type (Element_Type) then
!          Set_Component_Type (Base_Type (T),
             Class_Wide_Equivalent_Type (Element_Type));
  
        elsif not Is_Definite_Subtype (Element_Type) then
*************** package body Sem_Ch3 is
*** 8440,8454 ****
           Set_Has_Private_Declaration (Full_Der);
           Set_Has_Private_Declaration (Derived_Type);
  
!          Set_Scope                (Full_Der, Scope (Derived_Type));
!          Set_Is_First_Subtype     (Full_Der, Is_First_Subtype (Derived_Type));
!          Set_Has_Size_Clause      (Full_Der, False);
!          Set_Has_Alignment_Clause (Full_Der, False);
!          Set_Has_Delayed_Freeze   (Full_Der);
!          Set_Is_Frozen            (Full_Der, False);
!          Set_Freeze_Node          (Full_Der, Empty);
!          Set_Depends_On_Private   (Full_Der, Has_Private_Component (Full_Der));
!          Set_Is_Public            (Full_Der, Is_Public (Derived_Type));
  
           --  The convention on the base type may be set in the private part
           --  and not propagated to the subtype until later, so we obtain the
--- 8452,8468 ----
           Set_Has_Private_Declaration (Full_Der);
           Set_Has_Private_Declaration (Derived_Type);
  
!          Set_Scope                 (Full_Der, Scope (Derived_Type));
!          Set_Is_First_Subtype      (Full_Der, Is_First_Subtype (Derived_Type));
!          Set_Has_Size_Clause       (Full_Der, False);
!          Set_Has_Alignment_Clause  (Full_Der, False);
!          Set_Has_Delayed_Freeze    (Full_Der);
!          Set_Is_Frozen             (Full_Der, False);
!          Set_Freeze_Node           (Full_Der, Empty);
!          Set_Depends_On_Private
!            (Full_Der, Has_Private_Component (Full_Der));
!          Set_Is_Public             (Full_Der, Is_Public (Derived_Type));
!          Set_Is_Implicit_Full_View (Full_Der);
  
           --  The convention on the base type may be set in the private part
           --  and not propagated to the subtype until later, so we obtain the
*************** package body Sem_Ch3 is
*** 9646,9651 ****
--- 9660,9667 ----
             (New_Decl, Parent_Base, New_Base,
              Is_Completion => False, Derive_Subps => False);
  
+          Set_Is_Implicit_Full_View (New_Base);
+ 
           --  ??? This needs re-examination to determine whether the
           --  following call can simply be replaced by a call to Analyze.
  
*************** package body Sem_Ch3 is
*** 21279,21286 ****
        --  On entry, the current scope is the composite type.
  
        --  The discriminants are initially entered into the scope of the type
!       --  via Enter_Name with the default Ekind of E_Void to prevent premature
!       --  use, as explained at the end of this procedure.
  
        Discr := First (Discriminant_Specifications (N));
        while Present (Discr) loop
--- 21295,21302 ----
        --  On entry, the current scope is the composite type.
  
        --  The discriminants are initially entered into the scope of the type
!       --  via Enter_Name with Is_Not_Self_Hidden set to False to prevent
!       --  premature use, as explained at the end of this procedure.
  
        Discr := First (Discriminant_Specifications (N));
        while Present (Discr) loop
*************** package body Sem_Ch3 is
*** 21553,21564 ****
        --  expressions of a discriminant part if the specification of the
        --  discriminant is itself given in the discriminant part. (RM 3.7.1)
  
!       --  To detect this, the discriminant names are entered initially with an
!       --  Ekind of E_Void (which is the default Ekind given by Enter_Name). Any
!       --  attempt to use a void entity (for example in an expression that is
!       --  type-checked) produces the error message: premature usage. Now after
!       --  completing the semantic analysis of the discriminant part, we can set
!       --  the Ekind of all the discriminants appropriately.
  
        Discr := First (Discriminant_Specifications (N));
        Discr_Number := Uint_1;
--- 21569,21580 ----
        --  expressions of a discriminant part if the specification of the
        --  discriminant is itself given in the discriminant part. (RM 3.7.1)
  
!       --  To detect this, the discriminant names are entered initially with
!       --  Is_Not_Self_Hidden set to False. Any attempt to use a self-hidden
!       --  entity (for example in an expression that is type-checked) produces
!       --  the error message: premature usage. Now after completing the semantic
!       --  analysis of the discriminant part, we can set Is_Not_Self_Hidden on
!       --  all the discriminants appropriately.
  
        Discr := First (Discriminant_Specifications (N));
        Discr_Number := Uint_1;
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_ch4.adb gcc-16-20250727/gcc/ada/sem_ch4.adb
*** gcc-16-20250720/gcc/ada/sem_ch4.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_ch4.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Ch4 is
*** 5603,5608 ****
--- 5603,5612 ----
                    if No (Act_Decl) then
                       Set_Etype (N, Etype (Comp));
  
+                      if Is_Mutably_Tagged_CW_Equivalent_Type (Etype (N)) then
+                         Make_Mutably_Tagged_Conversion (N);
+                      end if;
+ 
                    else
                       --  If discriminants were present in the component
                       --  declaration, they have been replaced by the
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_ch5.adb gcc-16-20250727/gcc/ada/sem_ch5.adb
*** gcc-16-20250720/gcc/ada/sem_ch5.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_ch5.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Ch5 is
*** 807,813 ****
  
        if Is_Tag_Indeterminate (Rhs) then
           if Is_Class_Wide_Type (T1) then
!             Propagate_Tag (Lhs, Rhs);
  
           elsif Nkind (Rhs) = N_Function_Call
             and then Is_Entity_Name (Name (Rhs))
--- 807,820 ----
  
        if Is_Tag_Indeterminate (Rhs) then
           if Is_Class_Wide_Type (T1) then
! 
!             --  No need to propagate the tag when the RHS has function calls
!             --  that already propagated it (see Expand_Call_Helper), or if
!             --  some error was reported analyzing RHS.
! 
!             if not (Error_Posted (Rhs) or else Tag_Propagated (Lhs)) then
!                Propagate_Tag (Lhs, Rhs);
!             end if;
  
           elsif Nkind (Rhs) = N_Function_Call
             and then Is_Entity_Name (Name (Rhs))
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_ch6.adb gcc-16-20250727/gcc/ada/sem_ch6.adb
*** gcc-16-20250720/gcc/ada/sem_ch6.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_ch6.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Ch6 is
*** 3864,3872 ****
           Spec_Id := Build_Internal_Protected_Declaration (N);
        end if;
  
!       --  If a separate spec is present, then deal with freezing issues
  
!       if Present (Spec_Id) then
           Spec_Decl := Unit_Declaration_Node (Spec_Id);
           Verify_Overriding_Indicator;
  
--- 3864,3877 ----
           Spec_Id := Build_Internal_Protected_Declaration (N);
        end if;
  
!       --  Separate spec is not present
  
!       if No (Spec_Id) then
!          Create_Extra_Formals (Body_Id);
! 
!       --  Separate spec is present; deal with freezing issues
! 
!       else
           Spec_Decl := Unit_Declaration_Node (Spec_Id);
           Verify_Overriding_Indicator;
  
*************** package body Sem_Ch6 is
*** 3882,3887 ****
--- 3887,3894 ----
             and then not Has_BIP_Formals (Spec_Id)
           then
              Create_Extra_Formals (Spec_Id);
+             pragma Assert (not Expander_Active
+               or else Extra_Formals_Known (Spec_Id));
              Compute_Returns_By_Ref (Spec_Id);
           end if;
  
*************** package body Sem_Ch6 is
*** 8564,8577 ****
        --  without coordinating with CodePeer, which makes use of these to
        --  provide better messages.
  
        --  O denotes the Constrained bit.
        --  L denotes the accessibility level.
        --  BIP_xxx denotes an extra formal for a build-in-place function. See
        --  the full list in exp_ch6.BIP_Formal_Kind.
  
-       function Has_Extra_Formals (E : Entity_Id) return Boolean;
-       --  Determines if E has its extra formals
- 
        function Might_Need_BIP_Task_Actuals (E : Entity_Id) return Boolean;
        --  Determines if E is a function or an access to a function returning a
        --  limited tagged type object. On dispatching primitives this predicate
--- 8571,8583 ----
        --  without coordinating with CodePeer, which makes use of these to
        --  provide better messages.
  
+       --  A and B denote extra formals for unchecked unions equality. See
+       --  exp_ch3.Build_Variant_Record_Equality.
        --  O denotes the Constrained bit.
        --  L denotes the accessibility level.
        --  BIP_xxx denotes an extra formal for a build-in-place function. See
        --  the full list in exp_ch6.BIP_Formal_Kind.
  
        function Might_Need_BIP_Task_Actuals (E : Entity_Id) return Boolean;
        --  Determines if E is a function or an access to a function returning a
        --  limited tagged type object. On dispatching primitives this predicate
*************** package body Sem_Ch6 is
*** 8610,8623 ****
           EF : Entity_Id;
  
        begin
-          --  A little optimization. Never generate an extra formal for the
-          --  _init operand of an initialization procedure, since it could
-          --  never be used.
- 
-          if Chars (Formal) = Name_uInit then
-             return Empty;
-          end if;
- 
           EF := Make_Defining_Identifier (Sloc (Assoc_Entity),
                   Chars => New_External_Name (Chars (Assoc_Entity),
                                               Suffix => Suffix));
--- 8616,8621 ----
*************** package body Sem_Ch6 is
*** 8643,8667 ****
           return EF;
        end Add_Extra_Formal;
  
-       -----------------------
-       -- Has_Extra_Formals --
-       -----------------------
- 
-       function Has_Extra_Formals (E : Entity_Id) return Boolean is
-       begin
-          return Present (Extra_Formals (E))
-            or else
-              (Ekind (E) = E_Function
-                 and then Present (Extra_Accessibility_Of_Result (E)));
-       end Has_Extra_Formals;
- 
        ---------------------------------
        -- Might_Need_BIP_Task_Actuals --
        ---------------------------------
  
        function Might_Need_BIP_Task_Actuals (E : Entity_Id) return Boolean is
           Subp_Id  : Entity_Id;
!          Func_Typ : Entity_Id;
  
        begin
           if Global_No_Tasking or else No_Run_Time_Mode then
--- 8641,8662 ----
           return EF;
        end Add_Extra_Formal;
  
        ---------------------------------
        -- Might_Need_BIP_Task_Actuals --
        ---------------------------------
  
        function Might_Need_BIP_Task_Actuals (E : Entity_Id) return Boolean is
           Subp_Id  : Entity_Id;
!          Original : Entity_Id;
!          Root     : Entity_Id;
! 
!          function Has_No_Task_Parts_Enabled (E : Entity_Id) return Boolean
!          is (Has_Enabled_Aspect (E, Aspect_No_Task_Parts));
! 
!          function Collect_Ancestors_With_No_Task_Parts is new
!            Collect_Types_In_Hierarchy (Predicate => Has_No_Task_Parts_Enabled);
! 
!       --  Start of processing for Might_Need_BIP_Task_Actuals
  
        begin
           if Global_No_Tasking or else No_Run_Time_Mode then
*************** package body Sem_Ch6 is
*** 8689,8709 ****
           then
              Subp_Id := Protected_Body_Subprogram (E);
  
!          else
              Subp_Id := E;
-          end if;
  
!          --  We check the root type of the return type since the same
!          --  decision must be taken for all descendants overriding a
!          --  dispatching operation.
  
!          Func_Typ := Root_Type (Underlying_Type (Etype (Subp_Id)));
  
           return Ekind (Subp_Id) in E_Function | E_Subprogram_Type
!            and then not Has_Foreign_Convention (Func_Typ)
!            and then Is_Tagged_Type (Func_Typ)
!            and then Is_Limited_Type (Func_Typ)
!            and then not Has_Aspect (Func_Typ, Aspect_No_Task_Parts);
        end Might_Need_BIP_Task_Actuals;
  
        -------------------------------------
--- 8684,8712 ----
           then
              Subp_Id := Protected_Body_Subprogram (E);
  
!          --  For access-to-subprogram types we look at the return type of the
!          --  subprogram type itself, as it cannot be overridden or inherited.
! 
!          elsif Ekind (E) = E_Subprogram_Type then
              Subp_Id := E;
  
!          --  Otherwise, we need to return the same value we would return for
!          --  the original corresponding operation of the root of the aliased
!          --  chain.
  
!          else
!             Subp_Id := Original_Corresponding_Operation (Ultimate_Alias (E));
!          end if;
! 
!          Original := Underlying_Type (Etype (Subp_Id));
!          Root := Underlying_Type (Root_Type (Original));
  
           return Ekind (Subp_Id) in E_Function | E_Subprogram_Type
!            and then Is_Inherently_Limited_Type (Original)
!            and then not Has_Foreign_Convention (Root)
!            and then Is_Tagged_Type (Root)
!            and then Is_Empty_Elmt_List
!              (Collect_Ancestors_With_No_Task_Parts (Original));
        end Might_Need_BIP_Task_Actuals;
  
        -------------------------------------
*************** package body Sem_Ch6 is
*** 8792,8801 ****
                 --  we have no direct way to climb to the corresponding parent
                 --  subprogram but this internal entity has the extra formals
                 --  (if any) required for the purpose of checking the extra
!                --  formals of Subp_Id.
  
                 else
                    pragma Assert (not Comes_From_Source (Ovr_E));
                 end if;
  
              --  Use as our reference entity the ultimate renaming of the
--- 8795,8806 ----
                 --  we have no direct way to climb to the corresponding parent
                 --  subprogram but this internal entity has the extra formals
                 --  (if any) required for the purpose of checking the extra
!                --  formals of Subp_Id because its extra formals are shared
!                --  with its parent subprogram (see Sem_Ch3.Derive_Subprogram).
  
                 else
                    pragma Assert (not Comes_From_Source (Ovr_E));
+                   Freeze_Extra_Formals (Ovr_E);
                 end if;
  
              --  Use as our reference entity the ultimate renaming of the
*************** package body Sem_Ch6 is
*** 8818,8827 ****
  
        --  Local variables
  
!       Formal_Type      : Entity_Id;
!       May_Have_Alias   : Boolean;
        Alias_Formal     : Entity_Id := Empty;
        Alias_Subp       : Entity_Id := Empty;
        Parent_Formal    : Entity_Id := Empty;
        Parent_Subp      : Entity_Id := Empty;
        Ref_E            : Entity_Id;
--- 8823,8836 ----
  
        --  Local variables
  
!       use Deferred_Extra_Formals_Support;
! 
!       Can_Be_Deferred  : constant Boolean :=
!                            not Is_Unsupported_Extra_Formals_Entity (E);
        Alias_Formal     : Entity_Id := Empty;
        Alias_Subp       : Entity_Id := Empty;
+       Formal_Type      : Entity_Id;
+       May_Have_Alias   : Boolean;
        Parent_Formal    : Entity_Id := Empty;
        Parent_Subp      : Entity_Id := Empty;
        Ref_E            : Entity_Id;
*************** package body Sem_Ch6 is
*** 8832,8841 ****
        pragma Assert (Is_Subprogram_Or_Entry (E)
          or else Ekind (E) in E_Subprogram_Type);
  
        --  We never generate extra formals if expansion is not active because we
        --  don't need them unless we are generating code.
  
!       if not Expander_Active then
           return;
  
        --  Enumeration literals have no extra formal; this case occurs when
--- 8841,8858 ----
        pragma Assert (Is_Subprogram_Or_Entry (E)
          or else Ekind (E) in E_Subprogram_Type);
  
+       --  No action needed if extra formals were already handled. This
+       --  situation may arise because of a previous call to create the
+       --  extra formals, and also for subprogram types created as part
+       --  of dispatching calls (see Expand_Dispatching_Call).
+ 
+       if Extra_Formals_Known (E) then
+          return;
+ 
        --  We never generate extra formals if expansion is not active because we
        --  don't need them unless we are generating code.
  
!       elsif not Expander_Active then
           return;
  
        --  Enumeration literals have no extra formal; this case occurs when
*************** package body Sem_Ch6 is
*** 8844,8868 ****
        elsif Ekind (E) = E_Function
          and then Ekind (Ultimate_Alias (E)) = E_Enumeration_Literal
        then
           return;
  
!       --  Extra formals of Initialization procedures are added by the function
!       --  Exp_Ch3.Init_Formals
  
        elsif Is_Init_Proc (E) then
           return;
  
        --  No need to generate extra formals in thunks whose target has no extra
        --  formals, but we can have two of them chained (interface and stack).
  
!       elsif Is_Thunk (E) and then No (Extra_Formals (Thunk_Target (E))) then
           return;
  
!       --  If Extra_Formals were already created, don't do it again. This
!       --  situation may arise for subprogram types created as part of
!       --  dispatching calls (see Expand_Dispatching_Call).
  
!       elsif Has_Extra_Formals (E) then
           return;
  
        --  Extra formals of renamings of generic actual subprograms and
--- 8861,8898 ----
        elsif Ekind (E) = E_Function
          and then Ekind (Ultimate_Alias (E)) = E_Enumeration_Literal
        then
+          Freeze_Extra_Formals (E);
           return;
  
!       --  Extra formals of init procs are added by Exp_Ch3.Init_Formals and
!       --  Set_CPP_Constructors when they are built, but we must handle here
!       --  aliased init procs.
  
        elsif Is_Init_Proc (E) then
+          pragma Assert (Present (Alias (E)));
+          pragma Assert (Extra_Formals_Known (Ultimate_Alias (E)));
+          Freeze_Extra_Formals (E);
           return;
  
        --  No need to generate extra formals in thunks whose target has no extra
        --  formals, but we can have two of them chained (interface and stack).
  
!       elsif Is_Thunk (E)
!         and then Extra_Formals_Known (Thunk_Target (E))
!         and then No (Extra_Formals (Thunk_Target (E)))
!       then
!          Freeze_Extra_Formals (E);
           return;
  
!       --  Handle alias of unchecked union equality with frozen extra formals
  
!       elsif Is_Overloadable (E)
!         and then Present (Alias (E))
!         and then Extra_Formals_Known (Ultimate_Alias (E))
!         and then Is_Unchecked_Union_Equality (Ultimate_Alias (E))
!       then
!          Set_Extra_Formals (E, Extra_Formals (Ultimate_Alias (E)));
!          Freeze_Extra_Formals (E);
           return;
  
        --  Extra formals of renamings of generic actual subprograms and
*************** package body Sem_Ch6 is
*** 8880,8885 ****
--- 8910,8917 ----
             = Is_Generic_Instance (Ultimate_Alias (E)));
  
           Create_Extra_Formals (Ultimate_Alias (E));
+          pragma Assert (not Expander_Active
+            or else Extra_Formals_Known (Ultimate_Alias (E)));
  
           --  Share the extra formals
  
*************** package body Sem_Ch6 is
*** 8891,8907 ****
           end if;
  
           pragma Assert (Extra_Formals_OK (E));
           return;
        end if;
  
!       --  Locate the last formal; required by Add_Extra_Formal.
  
        Formal := First_Formal (E);
        while Present (Formal) loop
!          Last_Extra := Formal;
           Next_Formal (Formal);
        end loop;
  
        --  We rely on three entities to ensure consistency of extra formals of
        --  entity E:
        --
--- 8923,8994 ----
           end if;
  
           pragma Assert (Extra_Formals_OK (E));
+          Freeze_Extra_Formals (E);
           return;
        end if;
  
!       --  Check if the addition of the extra formals must be deferred
  
        Formal := First_Formal (E);
        while Present (Formal) loop
!          if No (Underlying_Type (Etype (Formal)))
!            and then Can_Be_Deferred
!          then
!             Register_Deferred_Extra_Formals_Entity (E);
!             return;
!          end if;
! 
           Next_Formal (Formal);
        end loop;
  
+       if Ekind (E) in E_Function
+                     | E_Subprogram_Type
+         and then No (Underlying_Type (Etype (E)))
+         and then Can_Be_Deferred
+       then
+          Register_Deferred_Extra_Formals_Entity (E);
+          return;
+       end if;
+ 
+       --  Here we start adding the extra formals
+ 
+       --  We we know that either the underlying type of all the formals and
+       --  returned results of E are known, or this is an special case where
+       --  some underlying type is still not available.
+ 
+       --  In the former case, we can already mark functions that return their
+       --  result by reference; in the latter case, we can mark them only if the
+       --  underlying return type is available (and it will be marked later).
+ 
+       if not Is_Unsupported_Extra_Formals_Entity (E)
+         or else (Ekind (E) in E_Function | E_Subprogram_Type
+                    and then Present (Underlying_Type (Etype (E))))
+       then
+          Compute_Returns_By_Ref (E);
+       end if;
+ 
+       --  Locate the last formal (required by Add_Extra_Formal)
+ 
+       if Present (First_Formal (E))
+         and then Is_Unchecked_Union (Etype (First_Formal (E)))
+         and then Present (Extra_Formals (E))
+         and then Has_Suffix (Extra_Formals (E), 'A')
+       then
+          --  An unchecked union equality has two extra formals per discriminant
+ 
+          First_Extra := Extra_Formals (E);
+          Last_Extra  := First_Extra;
+          while Present (Last_Extra) loop
+             pragma Assert (Has_Suffix (Last_Extra, 'A'));
+             Last_Extra := Extra_Formal (Last_Extra);
+ 
+             pragma Assert (Has_Suffix (Last_Extra, 'B'));
+             Last_Extra := Extra_Formal (Last_Extra);
+          end loop;
+       else
+          Last_Extra := Last_Formal (E);
+       end if;
+ 
        --  We rely on three entities to ensure consistency of extra formals of
        --  entity E:
        --
*************** package body Sem_Ch6 is
*** 8961,8966 ****
--- 9048,9054 ----
          or else (Present (Alias_Subp)
                     and then Has_Foreign_Convention (Alias_Subp))
        then
+          Freeze_Extra_Formals (E);
           return;
        end if;
  
*************** package body Sem_Ch6 is
*** 9039,9052 ****
           --  Here we establish our priority for deciding on the extra
           --  formals: 1) Parent primitive 2) Aliased primitive 3) Identity
  
!          if Present (Parent_Formal) then
!             Formal_Type := Etype (Parent_Formal);
  
!          elsif Present (Alias_Formal) then
!             Formal_Type := Etype (Alias_Formal);
  
           else
!             Formal_Type := Etype (Formal);
           end if;
  
           --  Create extra formal for supporting the attribute 'Constrained.
--- 9127,9170 ----
           --  Here we establish our priority for deciding on the extra
           --  formals: 1) Parent primitive 2) Aliased primitive 3) Identity
  
!          --  Common case: the underlying type of all the formals is known
!          --  to be available.
  
!          if Can_Be_Deferred then
!             if Present (Parent_Formal) then
!                Formal_Type := Underlying_Type (Etype (Parent_Formal));
!             elsif Present (Alias_Formal) then
!                Formal_Type := Underlying_Type (Etype (Alias_Formal));
!             else
!                Formal_Type := Underlying_Type (Etype (Formal));
!             end if;
! 
!             pragma Assert (Present (Formal_Type));
! 
!          --  Special case: The underlying type of some formal is not available.
!          --  We use the underlying type when present. More work needed here???
  
           else
!             if Present (Parent_Formal) then
!                Formal_Type := Etype (Parent_Formal);
! 
!                if Present (Underlying_Type (Formal_Type)) then
!                   Formal_Type := Underlying_Type (Formal_Type);
!                end if;
! 
!             elsif Present (Alias_Formal) then
!                Formal_Type := Etype (Alias_Formal);
! 
!                if Present (Underlying_Type (Formal_Type)) then
!                   Formal_Type := Underlying_Type (Formal_Type);
!                end if;
!             else
!                Formal_Type := Etype (Formal);
! 
!                if Present (Underlying_Type (Formal_Type)) then
!                   Formal_Type := Underlying_Type (Formal_Type);
!                end if;
!             end if;
           end if;
  
           --  Create extra formal for supporting the attribute 'Constrained.
*************** package body Sem_Ch6 is
*** 9093,9104 ****
                and then (Is_Definite_Subtype (Formal_Type)
                           or else Is_Mutably_Tagged_Type (Formal_Type))
                and then (Ada_Version < Ada_2012
!                          or else No (Underlying_Type (Formal_Type))
                           or else not
                             (Is_Limited_Type (Formal_Type)
                               and then
!                                Is_Tagged_Type
!                                  (Underlying_Type (Formal_Type))))
              then
                 Set_Extra_Constrained
                   (Formal, Add_Extra_Formal (Formal, Standard_Boolean, E, "O"));
--- 9211,9223 ----
                and then (Is_Definite_Subtype (Formal_Type)
                           or else Is_Mutably_Tagged_Type (Formal_Type))
                and then (Ada_Version < Ada_2012
!                          or else
!                            (not Can_Be_Deferred
!                              and then No (Underlying_Type (Formal_Type)))
                           or else not
                             (Is_Limited_Type (Formal_Type)
                               and then
!                                Is_Tagged_Type (Formal_Type)))
              then
                 Set_Extra_Constrained
                   (Formal, Add_Extra_Formal (Formal, Standard_Boolean, E, "O"));
*************** package body Sem_Ch6 is
*** 9337,9342 ****
--- 9456,9463 ----
           Set_Extra_Formals (Alias (E), Extra_Formals (E));
        end if;
  
+       Freeze_Extra_Formals (E);
+ 
        pragma Assert (No (Alias_Subp)
          or else Extra_Formals_Match_OK (E, Alias_Subp));
  
*************** package body Sem_Ch6 is
*** 9651,9656 ****
--- 9772,9790 ----
                    return False;
                 end if;
  
+             --  Extra formals (A and B) of Unchecked_Unions (see Build_Variant_
+             --  Record_Equality)
+ 
+             elsif Has_Suffix (Formal_1, 'A') then
+                if not Has_Suffix (Formal_2, 'A') then
+                   return False;
+                end if;
+ 
+             elsif Has_Suffix (Formal_1, 'B') then
+                if not Has_Suffix (Formal_2, 'B') then
+                   return False;
+                end if;
+ 
              elsif BIP_Suffix_Kind (Formal_1) /= BIP_Suffix_Kind (Formal_2) then
                 return False;
              end if;
*************** package body Sem_Ch6 is
*** 10003,10008 ****
--- 10137,10152 ----
        return Empty;
     end Find_Corresponding_Spec;
  
+    --------------------------
+    -- Freeze_Extra_Formals --
+    --------------------------
+ 
+    procedure Freeze_Extra_Formals (E : Entity_Id) is
+    begin
+       pragma Assert (not Extra_Formals_Known (E));
+       Set_Extra_Formals_Known (E);
+    end Freeze_Extra_Formals;
+ 
     ----------------------
     -- Fully_Conformant --
     ----------------------
*************** package body Sem_Ch6 is
*** 10622,10627 ****
--- 10766,10775 ----
        Formal : Entity_Id := First_Formal_With_Extras (E);
  
     begin
+       --  It makes no sense to perform this check if the extra formals
+       --  have not been added.
+       pragma Assert (Extra_Formals_Known (E));
+ 
        while Present (Formal) loop
           if Is_Build_In_Place_Entity (Formal) then
              return True;
*************** package body Sem_Ch6 is
*** 12795,12800 ****
--- 12943,13472 ----
           end if;
     end New_Overloaded_Entity;
  
+    ------------------------------------
+    -- Deferred_Extra_Formals_Support --
+    ------------------------------------
+ 
+    package body Deferred_Extra_Formals_Support is
+       Calls_List       : Elist_Id := No_Elist;
+       Calls_Scope_List : Elist_Id := No_Elist;
+       --  Calls to subprograms or entries with some unknown underlying type
+       --  in their parameters or result type, and the scope where each call
+       --  is performed.
+ 
+       Entities_List    : Elist_Id := No_Elist;
+       --  Subprograms, entries, and subprogram types with some unknown
+       --  underlying type in their formals or result type.
+ 
+       Types_List       : Elist_Id := No_Elist;
+       --  Types with no underlying type
+ 
+       function Underlying_Types_Available (E : Entity_Id) return Boolean;
+       --  Determines if the underlying type of all the formals and result
+       --  type of the given subprogram, subprogram type, or entry are
+       --  available.
+ 
+       -------------------------------
+       -- Add_Deferred_Extra_Params --
+       -------------------------------
+ 
+       procedure Add_Deferred_Extra_Params (Typ : Entity_Id) is
+ 
+          procedure Check_Registered_Calls;
+          --  Check all the registered calls; for each registered call that
+          --  has the underlying type of all the parameters and result types
+          --  of the called entity available, call Create_Extra_Actuals, and
+          --  unregister the call.
+ 
+          procedure Check_Registered_Entities;
+          --  Check all the registered entities (subprograms, entries and
+          --  subprogram types); for each registered entity E that has all
+          --  its underlying types available, call Create_Extra_Formals,
+          --  and unregister E.
+ 
+          ----------------------------
+          -- Check_Registered_Calls --
+          ----------------------------
+ 
+          procedure Check_Registered_Calls is
+ 
+             function Get_Relocated_Function_Call (N : Node_Id) return Node_Id;
+             --  Given a node N that references a function call that has been
+             --  relocated to remove possible side effects of the call (see
+             --  Remove_Side_Effects) or to wrap the call in a transient scope
+             --  (see Wrap_Transient_Expression), search and return the function
+             --  call. Notice that this function does not use the Original_Node
+             --  field of N; it searchs for the actual call associated with N
+             --  in the expanded code (since we need to add to such call its
+             --  missing extra actuals).
+ 
+             ---------------------------------
+             -- Get_Relocated_Function_Call --
+             ---------------------------------
+ 
+             function Get_Relocated_Function_Call (N : Node_Id) return Node_Id
+             is
+                Current_Node : Node_Id;
+                Decl         : Node_Id;
+                Id           : Entity_Id;
+ 
+             begin
+                Current_Node := N;
+ 
+                while Nkind (Current_Node) /= N_Function_Call loop
+                   case Nkind (Current_Node) is
+                      when N_Identifier =>
+                         Id   := Entity (Current_Node);
+                         Decl := Parent (Id);
+ 
+                         if Nkind (Decl) = N_Object_Renaming_Declaration then
+                            Current_Node := Name (Decl);
+ 
+                         else
+                            pragma Assert (Nkind (Decl) = N_Object_Declaration);
+ 
+                            if Present (Expression (Decl)) then
+                               Current_Node := Expression (Decl);
+ 
+                            elsif Present (BIP_Initialization_Call (Id)) then
+                               Decl := BIP_Initialization_Call (Id);
+                               pragma Assert (Present (Expression (Decl)));
+                               Current_Node := Expression (Decl);
+ 
+                            elsif Present (Related_Expression (Id)) then
+                               Current_Node := Related_Expression (Id);
+ 
+                            else
+                               pragma Assert (False);
+                               raise Program_Error;
+                            end if;
+                         end if;
+ 
+                      when N_Explicit_Dereference | N_Reference =>
+                         Current_Node := Prefix (Current_Node);
+ 
+                      when others =>
+                         pragma Assert (False);
+                         raise Program_Error;
+                   end case;
+                end loop;
+ 
+                return Current_Node;
+             end Get_Relocated_Function_Call;
+ 
+             --  Local variables
+ 
+             Call_Node        : Node_Id;
+             Call_Id          : Entity_Id;
+             Elmt_Call        : Elmt_Id;
+             Elmt_Scope       : Elmt_Id;
+             Remove_Call      : Boolean;
+             Scop_Id          : Entity_Id;
+ 
+          --  Start of processing for Check_Registered_Calls
+ 
+          begin
+             --  Perform a single traversal of both lists simultaneously,
+             --  since they have the same number of elements with a 1-to-1
+             --  relationship.
+ 
+             Elmt_Scope := First_Elmt (Calls_Scope_List);
+             Elmt_Call  := First_Elmt (Calls_List);
+ 
+             while Present (Elmt_Scope) loop
+                Scop_Id     := Node (Elmt_Scope);
+                Remove_Call := False;
+ 
+                --  Check the enclosing scope of the call: if the underlying
+                --  type of some formal or return type of the enclosing scope
+                --  of this call is not available then we must skip processing
+                --  this call.
+ 
+                if Underlying_Types_Available (Scop_Id) then
+                   Call_Node := Node (Elmt_Call);
+ 
+                   if Nkind (Call_Node) in N_Entry_Call_Statement
+                                         | N_Function_Call
+                                         | N_Procedure_Call_Statement
+                   then
+                      Call_Id := Get_Called_Entity (Call_Node);
+ 
+                   --  Handle expanded function calls that could have side
+                   --  effects.
+ 
+                   else
+                      pragma Assert
+                        (Nkind (Original_Node (Call_Node)) = N_Function_Call);
+ 
+                      Call_Node := Get_Relocated_Function_Call (Call_Node);
+                      Call_Id := Get_Called_Entity (Call_Node);
+                   end if;
+ 
+                   --  If the underlying types of all the formal and return
+                   --  types of this called entity are available then create
+                   --  its extra actuals and remove it from the list of
+                   --  registered calls.
+ 
+                   if Underlying_Types_Available (Call_Id) then
+ 
+                      --  Given that the call is placed in the body of an
+                      --  internally built subprogram, ensure that the extra
+                      --  formals of the enclosing scope are available before
+                      --  adding the extra actuals of this call.
+ 
+                      Create_Extra_Formals (Scop_Id);
+                      Create_Extra_Formals (Call_Id);
+ 
+                      pragma Assert (Extra_Formals_Known (Scop_Id));
+                      pragma Assert (Extra_Formals_Known (Call_Id));
+ 
+                      --  Mark functions that return a result by reference
+ 
+                      Compute_Returns_By_Ref (Scop_Id);
+                      Compute_Returns_By_Ref (Call_Id);
+ 
+                      Push_Scope (Scop_Id);
+                      Create_Extra_Actuals (Call_Node);
+                      Pop_Scope;
+ 
+                      Remove_Call := True;
+                   end if;
+                end if;
+ 
+                --  In order to safely remove these elements from their
+                --  containing lists, remember these elements before moving
+                --  to the next list elements.
+ 
+                if Remove_Call then
+                   declare
+                      Removed_Call  : constant Elmt_Id := Elmt_Call;
+                      Removed_Scope : constant Elmt_Id := Elmt_Scope;
+ 
+                   begin
+                      Next_Elmt (Elmt_Scope);
+                      Next_Elmt (Elmt_Call);
+ 
+                      Remove_Elmt (Calls_List, Removed_Call);
+                      Remove_Elmt (Calls_Scope_List, Removed_Scope);
+                   end;
+                else
+                   Next_Elmt (Elmt_Scope);
+                   Next_Elmt (Elmt_Call);
+                end if;
+ 
+             end loop;
+          end Check_Registered_Calls;
+ 
+          -------------------------------
+          -- Check_Registered_Entities --
+          -------------------------------
+ 
+          procedure Check_Registered_Entities is
+             Elmt       : Elmt_Id;
+             Found_Elmt : Elmt_Id;
+             Id         : Entity_Id;
+ 
+          begin
+             Elmt := First_Elmt (Entities_List);
+ 
+             while Present (Elmt) loop
+                Id := Node (Elmt);
+ 
+                --  If the underlying type of some formal or return type of this
+                --  entity is not available then skip this element.
+ 
+                if not Underlying_Types_Available (Id) then
+                   Next_Elmt (Elmt);
+ 
+                --  Otherwise, create its extra formals and remove it from the
+                --  list of entities that require adding the extra formals.
+ 
+                else
+                   --  In order to safely remove this element from the list,
+                   --  temporarily remember this element, and move to the next
+                   --  element.
+ 
+                   Found_Elmt := Elmt;
+                   Next_Elmt (Elmt);
+ 
+                   --  Create the extra formals, and mark functions that return
+                   --  by reference (not be done before if the underying return
+                   --  type was previously unknown).
+ 
+                   Create_Extra_Formals (Id);
+                   Compute_Returns_By_Ref (Id);
+ 
+                   Remove_Elmt (Entities_List, Found_Elmt);
+ 
+                   --  For deferred entries and entry families, the expansion of
+                   --  their entry declaration was deferred, and must be done
+                   --  now (after adding their extra formals).
+ 
+                   if Ekind (Id) in E_Entry | E_Entry_Family then
+                      Expand_N_Entry_Declaration (Parent (Id),
+                        Was_Deferred => True);
+                   end if;
+                end if;
+             end loop;
+          end Check_Registered_Entities;
+ 
+       --  Start of processing for Add_Deferred_Extra_Params
+ 
+       begin
+          pragma Assert (Present (Underlying_Type (Typ)));
+ 
+          if Present (Entities_List) then
+             Check_Registered_Entities;
+          end if;
+ 
+          if Present (Calls_List) then
+             Check_Registered_Calls;
+          end if;
+ 
+          Remove (Types_List, Typ);
+       end Add_Deferred_Extra_Params;
+ 
+       --------------------------------
+       -- Has_Deferred_Extra_Formals --
+       --------------------------------
+ 
+       function Has_Deferred_Extra_Formals (Typ : Entity_Id) return Boolean is
+       begin
+          return Contains (Types_List, Typ);
+       end Has_Deferred_Extra_Formals;
+ 
+       --------------------------------------
+       -- Is_Deferred_Extra_Formals_Entity --
+       --------------------------------------
+ 
+       function Is_Deferred_Extra_Formals_Entity
+         (Id : Entity_Id) return Boolean is
+       begin
+          return Contains (Entities_List, Id);
+       end Is_Deferred_Extra_Formals_Entity;
+ 
+       ---------------------------------------
+       -- Is_Unsupported_Extra_Actuals_Call --
+       ---------------------------------------
+ 
+       --  Similarly to Is_Unsupported_Extra_Formals_Entity, we cannot
+       --  determine if the extra formals are needed when the underlying
+       --  type of some formal or result type is not available, and we are
+       --  compiling the body of a subprogram or package. However, for calls
+       --  we must also handle internal calls generated by the compiler as
+       --  part of compiling a package spec. For example, internal calls
+       --  performed in thunks of secondary dispatch table entries.
+       --
+       --  Example
+       --  -------
+       --  package P is
+       --     type T is tagged null record;
+       --  end;
+       --
+       --  limited with P;
+       --  package Q is
+       --     type Iface is interface;
+       --     procedure Prim (Self : Iface; Current : P.T) is abstract;
+       --  end;
+       --
+       --  limited with P;
+       --  with Q;
+       --  package R is
+       --     type Root is tagged null record;
+       --     type DT is new Root and Q.Iface with null record;
+       --
+       --     procedure Prim (Self : DT; Current : P.T);
+       --  end;
+       --
+       --  The initialization of the secondary dispatch table of tagged type
+       --  DT has an internally generated thunk that displaces the pointer to
+       --  the object and calls the primitive Prim (and the underlying type
+       --  of type T is not available).
+ 
+       function Is_Unsupported_Extra_Actuals_Call
+         (Call_Node : Node_Id; Id : Entity_Id) return Boolean
+       is
+          Comp_Unit : constant Entity_Id :=
+                        Cunit_Entity (Get_Source_Unit (Call_Node));
+       begin
+          return not Underlying_Types_Available (Id)
+            and then Is_Compilation_Unit (Comp_Unit)
+            and then Ekind (Comp_Unit) in E_Package
+                                        | E_Package_Body
+                                        | E_Subprogram_Body;
+       end Is_Unsupported_Extra_Actuals_Call;
+ 
+       -----------------------------------------
+       -- Is_Unsupported_Extra_Formals_Entity --
+       -----------------------------------------
+ 
+       --  We cannot determine if the extra formals are needed when the
+       --  underlying type of some formal or result type is not available,
+       --  and we are compiling the body of a subprogram or package. The
+       --  scenery for this case is a package spec that has a limited_with_
+       --  clause on unit Q, and its body has no regular with-clause on Q
+       --  (AI05-0151-1/08).
+ 
+       function Is_Unsupported_Extra_Formals_Entity
+         (Id : Entity_Id) return Boolean
+       is
+          Comp_Unit : constant Entity_Id :=
+                        Cunit_Entity (Get_Source_Unit (Id));
+       begin
+          return not Underlying_Types_Available (Id)
+            and then Is_Compilation_Unit (Comp_Unit)
+            and then Ekind (Comp_Unit) in E_Package_Body
+                                        | E_Subprogram_Body;
+       end Is_Unsupported_Extra_Formals_Entity;
+ 
+       --------------------------------------------
+       -- Register_Deferred_Extra_Formals_Entity --
+       --------------------------------------------
+ 
+       procedure Register_Deferred_Extra_Formals_Entity (Id : Entity_Id) is
+ 
+          procedure Register_Type (Typ : Entity_Id);
+          --  Register the given type in Types_List; for types visible though
+          --  limited_with_clauses, register their non-limited view.
+ 
+          -------------------
+          -- Register_Type --
+          -------------------
+ 
+          procedure Register_Type (Typ : Entity_Id) is
+          begin
+             --  Handle entities visible through limited_with_clauses
+ 
+             if Has_Non_Limited_View (Typ) then
+                Append_Unique_Elmt (Non_Limited_View (Typ), Types_List);
+             else
+                Append_Unique_Elmt (Typ, Types_List);
+             end if;
+          end Register_Type;
+ 
+          --  Local variables
+ 
+          Formal : Entity_Id;
+ 
+       --  Start of processing for Register_Deferred_Extra_Formals_Entity
+ 
+       begin
+          pragma Assert (Is_Subprogram_Or_Entry (Id)
+            or else Ekind (Id) in E_Subprogram_Type);
+ 
+          if not Is_Deferred_Extra_Formals_Entity (Id) then
+             if No (Types_List) then
+                Types_List := New_Elmt_List;
+             end if;
+ 
+             if No (Entities_List) then
+                Entities_List := New_Elmt_List;
+             end if;
+ 
+             --  Register all the types of the subprogram profile that are not
+             --  fully known.
+ 
+             Formal := First_Formal (Id);
+             while Present (Formal) loop
+ 
+                if No (Underlying_Type (Etype (Formal))) then
+                   Register_Type (Etype (Formal));
+                end if;
+ 
+                Next_Formal (Formal);
+             end loop;
+ 
+             if Ekind (Id) in E_Function | E_Subprogram_Type
+               and then No (Underlying_Type (Etype (Id)))
+             then
+                Register_Type (Etype (Id));
+             end if;
+ 
+             --  Register this subprogram
+ 
+             Append_Elmt (Id, Entities_List);
+          end if;
+       end Register_Deferred_Extra_Formals_Entity;
+ 
+       ------------------------------------------
+       -- Register_Deferred_Extra_Formals_Call --
+       ------------------------------------------
+ 
+       procedure Register_Deferred_Extra_Formals_Call
+         (Call_Node : Node_Id;
+          Scope_Id  : Entity_Id) is
+       begin
+          pragma Assert (Nkind (Call_Node) in N_Subprogram_Call
+                                            | N_Entry_Call_Statement);
+          if No (Calls_List) then
+             Calls_List := New_Elmt_List;
+             Calls_Scope_List := New_Elmt_List;
+          end if;
+ 
+          --  Avoid registering any call twice; this may occur in dispatching
+          --  calls with deferred extra actuals because Expand_Call_Helper
+          --  registers the call and invokes Expand_Dispatching_Call (which
+          --  tries again to register the expanded call).
+ 
+          if not Contains (Calls_List, Call_Node) then
+             Append_Elmt (Call_Node, Calls_List);
+             Append_Elmt (Scope_Id, Calls_Scope_List);
+          end if;
+       end Register_Deferred_Extra_Formals_Call;
+ 
+       --------------------------------
+       -- Underlying_Types_Available --
+       --------------------------------
+ 
+       function Underlying_Types_Available (E : Entity_Id) return Boolean is
+          Formal     : Entity_Id;
+          Formal_Typ : Entity_Id;
+          Func_Typ   : Entity_Id;
+ 
+       begin
+          --  If the extra formals are available, then the nonlimited view
+          --  of all the types referenced in the profile are available.
+ 
+          if Extra_Formals_Known (E) then
+             return True;
+          end if;
+ 
+          --  Check the return type
+ 
+          if Ekind (E) in E_Function | E_Subprogram_Type then
+             Func_Typ := Etype (E);
+ 
+             if Has_Non_Limited_View (Func_Typ) then
+                Func_Typ := Non_Limited_View (Func_Typ);
+             end if;
+ 
+             if No (Underlying_Type (Func_Typ)) then
+                return False;
+             end if;
+          end if;
+ 
+          --  Check the type of the formals
+ 
+          Formal := First_Formal (E);
+          while Present (Formal) loop
+             Formal_Typ := Etype (Formal);
+ 
+             if Has_Non_Limited_View (Formal_Typ) then
+                Formal_Typ := Non_Limited_View (Formal_Typ);
+             end if;
+ 
+             if No (Underlying_Type (Formal_Typ)) then
+                return False;
+             end if;
+ 
+             Next_Formal (Formal);
+          end loop;
+ 
+          return True;
+       end Underlying_Types_Available;
+ 
+    end Deferred_Extra_Formals_Support;
+ 
     ---------------------
     -- Process_Formals --
     ---------------------
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_ch6.ads gcc-16-20250727/gcc/ada/sem_ch6.ads
*** gcc-16-20250720/gcc/ada/sem_ch6.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_ch6.ads	Sun Jul 27 22:32:08 2025
*************** package Sem_Ch6 is
*** 190,195 ****
--- 190,203 ----
     --  Use the subprogram specification in the body to retrieve the previous
     --  subprogram declaration, if any.
  
+    procedure Freeze_Extra_Formals (E : Entity_Id);
+    --  Given a subprogram, subprogram type, or entry, flag E to indicate that
+    --  its extra formals (if any) are known (by setting Extra_Formals_Known).
+    --  This subprogram serves three purposes: (1) Document the places where
+    --  the extra formals are known, (2) Ensure that extra formals are added
+    --  only once, and (3) Provide a convenient place for setting a debugger
+    --  breakpoint to locate when extra formals are known.
+ 
     function Fully_Conformant (New_Id, Old_Id : Entity_Id) return Boolean;
     --  Determine whether two callable entities (subprograms, entries,
     --  literals) are fully conformant (RM 6.3.1(17))
*************** package Sem_Ch6 is
*** 299,302 ****
--- 307,462 ----
     procedure Valid_Operator_Definition (Designator : Entity_Id);
     --  Verify that an operator definition has the proper number of formals
  
+    ------------------------------------
+    -- Deferred_Extra_Formals_Support --
+    ------------------------------------
+ 
+    --  This package provides support for deferring the addition of extra
+    --  formals to subprograms, entries, and subprogram types; it also provides
+    --  support for deferring the addition of extra actuals to direct calls to
+    --  subprograms and entries, and indirect calls through subprogram types.
+    --  The addition of the extra formals and actuals is deferred until the
+    --  underlying type of all the parameters and result types of registered
+    --  subprograms, entries, and subprogram types is known.
+ 
+    --  Functional Description
+    --  ----------------------
+    --
+    --  When Create_Extra_Formals identifies that the underlying type of
+    --  some parameter or result type of an entity E is not available, E is
+    --  registered by this package, and the addition of its extra formals is
+    --  deferred. As part of this registration, the types of all the params
+    --  and result types of E with no underlying type are also registered.
+    --
+    --  When Expand_Call_Helper identifies that the underlying type of some
+    --  parameter or result type of a called entity is not available, the call
+    --  is registered by Register_Deferred_Extra_Formals_Call, and the addition
+    --  of its extra actuals is deferred.
+    --
+    --  When the full type declaration of some registered type T is analyzed,
+    --  the subprogram Add_Deferred_Extra_Params is invoked; this subprogram
+    --  does the following actions:
+    --    1) Check all the registered entities (subprograms, entries, and
+    --       subprogram types); for each registered entity that has all its
+    --       underlying types available, call Create_Extra_Formals, and
+    --       unregister the entity.
+    --    2) Check all the registered calls; for each registered call that
+    --       has available the underlying type of all the parameters and result
+    --       types of the called entity, call Create_Extra_Actuals, and
+    --       unregister the call.
+    --    3) Unregister T.
+    --
+    --  Example 1
+    --  ---------
+    --  A package spec has a private type declaration T, and declarations of
+    --  expression functions and/or primitives with class-wide conditions
+    --  invoking primitives of type T before the full view of T is defined.
+    --
+    --  As part of processing the early freezing of the called subprograms
+    --  (and as part of processing the calls) the functions are registered as
+    --  subprograms with deferred extra formals, and the calls are registered
+    --  as calls with deferred extra actuals.
+    --
+    --  When the full type declaration of T is analyzed, extra formals are
+    --  added to all the registered subprograms, and extra actuals are added
+    --  to all the registered calls with deferred extra actuals.
+    --
+    --  Example 2
+    --  ---------
+    --  The specification of package P has a limited_with_clause on package Q,
+    --  and the type of the formals of subprograms defined in P are types
+    --  defined in Q.
+    --
+    --  When compiling the spec of P, similarly to the previous example,
+    --  subprograms with incomplete formals are registered as subprograms
+    --  with deferred extra formals; if the spec of P has calls to these
+    --  subprograms, then these calls are registered as calls with deferred
+    --  extra actuals. That is, when the analysis of package P completes,
+    --  deferred extra formals and actuals have not been added.
+    --
+    --  When another compilation unit is analyzed (including the body of
+    --  package P), and a regular with-clause on Q is processed, when the
+    --  full type declaration of deferred entities is analyzed, deferred
+    --  extra formals and deferred extra actuals are added.
+    --
+    --  This machinery relies on the GNAT Compilation Model; that is, when
+    --  we analyze the spec of P (for which we generally don't generate code),
+    --  it is safe to complete the compilation and still have entities with
+    --  deferred extra formals, and calls with deferred extra actuals.
+    --
+    --  The body package P generally has a regular with-clause on package Q.
+    --  Hence, when we compile the body of package P, the implicit dependence
+    --  on its package spec causes the analysis of the spec of P (thus
+    --  registering deferred entities), followed by the analysis of context
+    --  clauses in the body of P. When the regular with-clause on package Q
+    --  is analyzed, we add the extra formals and extra actuals to deferred
+    --  entities. Thus, the generated code will have all the needed formals.
+    --
+    --  The (still) unsupported case is when the body of package P does not
+    --  have a regular with-clause on package Q (AI05-0151-1/08). This case
+    --  is left documented in the front-end sources by means of calls to
+    --  the following subprograms: Is_Unsupported_Extra_Formals_Entity, and
+    --  Is_Unsupported_Extra_Actuals_Call.
+ 
+    package Deferred_Extra_Formals_Support is
+ 
+       procedure Add_Deferred_Extra_Params (Typ : Entity_Id);
+       --  Check all the registered subprograms, entries, and subprogram types
+       --  with deferred addition of their extra formals; if the underlying
+       --  types of all their formals is available then add their extra formals.
+       --  Check also all the registered calls with deferred addition of their
+       --  extra actuals; add their extra actuals if the underlying types of all
+       --  their parameters and result types are available. Finally unregister
+       --  Typ from the list of types used for the deferral of extra formals/
+       --  actuals.
+ 
+       procedure Register_Deferred_Extra_Formals_Entity (Id : Entity_Id);
+       --  Register the given subprogram, entry, or subprogram type to defer the
+       --  addition of its extra formals.
+ 
+       procedure Register_Deferred_Extra_Formals_Call
+         (Call_Node : Node_Id;
+          Scope_Id  : Entity_Id);
+       --  Register the given call, performed from the given scope, to defer the
+       --  addition of its extra actuals.
+ 
+       function Has_Deferred_Extra_Formals (Typ : Entity_Id) return Boolean;
+       --  Return True if there some registered subprogram, subprogram type, or
+       --  entry with deferred extra formals that has some formal type or
+       --  result type of type Typ (i.e. which depends on the given type to
+       --  add its extra formals).
+ 
+       function Is_Deferred_Extra_Formals_Entity
+         (Id : Entity_Id) return Boolean;
+       --  Return True if Id is a subprogram, subprogram type, or entry that has
+       --  been registered to defer the addition of its extra formals.
+ 
+       function Is_Unsupported_Extra_Formals_Entity
+         (Id : Entity_Id) return Boolean;
+       --  Id is a subprogram, subprogram type, or entry. Return True if Id is
+       --  unsupported for deferring the addition of its extra formals; that is,
+       --  it is defined in a compilation unit that is a package body or a
+       --  subprogram body, and the underlying type of some of its parameters
+       --  or result type is not available.
+       --
+       --  The context for this case is an unsupported case of AI05-0151-1/08
+       --  that allows incomplete tagged types as parameter and result types.
+       --  More concretely, a type T is visible in a package spec through a
+       --  limited_with_clause, and the body of the package has no regular
+       --  with_clause. In such a case, the machinery for deferring the
+       --  addition of extra formals does not work because the underlying
+       --  type of the type is not seen during the compilation of the
+       --  package body.
+       --
+       --  The purpose of this function is to facilitate locating in the sources
+       --  the places where the front end performs the current (incomplete)
+       --  management of such case (to facilitate further work) ???
+ 
+       function Is_Unsupported_Extra_Actuals_Call
+         (Call_Node : Node_Id; Id : Entity_Id) return Boolean;
+       --  Same as previous function but applicable to a call to the given
+       --  entity Id.
+ 
+    end Deferred_Extra_Formals_Support;
+ 
  end Sem_Ch6;
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_ch8.adb gcc-16-20250727/gcc/ada/sem_ch8.adb
*** gcc-16-20250720/gcc/ada/sem_ch8.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_ch8.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Ch8 is
*** 5444,5450 ****
           elsif In_Open_Scopes (Scope (Base_Type (T))) then
              null;
  
!          elsif not Redundant_Use (Id) then
              Set_In_Use (T, False);
              Set_In_Use (Base_Type (T), False);
              Set_Current_Use_Clause (T, Empty);
--- 5444,5458 ----
           elsif In_Open_Scopes (Scope (Base_Type (T))) then
              null;
  
!          --  Turn off the use_type_clause on the type unless the clause is
!          --  redundant, or there's a previous use_type_clause. (The case where
!          --  a use_type_clause without "all" is followed by one with "all" in
!          --  a more nested scope is not considered redundant, necessitating
!          --  the test for a previous clause. One might expect the latter test
!          --  to suffice, but it turns out there are cases where Redundant_Use
!          --  is set, but Prev_Use_Clause is not set. ???)
! 
!          elsif not Redundant_Use (Id) and then No (Prev_Use_Clause (N)) then
              Set_In_Use (T, False);
              Set_In_Use (Base_Type (T), False);
              Set_Current_Use_Clause (T, Empty);
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_ch9.adb gcc-16-20250727/gcc/ada/sem_ch9.adb
*** gcc-16-20250720/gcc/ada/sem_ch9.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_ch9.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Ch9 is
*** 1700,1705 ****
--- 1700,1711 ----
           Process_Formals (Formals, N);
           Create_Extra_Formals (Def_Id);
           End_Scope;
+ 
+       --  If the entry has no formals, extra formals are definitely not
+       --  required.
+ 
+       else
+          Freeze_Extra_Formals (Def_Id);
        end if;
  
        if Ekind (Def_Id) = E_Entry then
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_disp.adb gcc-16-20250727/gcc/ada/sem_disp.adb
*** gcc-16-20250720/gcc/ada/sem_disp.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_disp.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Disp is
*** 2416,2421 ****
--- 2416,2423 ----
        Formal    : Entity_Id;
        Ctrl_Type : Entity_Id;
  
+    --  Start of processing for Find_Dispatching_Type
+ 
     begin
        if Ekind (Subp) in E_Function | E_Procedure
          and then Present (DTC_Entity (Subp))
*************** package body Sem_Disp is
*** 3083,3088 ****
--- 3085,3136 ----
        then
           return Is_Tag_Indeterminate (Prefix (Orig_Node));
  
+       --  An if-expression is tag-indeterminate if all of the dependent
+       --  expressions are tag-indeterminate (RM 4.5.7 (17/3)).
+ 
+       elsif Nkind (Orig_Node) = N_If_Expression then
+          declare
+             Cond : constant Node_Id := First (Expressions (Orig_Node));
+             Expr : Node_Id := Next (Cond);
+ 
+          begin
+             if not Is_Tag_Indeterminate (Original_Node (Expr)) then
+                return False;
+             end if;
+ 
+             Next (Expr);
+ 
+             if Present (Expr)
+               and then not Is_Tag_Indeterminate (Original_Node (Expr))
+             then
+                return False;
+             end if;
+ 
+             return True;
+          end;
+ 
+       --  A case-expression is tag-indeterminate if all of the dependent
+       --  expressions are tag-indeterminate (RM 4.5.7 (17/3)).
+ 
+       elsif Nkind (Orig_Node) = N_Case_Expression then
+          declare
+             Alt  : Node_Id := First (Alternatives (Orig_Node));
+             Expr : Node_Id;
+ 
+          begin
+             while Present (Alt) loop
+                Expr := Expression (Alt);
+ 
+                if not Is_Tag_Indeterminate (Original_Node (Expr)) then
+                   return False;
+                end if;
+ 
+                Next (Alt);
+             end loop;
+ 
+             return True;
+          end;
+ 
        else
           return False;
        end if;
*************** package body Sem_Disp is
*** 3243,3248 ****
--- 3291,3297 ----
        elsif Nkind (Actual) = N_Explicit_Dereference
          and then Nkind (Original_Node (Prefix (Actual))) = N_Function_Call
        then
+          pragma Assert (Is_Expanded_Dispatching_Call (Actual));
           return;
  
        --  When expansion is suppressed, an unexpanded call to 'Input can occur,
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_res.adb gcc-16-20250727/gcc/ada/sem_res.adb
*** gcc-16-20250720/gcc/ada/sem_res.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_res.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Res is
*** 7270,7276 ****
  
        if Restriction_Check_Required (No_Relative_Delay)
          and then Is_RTE (Nam, RE_Set_Handler)
!         and then Is_RTE (Etype (Next_Actual (First_Actual (N))), RE_Time_Span)
        then
           Check_Restriction (No_Relative_Delay, N);
        end if;
--- 7270,7278 ----
  
        if Restriction_Check_Required (No_Relative_Delay)
          and then Is_RTE (Nam, RE_Set_Handler)
!         and then
!           Is_RTE
!             (Base_Type (Etype (Next_Actual (First_Actual (N)))), RE_Time_Span)
        then
           Check_Restriction (No_Relative_Delay, N);
        end if;
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_util.adb gcc-16-20250727/gcc/ada/sem_util.adb
*** gcc-16-20250720/gcc/ada/sem_util.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_util.adb	Sun Jul 27 22:32:08 2025
*************** package body Sem_Util is
*** 3706,3711 ****
--- 3706,3712 ----
             Aspect_Aggregate,
             Aspect_Max_Entry_Queue_Length
             --  , Aspect_No_Controlled_Parts
+            --  , Aspect_No_Task_Parts
            );
  
        --  Note that none of these 8 aspects can be specified (for a type)
*************** package body Sem_Util is
*** 10061,10076 ****
             and then not Has_Unknown_Discriminants (Utyp)
             and then not (Ekind (Utyp) = E_String_Literal_Subtype)
        then
!          --  Nothing to do if in spec expression (why not???)
  
!          if In_Spec_Expression then
              return Typ;
  
!          elsif Is_Private_Type (Typ) and then not Has_Discriminants (Typ) then
! 
!             --  If the type has no discriminants, there is no subtype to
!             --  build, even if the underlying type is discriminated.
  
              return Typ;
  
           --  Else build the actual subtype
--- 10062,10080 ----
             and then not Has_Unknown_Discriminants (Utyp)
             and then not (Ekind (Utyp) = E_String_Literal_Subtype)
        then
!          --  If the type has no discriminants, there is no subtype to build,
!          --  even if the underlying type is discriminated.
  
!          if Is_Private_Type (Typ) and then not Has_Discriminants (Typ) then
              return Typ;
  
!          --  If we are performing preanalysis on a conjured-up copy of a name
!          --  (see calls to Preanalyze_Range in sem_ch5.adb) then we don't want
!          --  to freeze Atyp, now or ever. In this case, the tree we eventually
!          --  pass to the back end should contain no references to Atyp (and a
!          --  freeze node would contain such a reference).
  
+          elsif not (Expander_Active or GNATprove_Mode) then
              return Typ;
  
           --  Else build the actual subtype
*************** package body Sem_Util is
*** 10086,10127 ****
  
              Atyp := Defining_Identifier (Decl);
  
!             --  If Build_Actual_Subtype generated a new declaration then use it
! 
!             if Atyp /= Typ then
! 
!                --  The actual subtype is an Itype, so analyze the declaration,
!                --  but do not attach it to the tree, to get the type defined.
! 
!                Set_Parent (Decl, N);
!                Set_Is_Itype (Atyp);
!                Analyze (Decl, Suppress => All_Checks);
!                Set_Associated_Node_For_Itype (Atyp, N);
!                if Expander_Active then
!                   Set_Has_Delayed_Freeze (Atyp, False);
! 
!                   --  We need to freeze the actual subtype immediately. This is
!                   --  needed because otherwise this Itype will not get frozen
!                   --  at all; it is always safe to freeze on creation because
!                   --  any associated types must be frozen at this point.
! 
!                   --  On the other hand, if we are performing preanalysis on
!                   --  a conjured-up copy of a name (see calls to
!                   --  Preanalyze_Range in sem_ch5.adb) then we don't want
!                   --  to freeze Atyp, now or ever. In this case, the tree
!                   --  we eventually pass to the back end should contain no
!                   --  references to Atyp (and a freeze node would contain
!                   --  such a reference). That's why Expander_Active is tested.
  
!                   Freeze_Itype (Atyp, N);
!                end if;
!                return Atyp;
  
!             --  Otherwise we did not build a declaration, so return original
  
!             else
!                return Typ;
!             end if;
           end if;
  
        --  For all remaining cases, the actual subtype is the same as
--- 10090,10110 ----
  
              Atyp := Defining_Identifier (Decl);
  
!             --  The actual subtype is an Itype, so analyze the declaration
!             --  after attaching it to the tree, to get the type defined.
  
!             Set_Parent (Decl, N);
!             Set_Is_Itype (Atyp);
!             Analyze (Decl, Suppress => All_Checks);
!             Set_Associated_Node_For_Itype (Atyp, N);
  
!             --  We need to freeze the actual subtype immediately. This is
!             --  needed because otherwise this Itype will not get frozen
!             --  at all; it is always safe to freeze on creation because
!             --  any associated types must be frozen at this point.
  
!             Freeze_Itype (Atyp, N);
!             return Atyp;
           end if;
  
        --  For all remaining cases, the actual subtype is the same as
*************** package body Sem_Util is
*** 15035,15040 ****
--- 15018,15024 ----
                 | Aspect_Iterator_Element
                 | Aspect_Max_Entry_Queue_Length
                 | Aspect_No_Controlled_Parts
+                | Aspect_No_Task_Parts
              =>
                 return;
           end case;
*************** package body Sem_Util is
*** 16294,16301 ****
                   Names_Match (Assign_Indexed_1, Assign_Indexed_2);
              end;
  
!          --  Checking for this aspect is performed elsewhere during freezing
!          when Aspect_No_Controlled_Parts =>
              return True;
  
           --  scalar-valued aspects; compare (static) values.
--- 16278,16286 ----
                   Names_Match (Assign_Indexed_1, Assign_Indexed_2);
              end;
  
!          --  Checking for these aspects is performed elsewhere during freezing
!          when Aspect_No_Controlled_Parts
!             | Aspect_No_Task_Parts =>
              return True;
  
           --  scalar-valued aspects; compare (static) values.
*************** package body Sem_Util is
*** 21391,21396 ****
--- 21376,21393 ----
        return False;
     end Is_Unchecked_Conversion_Instance;
  
+    ---------------------------------
+    -- Is_Unchecked_Union_Equality --
+    ---------------------------------
+ 
+    function Is_Unchecked_Union_Equality (Id : Entity_Id) return Boolean is
+    begin
+       return Ekind (Id) = E_Function
+         and then Present (First_Formal (Id))
+         and then Is_Unchecked_Union (Etype (First_Formal (Id)))
+         and then Id = TSS (Etype (First_Formal (Id)), TSS_Composite_Equality);
+    end Is_Unchecked_Union_Equality;
+ 
     -------------------------------
     -- Is_Universal_Numeric_Type --
     -------------------------------
*************** package body Sem_Util is
*** 26973,26978 ****
--- 26970,26979 ----
        if Has_Relaxed_Finalization (From_Typ) then
           Set_Has_Relaxed_Finalization (Typ);
        end if;
+ 
+       if Deriv and then Has_Destructor (From_Typ) then
+          Set_Has_Destructor (Typ);
+       end if;
     end Propagate_Controlled_Flags;
  
     ------------------------------
diff -Nrcpad gcc-16-20250720/gcc/ada/sem_util.ads gcc-16-20250727/gcc/ada/sem_util.ads
*** gcc-16-20250720/gcc/ada/sem_util.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sem_util.ads	Sun Jul 27 22:32:08 2025
*************** package Sem_Util is
*** 1578,1584 ****
     --  underlying type).
  
     function Has_Suffix (E : Entity_Id; Suffix : Character) return Boolean;
!    --  Returns true if the last character of E is Suffix. Used in Assertions.
  
     function Has_Tagged_Component (Typ : Entity_Id) return Boolean;
     --  Returns True if Typ is a composite type (array or record) that is either
--- 1578,1584 ----
     --  underlying type).
  
     function Has_Suffix (E : Entity_Id; Suffix : Character) return Boolean;
!    --  Returns true if the last character of E is Suffix.
  
     function Has_Tagged_Component (Typ : Entity_Id) return Boolean;
     --  Returns True if Typ is a composite type (array or record) that is either
*************** package Sem_Util is
*** 2131,2137 ****
     --  object as per RM C.6(8).
  
     function Is_Inherited_Operation (E : Entity_Id) return Boolean;
!    --  E is a subprogram. Return True is E is an implicit operation inherited
     --  by a derived type declaration.
  
     function Is_Inlinable_Expression_Function (Subp : Entity_Id) return Boolean;
--- 2131,2137 ----
     --  object as per RM C.6(8).
  
     function Is_Inherited_Operation (E : Entity_Id) return Boolean;
!    --  E is a subprogram. Return True if E is an implicit operation inherited
     --  by a derived type declaration.
  
     function Is_Inlinable_Expression_Function (Subp : Entity_Id) return Boolean;
*************** package Sem_Util is
*** 2196,2202 ****
     --  the encapsulated expression is nontrivial.
  
     function Is_Null_Extension
!     (T : Entity_Id; Ignore_Privacy : Boolean := False) return Boolean;
     --  Given a tagged type, returns True if argument is a type extension
     --  that introduces no new components (discriminant or nondiscriminant).
     --  Ignore_Privacy should be True for use in implementing dynamic semantics.
--- 2196,2202 ----
     --  the encapsulated expression is nontrivial.
  
     function Is_Null_Extension
!      (T : Entity_Id; Ignore_Privacy : Boolean := False) return Boolean;
     --  Given a tagged type, returns True if argument is a type extension
     --  that introduces no new components (discriminant or nondiscriminant).
     --  Ignore_Privacy should be True for use in implementing dynamic semantics.
*************** package Sem_Util is
*** 2449,2454 ****
--- 2449,2458 ----
     --  Determine whether an arbitrary entity denotes an instance of function
     --  Ada.Unchecked_Conversion.
  
+    function Is_Unchecked_Union_Equality (Id : Entity_Id) return Boolean;
+    --  Determine whether an arbitrary entity denotes the predefined equality
+    --  function of an Unchecked_Union type (see Build_Variant_Record_Equality).
+ 
     function Is_Unconstrained_Or_Tagged_Item (Item : Entity_Id) return Boolean;
     --  Subsidiary to Collect_Subprogram_Inputs_Outputs and the analysis of
     --  pragma Depends. Determine whether the type of dependency item Item is
*************** package Sem_Util is
*** 2973,2983 ****
        Comp     : Boolean := False;
        Deriv    : Boolean := False);
     --  Set Disable_Controlled, Finalize_Storage_Only, Has_Controlled_Component,
!    --  Has_Relaxed_Finalization, and Is_Controlled_Active on Typ when the flags
!    --  are set on From_Typ. If Comp is True, From_Typ is assumed to be the type
!    --  of a component of Typ while, if Deriv is True, From_Typ is assumed to be
!    --  the parent type of Typ. This procedure can only set flags for Typ, and
!    --  never clear them.
  
     procedure Propagate_DIC_Attributes
       (Typ      : Entity_Id;
--- 2977,2987 ----
        Comp     : Boolean := False;
        Deriv    : Boolean := False);
     --  Set Disable_Controlled, Finalize_Storage_Only, Has_Controlled_Component,
!    --  Has_Destructor, Has_Relaxed_Finalization, and Is_Controlled_Active on
!    --  Typ when the flags are set on From_Typ. If Comp is True, From_Typ is
!    --  assumed to be the type of a component of Typ while, if Deriv is True,
!    --  From_Typ is assumed to be the parent type of Typ. This procedure can
!    --  only set flags for Typ, and never clear them.
  
     procedure Propagate_DIC_Attributes
       (Typ      : Entity_Id;
diff -Nrcpad gcc-16-20250720/gcc/ada/sinfo.ads gcc-16-20250727/gcc/ada/sinfo.ads
*** gcc-16-20250720/gcc/ada/sinfo.ads	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sinfo.ads	Sun Jul 27 22:32:08 2025
*************** package Sinfo is
*** 402,417 ****
     --       Has_Secondary_Private_View  set in generic units
  
     --    "plus fields for expression"
!    --       Paren_Count               number of parentheses levels
!    --       Etype                     type of the expression
!    --       Is_Overloaded             >1 type interpretation exists
!    --       Is_Static_Expression      set for static expression
!    --       Raises_Constraint_Error   evaluation raises CE
!    --       Must_Not_Freeze           set if must not freeze
!    --       Do_Range_Check            set if a range check needed
!    --       Has_Dynamic_Length_Check  set if length check inserted
!    --       Assignment_OK             set if modification is OK
!    --       Is_Controlling_Actual     set for controlling argument
  
     --  Note: see under (EXPRESSION) for further details on the use of
     --  the Paren_Count field to record the number of parentheses levels.
--- 402,418 ----
     --       Has_Secondary_Private_View  set in generic units
  
     --    "plus fields for expression"
!    --       Paren_Count                  number of parentheses levels
!    --       Etype                        type of the expression
!    --       Is_Overloaded                >1 type interpretation exists
!    --       Is_Static_Expression         set for static expression
!    --       Raises_Constraint_Error      evaluation raises CE
!    --       Must_Not_Freeze              set if must not freeze
!    --       Do_Range_Check               set if a range check needed
!    --       Has_Dynamic_Length_Check     set if length check inserted
!    --       Assignment_OK                set if modification is OK
!    --       Is_Controlling_Actual        set for controlling argument
!    --       Is_Expanded_Dispatching_Call set for expanded dispatching calls
  
     --  Note: see under (EXPRESSION) for further details on the use of
     --  the Paren_Count field to record the number of parentheses levels.
*************** package Sinfo is
*** 1664,1669 ****
--- 1665,1674 ----
     --    actuals to support a build-in-place style of call have been added to
     --    the call.
  
+    --  Is_Expanded_Dispatching_Call
+    --    This flag is set in N_Block_Statement, and expression nodes to
+    --    indicate that it is an expanded dispatching call.
+ 
     --  Is_Expanded_Prefixed_Call
     --    This flag is set in N_Function_Call and N_Procedure_Call_Statement
     --    nodes to indicate that it is an expanded prefixed call.
*************** package Sinfo is
*** 2321,2326 ****
--- 2326,2338 ----
     --    statement applies to. Finally, if Analyze_Continue_Statement detects
     --    an error, this field is set to Empty.
  
+    --  Tag_Propagated
+    --    This flag is set in N_Identifier, N_Explicit_Dereference, and N_Type_
+    --    Conversion nodes that are the LHS of an assignment statement. Used to
+    --    remember that the RHS of the assignment has tag indeterminate function
+    --    calls and the tag has been propagated to the calls (as part of the
+    --    bottom-up analysis of the RHS of the assignment statement).
+ 
     --  Target_Type
     --    Used in an N_Validate_Unchecked_Conversion node to point to the target
     --    type entity for the unchecked conversion instantiation which gigi must
*************** package Sinfo is
*** 2507,2512 ****
--- 2519,2525 ----
        --  Has_Private_View (set in generic units)
        --  Has_Secondary_Private_View (set in generic units)
        --  Redundant_Use
+       --  Tag_Propagated
        --  Atomic_Sync_Required
        --  plus fields for expression
  
*************** package Sinfo is
*** 3820,3825 ****
--- 3833,3839 ----
        --  Prefix
        --  Actual_Designated_Subtype
        --  Has_Dereference_Action
+       --  Tag_Propagated
        --  Atomic_Sync_Required
        --  plus fields for expression
  
*************** package Sinfo is
*** 4755,4760 ****
--- 4769,4775 ----
        --  Conversion_OK
        --  Do_Overflow_Check
        --  Rounded_Result
+       --  Tag_Propagated
        --  plus fields for expression
  
        --  Note: if a range check is required, then the Do_Range_Check flag
*************** package Sinfo is
*** 5196,5201 ****
--- 5211,5217 ----
        --  Has_Created_Identifier
        --  Is_Abort_Block
        --  Is_Asynchronous_Call_Block
+       --  Is_Expanded_Dispatching_Call
        --  Is_Initialization_Block
        --  Is_Task_Allocation_Block
        --  Is_Task_Master
diff -Nrcpad gcc-16-20250720/gcc/ada/snames.ads-tmpl gcc-16-20250727/gcc/ada/snames.ads-tmpl
*** gcc-16-20250720/gcc/ada/snames.ads-tmpl	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/snames.ads-tmpl	Sun Jul 27 22:32:08 2025
*************** package Snames is
*** 151,156 ****
--- 151,157 ----
     Name_Default_Value                  : constant Name_Id := N + $;
     Name_Default_Component_Value        : constant Name_Id := N + $;
     Name_Designated_Storage_Model       : constant Name_Id := N + $;
+    Name_Destructor                     : constant Name_Id := N + $;
     Name_Dimension                      : constant Name_Id := N + $;
     Name_Dimension_System               : constant Name_Id := N + $;
     Name_Disable_Controlled             : constant Name_Id := N + $;
diff -Nrcpad gcc-16-20250720/gcc/ada/styleg.adb gcc-16-20250727/gcc/ada/styleg.adb
*** gcc-16-20250720/gcc/ada/styleg.adb	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/styleg.adb	Sun Jul 27 22:32:08 2025
*************** package body Styleg is
*** 499,505 ****
                    if Is_Box_Comment
                      or else Style_Check_Comments_Spacing = 1
                    then
!                      Error_Space_Required (Scan_Ptr + 2);
                    else
                       Error_Msg -- CODEFIX
                         ("(style) two spaces required?c?", Scan_Ptr + 2);
--- 499,506 ----
                    if Is_Box_Comment
                      or else Style_Check_Comments_Spacing = 1
                    then
!                      Error_Msg -- CODEFIX
!                        ("(style) space required?c?", Scan_Ptr + 2);
                    else
                       Error_Msg -- CODEFIX
                         ("(style) two spaces required?c?", Scan_Ptr + 2);
*************** package body Styleg is
*** 526,532 ****
           --  box comment.
  
           elsif not Is_Box_Comment then
!             Error_Space_Required (Scan_Ptr + 3);
           end if;
        end if;
     end Check_Comment;
--- 527,534 ----
           --  box comment.
  
           elsif not Is_Box_Comment then
!             Error_Msg -- CODEFIX
!               ("(style) space required?c?", Scan_Ptr + 3);
           end if;
        end if;
     end Check_Comment;
diff -Nrcpad gcc-16-20250720/gcc/ada/sysdep.c gcc-16-20250727/gcc/ada/sysdep.c
*** gcc-16-20250720/gcc/ada/sysdep.c	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/ada/sysdep.c	Sun Jul 27 22:32:08 2025
***************
*** 40,45 ****
--- 40,51 ----
     - either they are defined as ENOENT (vx7r2);
     - or the corresponding system includes are not provided (Helix Cert).  */
  
+ #if __has_include ("strings.h")
+ /* On VxWorks6, FD_ZERO uses bzero, and index is also declared in strings.h,
+    but since it's not a standard header, don't require it.  */
+ #include "strings.h"
+ #endif
+ 
  #if __has_include ("dosFsLib.h")
  /* On helix-cert, this include is only provided for RTPs.  */
  #include "dosFsLib.h"
diff -Nrcpad gcc-16-20250720/gcc/analyzer/ChangeLog gcc-16-20250727/gcc/analyzer/ChangeLog
*** gcc-16-20250720/gcc/analyzer/ChangeLog	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/ChangeLog	Sun Jul 27 22:32:08 2025
***************
*** 1,3 ****
--- 1,110 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* program-point.cc: Make diagnostics::context::m_source_printing
+ 	private.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* pending-diagnostic.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* program-point.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* program-point.cc: : Update for diagnostic_context becoming
+ 	diagnostics::context, and for diagnostic_source_print_policy
+ 	becoming diagnostics::source_print_policy.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* ana-state-to-diagnostic-state.cc: Update for move of
+ 	diagnostics output formats into namespace "diagnostics" as
+ 	"sinks".
+ 	* bounds-checking.cc: Likewise.
+ 	* call-details.cc: Likewise.
+ 	* checker-event.cc: Likewise.
+ 	* checker-event.h: Likewise.
+ 	* diagnostic-manager.cc: Likewise.
+ 	* diagnostic-manager.h: Likewise.
+ 	* infinite-loop.cc: Likewise.
+ 	* infinite-recursion.cc: Likewise.
+ 	* pending-diagnostic.h: Likewise.
+ 	* region-model.cc: Likewise.
+ 	* sm-taint.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* access-diagram.cc: Update for changes to diagnostic paths:
+ 	"diagnostic-path.h" moving to "diagnostics/paths.h",
+ 	"diagnostic-event-id.h" moving to "diagnostics/event-id.h",
+ 	diagnostic_event_id_t to diagnostics::paths::event_id_t,
+ 	diagnostic_path to diagnostics::paths::path, and
+ 	diagnostic_event to diagnostics::paths::event.
+ 	* access-diagram.h: Likewise.
+ 	* analyzer.cc: Likewise.
+ 	* bounds-checking.cc: Likewise.
+ 	* call-info.cc: Likewise.
+ 	* checker-event.cc: Likewise.
+ 	* checker-event.h: Likewise.
+ 	* checker-path.cc: Likewise.
+ 	* checker-path.h: Likewise.
+ 	* common.h: Likewise.
+ 	* diagnostic-manager.cc: Likewise.
+ 	* pending-diagnostic.cc: Likewise.
+ 	* pending-diagnostic.h: Likewise.
+ 	* program-point.cc: Likewise.
+ 	* program-state.cc: Likewise.
+ 	* region-model.cc: Likewise.
+ 	* sm-fd.cc: Likewise.
+ 	* sm-file.cc: Likewise.
+ 	* sm-malloc.cc: Likewise.
+ 	* sm-pattern-test.cc: Likewise.
+ 	* sm-sensitive.cc: Likewise.
+ 	* sm-signal.cc: Likewise.
+ 	* sm-taint.cc: Likewise.
+ 	* varargs.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* bounds-checking.cc: Update #include for move of
+ 	"diagnostic-diagram.h" to "diagnostics/diagram.h". Update for
+ 	move of diagnostic_diagram to diagnostics::diagram.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* diagnostic-manager.cc: Update for move of diagnostic_metadata to
+ 	diagnostics::metadata.
+ 	* kf.cc: Likewise.
+ 	* pending-diagnostic.h: Likewise; also, update #include for move
+ 	of "diagnostic-metadata.h" to "diagnostics/metadata.h".
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* checker-event.h (checker_event::get_logical_location): Update
+ 	for conversion of logical_location to
+ 	diagnostics::logical_locations::key.
+ 	(checker_event::m_logical_loc): Likewise.
+ 	* diagnostic-manager.cc
+ 	(diagnostic_manager::get_logical_location_manager): Likewise.
+ 	* diagnostic-manager.h
+ 	(diagnostic_manager::get_logical_location_manager): Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* ana-state-to-diagnostic-state.cc: Update #include for move of
+ 	"diagnostic-state-graphs.h" to "diagnostics/state-graphs.h".
+ 	* ana-state-to-diagnostic-state.h: Likewise.
+ 	* checker-event.cc: Likewise.
+ 	* checker-event.h: Update #include for move of
+ 	"diagnostic-digraphs.h" to "diagnostics/digraphs.h".
+ 	* program-state.cc: : Update #include for move of
+ 	"diagnostic-state-graphs.h" to "diagnostics/state-graphs.h".
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* region-model-asm.cc (region_model::on_asm_stmt): Pass null
+ 	pointer to parse_{input,output}_constraint().
+ 
  2025-07-11  David Malcolm  <dmalcolm@redhat.com>
  
  	* ana-state-to-diagnostic-state.cc: Reimplement, replacing
diff -Nrcpad gcc-16-20250720/gcc/analyzer/access-diagram.cc gcc-16-20250727/gcc/analyzer/access-diagram.cc
*** gcc-16-20250720/gcc/analyzer/access-diagram.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/access-diagram.cc	Sun Jul 27 22:32:08 2025
*************** class valid_region_spatial_item : public
*** 1300,1306 ****
  {
  public:
    valid_region_spatial_item (const access_operation &op,
! 			     diagnostic_event_id_t region_creation_event_id,
  			     const theme &theme)
    : m_op (op),
      m_region_creation_event_id (region_creation_event_id),
--- 1300,1306 ----
  {
  public:
    valid_region_spatial_item (const access_operation &op,
! 			     diagnostics::paths::event_id_t region_creation_event_id,
  			     const theme &theme)
    : m_op (op),
      m_region_creation_event_id (region_creation_event_id),
*************** public:
*** 1523,1529 ****
  
  private:
    const access_operation &m_op;
!   diagnostic_event_id_t m_region_creation_event_id;
    mutable const boundaries *m_boundaries;
    const svalue *m_existing_sval;
    std::unique_ptr<spatial_item> m_existing_sval_spatial_item;
--- 1523,1529 ----
  
  private:
    const access_operation &m_op;
!   diagnostics::paths::event_id_t m_region_creation_event_id;
    mutable const boundaries *m_boundaries;
    const svalue *m_existing_sval;
    std::unique_ptr<spatial_item> m_existing_sval_spatial_item;
*************** class access_diagram_impl : public vbox_
*** 2012,2018 ****
  {
  public:
    access_diagram_impl (const access_operation &op,
! 		       diagnostic_event_id_t region_creation_event_id,
  		       style_manager &sm,
  		       const theme &theme,
  		       logger *logger)
--- 2012,2018 ----
  {
  public:
    access_diagram_impl (const access_operation &op,
! 		       diagnostics::paths::event_id_t region_creation_event_id,
  		       style_manager &sm,
  		       const theme &theme,
  		       logger *logger)
*************** private:
*** 2564,2570 ****
    }
  
    const access_operation &m_op;
!   diagnostic_event_id_t m_region_creation_event_id;
    style_manager &m_sm;
    const theme &m_theme;
    logger *m_logger;
--- 2564,2570 ----
    }
  
    const access_operation &m_op;
!   diagnostics::paths::event_id_t m_region_creation_event_id;
    style_manager &m_sm;
    const theme &m_theme;
    logger *m_logger;
*************** direction_widget::paint_to_canvas (canva
*** 2662,2668 ****
     an access_diagram_impl.  */
  
  access_diagram::access_diagram (const access_operation &op,
! 				diagnostic_event_id_t region_creation_event_id,
  				style_manager &sm,
  				const theme &theme,
  				logger *logger)
--- 2662,2668 ----
     an access_diagram_impl.  */
  
  access_diagram::access_diagram (const access_operation &op,
! 				diagnostics::paths::event_id_t region_creation_event_id,
  				style_manager &sm,
  				const theme &theme,
  				logger *logger)
diff -Nrcpad gcc-16-20250720/gcc/analyzer/access-diagram.h gcc-16-20250727/gcc/analyzer/access-diagram.h
*** gcc-16-20250720/gcc/analyzer/access-diagram.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/access-diagram.h	Sun Jul 27 22:32:08 2025
*************** class access_diagram : public text_art::
*** 152,158 ****
  {
  public:
    access_diagram (const access_operation &op,
! 		  diagnostic_event_id_t region_creation_event_id,
  		  text_art::style_manager &sm,
  		  const text_art::theme &theme,
  		  logger *logger);
--- 152,158 ----
  {
  public:
    access_diagram (const access_operation &op,
! 		  diagnostics::paths::event_id_t region_creation_event_id,
  		  text_art::style_manager &sm,
  		  const text_art::theme &theme,
  		  logger *logger);
diff -Nrcpad gcc-16-20250720/gcc/analyzer/ana-state-to-diagnostic-state.cc gcc-16-20250727/gcc/analyzer/ana-state-to-diagnostic-state.cc
*** gcc-16-20250720/gcc/analyzer/ana-state-to-diagnostic-state.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/ana-state-to-diagnostic-state.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 23,30 ****
  #define INCLUDE_SET
  #include "analyzer/common.h"
  
! #include "diagnostic-state-graphs.h"
! #include "diagnostic-format-sarif.h"
  
  #include "analyzer/region-model.h"
  #include "analyzer/program-state.h"
--- 23,30 ----
  #define INCLUDE_SET
  #include "analyzer/common.h"
  
! #include "diagnostics/state-graphs.h"
! #include "diagnostics/sarif-sink.h"
  
  #include "analyzer/region-model.h"
  #include "analyzer/program-state.h"
diff -Nrcpad gcc-16-20250720/gcc/analyzer/ana-state-to-diagnostic-state.h gcc-16-20250727/gcc/analyzer/ana-state-to-diagnostic-state.h
*** gcc-16-20250720/gcc/analyzer/ana-state-to-diagnostic-state.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/ana-state-to-diagnostic-state.h	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 21,27 ****
  #ifndef GCC_ANALYZER_ANA_STATE_TO_DIAGNOSTIC_STATE_H
  #define GCC_ANALYZER_ANA_STATE_TO_DIAGNOSTIC_STATE_H
  
! #include "diagnostic-state-graphs.h"
  #include "tree-logical-location.h"
  
  namespace ana {
--- 21,27 ----
  #ifndef GCC_ANALYZER_ANA_STATE_TO_DIAGNOSTIC_STATE_H
  #define GCC_ANALYZER_ANA_STATE_TO_DIAGNOSTIC_STATE_H
  
! #include "diagnostics/state-graphs.h"
  #include "tree-logical-location.h"
  
  namespace ana {
diff -Nrcpad gcc-16-20250720/gcc/analyzer/analyzer.cc gcc-16-20250727/gcc/analyzer/analyzer.cc
*** gcc-16-20250720/gcc/analyzer/analyzer.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/analyzer.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 21,27 ****
  #include "analyzer/common.h"
  
  #include "tree-pretty-print.h"
! #include "diagnostic-event-id.h"
  #include "tree-dfa.h"
  #include "intl.h"
  
--- 21,27 ----
  #include "analyzer/common.h"
  
  #include "tree-pretty-print.h"
! #include "diagnostics/event-id.h"
  #include "tree-dfa.h"
  #include "intl.h"
  
*************** tree_to_json (tree node)
*** 232,238 ****
     for unknown).  */
  
  std::unique_ptr<json::value>
! diagnostic_event_id_to_json (const diagnostic_event_id_t &event_id)
  {
    if (event_id.known_p ())
      {
--- 232,238 ----
     for unknown).  */
  
  std::unique_ptr<json::value>
! diagnostic_event_id_to_json (const diagnostics::paths::event_id_t &event_id)
  {
    if (event_id.known_p ())
      {
diff -Nrcpad gcc-16-20250720/gcc/analyzer/bounds-checking.cc gcc-16-20250727/gcc/analyzer/bounds-checking.cc
*** gcc-16-20250720/gcc/analyzer/bounds-checking.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/bounds-checking.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 20,27 ****
  #include "analyzer/common.h"
  
  #include "intl.h"
! #include "diagnostic-diagram.h"
! #include "diagnostic-format-sarif.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/region-model.h"
--- 20,27 ----
  #include "analyzer/common.h"
  
  #include "intl.h"
! #include "diagnostics/diagram.h"
! #include "diagnostics/sarif-sink.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/region-model.h"
*************** public:
*** 51,57 ****
      }
      void prepare_for_emission (checker_path *path,
  			       pending_diagnostic *pd,
! 			       diagnostic_event_id_t emission_id) override
      {
        region_creation_event_capacity::prepare_for_emission (path,
  							    pd,
--- 51,57 ----
      }
      void prepare_for_emission (checker_path *path,
  			       pending_diagnostic *pd,
! 			       diagnostics::paths::event_id_t emission_id) override
      {
        region_creation_event_capacity::prepare_for_emission (path,
  							    pd,
*************** public:
*** 101,110 ****
  							       *this));
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const override
    {
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/out_of_bounds/"
      props.set_string (PROPERTY_PREFIX "dir",
  		      get_dir () == access_direction::read ? "read" : "write");
--- 101,111 ----
  							       *this));
    }
  
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const override
    {
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/out_of_bounds/"
      props.set_string (PROPERTY_PREFIX "dir",
  		      get_dir () == access_direction::read ? "read" : "write");
*************** protected:
*** 181,187 ****
  	       a problem.  Give up if that's happened.  */
  	    return;
  	  }
! 	diagnostic_diagram diagram
  	  (canvas,
  	   /* Alt text.  */
  	   _("Diagram visualizing the predicted out-of-bounds access"));
--- 182,188 ----
  	       a problem.  Give up if that's happened.  */
  	    return;
  	  }
! 	diagnostics::diagram diagram
  	  (canvas,
  	   /* Alt text.  */
  	   _("Diagram visualizing the predicted out-of-bounds access"));
*************** protected:
*** 203,209 ****
    const region *m_reg;
    tree m_diag_arg;
    const svalue *m_sval_hint;
!   diagnostic_event_id_t m_region_creation_event_id;
  };
  
  /* Abstract base class for all out-of-bounds warnings where the
--- 204,210 ----
    const region *m_reg;
    tree m_diag_arg;
    const svalue *m_sval_hint;
!   diagnostics::paths::event_id_t m_region_creation_event_id;
  };
  
  /* Abstract base class for all out-of-bounds warnings where the
*************** public:
*** 228,238 ****
  	    && m_out_of_bounds_bits == other.m_out_of_bounds_bits);
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const override
    {
      out_of_bounds::maybe_add_sarif_properties (result_obj);
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/concrete_out_of_bounds/"
      props.set (PROPERTY_PREFIX "out_of_bounds_bits",
  	       m_out_of_bounds_bits.to_json ());
--- 229,239 ----
  	    && m_out_of_bounds_bits == other.m_out_of_bounds_bits);
    }
  
!   void maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const override
    {
      out_of_bounds::maybe_add_sarif_properties (result_obj);
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/concrete_out_of_bounds/"
      props.set (PROPERTY_PREFIX "out_of_bounds_bits",
  	       m_out_of_bounds_bits.to_json ());
*************** public:
*** 294,304 ****
  							       *this));
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const final override
    {
      concrete_out_of_bounds::maybe_add_sarif_properties (result_obj);
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/concrete_past_the_end/"
      props.set (PROPERTY_PREFIX "bit_bound",
  	       tree_to_json (m_bit_bound));
--- 295,305 ----
  							       *this));
    }
  
!   void maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const final override
    {
      concrete_out_of_bounds::maybe_add_sarif_properties (result_obj);
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/concrete_past_the_end/"
      props.set (PROPERTY_PREFIX "bit_bound",
  	       tree_to_json (m_bit_bound));
*************** public:
*** 966,976 ****
  	    && pending_diagnostic::same_tree_p (m_capacity, other.m_capacity));
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const final override
    {
      out_of_bounds::maybe_add_sarif_properties (result_obj);
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/symbolic_past_the_end/"
      props.set (PROPERTY_PREFIX "offset", tree_to_json (m_offset));
      props.set (PROPERTY_PREFIX "num_bytes", tree_to_json (m_num_bytes));
--- 967,978 ----
  	    && pending_diagnostic::same_tree_p (m_capacity, other.m_capacity));
    }
  
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const final override
    {
      out_of_bounds::maybe_add_sarif_properties (result_obj);
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/symbolic_past_the_end/"
      props.set (PROPERTY_PREFIX "offset", tree_to_json (m_offset));
      props.set (PROPERTY_PREFIX "num_bytes", tree_to_json (m_num_bytes));
diff -Nrcpad gcc-16-20250720/gcc/analyzer/call-details.cc gcc-16-20250727/gcc/analyzer/call-details.cc
*** gcc-16-20250720/gcc/analyzer/call-details.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/call-details.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 25,31 ****
  #include "gimple-pretty-print.h"
  #include "stringpool.h"
  #include "attribs.h"
! #include "diagnostic-format-sarif.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/region-model.h"
--- 25,31 ----
  #include "gimple-pretty-print.h"
  #include "stringpool.h"
  #include "attribs.h"
! #include "diagnostics/sarif-sink.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/region-model.h"
*************** public:
*** 528,537 ****
      return true;
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const final override
    {
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/overlapping_buffers/"
      props.set (PROPERTY_PREFIX "bytes_range_a",
  	       m_byte_range_a.to_json ());
--- 528,537 ----
      return true;
    }
  
!   void maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const final override
    {
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/overlapping_buffers/"
      props.set (PROPERTY_PREFIX "bytes_range_a",
  	       m_byte_range_a.to_json ());
diff -Nrcpad gcc-16-20250720/gcc/analyzer/call-info.cc gcc-16-20250727/gcc/analyzer/call-info.cc
*** gcc-16-20250720/gcc/analyzer/call-info.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/call-info.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 24,30 ****
  #include "cfg.h"
  #include "digraph.h"
  #include "sbitmap.h"
! #include "diagnostic-event-id.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/supergraph.h"
--- 24,30 ----
  #include "cfg.h"
  #include "digraph.h"
  #include "sbitmap.h"
! #include "diagnostics/event-id.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/supergraph.h"
diff -Nrcpad gcc-16-20250720/gcc/analyzer/checker-event.cc gcc-16-20250727/gcc/analyzer/checker-event.cc
*** gcc-16-20250720/gcc/analyzer/checker-event.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/checker-event.cc	Sun Jul 27 22:32:08 2025
***************
*** 1,4 ****
! /* Subclasses of diagnostic_event for analyzer diagnostics.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
  
--- 1,4 ----
! /* Subclasses of diagnostics::paths::event for analyzer diagnostics.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
  
*************** along with GCC; see the file COPYING3.
*** 27,34 ****
  #include "gimple-iterator.h"
  #include "inlining-iterator.h"
  #include "tree-logical-location.h"
! #include "diagnostic-format-sarif.h"
! #include "diagnostic-state-graphs.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/sm.h"
--- 27,34 ----
  #include "gimple-iterator.h"
  #include "inlining-iterator.h"
  #include "tree-logical-location.h"
! #include "diagnostics/sarif-sink.h"
! #include "diagnostics/state-graphs.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/sm.h"
*************** event_kind_to_string (enum event_kind ek
*** 101,107 ****
      }
  }
  
! /* class checker_event : public diagnostic_event.  */
  
  /* checker_event's ctor.  */
  
--- 101,107 ----
      }
  }
  
! /* class checker_event : public diagnostics::paths::event.  */
  
  /* checker_event's ctor.  */
  
*************** checker_event::checker_event (enum event
*** 131,154 ****
      }
  }
  
! /* No-op implementation of diagnostic_event::get_meaning vfunc for
     checker_event: checker events have no meaning by default.  */
  
! diagnostic_event::meaning
  checker_event::get_meaning () const
  {
!   return meaning ();
  }
  
! /* Implementation of diagnostic_event::maybe_add_sarif_properties
     for checker_event.  */
  
  void
  checker_event::
! maybe_add_sarif_properties (sarif_builder &builder,
! 			    sarif_object &thread_flow_loc_obj) const
  {
!   sarif_property_bag &props = thread_flow_loc_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/checker_event/"
    props.set (PROPERTY_PREFIX "emission_id",
  	     diagnostic_event_id_to_json  (m_emission_id));
--- 131,154 ----
      }
  }
  
! /* No-op implementation of diagnostics::paths::event::get_meaning vfunc for
     checker_event: checker events have no meaning by default.  */
  
! diagnostics::paths::event::meaning
  checker_event::get_meaning () const
  {
!   return diagnostics::paths::event::meaning ();
  }
  
! /* Implementation of diagnostics::paths::event::maybe_add_sarif_properties
     for checker_event.  */
  
  void
  checker_event::
! maybe_add_sarif_properties (diagnostics::sarif_builder &builder,
! 			    diagnostics::sarif_object &thread_flow_loc_obj) const
  {
!   auto &props = thread_flow_loc_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/checker_event/"
    props.set (PROPERTY_PREFIX "emission_id",
  	     diagnostic_event_id_to_json  (m_emission_id));
*************** checker_event::debug () const
*** 215,221 ****
  void
  checker_event::prepare_for_emission (checker_path *path,
  				     pending_diagnostic *pd,
! 				     diagnostic_event_id_t emission_id)
  {
    m_path = path;
    m_pending_diagnostic = pd;
--- 215,221 ----
  void
  checker_event::prepare_for_emission (checker_path *path,
  				     pending_diagnostic *pd,
! 				     diagnostics::paths::event_id_t emission_id)
  {
    m_path = path;
    m_pending_diagnostic = pd;
*************** checker_event::maybe_make_diagnostic_sta
*** 252,258 ****
  
  /* class debug_event : public checker_event.  */
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     debug_event.
     Use the saved string as the event's description.  */
  
--- 252,258 ----
  
  /* class debug_event : public checker_event.  */
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     debug_event.
     Use the saved string as the event's description.  */
  
*************** debug_event::print_desc (pretty_printer
*** 264,270 ****
  
  /* class precanned_custom_event : public custom_event.  */
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     precanned_custom_event.
     Use the saved string as the event's description.  */
  
--- 264,270 ----
  
  /* class precanned_custom_event : public custom_event.  */
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     precanned_custom_event.
     Use the saved string as the event's description.  */
  
*************** statement_event::statement_event (const
*** 287,293 ****
  {
  }
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     statement_event.
     Use the statement's dump form as the event's description.  */
  
--- 287,293 ----
  {
  }
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     statement_event.
     Use the statement's dump form as the event's description.  */
  
*************** function_entry_event::function_entry_eve
*** 383,389 ****
  {
  }
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     function_entry_event.
  
     Use a string such as "entry to 'foo'" as the event's description.  */
--- 383,389 ----
  {
  }
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     function_entry_event.
  
     Use a string such as "entry to 'foo'" as the event's description.  */
*************** function_entry_event::print_desc (pretty
*** 394,403 ****
    pp_printf (&pp, "entry to %qE", m_effective_fndecl);
  }
  
! /* Implementation of diagnostic_event::get_meaning vfunc for
     function entry.  */
  
! diagnostic_event::meaning
  function_entry_event::get_meaning () const
  {
    return meaning (verb::enter, noun::function);
--- 394,403 ----
    pp_printf (&pp, "entry to %qE", m_effective_fndecl);
  }
  
! /* Implementation of diagnostics::paths::event::get_meaning vfunc for
     function entry.  */
  
! diagnostics::paths::event::meaning
  function_entry_event::get_meaning () const
  {
    return meaning (verb::enter, noun::function);
*************** state_change_event::state_change_event (
*** 429,435 ****
  {
  }
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     state_change_event.
  
     Attempt to generate a nicer human-readable description.
--- 429,435 ----
  {
  }
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     state_change_event.
  
     Attempt to generate a nicer human-readable description.
*************** state_change_event::print_desc (pretty_p
*** 471,477 ****
  		pp_string (&pp, "NULL origin");
  
  	      /* Get any "meaning" of event.  */
! 	      diagnostic_event::meaning meaning = get_meaning ();
  	      pp_string (&pp, ", meaning: ");
  	      meaning.dump_to_pp (&pp);
  	      pp_string (&pp, ")");
--- 471,477 ----
  		pp_string (&pp, "NULL origin");
  
  	      /* Get any "meaning" of event.  */
! 	      diagnostics::paths::event::meaning meaning = get_meaning ();
  	      pp_string (&pp, ", meaning: ");
  	      meaning.dump_to_pp (&pp);
  	      pp_string (&pp, ")");
*************** state_change_event::print_desc (pretty_p
*** 508,518 ****
      }
  }
  
! /* Implementation of diagnostic_event::get_meaning vfunc for
     state change events: delegate to the pending_diagnostic to
     get any meaning.  */
  
! diagnostic_event::meaning
  state_change_event::get_meaning () const
  {
    if (m_pending_diagnostic)
--- 508,518 ----
      }
  }
  
! /* Implementation of diagnostics::paths::event::get_meaning vfunc for
     state change events: delegate to the pending_diagnostic to
     get any meaning.  */
  
! diagnostics::paths::event::meaning
  state_change_event::get_meaning () const
  {
    if (m_pending_diagnostic)
*************** state_change_event::get_meaning () const
*** 530,545 ****
  
  /* class superedge_event : public checker_event.  */
  
! /* Implementation of diagnostic_event::maybe_add_sarif_properties
     for superedge_event.  */
  
  void
! superedge_event::maybe_add_sarif_properties (sarif_builder &builder,
! 					     sarif_object &thread_flow_loc_obj)
    const
  {
    checker_event::maybe_add_sarif_properties (builder, thread_flow_loc_obj);
!   sarif_property_bag &props = thread_flow_loc_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/superedge_event/"
    if (m_sedge)
      props.set (PROPERTY_PREFIX "superedge", m_sedge->to_json ());
--- 530,546 ----
  
  /* class superedge_event : public checker_event.  */
  
! /* Implementation of diagnostics::paths::event::maybe_add_sarif_properties
     for superedge_event.  */
  
  void
! superedge_event::
! maybe_add_sarif_properties (diagnostics::sarif_builder &builder,
! 			    diagnostics::sarif_object &thread_flow_loc_obj)
    const
  {
    checker_event::maybe_add_sarif_properties (builder, thread_flow_loc_obj);
!   auto &props = thread_flow_loc_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/superedge_event/"
    if (m_sedge)
      props.set (PROPERTY_PREFIX "superedge", m_sedge->to_json ());
*************** cfg_edge_event::cfg_edge_event (enum eve
*** 626,635 ****
    gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CFG_EDGE);
  }
  
! /* Implementation of diagnostic_event::get_meaning vfunc for
     CFG edge events.  */
  
! diagnostic_event::meaning
  cfg_edge_event::get_meaning () const
  {
    const cfg_superedge& cfg_sedge = get_cfg_superedge ();
--- 627,636 ----
    gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CFG_EDGE);
  }
  
! /* Implementation of diagnostics::paths::event::get_meaning vfunc for
     CFG edge events.  */
  
! diagnostics::paths::event::meaning
  cfg_edge_event::get_meaning () const
  {
    const cfg_superedge& cfg_sedge = get_cfg_superedge ();
*************** cfg_edge_event::get_meaning () const
*** 643,649 ****
  
  /* class start_cfg_edge_event : public cfg_edge_event.  */
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     start_cfg_edge_event.
  
     If -fanalyzer-verbose-edges, then generate low-level descriptions, such
--- 644,650 ----
  
  /* class start_cfg_edge_event : public cfg_edge_event.  */
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     start_cfg_edge_event.
  
     If -fanalyzer-verbose-edges, then generate low-level descriptions, such
*************** call_event::call_event (const exploded_e
*** 844,850 ****
     m_dest_snode = eedge.m_dest->get_supernode ();
  }
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     call_event.
  
     If this call event passes critical state for an sm-based warning,
--- 845,851 ----
     m_dest_snode = eedge.m_dest->get_supernode ();
  }
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     call_event.
  
     If this call event passes critical state for an sm-based warning,
*************** call_event::print_desc (pretty_printer &
*** 876,885 ****
  	     get_caller_fndecl ());
  }
  
! /* Implementation of diagnostic_event::get_meaning vfunc for
     function call events.  */
  
! diagnostic_event::meaning
  call_event::get_meaning () const
  {
    return meaning (verb::call, noun::function);
--- 877,886 ----
  	     get_caller_fndecl ());
  }
  
! /* Implementation of diagnostics::paths::event::get_meaning vfunc for
     function call events.  */
  
! diagnostics::paths::event::meaning
  call_event::get_meaning () const
  {
    return meaning (verb::call, noun::function);
*************** return_event::return_event (const explod
*** 928,934 ****
    m_dest_snode = eedge.m_dest->get_supernode ();
  }
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     return_event.
  
     If this return event returns critical state for an sm-based warning,
--- 929,935 ----
    m_dest_snode = eedge.m_dest->get_supernode ();
  }
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     return_event.
  
     If this return event returns critical state for an sm-based warning,
*************** return_event::print_desc (pretty_printer
*** 960,969 ****
  	     m_src_snode->m_fun->decl);
  }
  
! /* Implementation of diagnostic_event::get_meaning vfunc for
     function return events.  */
  
! diagnostic_event::meaning
  return_event::get_meaning () const
  {
    return meaning (verb::return_, noun::function);
--- 961,970 ----
  	     m_src_snode->m_fun->decl);
  }
  
! /* Implementation of diagnostics::paths::event::get_meaning vfunc for
     function return events.  */
  
! diagnostics::paths::event::meaning
  return_event::get_meaning () const
  {
    return meaning (verb::return_, noun::function);
*************** start_consolidated_cfg_edges_event::prin
*** 987,996 ****
  	     m_edge_sense ? "true" : "false");
  }
  
! /* Implementation of diagnostic_event::get_meaning vfunc for
     start_consolidated_cfg_edges_event.  */
  
! diagnostic_event::meaning
  start_consolidated_cfg_edges_event::get_meaning () const
  {
    return meaning (verb::branch,
--- 988,997 ----
  	     m_edge_sense ? "true" : "false");
  }
  
! /* Implementation of diagnostics::paths::event::get_meaning vfunc for
     start_consolidated_cfg_edges_event.  */
  
! diagnostics::paths::event::meaning
  start_consolidated_cfg_edges_event::get_meaning () const
  {
    return meaning (verb::branch,
*************** inlined_call_event::print_desc (pretty_p
*** 1008,1017 ****
  	     m_apparent_caller_fndecl);
  }
  
! /* Implementation of diagnostic_event::get_meaning vfunc for
     reconstructed inlined function calls.  */
  
! diagnostic_event::meaning
  inlined_call_event::get_meaning () const
  {
    return meaning (verb::call, noun::function);
--- 1009,1018 ----
  	     m_apparent_caller_fndecl);
  }
  
! /* Implementation of diagnostics::paths::event::get_meaning vfunc for
     reconstructed inlined function calls.  */
  
! diagnostics::paths::event::meaning
  inlined_call_event::get_meaning () const
  {
    return meaning (verb::call, noun::function);
*************** inlined_call_event::get_meaning () const
*** 1019,1025 ****
  
  /* class setjmp_event : public checker_event.  */
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     setjmp_event.  */
  
  void
--- 1020,1026 ----
  
  /* class setjmp_event : public checker_event.  */
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     setjmp_event.  */
  
  void
*************** setjmp_event::print_desc (pretty_printer
*** 1038,1044 ****
  void
  setjmp_event::prepare_for_emission (checker_path *path,
  				    pending_diagnostic *pd,
! 				    diagnostic_event_id_t emission_id)
  {
    checker_event::prepare_for_emission (path, pd, emission_id);
    path->record_setjmp_event (m_enode, emission_id);
--- 1039,1045 ----
  void
  setjmp_event::prepare_for_emission (checker_path *path,
  				    pending_diagnostic *pd,
! 				    diagnostics::paths::event_id_t emission_id)
  {
    checker_event::prepare_for_emission (path, pd, emission_id);
    path->record_setjmp_event (m_enode, emission_id);
*************** rewind_event::rewind_event (const explod
*** 1077,1083 ****
  
  /* class rewind_from_longjmp_event : public rewind_event.  */
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     rewind_from_longjmp_event.  */
  
  void
--- 1078,1084 ----
  
  /* class rewind_from_longjmp_event : public rewind_event.  */
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     rewind_from_longjmp_event.  */
  
  void
*************** rewind_from_longjmp_event::print_desc (p
*** 1101,1107 ****
  
  /* class rewind_to_setjmp_event : public rewind_event.  */
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     rewind_to_setjmp_event.  */
  
  void
--- 1102,1108 ----
  
  /* class rewind_to_setjmp_event : public rewind_event.  */
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     rewind_to_setjmp_event.  */
  
  void
*************** rewind_to_setjmp_event::print_desc (pret
*** 1150,1156 ****
  void
  rewind_to_setjmp_event::prepare_for_emission (checker_path *path,
  					      pending_diagnostic *pd,
! 					      diagnostic_event_id_t emission_id)
  {
    checker_event::prepare_for_emission (path, pd, emission_id);
    path->get_setjmp_event (m_rewind_info->get_enode_origin (),
--- 1151,1157 ----
  void
  rewind_to_setjmp_event::prepare_for_emission (checker_path *path,
  					      pending_diagnostic *pd,
! 					      diagnostics::paths::event_id_t emission_id)
  {
    checker_event::prepare_for_emission (path, pd, emission_id);
    path->get_setjmp_event (m_rewind_info->get_enode_origin (),
*************** unwind_event::print_desc (pretty_printer
*** 1203,1209 ****
  
  /* class warning_event : public checker_event.  */
  
! /* Implementation of diagnostic_event::print_desc vfunc for
     warning_event.
  
     If the pending diagnostic implements describe_final_event, use it,
--- 1204,1210 ----
  
  /* class warning_event : public checker_event.  */
  
! /* Implementation of diagnostics::paths::event::print_desc vfunc for
     warning_event.
  
     If the pending diagnostic implements describe_final_event, use it,
*************** warning_event::print_desc (pretty_printe
*** 1248,1257 ****
      pp_string (&pp, "here");
  }
  
! /* Implementation of diagnostic_event::get_meaning vfunc for
     warning_event.  */
  
! diagnostic_event::meaning
  warning_event::get_meaning () const
  {
    return meaning (verb::danger, noun::unknown);
--- 1249,1258 ----
      pp_string (&pp, "here");
  }
  
! /* Implementation of diagnostics::paths::event::get_meaning vfunc for
     warning_event.  */
  
! diagnostics::paths::event::meaning
  warning_event::get_meaning () const
  {
    return meaning (verb::danger, noun::unknown);
diff -Nrcpad gcc-16-20250720/gcc/analyzer/checker-event.h gcc-16-20250727/gcc/analyzer/checker-event.h
*** gcc-16-20250720/gcc/analyzer/checker-event.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/checker-event.h	Sun Jul 27 22:32:08 2025
***************
*** 1,4 ****
! /* Subclasses of diagnostic_event for analyzer diagnostics.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
  
--- 1,4 ----
! /* Subclasses of diagnostics::paths::event for analyzer diagnostics.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
  
*************** along with GCC; see the file COPYING3.
*** 24,30 ****
  #include "tree-logical-location.h"
  #include "analyzer/program-state.h"
  #include "analyzer/event-loc-info.h"
! #include "diagnostic-digraphs.h"
  
  namespace ana {
  
--- 24,30 ----
  #include "tree-logical-location.h"
  #include "analyzer/program-state.h"
  #include "analyzer/event-loc-info.h"
! #include "diagnostics/digraphs.h"
  
  namespace ana {
  
*************** extern const char *event_kind_to_string
*** 62,68 ****
     The class hierarchy looks like this (using indentation to show
     inheritance, and with event_kinds shown for the concrete subclasses):
  
!    diagnostic_event
       checker_event
         debug_event (event_kind::debug)
         custom_event (event_kind::custom)
--- 62,68 ----
     The class hierarchy looks like this (using indentation to show
     inheritance, and with event_kinds shown for the concrete subclasses):
  
!    diagnostics::paths::event
       checker_event
         debug_event (event_kind::debug)
         custom_event (event_kind::custom)
*************** extern const char *event_kind_to_string
*** 91,120 ****
         unwind_event (event_kind::unwind)
         warning_event (event_kind::warning).  */
  
! /* Abstract subclass of diagnostic_event; the base class for use in
!    checker_path (the analyzer's diagnostic_path subclass).  */
  
! class checker_event : public diagnostic_event
  {
  public:
!   /* Implementation of diagnostic_event.  */
  
    location_t get_location () const final override { return m_loc; }
    int get_stack_depth () const final override { return m_effective_depth; }
!   logical_location get_logical_location () const final override
    {
      return m_logical_loc;
    }
    meaning get_meaning () const override;
    bool connect_to_next_event_p () const override { return false; }
!   diagnostic_thread_id_t get_thread_id () const final override
    {
      return 0;
    }
  
    void
!   maybe_add_sarif_properties (sarif_builder &,
! 			      sarif_object &thread_flow_loc_obj) const override;
  
    /* Additional functionality.  */
    enum event_kind get_kind () const { return m_kind; }
--- 91,122 ----
         unwind_event (event_kind::unwind)
         warning_event (event_kind::warning).  */
  
! /* Abstract subclass of diagnostics::paths::event; the base class for use in
!    checker_path (the analyzer's diagnostics::paths::path subclass).  */
  
! class checker_event : public diagnostics::paths::event
  {
  public:
!   /* Implementation of diagnostics::paths::event.  */
  
    location_t get_location () const final override { return m_loc; }
    int get_stack_depth () const final override { return m_effective_depth; }
!   diagnostics::logical_locations::key
!   get_logical_location () const final override
    {
      return m_logical_loc;
    }
    meaning get_meaning () const override;
    bool connect_to_next_event_p () const override { return false; }
!   diagnostics::paths::thread_id_t get_thread_id () const final override
    {
      return 0;
    }
  
    void
!   maybe_add_sarif_properties (diagnostics::sarif_builder &,
! 			      diagnostics::sarif_object &thread_flow_loc_obj)
!     const override;
  
    /* Additional functionality.  */
    enum event_kind get_kind () const { return m_kind; }
*************** public:
*** 124,130 ****
  
    virtual void prepare_for_emission (checker_path *,
  				     pending_diagnostic *pd,
! 				     diagnostic_event_id_t emission_id);
    virtual bool is_call_p () const { return false; }
    virtual bool is_function_entry_p () const  { return false; }
    virtual bool is_return_p () const  { return false; }
--- 126,132 ----
  
    virtual void prepare_for_emission (checker_path *,
  				     pending_diagnostic *pd,
! 				     diagnostics::paths::event_id_t emission_id);
    virtual bool is_call_p () const { return false; }
    virtual bool is_function_entry_p () const  { return false; }
    virtual bool is_return_p () const  { return false; }
*************** public:
*** 136,142 ****
    get_program_state () const { return nullptr; }
  
    /* For use with %@.  */
!   const diagnostic_event_id_t *get_id_ptr () const
    {
      return &m_emission_id;
    }
--- 138,144 ----
    get_program_state () const { return nullptr; }
  
    /* For use with %@.  */
!   const diagnostics::paths::event_id_t *get_id_ptr () const
    {
      return &m_emission_id;
    }
*************** protected:
*** 160,167 ****
    int m_original_depth;
    int m_effective_depth;
    pending_diagnostic *m_pending_diagnostic;
!   diagnostic_event_id_t m_emission_id; // only set once all pruning has occurred
!   logical_location m_logical_loc;
  };
  
  /* A concrete event subclass for a purely textual event, for use in
--- 162,169 ----
    int m_original_depth;
    int m_effective_depth;
    pending_diagnostic *m_pending_diagnostic;
!   diagnostics::paths::event_id_t m_emission_id; // only set once all pruning has occurred
!   diagnostics::logical_locations::key m_logical_loc;
  };
  
  /* A concrete event subclass for a purely textual event, for use in
*************** public:
*** 422,429 ****
  class superedge_event : public checker_event
  {
  public:
!   void maybe_add_sarif_properties (sarif_builder &,
! 				   sarif_object &thread_flow_loc_obj)
      const override;
  
    /* Mark this edge event as being either an interprocedural call or
--- 424,432 ----
  class superedge_event : public checker_event
  {
  public:
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_builder &,
! 			      diagnostics::sarif_object &thread_flow_loc_obj)
      const override;
  
    /* Mark this edge event as being either an interprocedural call or
*************** public:
*** 665,671 ****
  
    void prepare_for_emission (checker_path *path,
  			     pending_diagnostic *pd,
! 			     diagnostic_event_id_t emission_id) final override;
  
  private:
    const exploded_node *m_enode;
--- 668,674 ----
  
    void prepare_for_emission (checker_path *path,
  			     pending_diagnostic *pd,
! 			     diagnostics::paths::event_id_t emission_id) final override;
  
  private:
    const exploded_node *m_enode;
*************** public:
*** 731,740 ****
  
    void prepare_for_emission (checker_path *path,
  			     pending_diagnostic *pd,
! 			     diagnostic_event_id_t emission_id) final override;
  
  private:
!   diagnostic_event_id_t m_original_setjmp_event_id;
  };
  
  /* An abstract subclass for throwing/rethrowing an exception.  */
--- 734,743 ----
  
    void prepare_for_emission (checker_path *path,
  			     pending_diagnostic *pd,
! 			     diagnostics::paths::event_id_t emission_id) final override;
  
  private:
!   diagnostics::paths::event_id_t m_original_setjmp_event_id;
  };
  
  /* An abstract subclass for throwing/rethrowing an exception.  */
diff -Nrcpad gcc-16-20250720/gcc/analyzer/checker-path.cc gcc-16-20250727/gcc/analyzer/checker-path.cc
*** gcc-16-20250720/gcc/analyzer/checker-path.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/checker-path.cc	Sun Jul 27 22:32:08 2025
***************
*** 1,4 ****
! /* Subclass of diagnostic_path for analyzer diagnostics.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
  
--- 1,4 ----
! /* Subclass of diagnostics::paths::path for analyzer diagnostics.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
  
diff -Nrcpad gcc-16-20250720/gcc/analyzer/checker-path.h gcc-16-20250727/gcc/analyzer/checker-path.h
*** gcc-16-20250720/gcc/analyzer/checker-path.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/checker-path.h	Sun Jul 27 22:32:08 2025
***************
*** 1,4 ****
! /* Subclass of diagnostic_path for analyzer diagnostics.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
  
--- 1,4 ----
! /* Subclass of diagnostics::paths::path for analyzer diagnostics.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
  
*************** along with GCC; see the file COPYING3.
*** 26,53 ****
  
  namespace ana {
  
! /* Subclass of diagnostic_path for analyzer diagnostics.  */
  
! class checker_path : public diagnostic_path
  {
  public:
!   checker_path (const logical_location_manager &logical_loc_mgr,
  		const extrinsic_state &ext_state,
  		logger *logger)
!   : diagnostic_path (logical_loc_mgr),
      m_ext_state (ext_state),
      m_thread ("main"),
      m_logger (logger)
    {}
  
!   /* Implementation of diagnostic_path vfuncs.  */
  
    unsigned num_events () const final override
    {
      return m_events.length ();
    }
  
!   const diagnostic_event & get_event (int idx) const final override
    {
      return *m_events[idx];
    }
--- 26,54 ----
  
  namespace ana {
  
! /* Subclass of diagnostic path for analyzer diagnostics.  */
  
! class checker_path : public diagnostics::paths::path
  {
  public:
!   checker_path (const diagnostics::logical_locations::manager &logical_loc_mgr,
  		const extrinsic_state &ext_state,
  		logger *logger)
!   : diagnostics::paths::path (logical_loc_mgr),
      m_ext_state (ext_state),
      m_thread ("main"),
      m_logger (logger)
    {}
  
!   /* Implementation of diagnostics::paths::path vfuncs.  */
  
    unsigned num_events () const final override
    {
      return m_events.length ();
    }
  
!   const diagnostics::paths::event &
!   get_event (int idx) const final override
    {
      return *m_events[idx];
    }
*************** public:
*** 55,62 ****
    {
      return 1;
    }
!   const diagnostic_thread &
!   get_thread (diagnostic_thread_id_t) const final override
    {
      return m_thread;
    }
--- 56,63 ----
    {
      return 1;
    }
!   const diagnostics::paths::thread &
!   get_thread (diagnostics::paths::thread_id_t) const final override
    {
      return m_thread;
    }
*************** public:
*** 115,135 ****
      checker_event *e;
      int i;
      FOR_EACH_VEC_ELT (m_events, i, e)
!       e->prepare_for_emission (this, pd, diagnostic_event_id_t (i));
    }
  
    void fixup_locations (pending_diagnostic *pd);
  
    void record_setjmp_event (const exploded_node *enode,
! 			    diagnostic_event_id_t setjmp_emission_id)
    {
      m_setjmp_event_ids.put (enode, setjmp_emission_id);
    }
  
    bool get_setjmp_event (const exploded_node *enode,
! 			 diagnostic_event_id_t *out_emission_id)
    {
!     if (diagnostic_event_id_t *emission_id = m_setjmp_event_ids.get (enode))
        {
  	*out_emission_id = *emission_id;
  	return true;
--- 116,137 ----
      checker_event *e;
      int i;
      FOR_EACH_VEC_ELT (m_events, i, e)
!       e->prepare_for_emission (this, pd, diagnostics::paths::event_id_t (i));
    }
  
    void fixup_locations (pending_diagnostic *pd);
  
    void record_setjmp_event (const exploded_node *enode,
! 			    diagnostics::paths::event_id_t setjmp_emission_id)
    {
      m_setjmp_event_ids.put (enode, setjmp_emission_id);
    }
  
    bool get_setjmp_event (const exploded_node *enode,
! 			 diagnostics::paths::event_id_t *out_emission_id)
    {
!     if (diagnostics::paths::event_id_t *emission_id
! 	  = m_setjmp_event_ids.get (enode))
        {
  	*out_emission_id = *emission_id;
  	return true;
*************** private:
*** 154,160 ****
    /* During prepare_for_emission (and after), the setjmp_event for each
       exploded_node *, so that rewind events can refer to them in their
       descriptions.  */
!   hash_map <const exploded_node *, diagnostic_event_id_t> m_setjmp_event_ids;
  
    logger *m_logger;
  };
--- 156,162 ----
    /* During prepare_for_emission (and after), the setjmp_event for each
       exploded_node *, so that rewind events can refer to them in their
       descriptions.  */
!   hash_map <const exploded_node *, diagnostics::paths::event_id_t> m_setjmp_event_ids;
  
    logger *m_logger;
  };
diff -Nrcpad gcc-16-20250720/gcc/analyzer/common.h gcc-16-20250727/gcc/analyzer/common.h
*** gcc-16-20250720/gcc/analyzer/common.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/common.h	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 34,40 ****
  #include "options.h"
  #include "bitmap.h"
  #include "diagnostic-core.h"
! #include "diagnostic-path.h"
  #include "rich-location.h"
  #include "function.h"
  #include "json.h"
--- 34,40 ----
  #include "options.h"
  #include "bitmap.h"
  #include "diagnostic-core.h"
! #include "diagnostics/paths.h"
  #include "rich-location.h"
  #include "function.h"
  #include "json.h"
*************** extern std::unique_ptr<json::value>
*** 443,449 ****
  tree_to_json (tree node);
  
  extern std::unique_ptr<json::value>
! diagnostic_event_id_to_json (const diagnostic_event_id_t &);
  
  extern std::unique_ptr<json::value>
  bit_offset_to_json (const bit_offset_t &offset);
--- 443,449 ----
  tree_to_json (tree node);
  
  extern std::unique_ptr<json::value>
! diagnostic_event_id_to_json (const diagnostics::paths::event_id_t &);
  
  extern std::unique_ptr<json::value>
  bit_offset_to_json (const bit_offset_t &offset);
diff -Nrcpad gcc-16-20250720/gcc/analyzer/diagnostic-manager.cc gcc-16-20250727/gcc/analyzer/diagnostic-manager.cc
*** gcc-16-20250720/gcc/analyzer/diagnostic-manager.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/diagnostic-manager.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 29,35 ****
  #include "cgraph.h"
  #include "digraph.h"
  #include "gcc-rich-location.h"
! #include "diagnostic-format-sarif.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/sm.h"
--- 29,35 ----
  #include "cgraph.h"
  #include "digraph.h"
  #include "gcc-rich-location.h"
! #include "diagnostics/sarif-sink.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/sm.h"
*************** saved_diagnostic::emit_any_notes () cons
*** 1017,1025 ****
     This extra data is intended for use when debugging the analyzer.  */
  
  void
! saved_diagnostic::maybe_add_sarif_properties (sarif_object &result_obj) const
  {
!   sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/saved_diagnostic/"
    if (m_sm)
      props.set_string (PROPERTY_PREFIX "sm", m_sm->get_name ());
--- 1017,1026 ----
     This extra data is intended for use when debugging the analyzer.  */
  
  void
! saved_diagnostic::
! maybe_add_sarif_properties (diagnostics::sarif_object &result_obj) const
  {
!   auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/saved_diagnostic/"
    if (m_sm)
      props.set_string (PROPERTY_PREFIX "sm", m_sm->get_name ());
*************** saved_diagnostic::maybe_add_sarif_proper
*** 1044,1050 ****
        auto duplicates_arr = std::make_unique<json::array> ();
        for (auto iter : m_duplicates)
  	{
! 	  auto sd_obj = std::make_unique<sarif_object> ();
  	  iter->maybe_add_sarif_properties (*sd_obj);
  	  duplicates_arr->append (std::move (sd_obj));
  	}
--- 1045,1051 ----
        auto duplicates_arr = std::make_unique<json::array> ();
        for (auto iter : m_duplicates)
  	{
! 	  auto sd_obj = std::make_unique<diagnostics::sarif_object> ();
  	  iter->maybe_add_sarif_properties (*sd_obj);
  	  duplicates_arr->append (std::move (sd_obj));
  	}
*************** diagnostic_manager::emit_saved_diagnosti
*** 1541,1552 ****
    best_candidates.emit_best (this, eg);
  }
  
! /* Custom subclass of diagnostic_metadata which, for SARIF output,
     populates the property bag of the diagnostic's "result" object
     with information from the saved_diagnostic and the
     pending_diagnostic.  */
  
! class pending_diagnostic_metadata : public diagnostic_metadata
  {
  public:
    pending_diagnostic_metadata (const saved_diagnostic &sd)
--- 1542,1553 ----
    best_candidates.emit_best (this, eg);
  }
  
! /* Custom subclass of diagnostics::metadata which, for SARIF output,
     populates the property bag of the diagnostic's "result" object
     with information from the saved_diagnostic and the
     pending_diagnostic.  */
  
! class pending_diagnostic_metadata : public diagnostics::metadata
  {
  public:
    pending_diagnostic_metadata (const saved_diagnostic &sd)
*************** public:
*** 1555,1561 ****
    }
  
    void
!   maybe_add_sarif_properties (sarif_object &result_obj) const override
    {
      m_sd.maybe_add_sarif_properties (result_obj);
    }
--- 1556,1563 ----
    }
  
    void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
!     const override
    {
      m_sd.maybe_add_sarif_properties (result_obj);
    }
*************** diagnostic_manager::emit_saved_diagnosti
*** 1583,1589 ****
    /* Precompute all enodes from which the diagnostic is reachable.  */
    path_builder pb (eg, *epath, sd.get_feasibility_problem (), sd);
  
!   /* This is the diagnostic_path subclass that will be built for
       the diagnostic.  */
    checker_path emission_path (get_logical_location_manager (),
  			      eg.get_ext_state (),
--- 1585,1591 ----
    /* Precompute all enodes from which the diagnostic is reachable.  */
    path_builder pb (eg, *epath, sd.get_feasibility_problem (), sd);
  
!   /* This is the diagnostics::paths::path subclass that will be built for
       the diagnostic.  */
    checker_path emission_path (get_logical_location_manager (),
  			      eg.get_ext_state (),
*************** diagnostic_manager::emit_saved_diagnosti
*** 1663,1669 ****
      }
  }
  
! const logical_location_manager &
  diagnostic_manager::get_logical_location_manager () const
  {
    gcc_assert (global_dc);
--- 1665,1671 ----
      }
  }
  
! const diagnostics::logical_locations::manager &
  diagnostic_manager::get_logical_location_manager () const
  {
    gcc_assert (global_dc);
diff -Nrcpad gcc-16-20250720/gcc/analyzer/diagnostic-manager.h gcc-16-20250727/gcc/analyzer/diagnostic-manager.h
*** gcc-16-20250720/gcc/analyzer/diagnostic-manager.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/diagnostic-manager.h	Sun Jul 27 22:32:08 2025
*************** public:
*** 67,73 ****
  
    void emit_any_notes () const;
  
!   void maybe_add_sarif_properties (sarif_object &result_obj) const;
  
    //private:
    const state_machine *m_sm;
--- 67,74 ----
  
    void emit_any_notes () const;
  
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj) const;
  
    //private:
    const state_machine *m_sm;
*************** public:
*** 191,197 ****
    }
  
  private:
!   const logical_location_manager &
    get_logical_location_manager () const;
  
    void build_emission_path (const path_builder &pb,
--- 192,198 ----
    }
  
  private:
!   const diagnostics::logical_locations::manager &
    get_logical_location_manager () const;
  
    void build_emission_path (const path_builder &pb,
diff -Nrcpad gcc-16-20250720/gcc/analyzer/infinite-loop.cc gcc-16-20250727/gcc/analyzer/infinite-loop.cc
*** gcc-16-20250720/gcc/analyzer/infinite-loop.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/infinite-loop.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 25,31 ****
  #include "gimple-pretty-print.h"
  #include "cgraph.h"
  #include "digraph.h"
! #include "diagnostic-format-sarif.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/call-string.h"
--- 25,31 ----
  #include "gimple-pretty-print.h"
  #include "cgraph.h"
  #include "digraph.h"
! #include "diagnostics/sarif-sink.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/call-string.h"
*************** public:
*** 307,316 ****
        }
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const final override
    {
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/infinite_loop_diagnostic/"
      props.set (PROPERTY_PREFIX "inf_loop", m_inf_loop->to_json ());
  #undef PROPERTY_PREFIX
--- 307,317 ----
        }
    }
  
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const final override
    {
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/infinite_loop_diagnostic/"
      props.set (PROPERTY_PREFIX "inf_loop", m_inf_loop->to_json ());
  #undef PROPERTY_PREFIX
diff -Nrcpad gcc-16-20250720/gcc/analyzer/infinite-recursion.cc gcc-16-20250727/gcc/analyzer/infinite-recursion.cc
*** gcc-16-20250720/gcc/analyzer/infinite-recursion.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/infinite-recursion.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 25,30 ****
--- 25,31 ----
  #include "gimple-pretty-print.h"
  #include "cgraph.h"
  #include "digraph.h"
+ #include "diagnostics/sarif-sink.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/call-string.h"
*************** along with GCC; see the file COPYING3.
*** 40,46 ****
  #include "analyzer/exploded-graph.h"
  #include "analyzer/checker-path.h"
  #include "analyzer/feasible-graph.h"
- #include "diagnostic-format-sarif.h"
  
  /* A subclass of pending_diagnostic for complaining about suspected
     infinite recursion.  */
--- 41,46 ----
*************** public:
*** 223,232 ****
      return false;
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const final override
    {
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/infinite_recursion_diagnostic/"
      props.set_integer (PROPERTY_PREFIX "prev_entry_enode",
  		       m_prev_entry_enode->m_index);
--- 223,233 ----
      return false;
    }
  
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const final override
    {
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/infinite_recursion_diagnostic/"
      props.set_integer (PROPERTY_PREFIX "prev_entry_enode",
  		       m_prev_entry_enode->m_index);
diff -Nrcpad gcc-16-20250720/gcc/analyzer/kf.cc gcc-16-20250727/gcc/analyzer/kf.cc
*** gcc-16-20250720/gcc/analyzer/kf.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/kf.cc	Sun Jul 27 22:32:08 2025
*************** public:
*** 783,789 ****
  
      /* SEI CERT C Coding Standard: "POS34-C. Do not call putenv() with a
         pointer to an automatic variable as the argument".  */
!     diagnostic_metadata::precanned_rule
        rule ("POS34-C", "https://wiki.sei.cmu.edu/confluence/x/6NYxBQ");
      ctxt.add_rule (rule);
  
--- 783,789 ----
  
      /* SEI CERT C Coding Standard: "POS34-C. Do not call putenv() with a
         pointer to an automatic variable as the argument".  */
!     diagnostics::metadata::precanned_rule
        rule ("POS34-C", "https://wiki.sei.cmu.edu/confluence/x/6NYxBQ");
      ctxt.add_rule (rule);
  
diff -Nrcpad gcc-16-20250720/gcc/analyzer/pending-diagnostic.cc gcc-16-20250727/gcc/analyzer/pending-diagnostic.cc
*** gcc-16-20250720/gcc/analyzer/pending-diagnostic.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/pending-diagnostic.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 20,26 ****
  
  #include "analyzer/common.h"
  
! #include "diagnostic-event-id.h"
  #include "cpplib.h"
  #include "digraph.h"
  #include "ordered-hash-map.h"
--- 20,26 ----
  
  #include "analyzer/common.h"
  
! #include "diagnostics/event-id.h"
  #include "cpplib.h"
  #include "digraph.h"
  #include "ordered-hash-map.h"
*************** diagnostic_emission_context::warn (const
*** 92,98 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   const bool result = emit_diagnostic_valist_meta (DK_WARNING,
  						   &m_rich_loc, &m_metadata,
  						   pd.get_controlling_option (),
  						   gmsgid, &ap);
--- 92,98 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   const bool result = emit_diagnostic_valist_meta (diagnostics::kind::warning,
  						   &m_rich_loc, &m_metadata,
  						   pd.get_controlling_option (),
  						   gmsgid, &ap);
*************** diagnostic_emission_context::inform (con
*** 110,116 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   emit_diagnostic_valist_meta (DK_NOTE,
  			       &m_rich_loc, &m_metadata,
  			       pd.get_controlling_option (),
  			       gmsgid, &ap);
--- 110,116 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   emit_diagnostic_valist_meta (diagnostics::kind::note,
  			       &m_rich_loc, &m_metadata,
  			       pd.get_controlling_option (),
  			       gmsgid, &ap);
diff -Nrcpad gcc-16-20250720/gcc/analyzer/pending-diagnostic.h gcc-16-20250727/gcc/analyzer/pending-diagnostic.h
*** gcc-16-20250720/gcc/analyzer/pending-diagnostic.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/pending-diagnostic.h	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 21,28 ****
  #ifndef GCC_ANALYZER_PENDING_DIAGNOSTIC_H
  #define GCC_ANALYZER_PENDING_DIAGNOSTIC_H
  
! #include "diagnostic-metadata.h"
! #include "diagnostic-path.h"
  #include "analyzer/sm.h"
  
  namespace ana {
--- 21,27 ----
  #ifndef GCC_ANALYZER_PENDING_DIAGNOSTIC_H
  #define GCC_ANALYZER_PENDING_DIAGNOSTIC_H
  
! #include "diagnostics/metadata.h"
  #include "analyzer/sm.h"
  
  namespace ana {
*************** struct interesting_t
*** 44,50 ****
  };
  
  /* Various bundles of information used for generating more precise
!    messages for events within a diagnostic_path, for passing to the
     various "describe_*" vfuncs of pending_diagnostic.  See those
     for more information.  */
  
--- 43,49 ----
  };
  
  /* Various bundles of information used for generating more precise
!    messages for events within a diagnostic path, for passing to the
     various "describe_*" vfuncs of pending_diagnostic.  See those
     for more information.  */
  
*************** struct state_change
*** 58,64 ****
  		tree origin,
  		state_machine::state_t old_state,
  		state_machine::state_t new_state,
! 		diagnostic_event_id_t event_id,
  		const state_change_event &event)
    : m_expr (expr), m_origin (origin),
      m_old_state (old_state), m_new_state (new_state),
--- 57,63 ----
  		tree origin,
  		state_machine::state_t old_state,
  		state_machine::state_t new_state,
! 		diagnostics::paths::event_id_t event_id,
  		const state_change_event &event)
    : m_expr (expr), m_origin (origin),
      m_old_state (old_state), m_new_state (new_state),
*************** struct state_change
*** 71,77 ****
    tree m_origin;
    state_machine::state_t m_old_state;
    state_machine::state_t m_new_state;
!   diagnostic_event_id_t m_event_id;
    const state_change_event &m_event;
  };
  
--- 70,76 ----
    tree m_origin;
    state_machine::state_t m_old_state;
    state_machine::state_t m_new_state;
!   diagnostics::paths::event_id_t m_event_id;
    const state_change_event &m_event;
  };
  
*************** struct final_event
*** 131,144 ****
      pending_diagnostic::emit vfunc.
  
      The rich_location will have already been populated with a
!     diagnostic_path.  */
  
  class diagnostic_emission_context
  {
  public:
    diagnostic_emission_context (const saved_diagnostic &sd,
  			       rich_location &rich_loc,
! 			       diagnostic_metadata &metadata,
  			       logger *logger)
    : m_sd (sd),
      m_rich_loc (rich_loc),
--- 130,143 ----
      pending_diagnostic::emit vfunc.
  
      The rich_location will have already been populated with a
!     diagnostics::paths::path.  */
  
  class diagnostic_emission_context
  {
  public:
    diagnostic_emission_context (const saved_diagnostic &sd,
  			       rich_location &rich_loc,
! 			       diagnostics::metadata &metadata,
  			       logger *logger)
    : m_sd (sd),
      m_rich_loc (rich_loc),
*************** public:
*** 156,162 ****
    logger *get_logger () const { return m_logger; }
  
    void add_cwe (int cwe) { m_metadata.add_cwe (cwe); }
!   void add_rule (const diagnostic_metadata::rule &r)
    {
      m_metadata.add_rule (r);
    }
--- 155,161 ----
    logger *get_logger () const { return m_logger; }
  
    void add_cwe (int cwe) { m_metadata.add_cwe (cwe); }
!   void add_rule (const diagnostics::metadata::rule &r)
    {
      m_metadata.add_rule (r);
    }
*************** public:
*** 164,170 ****
  private:
    const saved_diagnostic &m_sd;
    rich_location &m_rich_loc;
!   diagnostic_metadata &m_metadata;
    logger *m_logger;
  };
  
--- 163,169 ----
  private:
    const saved_diagnostic &m_sd;
    rich_location &m_rich_loc;
!   diagnostics::metadata &m_metadata;
    logger *m_logger;
  };
  
*************** private:
*** 182,188 ****
  
     As well as emitting a diagnostic, the class has various "precision of
     wording" virtual functions, for generating descriptions for events
!    within a diagnostic_path.  These are optional, but implementing these
     allows for more precise wordings than the more generic
     implementation.  */
  
--- 181,187 ----
  
     As well as emitting a diagnostic, the class has various "precision of
     wording" virtual functions, for generating descriptions for events
!    within a diagnostic path.  These are optional, but implementing these
     allows for more precise wordings than the more generic
     implementation.  */
  
*************** class pending_diagnostic
*** 238,244 ****
    virtual location_t fixup_location (location_t loc, bool primary) const;
  
    /* Precision-of-wording vfunc for describing a critical state change
!      within the diagnostic_path.
  
       For example, a double-free diagnostic might use the descriptions:
       - "first 'free' happens here"
--- 237,243 ----
    virtual location_t fixup_location (location_t loc, bool primary) const;
  
    /* Precision-of-wording vfunc for describing a critical state change
!      within the diagnostic path.
  
       For example, a double-free diagnostic might use the descriptions:
       - "first 'free' happens here"
*************** class pending_diagnostic
*** 260,272 ****
      return false;
    }
  
!   /* Vfunc for implementing diagnostic_event::get_meaning for
       state_change_event.  */
!   virtual diagnostic_event::meaning
    get_meaning_for_state_change (const evdesc::state_change &) const
    {
      /* Default no-op implementation.  */
!     return diagnostic_event::meaning ();
    }
  
    /* Precision-of-wording vfunc for describing an interprocedural call
--- 259,271 ----
      return false;
    }
  
!   /* Vfunc for implementing event::get_meaning for
       state_change_event.  */
!   virtual diagnostics::paths::event::meaning
    get_meaning_for_state_change (const evdesc::state_change &) const
    {
      /* Default no-op implementation.  */
!     return diagnostics::paths::event::meaning ();
    }
  
    /* Precision-of-wording vfunc for describing an interprocedural call
*************** class pending_diagnostic
*** 285,291 ****
    }
  
    /* Precision-of-wording vfunc for describing an interprocedural return
!      within the diagnostic_path that carries critial state for the
       diagnostic, from callee back to caller.
  
       For example, a deref-of-unchecked-malloc diagnostic might use:
--- 284,290 ----
    }
  
    /* Precision-of-wording vfunc for describing an interprocedural return
!      within the diagnostic path that carries critial state for the
       diagnostic, from callee back to caller.
  
       For example, a deref-of-unchecked-malloc diagnostic might use:
*************** class pending_diagnostic
*** 301,307 ****
    }
  
    /* Precision-of-wording vfunc for describing the final event within a
!      diagnostic_path.
  
       For example a double-free diagnostic might use:
        - "second 'free' here; first 'free' was at (3)"
--- 300,306 ----
    }
  
    /* Precision-of-wording vfunc for describing the final event within a
!      diagnostic path.
  
       For example a double-free diagnostic might use:
        - "second 'free' here; first 'free' was at (3)"
*************** class pending_diagnostic
*** 402,408 ****
       the opportunity to add diagnostic-specific properties to the SARIF
       "result" object for the diagnostic.
       This is intended for use when debugging a diagnostic.  */
!   virtual void maybe_add_sarif_properties (sarif_object &/*result_obj*/) const
    {
      /* Default no-op implementation.  */
    }
--- 401,408 ----
       the opportunity to add diagnostic-specific properties to the SARIF
       "result" object for the diagnostic.
       This is intended for use when debugging a diagnostic.  */
!   virtual void
!   maybe_add_sarif_properties (diagnostics::sarif_object &/*result_obj*/) const
    {
      /* Default no-op implementation.  */
    }
diff -Nrcpad gcc-16-20250720/gcc/analyzer/program-point.cc gcc-16-20250727/gcc/analyzer/program-point.cc
*** gcc-16-20250720/gcc/analyzer/program-point.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/program-point.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 20,26 ****
  
  #include "analyzer/common.h"
  
! #include "diagnostic-event-id.h"
  #include "gcc-rich-location.h"
  #include "gimple-pretty-print.h"
  #include "sbitmap.h"
--- 20,26 ----
  
  #include "analyzer/common.h"
  
! #include "diagnostics/event-id.h"
  #include "gcc-rich-location.h"
  #include "gimple-pretty-print.h"
  #include "sbitmap.h"
*************** function_point::before_supernode (const
*** 234,250 ****
    return function_point (supernode, from_edge, 0, PK_BEFORE_SUPERNODE);
  }
  
! /* A subclass of diagnostic_context for use by
     program_point::print_source_line.  */
  
! class debug_diagnostic_context : public diagnostic_context
  {
  public:
    debug_diagnostic_context ()
    {
      diagnostic_initialize (this, 0);
!     m_source_printing.show_line_numbers_p = true;
!     m_source_printing.enabled = true;
    }
    ~debug_diagnostic_context ()
    {
--- 234,251 ----
    return function_point (supernode, from_edge, 0, PK_BEFORE_SUPERNODE);
  }
  
! /* A subclass of diagnostics::context for use by
     program_point::print_source_line.  */
  
! class debug_diagnostic_context : public diagnostics::context
  {
  public:
    debug_diagnostic_context ()
    {
      diagnostic_initialize (this, 0);
!     auto &source_printing_opts = get_source_printing_options ();
!     source_printing_opts.show_line_numbers_p = true;
!     source_printing_opts.enabled = true;
    }
    ~debug_diagnostic_context ()
    {
*************** function_point::print_source_line (prett
*** 263,271 ****
    // TODO: monospace font
    debug_diagnostic_context tmp_dc;
    gcc_rich_location richloc (stmt->location);
!   diagnostic_source_print_policy source_policy (tmp_dc);
    gcc_assert (pp);
!   source_policy.print (*pp, richloc, DK_ERROR, nullptr);
    pp_string (pp, pp_formatted_text (tmp_dc.get_reference_printer ()));
  }
  
--- 264,272 ----
    // TODO: monospace font
    debug_diagnostic_context tmp_dc;
    gcc_rich_location richloc (stmt->location);
!   diagnostics::source_print_policy source_policy (tmp_dc);
    gcc_assert (pp);
!   source_policy.print (*pp, richloc, diagnostics::kind::error, nullptr);
    pp_string (pp, pp_formatted_text (tmp_dc.get_reference_printer ()));
  }
  
diff -Nrcpad gcc-16-20250720/gcc/analyzer/program-state.cc gcc-16-20250727/gcc/analyzer/program-state.cc
*** gcc-16-20250720/gcc/analyzer/program-state.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/program-state.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 27,34 ****
  #include "gimple-iterator.h"
  #include "cgraph.h"
  #include "digraph.h"
! #include "diagnostic-event-id.h"
! #include "diagnostic-state-graphs.h"
  #include "graphviz.h"
  
  #include "text-art/tree-widget.h"
--- 27,34 ----
  #include "gimple-iterator.h"
  #include "cgraph.h"
  #include "digraph.h"
! #include "diagnostics/event-id.h"
! #include "diagnostics/state-graphs.h"
  #include "graphviz.h"
  
  #include "text-art/tree-widget.h"
diff -Nrcpad gcc-16-20250720/gcc/analyzer/region-model-asm.cc gcc-16-20250727/gcc/analyzer/region-model-asm.cc
*** gcc-16-20250720/gcc/analyzer/region-model-asm.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/region-model-asm.cc	Sun Jul 27 22:32:08 2025
*************** region_model::on_asm_stmt (const gasm *s
*** 171,177 ****
  	 no point in going further.  */
        constraint = constraints[i];
        if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
! 				    &allows_mem, &allows_reg, &is_inout))
  	{
  	  if (logger)
  	    logger->log ("error parsing constraint for output %i: %qs",
--- 171,178 ----
  	 no point in going further.  */
        constraint = constraints[i];
        if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
! 				    &allows_mem, &allows_reg, &is_inout,
! 				    nullptr))
  	{
  	  if (logger)
  	    logger->log ("error parsing constraint for output %i: %qs",
*************** region_model::on_asm_stmt (const gasm *s
*** 204,211 ****
        const char *constraint = constraints[i + noutputs];
        bool allows_reg, allows_mem;
        if (! parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 				    constraints.address (),
! 				    &allows_mem, &allows_reg))
  	{
  	  if (logger)
  	    logger->log ("error parsing constraint for input %i: %qs",
--- 205,212 ----
        const char *constraint = constraints[i + noutputs];
        bool allows_reg, allows_mem;
        if (! parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 				    constraints.address (), &allows_mem,
! 				    &allows_reg, nullptr))
  	{
  	  if (logger)
  	    logger->log ("error parsing constraint for input %i: %qs",
diff -Nrcpad gcc-16-20250720/gcc/analyzer/region-model.cc gcc-16-20250727/gcc/analyzer/region-model.cc
*** gcc-16-20250720/gcc/analyzer/region-model.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/region-model.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 26,32 ****
  #include "cgraph.h"
  #include "cfg.h"
  #include "sbitmap.h"
! #include "diagnostic-event-id.h"
  #include "stor-layout.h"
  #include "stringpool.h"
  #include "attribs.h"
--- 26,32 ----
  #include "cgraph.h"
  #include "cfg.h"
  #include "sbitmap.h"
! #include "diagnostics/event-id.h"
  #include "stor-layout.h"
  #include "stringpool.h"
  #include "attribs.h"
*************** along with GCC; see the file COPYING3.
*** 40,46 ****
  #include "is-a.h"
  #include "gcc-rich-location.h"
  #include "gcc-urlifier.h"
! #include "diagnostic-format-sarif.h"
  #include "tree-pretty-print.h"
  #include "fold-const.h"
  #include "selftest-tree.h"
--- 40,46 ----
  #include "is-a.h"
  #include "gcc-rich-location.h"
  #include "gcc-urlifier.h"
! #include "diagnostics/sarif-sink.h"
  #include "tree-pretty-print.h"
  #include "fold-const.h"
  #include "selftest-tree.h"
*************** public:
*** 907,915 ****
    }
  
    void
!   maybe_add_sarif_properties (sarif_object &result_obj) const final override
    {
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/poisoned_value_diagnostic/"
      props.set (PROPERTY_PREFIX "expr", tree_to_json (m_expr));
      props.set_string (PROPERTY_PREFIX "kind", poison_kind_to_str (m_pkind));
--- 907,916 ----
    }
  
    void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
!     const final override
    {
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/poisoned_value_diagnostic/"
      props.set (PROPERTY_PREFIX "expr", tree_to_json (m_expr));
      props.set_string (PROPERTY_PREFIX "kind", poison_kind_to_str (m_pkind));
*************** public:
*** 3835,3844 ****
      interest->add_region_creation (m_rhs);
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const final override
    {
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/dubious_allocation_size/"
      props.set (PROPERTY_PREFIX "lhs", m_lhs->to_json ());
      props.set (PROPERTY_PREFIX "rhs", m_rhs->to_json ());
--- 3836,3846 ----
      interest->add_region_creation (m_rhs);
    }
  
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const final override
    {
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/dubious_allocation_size/"
      props.set (PROPERTY_PREFIX "lhs", m_lhs->to_json ());
      props.set (PROPERTY_PREFIX "rhs", m_rhs->to_json ());
*************** public:
*** 7595,7603 ****
    }
  
    void
!   maybe_add_sarif_properties (sarif_object &result_obj) const final override
    {
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/-Wanalyzer-exposure-through-uninit-copy/"
      props.set (PROPERTY_PREFIX "src_region", m_src_region->to_json ());
      props.set (PROPERTY_PREFIX "dest_region", m_dest_region->to_json ());
--- 7597,7606 ----
    }
  
    void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
!     const final override
    {
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/-Wanalyzer-exposure-through-uninit-copy/"
      props.set (PROPERTY_PREFIX "src_region", m_src_region->to_json ());
      props.set (PROPERTY_PREFIX "dest_region", m_dest_region->to_json ());
diff -Nrcpad gcc-16-20250720/gcc/analyzer/sm-fd.cc gcc-16-20250727/gcc/analyzer/sm-fd.cc
*** gcc-16-20250720/gcc/analyzer/sm-fd.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/sm-fd.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 20,26 ****
  
  #include "analyzer/common.h"
  
! #include "diagnostic-event-id.h"
  #include "stringpool.h"
  #include "attribs.h"
  
--- 20,26 ----
  
  #include "analyzer/common.h"
  
! #include "diagnostics/event-id.h"
  #include "stringpool.h"
  #include "attribs.h"
  
*************** public:
*** 392,412 ****
      return false;
    }
  
!   diagnostic_event::meaning
    get_meaning_for_state_change (
        const evdesc::state_change &change) const final override
    {
      if (change.m_old_state == m_sm.get_start_state ()
  	&& (m_sm.is_unchecked_fd_p (change.m_new_state)
  	    || change.m_new_state == m_sm.m_new_datagram_socket
  	    || change.m_new_state == m_sm.m_new_stream_socket
  	    || change.m_new_state == m_sm.m_new_unknown_socket))
!       return diagnostic_event::meaning (diagnostic_event::verb::acquire,
! 					diagnostic_event::noun::resource);
      if (change.m_new_state == m_sm.m_closed)
!       return diagnostic_event::meaning (diagnostic_event::verb::release,
! 					diagnostic_event::noun::resource);
!     return diagnostic_event::meaning ();
    }
  
  protected:
--- 392,413 ----
      return false;
    }
  
!   diagnostics::paths::event::meaning
    get_meaning_for_state_change (
        const evdesc::state_change &change) const final override
    {
+     using event = diagnostics::paths::event;
      if (change.m_old_state == m_sm.get_start_state ()
  	&& (m_sm.is_unchecked_fd_p (change.m_new_state)
  	    || change.m_new_state == m_sm.m_new_datagram_socket
  	    || change.m_new_state == m_sm.m_new_stream_socket
  	    || change.m_new_state == m_sm.m_new_unknown_socket))
!       return event::meaning (event::verb::acquire,
! 			     event::noun::resource);
      if (change.m_new_state == m_sm.m_closed)
!       return event::meaning (event::verb::release,
! 			     event::noun::resource);
!     return event::meaning ();
    }
  
  protected:
*************** public:
*** 561,567 ****
    }
  
  private:
!   diagnostic_event_id_t m_open_event;
    std::unique_ptr<program_state> m_final_state;
  };
  
--- 562,568 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_open_event;
    std::unique_ptr<program_state> m_final_state;
  };
  
*************** public:
*** 705,711 ****
    }
  
  private:
!   diagnostic_event_id_t m_first_close_event;
  };
  
  class fd_use_after_close : public fd_param_diagnostic
--- 706,712 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_first_close_event;
  };
  
  class fd_use_after_close : public fd_param_diagnostic
*************** public:
*** 784,790 ****
    }
  
  private:
!   diagnostic_event_id_t m_first_close_event;
  };
  
  class fd_use_without_check : public fd_param_diagnostic
--- 785,791 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_first_close_event;
  };
  
  class fd_use_without_check : public fd_param_diagnostic
*************** public:
*** 854,860 ****
    }
  
  private:
!   diagnostic_event_id_t m_first_open_event;
  };
  
  /* Concrete pending_diagnostic subclass for -Wanalyzer-fd-phase-mismatch.  */
--- 855,861 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_first_open_event;
  };
  
  /* Concrete pending_diagnostic subclass for -Wanalyzer-fd-phase-mismatch.  */
diff -Nrcpad gcc-16-20250720/gcc/analyzer/sm-file.cc gcc-16-20250727/gcc/analyzer/sm-file.cc
*** gcc-16-20250720/gcc/analyzer/sm-file.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/sm-file.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 20,26 ****
  
  #include "analyzer/common.h"
  
! #include "diagnostic-event-id.h"
  #include "selftest.h"
  
  #include "analyzer/analyzer-logging.h"
--- 20,26 ----
  
  #include "analyzer/common.h"
  
! #include "diagnostics/event-id.h"
  #include "selftest.h"
  
  #include "analyzer/analyzer-logging.h"
*************** public:
*** 155,172 ****
      return false;
    }
  
!   diagnostic_event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
      if (change.m_old_state == m_sm.get_start_state ()
  	&& change.m_new_state == m_sm.m_unchecked)
!       return diagnostic_event::meaning (diagnostic_event::verb::acquire,
! 					diagnostic_event::noun::resource);
      if (change.m_new_state == m_sm.m_closed)
!       return diagnostic_event::meaning (diagnostic_event::verb::release,
! 					diagnostic_event::noun::resource);
!     return diagnostic_event::meaning ();
    }
  
  protected:
--- 155,174 ----
      return false;
    }
  
!   diagnostics::paths::event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
+     using event = diagnostics::paths::event;
+ 
      if (change.m_old_state == m_sm.get_start_state ()
  	&& change.m_new_state == m_sm.m_unchecked)
!       return event::meaning (event::verb::acquire,
! 			     event::noun::resource);
      if (change.m_new_state == m_sm.m_closed)
!       return event::meaning (event::verb::release,
! 			     event::noun::resource);
!     return event::meaning ();
    }
  
  protected:
*************** public:
*** 225,231 ****
    }
  
  private:
!   diagnostic_event_id_t m_first_fclose_event;
  };
  
  class file_leak : public file_diagnostic
--- 227,233 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_first_fclose_event;
  };
  
  class file_leak : public file_diagnostic
*************** public:
*** 303,309 ****
    }
  
  private:
!   diagnostic_event_id_t m_fopen_event;
    std::unique_ptr<program_state> m_final_state;
  };
  
--- 305,311 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_fopen_event;
    std::unique_ptr<program_state> m_final_state;
  };
  
diff -Nrcpad gcc-16-20250720/gcc/analyzer/sm-malloc.cc gcc-16-20250727/gcc/analyzer/sm-malloc.cc
*** gcc-16-20250720/gcc/analyzer/sm-malloc.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/sm-malloc.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 20,26 ****
  
  #include "analyzer/common.h"
  
! #include "diagnostic-event-id.h"
  #include "stringpool.h"
  #include "attribs.h"
  #include "xml-printer.h"
--- 20,26 ----
  
  #include "analyzer/common.h"
  
! #include "diagnostics/event-id.h"
  #include "stringpool.h"
  #include "attribs.h"
  #include "xml-printer.h"
*************** public:
*** 814,831 ****
      return false;
    }
  
!   diagnostic_event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
      if (change.m_old_state == m_sm.get_start_state ()
  	&& unchecked_p (change.m_new_state))
!       return diagnostic_event::meaning (diagnostic_event::verb::acquire,
! 					diagnostic_event::noun::memory);
      if (freed_p (change.m_new_state))
!       return diagnostic_event::meaning (diagnostic_event::verb::release,
! 					diagnostic_event::noun::memory);
!     return diagnostic_event::meaning ();
    }
  
  protected:
--- 814,831 ----
      return false;
    }
  
!   diagnostics::paths::event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
      if (change.m_old_state == m_sm.get_start_state ()
  	&& unchecked_p (change.m_new_state))
!       return diagnostics::paths::event::meaning (diagnostics::paths::event::verb::acquire,
! 					diagnostics::paths::event::noun::memory);
      if (freed_p (change.m_new_state))
!       return diagnostics::paths::event::meaning (diagnostics::paths::event::verb::release,
! 					diagnostics::paths::event::noun::memory);
!     return diagnostics::paths::event::meaning ();
    }
  
  protected:
*************** public:
*** 918,924 ****
    }
  
  private:
!   diagnostic_event_id_t m_alloc_event;
    const deallocator_set *m_expected_deallocators;
    const deallocator *m_actual_dealloc;
  };
--- 918,924 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_alloc_event;
    const deallocator_set *m_expected_deallocators;
    const deallocator *m_actual_dealloc;
  };
*************** public:
*** 988,994 ****
    }
  
  private:
!   diagnostic_event_id_t m_first_free_event;
    const char *m_funcname;
  };
  
--- 988,994 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_first_free_event;
    const char *m_funcname;
  };
  
*************** public:
*** 1031,1037 ****
    }
  
  protected:
!   diagnostic_event_id_t m_origin_of_unchecked_event;
  };
  
  /* Concrete subclass for describing dereference of a possible NULL
--- 1031,1037 ----
    }
  
  protected:
!   diagnostics::paths::event_id_t m_origin_of_unchecked_event;
  };
  
  /* Concrete subclass for describing dereference of a possible NULL
*************** public:
*** 1419,1425 ****
    }
  
  private:
!   diagnostic_event_id_t m_free_event;
    const deallocator *m_deallocator;
  };
  
--- 1419,1425 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_free_event;
    const deallocator *m_deallocator;
  };
  
*************** public:
*** 1500,1506 ****
    }
  
  private:
!   diagnostic_event_id_t m_alloc_event;
    std::unique_ptr<program_state> m_final_state;
  };
  
--- 1500,1506 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_alloc_event;
    std::unique_ptr<program_state> m_final_state;
  };
  
*************** private:
*** 1768,1774 ****
      return result;
    }
  
!   diagnostic_event_id_t m_first_deref_event;
    const exploded_node *m_deref_enode;
    tree m_deref_expr;
    const exploded_node *m_check_enode;
--- 1768,1774 ----
      return result;
    }
  
!   diagnostics::paths::event_id_t m_first_deref_event;
    const exploded_node *m_deref_enode;
    tree m_deref_expr;
    const exploded_node *m_check_enode;
diff -Nrcpad gcc-16-20250720/gcc/analyzer/sm-pattern-test.cc gcc-16-20250727/gcc/analyzer/sm-pattern-test.cc
*** gcc-16-20250720/gcc/analyzer/sm-pattern-test.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/sm-pattern-test.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 23,29 ****
  #include "analyzer/common.h"
  
  #include "tree-pretty-print.h"
! #include "diagnostic-event-id.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/sm.h"
--- 23,29 ----
  #include "analyzer/common.h"
  
  #include "tree-pretty-print.h"
! #include "diagnostics/event-id.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/sm.h"
diff -Nrcpad gcc-16-20250720/gcc/analyzer/sm-sensitive.cc gcc-16-20250727/gcc/analyzer/sm-sensitive.cc
*** gcc-16-20250720/gcc/analyzer/sm-sensitive.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/sm-sensitive.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 21,27 ****
  
  #include "analyzer/common.h"
  
! #include "diagnostic-event-id.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/sm.h"
--- 21,27 ----
  
  #include "analyzer/common.h"
  
! #include "diagnostics/event-id.h"
  
  #include "analyzer/analyzer-logging.h"
  #include "analyzer/sm.h"
*************** public:
*** 106,119 ****
      return false;
    }
  
!   diagnostic_event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
      if (change.m_new_state == m_sm.m_sensitive)
!       return diagnostic_event::meaning (diagnostic_event::verb::acquire,
! 					diagnostic_event::noun::sensitive);
!     return diagnostic_event::meaning ();
    }
    bool
    describe_call_with_state (pretty_printer &pp,
--- 106,120 ----
      return false;
    }
  
!   diagnostics::paths::event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
+     using event = diagnostics::paths::event;
+ 
      if (change.m_new_state == m_sm.m_sensitive)
!       return event::meaning (event::verb::acquire, event::noun::sensitive);
!     return event::meaning ();
    }
    bool
    describe_call_with_state (pretty_printer &pp,
*************** public:
*** 162,168 ****
  private:
    const sensitive_state_machine &m_sm;
    tree m_arg;
!   diagnostic_event_id_t m_first_sensitive_event;
  };
  
  /* sensitive_state_machine's ctor.  */
--- 163,169 ----
  private:
    const sensitive_state_machine &m_sm;
    tree m_arg;
!   diagnostics::paths::event_id_t m_first_sensitive_event;
  };
  
  /* sensitive_state_machine's ctor.  */
diff -Nrcpad gcc-16-20250720/gcc/analyzer/sm-signal.cc gcc-16-20250727/gcc/analyzer/sm-signal.cc
*** gcc-16-20250720/gcc/analyzer/sm-signal.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/sm-signal.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 22,28 ****
  
  #include "analyzer/common.h"
  
! #include "diagnostic-event-id.h"
  #include "sbitmap.h"
  #include "ordered-hash-map.h"
  #include "selftest.h"
--- 22,28 ----
  
  #include "analyzer/common.h"
  
! #include "diagnostics/event-id.h"
  #include "sbitmap.h"
  #include "ordered-hash-map.h"
  #include "selftest.h"
diff -Nrcpad gcc-16-20250720/gcc/analyzer/sm-taint.cc gcc-16-20250727/gcc/analyzer/sm-taint.cc
*** gcc-16-20250720/gcc/analyzer/sm-taint.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/sm-taint.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 30,36 ****
  #include "stringpool.h"
  #include "attribs.h"
  #include "fold-const.h"
! #include "diagnostic-format-sarif.h"
  #include "gcc-urlifier.h"
  
  #include "analyzer/analyzer-logging.h"
--- 30,36 ----
  #include "stringpool.h"
  #include "attribs.h"
  #include "fold-const.h"
! #include "diagnostics/sarif-sink.h"
  #include "gcc-urlifier.h"
  
  #include "analyzer/analyzer-logging.h"
*************** public:
*** 209,228 ****
      return false;
    }
  
!   diagnostic_event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
      if (change.m_new_state == m_sm.m_tainted)
!       return diagnostic_event::meaning (diagnostic_event::verb::acquire,
! 					diagnostic_event::noun::taint);
!     return diagnostic_event::meaning ();
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const override
    {
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/taint_diagnostic/"
      props.set (PROPERTY_PREFIX "arg", tree_to_json (m_arg));
      props.set_string (PROPERTY_PREFIX "has_bounds",
--- 209,230 ----
      return false;
    }
  
!   diagnostics::paths::event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
+     using event = diagnostics::paths::event;
      if (change.m_new_state == m_sm.m_tainted)
!       return event::meaning (event::verb::acquire,
! 			     event::noun::taint);
!     return event::meaning ();
    }
  
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const override
    {
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/taint_diagnostic/"
      props.set (PROPERTY_PREFIX "arg", tree_to_json (m_arg));
      props.set_string (PROPERTY_PREFIX "has_bounds",
*************** public:
*** 495,505 ****
  	}
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const final override
    {
      taint_diagnostic::maybe_add_sarif_properties (result_obj);
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/tainted_offset/"
      props.set (PROPERTY_PREFIX "offset", m_offset->to_json ());
  #undef PROPERTY_PREFIX
--- 497,508 ----
  	}
    }
  
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const final override
    {
      taint_diagnostic::maybe_add_sarif_properties (result_obj);
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/tainted_offset/"
      props.set (PROPERTY_PREFIX "offset", m_offset->to_json ());
  #undef PROPERTY_PREFIX
*************** public:
*** 864,874 ****
  	}
    }
  
!   void maybe_add_sarif_properties (sarif_object &result_obj)
      const final override
    {
      taint_diagnostic::maybe_add_sarif_properties (result_obj);
!     sarif_property_bag &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/tainted_allocation_size/"
      props.set (PROPERTY_PREFIX "size_in_bytes", m_size_in_bytes->to_json ());
  #undef PROPERTY_PREFIX
--- 867,878 ----
  	}
    }
  
!   void
!   maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
      const final override
    {
      taint_diagnostic::maybe_add_sarif_properties (result_obj);
!     auto &props = result_obj.get_or_create_properties ();
  #define PROPERTY_PREFIX "gcc/analyzer/tainted_allocation_size/"
      props.set (PROPERTY_PREFIX "size_in_bytes", m_size_in_bytes->to_json ());
  #undef PROPERTY_PREFIX
diff -Nrcpad gcc-16-20250720/gcc/analyzer/varargs.cc gcc-16-20250727/gcc/analyzer/varargs.cc
*** gcc-16-20250720/gcc/analyzer/varargs.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/analyzer/varargs.cc	Sun Jul 27 22:32:08 2025
*************** public:
*** 334,350 ****
      return false;
    }
  
!   diagnostic_event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
      if (change.m_new_state == m_sm.m_started)
!       return diagnostic_event::meaning (diagnostic_event::verb::acquire,
! 					diagnostic_event::noun::resource);
      if (change.m_new_state == m_sm.m_ended)
!       return diagnostic_event::meaning (diagnostic_event::verb::release,
! 					diagnostic_event::noun::resource);
!     return diagnostic_event::meaning ();
    }
  
  protected:
--- 334,350 ----
      return false;
    }
  
!   diagnostics::paths::event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
      if (change.m_new_state == m_sm.m_started)
!       return diagnostics::paths::event::meaning (diagnostics::paths::event::verb::acquire,
! 					diagnostics::paths::event::noun::resource);
      if (change.m_new_state == m_sm.m_ended)
!       return diagnostics::paths::event::meaning (diagnostics::paths::event::verb::release,
! 					diagnostics::paths::event::noun::resource);
!     return diagnostics::paths::event::meaning ();
    }
  
  protected:
*************** public:
*** 452,458 ****
    }
  
  private:
!   diagnostic_event_id_t m_va_end_event;
    const char *m_usage_fnname;
  };
  
--- 452,458 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_va_end_event;
    const char *m_usage_fnname;
  };
  
*************** public:
*** 539,545 ****
    }
  
  private:
!   diagnostic_event_id_t m_start_event;
    const char *m_start_event_fnname;
    std::unique_ptr<program_state> m_final_state;
  };
--- 539,545 ----
    }
  
  private:
!   diagnostics::paths::event_id_t m_start_event;
    const char *m_start_event_fnname;
    std::unique_ptr<program_state> m_final_state;
  };
diff -Nrcpad gcc-16-20250720/gcc/c/ChangeLog gcc-16-20250727/gcc/c/ChangeLog
*** gcc-16-20250720/gcc/c/ChangeLog	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c/ChangeLog	Sun Jul 27 22:32:08 2025
***************
*** 1,3 ****
--- 1,38 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-errors.cc: Update usage of "diagnostic_info" to explicitly
+ 	refer to "diagnostics::diagnostic_info".
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-errors.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* c-parser.cc: Likewise.
+ 	* c-typeck.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-decl.cc: Update for renaming of diagnostic_option_id to
+ 	diagnostics::option_id.
+ 	* c-errors.cc: Likewise.
+ 	* c-tree.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-objc-common.cc: Update for diagnostic_context becoming
+ 	diagnostics::context.
+ 	* c-tree.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-errors.cc: Update to add "m_" prefix to fields of
+ 	diagnostic_info throughout.
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* c-typeck.cc (build_asm_expr): Pass null pointer to
+ 	parse_{input,output}_constraint().
+ 
  2025-07-16  Kwok Cheung Yeung  <kcyeung@baylibre.com>
  
  	* c-typeck.cc (handle_omp_array_sections): Use OMP_ITERATOR_DECL_P.
diff -Nrcpad gcc-16-20250720/gcc/c/c-decl.cc gcc-16-20250727/gcc/c/c-decl.cc
*** gcc-16-20250720/gcc/c/c-decl.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c/c-decl.cc	Sun Jul 27 22:32:08 2025
*************** lookup_name_fuzzy (tree name, enum looku
*** 4556,4562 ****
    /* Next, look for exact matches for builtin defines that would have been
       defined if the user had passed a command-line option (e.g. -fopenmp
       for "_OPENMP").  */
!   diagnostic_option_id option_id
      = get_option_for_builtin_define (IDENTIFIER_POINTER (name));
    if (option_id.m_idx > 0)
      return name_hint
--- 4556,4562 ----
    /* Next, look for exact matches for builtin defines that would have been
       defined if the user had passed a command-line option (e.g. -fopenmp
       for "_OPENMP").  */
!   diagnostics::option_id option_id
      = get_option_for_builtin_define (IDENTIFIER_POINTER (name));
    if (option_id.m_idx > 0)
      return name_hint
diff -Nrcpad gcc-16-20250720/gcc/c/c-errors.cc gcc-16-20250727/gcc/c/c-errors.cc
*** gcc-16-20250720/gcc/c/c-errors.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c/c-errors.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 33,42 ****
  
  bool
  pedwarn_c23 (location_t location,
! 	     diagnostic_option_id option_id,
  	     const char *gmsgid, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    bool warned = false;
    rich_location richloc (line_table, location);
--- 33,42 ----
  
  bool
  pedwarn_c23 (location_t location,
! 	     diagnostics::option_id option_id,
  	     const char *gmsgid, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    bool warned = false;
    rich_location richloc (line_table, location);
*************** pedwarn_c23 (location_t location,
*** 48,55 ****
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			   (pedantic && !flag_isoc2y)
! 			   ? DK_PEDWARN : DK_WARNING);
!       diagnostic.option_id = OPT_Wc23_c2y_compat;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    /* -Wno-c23-c2y-compat suppresses even the pedwarns.  */
--- 48,56 ----
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			   (pedantic && !flag_isoc2y)
! 			   ? diagnostics::kind::pedwarn
! 			   : diagnostics::kind::warning);
!       diagnostic.m_option_id = OPT_Wc23_c2y_compat;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    /* -Wno-c23-c2y-compat suppresses even the pedwarns.  */
*************** pedwarn_c23 (location_t location,
*** 58,65 ****
    /* For -pedantic outside C2Y, issue a pedwarn.  */
    else if (pedantic && !flag_isoc2y)
      {
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
!       diagnostic.option_id = option_id;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    va_end (ap);
--- 59,67 ----
    /* For -pedantic outside C2Y, issue a pedwarn.  */
    else if (pedantic && !flag_isoc2y)
      {
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
! 			   diagnostics::kind::pedwarn);
!       diagnostic.m_option_id = option_id;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    va_end (ap);
*************** pedwarn_c23 (location_t location,
*** 77,86 ****
  
  bool
  pedwarn_c11 (location_t location,
! 	     diagnostic_option_id option_id,
  	     const char *gmsgid, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    bool warned = false;
    rich_location richloc (line_table, location);
--- 79,88 ----
  
  bool
  pedwarn_c11 (location_t location,
! 	     diagnostics::option_id option_id,
  	     const char *gmsgid, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    bool warned = false;
    rich_location richloc (line_table, location);
*************** pedwarn_c11 (location_t location,
*** 93,103 ****
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			   (pedantic && !flag_isoc23)
! 			   ? DK_PEDWARN : DK_WARNING);
        if (option_id == OPT_Wpedantic)
! 	diagnostic.option_id = OPT_Wc11_c23_compat;
        else
! 	diagnostic.option_id = option_id;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    /* -Wno-c11-c23-compat suppresses even the pedwarns.  */
--- 95,106 ----
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			   (pedantic && !flag_isoc23)
! 			   ? diagnostics::kind::pedwarn
! 			   : diagnostics::kind::warning);
        if (option_id == OPT_Wpedantic)
! 	diagnostic.m_option_id = OPT_Wc11_c23_compat;
        else
! 	diagnostic.m_option_id = option_id;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    /* -Wno-c11-c23-compat suppresses even the pedwarns.  */
*************** pedwarn_c11 (location_t location,
*** 106,113 ****
    /* For -pedantic outside C23, issue a pedwarn.  */
    else if (pedantic && !flag_isoc23)
      {
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
!       diagnostic.option_id = option_id;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    va_end (ap);
--- 109,117 ----
    /* For -pedantic outside C23, issue a pedwarn.  */
    else if (pedantic && !flag_isoc23)
      {
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
! 			   diagnostics::kind::pedwarn);
!       diagnostic.m_option_id = option_id;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    va_end (ap);
*************** pedwarn_c11 (location_t location,
*** 122,131 ****
  
  bool
  pedwarn_c99 (location_t location,
! 	     diagnostic_option_id option_id,
  	     const char *gmsgid, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    bool warned = false;
    rich_location richloc (line_table, location);
--- 126,135 ----
  
  bool
  pedwarn_c99 (location_t location,
! 	     diagnostics::option_id option_id,
  	     const char *gmsgid, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    bool warned = false;
    rich_location richloc (line_table, location);
*************** pedwarn_c99 (location_t location,
*** 137,144 ****
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			   (pedantic && !flag_isoc11)
! 			   ? DK_PEDWARN : DK_WARNING);
!       diagnostic.option_id = OPT_Wc99_c11_compat;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    /* -Wno-c99-c11-compat suppresses even the pedwarns.  */
--- 141,149 ----
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			   (pedantic && !flag_isoc11)
! 			   ? diagnostics::kind::pedwarn
! 			   : diagnostics::kind::warning);
!       diagnostic.m_option_id = OPT_Wc99_c11_compat;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    /* -Wno-c99-c11-compat suppresses even the pedwarns.  */
*************** pedwarn_c99 (location_t location,
*** 147,154 ****
    /* For -pedantic outside C11, issue a pedwarn.  */
    else if (pedantic && !flag_isoc11)
      {
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
!       diagnostic.option_id = option_id;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    va_end (ap);
--- 152,160 ----
    /* For -pedantic outside C11, issue a pedwarn.  */
    else if (pedantic && !flag_isoc11)
      {
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
! 			   diagnostics::kind::pedwarn);
!       diagnostic.m_option_id = option_id;
        warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    va_end (ap);
*************** pedwarn_c99 (location_t location,
*** 164,173 ****
  
  bool
  pedwarn_c90 (location_t location,
! 	     diagnostic_option_id option_id,
  	     const char *gmsgid, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    bool warned = false;
    rich_location richloc (line_table, location);
--- 170,179 ----
  
  bool
  pedwarn_c90 (location_t location,
! 	     diagnostics::option_id option_id,
  	     const char *gmsgid, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    bool warned = false;
    rich_location richloc (line_table, location);
*************** pedwarn_c90 (location_t location,
*** 183,190 ****
  	{
  	  diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			       (pedantic && !flag_isoc99)
! 			       ? DK_PEDWARN : DK_WARNING);
! 	  diagnostic.option_id = option_id;
  	  diagnostic_report_diagnostic (global_dc, &diagnostic);
  	  warned = true;
  	  goto out;
--- 189,197 ----
  	{
  	  diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			       (pedantic && !flag_isoc99)
! 			       ? diagnostics::kind::pedwarn
! 			       : diagnostics::kind::warning);
! 	  diagnostic.m_option_id = option_id;
  	  diagnostic_report_diagnostic (global_dc, &diagnostic);
  	  warned = true;
  	  goto out;
*************** pedwarn_c90 (location_t location,
*** 196,203 ****
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			   (pedantic && !flag_isoc99)
! 			   ? DK_PEDWARN : DK_WARNING);
!       diagnostic.option_id = OPT_Wc90_c99_compat;
        diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    /* -Wno-c90-c99-compat suppresses the pedwarns.  */
--- 203,211 ----
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
  			   (pedantic && !flag_isoc99)
! 			   ? diagnostics::kind::pedwarn
! 			   : diagnostics::kind::warning);
!       diagnostic.m_option_id = OPT_Wc90_c99_compat;
        diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    /* -Wno-c90-c99-compat suppresses the pedwarns.  */
*************** pedwarn_c90 (location_t location,
*** 206,213 ****
    /* For -pedantic outside C99, issue a pedwarn.  */
    else if (pedantic && !flag_isoc99)
      {
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
!       diagnostic.option_id = option_id;
        diagnostic_report_diagnostic (global_dc, &diagnostic);
        warned = true;
      }
--- 214,222 ----
    /* For -pedantic outside C99, issue a pedwarn.  */
    else if (pedantic && !flag_isoc99)
      {
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
! 			   diagnostics::kind::pedwarn);
!       diagnostic.m_option_id = option_id;
        diagnostic_report_diagnostic (global_dc, &diagnostic);
        warned = true;
      }
diff -Nrcpad gcc-16-20250720/gcc/c/c-objc-common.cc gcc-16-20250727/gcc/c/c-objc-common.cc
*** gcc-16-20250720/gcc/c/c-objc-common.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c/c-objc-common.cc	Sun Jul 27 22:32:08 2025
*************** has_c_linkage (const_tree decl ATTRIBUTE
*** 414,420 ****
  }
  
  void
! c_initialize_diagnostics (diagnostic_context *context)
  {
    context->set_pretty_printer (std::make_unique<c_pretty_printer> ());
    c_common_diagnostics_set_defaults (context);
--- 414,420 ----
  }
  
  void
! c_initialize_diagnostics (diagnostics::context *context)
  {
    context->set_pretty_printer (std::make_unique<c_pretty_printer> ());
    c_common_diagnostics_set_defaults (context);
diff -Nrcpad gcc-16-20250720/gcc/c/c-parser.cc gcc-16-20250727/gcc/c/c-parser.cc
*** gcc-16-20250720/gcc/c/c-parser.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c/c-parser.cc	Sun Jul 27 22:32:08 2025
*************** c_parser_omp_error (c_parser *parser, en
*** 29162,29172 ****
        if (msg == NULL)
  	msg = _("<message unknown at compile time>");
      }
    if (msg)
!     emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
  		     "%<pragma omp error%> encountered: %s", msg);
    else
!     emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
  		     "%<pragma omp error%> encountered");
    return false;
  }
--- 29162,29175 ----
        if (msg == NULL)
  	msg = _("<message unknown at compile time>");
      }
+   const enum diagnostics::kind diag_kind = (severity_fatal
+ 					    ? diagnostics::kind::error
+ 					    : diagnostics::kind::warning);
    if (msg)
!     emit_diagnostic (diag_kind, loc, 0,
  		     "%<pragma omp error%> encountered: %s", msg);
    else
!     emit_diagnostic (diag_kind, loc, 0,
  		     "%<pragma omp error%> encountered");
    return false;
  }
diff -Nrcpad gcc-16-20250720/gcc/c/c-tree.h gcc-16-20250727/gcc/c/c-tree.h
*** gcc-16-20250720/gcc/c/c-tree.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c/c-tree.h	Sun Jul 27 22:32:08 2025
*************** extern tree c_finish_bc_name (location_t
*** 757,763 ****
  extern bool c_objc_common_init (void);
  extern bool c_missing_noreturn_ok_p (tree);
  extern bool c_warn_unused_global_decl (const_tree);
! extern void c_initialize_diagnostics (diagnostic_context *);
  extern bool c_var_mod_p (tree x, tree fn);
  extern alias_set_type c_get_alias_set (tree);
  extern int c_type_dwarf_attribute (const_tree, int);
--- 757,763 ----
  extern bool c_objc_common_init (void);
  extern bool c_missing_noreturn_ok_p (tree);
  extern bool c_warn_unused_global_decl (const_tree);
! extern void c_initialize_diagnostics (diagnostics::context *);
  extern bool c_var_mod_p (tree x, tree fn);
  extern alias_set_type c_get_alias_set (tree);
  extern int c_type_dwarf_attribute (const_tree, int);
*************** extern void c_bind (location_t, tree, bo
*** 960,972 ****
  extern bool tag_exists_p (enum tree_code, tree);
  
  /* In c-errors.cc */
! extern bool pedwarn_c90 (location_t, diagnostic_option_id, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
! extern bool pedwarn_c99 (location_t, diagnostic_option_id, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
! extern bool pedwarn_c11 (location_t, diagnostic_option_id, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
! extern bool pedwarn_c23 (location_t, diagnostic_option_id, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
  extern void add_note_about_new_keyword (location_t loc,
  					tree keyword_id);
--- 960,972 ----
  extern bool tag_exists_p (enum tree_code, tree);
  
  /* In c-errors.cc */
! extern bool pedwarn_c90 (location_t, diagnostics::option_id, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
! extern bool pedwarn_c99 (location_t, diagnostics::option_id, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
! extern bool pedwarn_c11 (location_t, diagnostics::option_id, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
! extern bool pedwarn_c23 (location_t, diagnostics::option_id, const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
  extern void add_note_about_new_keyword (location_t loc,
  					tree keyword_id);
diff -Nrcpad gcc-16-20250720/gcc/c/c-typeck.cc gcc-16-20250727/gcc/c/c-typeck.cc
*** gcc-16-20250720/gcc/c/c-typeck.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c/c-typeck.cc	Sun Jul 27 22:32:08 2025
*************** build_conditional_expr (location_t colon
*** 6433,6446 ****
        else
  	{
  	  int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
! 	  diagnostic_t kind = DK_PERMERROR;
  	  if (!flag_isoc99)
  	    /* This downgrade to a warning ensures that -std=gnu89
  	       -pedantic-errors does not flag these mismatches between
! 	       builtins as errors (as DK_PERMERROR would).  ISO C99
! 	       and later do not have implicit function declarations,
  	       so the mismatch cannot occur naturally there.  */
! 	    kind = bltin1 && bltin2 ? DK_WARNING : DK_PEDWARN;
  	  if (emit_diagnostic (kind, colon_loc, OPT_Wincompatible_pointer_types,
  			       "pointer type mismatch "
  			       "in conditional expression"))
--- 6433,6448 ----
        else
  	{
  	  int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
! 	  enum diagnostics::kind kind = diagnostics::kind::permerror;
  	  if (!flag_isoc99)
  	    /* This downgrade to a warning ensures that -std=gnu89
  	       -pedantic-errors does not flag these mismatches between
! 	       builtins as errors (as diagnostics::kind::permerror would)
! 	       ISO C99 and later do not have implicit function declarations,
  	       so the mismatch cannot occur naturally there.  */
! 	    kind = (bltin1 && bltin2
! 		    ? diagnostics::kind::warning
! 		    : diagnostics::kind::pedwarn);
  	  if (emit_diagnostic (kind, colon_loc, OPT_Wincompatible_pointer_types,
  			       "pointer type mismatch "
  			       "in conditional expression"))
*************** error_init (location_t loc, const char *
*** 7598,7604 ****
    /* The gmsgid may be a format string with %< and %>. */
    va_list ap;
    va_start (ap, gmsgid);
!   bool warned = emit_diagnostic_valist (DK_ERROR, loc, -1, gmsgid, &ap);
    va_end (ap);
  
    ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
--- 7600,7607 ----
    /* The gmsgid may be a format string with %< and %>. */
    va_list ap;
    va_start (ap, gmsgid);
!   bool warned = emit_diagnostic_valist (diagnostics::kind::error,
! 					loc, -1, gmsgid, &ap);
    va_end (ap);
  
    ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
*************** error_init (location_t loc, const char *
*** 7610,7616 ****
  
  static bool ATTRIBUTE_GCC_DIAG (3,0)
  pedwarn_permerror_init (location_t loc, int opt, const char *gmsgid,
! 			va_list *ap, diagnostic_t kind)
  {
    /* Use the location where a macro was expanded rather than where
       it was defined to make sure macros defined in system headers
--- 7613,7619 ----
  
  static bool ATTRIBUTE_GCC_DIAG (3,0)
  pedwarn_permerror_init (location_t loc, int opt, const char *gmsgid,
! 			va_list *ap, enum diagnostics::kind kind)
  {
    /* Use the location where a macro was expanded rather than where
       it was defined to make sure macros defined in system headers
*************** pedwarn_init (location_t loc, int opt, c
*** 7637,7643 ****
  {
    va_list ap;
    va_start (ap, gmsgid);
!   bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap, DK_PEDWARN);
    va_end (ap);
    return warned;
  }
--- 7640,7647 ----
  {
    va_list ap;
    va_start (ap, gmsgid);
!   bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap,
! 					diagnostics::kind::pedwarn);
    va_end (ap);
    return warned;
  }
*************** permerror_init (location_t loc, int opt,
*** 7649,7655 ****
  {
    va_list ap;
    va_start (ap, gmsgid);
!   bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap, DK_PERMERROR);
    va_end (ap);
    return warned;
  }
--- 7653,7660 ----
  {
    va_list ap;
    va_start (ap, gmsgid);
!   bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap,
! 					diagnostics::kind::permerror);
    va_end (ap);
    return warned;
  }
*************** build_asm_expr (location_t loc, tree str
*** 12646,12652 ****
        oconstraints[i] = constraint;
  
        if (parse_output_constraint (&constraint, i, ninputs, noutputs,
! 				   &allows_mem, &allows_reg, &is_inout))
  	{
  	  /* If the operand is going to end up in memory,
  	     mark it addressable.  */
--- 12651,12658 ----
        oconstraints[i] = constraint;
  
        if (parse_output_constraint (&constraint, i, ninputs, noutputs,
! 				   &allows_mem, &allows_reg, &is_inout,
! 				   nullptr))
  	{
  	  /* If the operand is going to end up in memory,
  	     mark it addressable.  */
*************** build_asm_expr (location_t loc, tree str
*** 12707,12713 ****
        input = TREE_VALUE (tail);
  
        if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 				  oconstraints, &allows_mem, &allows_reg))
  	{
  	  /* If the operand is going to end up in memory,
  	     mark it addressable.  */
--- 12713,12720 ----
        input = TREE_VALUE (tail);
  
        if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 				  oconstraints, &allows_mem, &allows_reg,
! 				  nullptr))
  	{
  	  /* If the operand is going to end up in memory,
  	     mark it addressable.  */
*************** c_finish_return (location_t loc, tree re
*** 12889,12895 ****
  	  && valtype != NULL_TREE && TREE_CODE (valtype) != VOID_TYPE)
  	{
  	  no_warning = true;
! 	  if (emit_diagnostic (flag_isoc99 ? DK_PERMERROR : DK_WARNING,
  			       loc, OPT_Wreturn_mismatch,
  			       "%<return%> with no value,"
  			       " in function returning non-void"))
--- 12896,12904 ----
  	  && valtype != NULL_TREE && TREE_CODE (valtype) != VOID_TYPE)
  	{
  	  no_warning = true;
! 	  if (emit_diagnostic (flag_isoc99
! 			       ? diagnostics::kind::permerror
! 			       : diagnostics::kind::warning,
  			       loc, OPT_Wreturn_mismatch,
  			       "%<return%> with no value,"
  			       " in function returning non-void"))
diff -Nrcpad gcc-16-20250720/gcc/c-family/ChangeLog gcc-16-20250727/gcc/c-family/ChangeLog
*** gcc-16-20250720/gcc/c-family/ChangeLog	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/ChangeLog	Sun Jul 27 22:32:08 2025
***************
*** 1,3 ****
--- 1,86 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-common.cc: Make diagnostics::context::m_source_printing
+ 	private.
+ 	* c-format.cc: Likewise.
+ 	* c-opts.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-common.cc: Update usage of "diagnostic_info" to explicitly
+ 	refer to "diagnostics::diagnostic_info".
+ 	* c-opts.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-format.cc: Update for file_cache and char_span moving from
+ 	input.h to diagnostics/file-cache.h and into the "diagnostics::"
+ 	namespace.
+ 	* c-indentation.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-common.cc (c_family_tests): Add include of
+ 	"diagnostics/diagnostics-selftests.h".  Replace
+ 	c_diagnostic_cc_tests with
+ 	diagnostics::selftest::context_cc_tests.
+ 	* c-common.h: Drop c_diagnostic_cc_tests decl.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-common.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* c-format.cc: Likewise.
+ 	* c-lex.cc: Likewise.
+ 	* c-opts.cc: Likewise.
+ 	* c-pragma.cc: Likewise.
+ 	* c-warn.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-common.cc: Update for renaming of diagnostic_option_id to
+ 	diagnostics::option_id.
+ 	* c-common.h: Likewise.
+ 	* c-cppbuiltin.cc: Likewise.
+ 	* known-headers.cc: Likewise.
+ 	* known-headers.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-common.cc: Update comment for renaming of edit_context.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-format.cc (test_type_mismatch_range_labels): Update for
+ 	move of selftest::test_diagnostic_context to
+ 	diagnostics::selftest::test_context.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-format.cc: Update for move of selftest-diagnostic.h to
+ 	diagnostics/selftest-context.h.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-common.h: Update for diagnostic_context becoming
+ 	diagnostics::context.
+ 	* c-opts.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-opts.cc (c_diagnostic_text_finalizer): Add "m_" prefix to
+ 	fields of diagnostic_info.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-opts.cc: Update for move of "diagnostic-macro-unwinding.h"
+ 	to "diagnostics/macro-unwinding.h".
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* c-opts.cc: Update for move of diagnostics output formats into
+ 	namespace "diagnostics" as "sinks".
+ 
  2025-07-16  Kwok Cheung Yeung  <kcyeung@baylibre.com>
  
  	* c-omp.cc (c_finish_omp_depobj): Use OMP_ITERATOR_DECL_P.
diff -Nrcpad gcc-16-20250720/gcc/c-family/c-common.cc gcc-16-20250727/gcc/c-family/c-common.cc
*** gcc-16-20250720/gcc/c-family/c-common.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/c-common.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 56,61 ****
--- 56,62 ----
  #include "tree-pretty-print-markup.h"
  #include "gcc-rich-location.h"
  #include "gcc-urlifier.h"
+ #include "diagnostics/diagnostics-selftests.h"
  
  cpp_reader *parse_in;		/* Declared in c-pragma.h.  */
  
*************** c_parse_error (const char *gmsgid, enum
*** 7025,7031 ****
  /* Return the gcc option code associated with the reason for a cpp
     message, or 0 if none.  */
  
! static diagnostic_option_id
  c_option_controlling_cpp_diagnostic (enum cpp_warning_reason reason)
  {
    const struct cpp_reason_option_codes_t *entry;
--- 7026,7032 ----
  /* Return the gcc option code associated with the reason for a cpp
     message, or 0 if none.  */
  
! static diagnostics::option_id
  c_option_controlling_cpp_diagnostic (enum cpp_warning_reason reason)
  {
    const struct cpp_reason_option_codes_t *entry;
*************** c_cpp_diagnostic (cpp_reader *pfile ATTR
*** 7067,7074 ****
  		  rich_location *richloc,
  		  const char *msg, va_list *ap)
  {
!   diagnostic_info diagnostic;
!   diagnostic_t dlevel;
    bool save_warn_system_headers = global_dc->m_warn_system_headers;
    bool ret;
  
--- 7068,7075 ----
  		  rich_location *richloc,
  		  const char *msg, va_list *ap)
  {
!   diagnostics::diagnostic_info diagnostic;
!   enum diagnostics::kind dlevel;
    bool save_warn_system_headers = global_dc->m_warn_system_headers;
    bool ret;
  
*************** c_cpp_diagnostic (cpp_reader *pfile ATTR
*** 7082,7105 ****
      case CPP_DL_WARNING:
        if (flag_no_output)
  	return false;
!       dlevel = DK_WARNING;
        break;
      case CPP_DL_PEDWARN:
        if (flag_no_output && !flag_pedantic_errors)
  	return false;
!       dlevel = DK_PEDWARN;
        break;
      case CPP_DL_ERROR:
!       dlevel = DK_ERROR;
        break;
      case CPP_DL_ICE:
!       dlevel = DK_ICE;
        break;
      case CPP_DL_NOTE:
!       dlevel = DK_NOTE;
        break;
      case CPP_DL_FATAL:
!       dlevel = DK_FATAL;
        break;
      default:
        gcc_unreachable ();
--- 7083,7106 ----
      case CPP_DL_WARNING:
        if (flag_no_output)
  	return false;
!       dlevel = diagnostics::kind::warning;
        break;
      case CPP_DL_PEDWARN:
        if (flag_no_output && !flag_pedantic_errors)
  	return false;
!       dlevel = diagnostics::kind::pedwarn;
        break;
      case CPP_DL_ERROR:
!       dlevel = diagnostics::kind::error;
        break;
      case CPP_DL_ICE:
!       dlevel = diagnostics::kind::ice;
        break;
      case CPP_DL_NOTE:
!       dlevel = diagnostics::kind::note;
        break;
      case CPP_DL_FATAL:
!       dlevel = diagnostics::kind::fatal;
        break;
      default:
        gcc_unreachable ();
*************** c_family_tests (void)
*** 9963,9970 ****
    c_indentation_cc_tests ();
    c_pretty_print_cc_tests ();
    c_spellcheck_cc_tests ();
-   c_diagnostic_cc_tests ();
    c_opt_problem_cc_tests ();
  }
  
  } // namespace selftest
--- 9964,9974 ----
    c_indentation_cc_tests ();
    c_pretty_print_cc_tests ();
    c_spellcheck_cc_tests ();
    c_opt_problem_cc_tests ();
+ 
+   /* According to https://gcc.gnu.org/pipermail/gcc/2021-November/237703.html
+      this has some language-specific assumptions, so we run it here.  */
+   diagnostics::selftest::context_cc_tests ();
  }
  
  } // namespace selftest
*************** try_to_locate_new_include_insertion_poin
*** 10046,10052 ****
      return UNKNOWN_LOCATION;
  
    /* The "start_location" is column 0, meaning "the whole line".
!      rich_location and edit_context can't cope with this, so use
       column 1 instead.  */
    location_t col_0 = ord_map_for_insertion->start_location;
    return linemap_position_for_loc_and_offset (line_table, col_0, 1);
--- 10050,10056 ----
      return UNKNOWN_LOCATION;
  
    /* The "start_location" is column 0, meaning "the whole line".
!      rich_location and diagnostics::changes can't cope with this, so use
       column 1 instead.  */
    location_t col_0 = ord_map_for_insertion->start_location;
    return linemap_position_for_loc_and_offset (line_table, col_0, 1);
*************** maybe_add_include_fixit (rich_location *
*** 10110,10116 ****
    richloc->add_fixit_insert_before (include_insert_loc, text);
    free (text);
  
!   if (override_location && global_dc->m_source_printing.enabled)
      {
        /* Replace the primary location with that of the insertion point for the
  	 fix-it hint.
--- 10114,10120 ----
    richloc->add_fixit_insert_before (include_insert_loc, text);
    free (text);
  
!   if (override_location && global_dc->get_source_printing_options ().enabled)
      {
        /* Replace the primary location with that of the insertion point for the
  	 fix-it hint.
diff -Nrcpad gcc-16-20250720/gcc/c-family/c-common.h gcc-16-20250727/gcc/c-family/c-common.h
*** gcc-16-20250720/gcc/c-family/c-common.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/c-common.h	Sun Jul 27 22:32:08 2025
*************** extern tree build_va_arg (location_t, tr
*** 979,985 ****
  
  extern const unsigned int c_family_lang_mask;
  extern unsigned int c_common_option_lang_mask (void);
! extern void c_common_diagnostics_set_defaults (diagnostic_context *);
  extern bool c_common_complain_wrong_lang_p (const struct cl_option *);
  extern void c_common_init_options_struct (struct gcc_options *);
  extern void c_common_init_options (unsigned int, struct cl_decoded_option *);
--- 979,985 ----
  
  extern const unsigned int c_family_lang_mask;
  extern unsigned int c_common_option_lang_mask (void);
! extern void c_common_diagnostics_set_defaults (diagnostics::context *);
  extern bool c_common_complain_wrong_lang_p (const struct cl_option *);
  extern void c_common_init_options_struct (struct gcc_options *);
  extern void c_common_init_options (unsigned int, struct cl_decoded_option *);
*************** extern void c_stddef_cpp_builtins (void)
*** 1265,1271 ****
  extern void fe_file_change (const line_map_ordinary *);
  extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char,
  			   rich_location *richloc);
! extern diagnostic_option_id get_option_for_builtin_define (const char *macro_name);
  
  /* In c-ppoutput.cc  */
  extern void init_pp_output (FILE *);
--- 1265,1271 ----
  extern void fe_file_change (const line_map_ordinary *);
  extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char,
  			   rich_location *richloc);
! extern diagnostics::option_id get_option_for_builtin_define (const char *macro_name);
  
  /* In c-ppoutput.cc  */
  extern void init_pp_output (FILE *);
*************** extern tree braced_lists_to_strings (tre
*** 1729,1735 ****
  namespace selftest {
    /* Declarations for specific families of tests within c-family,
       by source file, in alphabetical order.  */
-   extern void c_diagnostic_cc_tests (void);
    extern void c_format_cc_tests (void);
    extern void c_indentation_cc_tests (void);
    extern void c_opt_problem_cc_tests (void);
--- 1729,1734 ----
diff -Nrcpad gcc-16-20250720/gcc/c-family/c-cppbuiltin.cc gcc-16-20250727/gcc/c-family/c-cppbuiltin.cc
*** gcc-16-20250720/gcc/c-family/c-cppbuiltin.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/c-cppbuiltin.cc	Sun Jul 27 22:32:08 2025
*************** c_cpp_builtins (cpp_reader *pfile)
*** 1681,1687 ****
  /* Given NAME, return the command-line option that would make it be
     a builtin define, or 0 if unrecognized.  */
  
! diagnostic_option_id
  get_option_for_builtin_define (const char *name)
  {
    if (!strcmp (name, "_OPENACC"))
--- 1681,1687 ----
  /* Given NAME, return the command-line option that would make it be
     a builtin define, or 0 if unrecognized.  */
  
! diagnostics::option_id
  get_option_for_builtin_define (const char *name)
  {
    if (!strcmp (name, "_OPENACC"))
diff -Nrcpad gcc-16-20250720/gcc/c-family/c-format.cc gcc-16-20250727/gcc/c-family/c-format.cc
*** gcc-16-20250720/gcc/c-family/c-format.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/c-format.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 32,38 ****
  #include "diagnostic.h"
  #include "substring-locations.h"
  #include "selftest.h"
! #include "selftest-diagnostic.h"
  #include "builtins.h"
  #include "attribs.h"
  #include "c-family/c-type-mismatch.h"
--- 32,39 ----
  #include "diagnostic.h"
  #include "substring-locations.h"
  #include "selftest.h"
! #include "diagnostics/selftest-context.h"
! #include "diagnostics/file-cache.h"
  #include "builtins.h"
  #include "attribs.h"
  #include "c-family/c-type-mismatch.h"
*************** get_corrected_substring (const substring
*** 4634,4640 ****
    if (caret.column > finish.column)
      return NULL;
  
!   char_span line
      = global_dc->get_file_cache ().get_source_line (start.file, start.line);
    if (!line)
      return NULL;
--- 4635,4641 ----
    if (caret.column > finish.column)
      return NULL;
  
!   diagnostics::char_span line
      = global_dc->get_file_cache ().get_source_line (start.file, start.line);
    if (!line)
      return NULL;
*************** get_corrected_substring (const substring
*** 4646,4652 ****
       specification, up to the (but not including) the length modifier.
       In the above example, this would be "%-+*.*".  */
    int length_up_to_type = caret.column - start.column;
!   char_span prefix_span = line.subspan (start.column - 1, length_up_to_type);
    char *prefix = prefix_span.xstrdup ();
  
    /* Now attempt to generate a suggestion for the rest of the specification
--- 4647,4654 ----
       specification, up to the (but not including) the length modifier.
       In the above example, this would be "%-+*.*".  */
    int length_up_to_type = caret.column - start.column;
!   diagnostics::char_span prefix_span
!     = line.subspan (start.column - 1, length_up_to_type);
    char *prefix = prefix_span.xstrdup ();
  
    /* Now attempt to generate a suggestion for the rest of the specification
*************** test_type_mismatch_range_labels ()
*** 5584,5593 ****
    gcc_rich_location richloc (fmt, &fmt_label, nullptr);
    richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, &param_label);
  
!   test_diagnostic_context dc;
    diagnostic_show_locus (&dc,
! 			 dc.m_source_printing,
! 			 &richloc, DK_ERROR, dc.get_reference_printer ());
    if (c_dialect_cxx ())
      /* "char*", without a space.  */
      ASSERT_STREQ ("   printf (\"msg: %i\\n\", msg);\n"
--- 5586,5597 ----
    gcc_rich_location richloc (fmt, &fmt_label, nullptr);
    richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, &param_label);
  
!   diagnostics::selftest::test_context dc;
    diagnostic_show_locus (&dc,
! 			 dc.get_source_printing_options (),
! 			 &richloc,
! 			 diagnostics::kind::error,
! 			 dc.get_reference_printer ());
    if (c_dialect_cxx ())
      /* "char*", without a space.  */
      ASSERT_STREQ ("   printf (\"msg: %i\\n\", msg);\n"
diff -Nrcpad gcc-16-20250720/gcc/c-family/c-indentation.cc gcc-16-20250727/gcc/c-family/c-indentation.cc
*** gcc-16-20250720/gcc/c-family/c-indentation.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/c-indentation.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 25,30 ****
--- 25,31 ----
  #include "c-indentation.h"
  #include "selftest.h"
  #include "diagnostic.h"
+ #include "diagnostics/file-cache.h"
  
  /* Round up VIS_COLUMN to nearest tab stop. */
  
*************** next_tab_stop (unsigned int vis_column,
*** 45,57 ****
     on the line (up to or before EXPLOC).  */
  
  static bool
! get_visual_column (file_cache &fc,
  		   expanded_location exploc,
  		   unsigned int *out,
  		   unsigned int *first_nws,
  		   unsigned int tab_width)
  {
!   char_span line = fc.get_source_line (exploc.file, exploc.line);
    if (!line)
      return false;
    if ((size_t)exploc.column > line.length ())
--- 46,58 ----
     on the line (up to or before EXPLOC).  */
  
  static bool
! get_visual_column (diagnostics::file_cache &fc,
  		   expanded_location exploc,
  		   unsigned int *out,
  		   unsigned int *first_nws,
  		   unsigned int tab_width)
  {
!   diagnostics::char_span line = fc.get_source_line (exploc.file, exploc.line);
    if (!line)
      return false;
    if ((size_t)exploc.column > line.length ())
*************** get_visual_column (file_cache &fc,
*** 88,101 ****
     Otherwise, return false, leaving *FIRST_NWS untouched.  */
  
  static bool
! get_first_nws_vis_column (file_cache &fc,
  			  const char *file, int line_num,
  			  unsigned int *first_nws,
  			  unsigned int tab_width)
  {
    gcc_assert (first_nws);
  
!   char_span line = fc.get_source_line (file, line_num);
    if (!line)
      return false;
    unsigned int vis_column = 0;
--- 89,102 ----
     Otherwise, return false, leaving *FIRST_NWS untouched.  */
  
  static bool
! get_first_nws_vis_column (diagnostics::file_cache &fc,
  			  const char *file, int line_num,
  			  unsigned int *first_nws,
  			  unsigned int tab_width)
  {
    gcc_assert (first_nws);
  
!   diagnostics::char_span line = fc.get_source_line (file, line_num);
    if (!line)
      return false;
    unsigned int vis_column = 0;
*************** get_first_nws_vis_column (file_cache &fc
*** 160,166 ****
     Return true if such an unindent/outdent is detected.  */
  
  static bool
! detect_intervening_unindent (file_cache &fc,
  			     const char *file,
  			     int body_line,
  			     int next_stmt_line,
--- 161,167 ----
     Return true if such an unindent/outdent is detected.  */
  
  static bool
! detect_intervening_unindent (diagnostics::file_cache &fc,
  			     const char *file,
  			     int body_line,
  			     int next_stmt_line,
*************** should_warn_for_misleading_indentation (
*** 335,341 ****
    if (next_stmt_exploc.file != body_exploc.file)
      return false;
  
!   file_cache &fc = global_dc->get_file_cache ();
  
    /* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider
       the location of the guard.
--- 336,342 ----
    if (next_stmt_exploc.file != body_exploc.file)
      return false;
  
!   diagnostics::file_cache &fc = global_dc->get_file_cache ();
  
    /* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider
       the location of the guard.
*************** test_next_tab_stop ()
*** 691,697 ****
  
  static void
  assert_get_visual_column_succeeds (const location &loc,
! 				   file_cache &fc,
  				   const char *file, int line, int column,
  				   const unsigned int tab_width,
  				   unsigned int expected_visual_column,
--- 692,698 ----
  
  static void
  assert_get_visual_column_succeeds (const location &loc,
! 				   diagnostics::file_cache &fc,
  				   const char *file, int line, int column,
  				   const unsigned int tab_width,
  				   unsigned int expected_visual_column,
*************** assert_get_visual_column_succeeds (const
*** 735,741 ****
  
  static void
  assert_get_visual_column_fails (const location &loc,
! 				file_cache &fc,
  				const char *file, int line, int column,
  				const unsigned int tab_width)
  {
--- 736,742 ----
  
  static void
  assert_get_visual_column_fails (const location &loc,
! 				diagnostics::file_cache &fc,
  				const char *file, int line, int column,
  				const unsigned int tab_width)
  {
*************** test_get_visual_column ()
*** 783,789 ****
  			 "\t line 2\n");
    line_table_test ltt;
    temp_source_file tmp (SELFTEST_LOCATION, ".txt", content);
!   file_cache fc;
  
    const unsigned int tab_width = 8;
    const char *file = tmp.get_filename ();
--- 784,790 ----
  			 "\t line 2\n");
    line_table_test ltt;
    temp_source_file tmp (SELFTEST_LOCATION, ".txt", content);
!   diagnostics::file_cache fc;
  
    const unsigned int tab_width = 8;
    const char *file = tmp.get_filename ();
diff -Nrcpad gcc-16-20250720/gcc/c-family/c-lex.cc gcc-16-20250727/gcc/c-family/c-lex.cc
*** gcc-16-20250720/gcc/c-family/c-lex.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/c-lex.cc	Sun Jul 27 22:32:08 2025
*************** interpret_integer (const cpp_token *toke
*** 1176,1182 ****
  	  && (flags & CPP_N_WIDTH) != CPP_N_LARGE)
  	emit_diagnostic
  	  ((c_dialect_cxx () ? cxx_dialect == cxx98 : !flag_isoc99)
! 	   ? DK_PEDWARN : DK_WARNING,
  	   input_location, OPT_Wlong_long,
  	   (flags & CPP_N_UNSIGNED)
  	   ? "integer constant is too large for %<unsigned long%> type"
--- 1176,1182 ----
  	  && (flags & CPP_N_WIDTH) != CPP_N_LARGE)
  	emit_diagnostic
  	  ((c_dialect_cxx () ? cxx_dialect == cxx98 : !flag_isoc99)
! 	   ? diagnostics::kind::pedwarn : diagnostics::kind::warning,
  	   input_location, OPT_Wlong_long,
  	   (flags & CPP_N_UNSIGNED)
  	   ? "integer constant is too large for %<unsigned long%> type"
diff -Nrcpad gcc-16-20250720/gcc/c-family/c-opts.cc gcc-16-20250727/gcc/c-family/c-opts.cc
*** gcc-16-20250720/gcc/c-family/c-opts.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/c-opts.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 32,38 ****
  #include "flags.h"
  #include "toplev.h"
  #include "langhooks.h"
! #include "diagnostic-macro-unwinding.h" /* for virt_loc_aware_diagnostic_finalizer */
  #include "intl.h"
  #include "cppdefault.h"
  #include "incpath.h"
--- 32,38 ----
  #include "flags.h"
  #include "toplev.h"
  #include "langhooks.h"
! #include "diagnostics/macro-unwinding.h" /* for virt_loc_aware_diagnostic_finalizer */
  #include "intl.h"
  #include "cppdefault.h"
  #include "incpath.h"
*************** along with GCC; see the file COPYING3.
*** 43,49 ****
  #include "dumpfile.h"
  #include "file-prefix-map.h"    /* add_*_prefix_map()  */
  #include "context.h"
! #include "diagnostic-format-text.h"
  
  #ifndef DOLLARS_IN_IDENTIFIERS
  # define DOLLARS_IN_IDENTIFIERS true
--- 43,49 ----
  #include "dumpfile.h"
  #include "file-prefix-map.h"    /* add_*_prefix_map()  */
  #include "context.h"
! #include "diagnostics/text-sink.h"
  
  #ifndef DOLLARS_IN_IDENTIFIERS
  # define DOLLARS_IN_IDENTIFIERS true
*************** c_common_option_lang_mask (void)
*** 169,177 ****
  
  /* Diagnostic finalizer for C/C++/Objective-C/Objective-C++.  */
  static void
! c_diagnostic_text_finalizer (diagnostic_text_output_format &text_output,
! 			     const diagnostic_info *diagnostic,
! 			     diagnostic_t)
  {
    pretty_printer *const pp = text_output.get_printer ();
    char *saved_prefix = pp_take_prefix (pp);
--- 169,177 ----
  
  /* Diagnostic finalizer for C/C++/Objective-C/Objective-C++.  */
  static void
! c_diagnostic_text_finalizer (diagnostics::text_sink &text_output,
! 			     const diagnostics::diagnostic_info *diagnostic,
! 			     enum diagnostics::kind)
  {
    pretty_printer *const pp = text_output.get_printer ();
    char *saved_prefix = pp_take_prefix (pp);
*************** c_diagnostic_text_finalizer (diagnostic_
*** 179,197 ****
    pp_newline (pp);
    diagnostic_show_locus (&text_output.get_context (),
  			 text_output.get_source_printing_options (),
! 			 diagnostic->richloc, diagnostic->kind, pp);
    /* By default print macro expansion contexts in the diagnostic
       finalizer -- for tokens resulting from macro expansion.  */
!   virt_loc_aware_diagnostic_finalizer (text_output, diagnostic);
    pp_set_prefix (pp, saved_prefix);
    pp_flush (pp);
  }
  
  /* Common default settings for diagnostics.  */
  void
! c_common_diagnostics_set_defaults (diagnostic_context *context)
  {
!   diagnostic_text_finalizer (context) = c_diagnostic_text_finalizer;
    context->set_permissive_option (OPT_fpermissive);
  }
  
--- 179,197 ----
    pp_newline (pp);
    diagnostic_show_locus (&text_output.get_context (),
  			 text_output.get_source_printing_options (),
! 			 diagnostic->m_richloc, diagnostic->m_kind, pp);
    /* By default print macro expansion contexts in the diagnostic
       finalizer -- for tokens resulting from macro expansion.  */
!   diagnostics::virt_loc_aware_text_finalizer (text_output, diagnostic);
    pp_set_prefix (pp, saved_prefix);
    pp_flush (pp);
  }
  
  /* Common default settings for diagnostics.  */
  void
! c_common_diagnostics_set_defaults (diagnostics::context *context)
  {
!   diagnostics::text_finalizer (context) = c_diagnostic_text_finalizer;
    context->set_permissive_option (OPT_fpermissive);
  }
  
*************** c_common_init_options (unsigned int deco
*** 278,284 ****
    if (c_dialect_cxx ())
      set_std_cxx17 (/*ISO*/false);
  
!   global_dc->m_source_printing.colorize_source_p = true;
  }
  
  /* Handle switch SCODE with argument ARG.  VALUE is true, unless no-
--- 278,284 ----
    if (c_dialect_cxx ())
      set_std_cxx17 (/*ISO*/false);
  
!   global_dc->get_source_printing_options ().colorize_source_p = true;
  }
  
  /* Handle switch SCODE with argument ARG.  VALUE is true, unless no-
diff -Nrcpad gcc-16-20250720/gcc/c-family/c-pragma.cc gcc-16-20250727/gcc/c-family/c-pragma.cc
*** gcc-16-20250720/gcc/c-family/c-pragma.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/c-pragma.cc	Sun Jul 27 22:32:08 2025
*************** public:
*** 781,787 ****
        PK_IGNORED_ATTRIBUTES,
        PK_DIAGNOSTIC,
      } pd_kind;
!   diagnostic_t diagnostic_kind;
    const char *kind_str;
    const char *option_str;
    bool own_option_str;
--- 781,787 ----
        PK_IGNORED_ATTRIBUTES,
        PK_DIAGNOSTIC,
      } pd_kind;
!   enum diagnostics::kind diagnostic_kind;
    const char *kind_str;
    const char *option_str;
    bool own_option_str;
*************** public:
*** 792,798 ****
      valid = false;
      loc_kind = loc_option = UNKNOWN_LOCATION;
      pd_kind = PK_INVALID;
!     diagnostic_kind = DK_UNSPECIFIED;
      kind_str = option_str = nullptr;
      own_option_str = false;
    }
--- 792,798 ----
      valid = false;
      loc_kind = loc_option = UNKNOWN_LOCATION;
      pd_kind = PK_INVALID;
!     diagnostic_kind = diagnostics::kind::unspecified;
      kind_str = option_str = nullptr;
      own_option_str = false;
    }
*************** public:
*** 808,814 ****
      kind_str = kind_string;
  
      pd_kind = PK_INVALID;
!     diagnostic_kind = DK_UNSPECIFIED;
      if (strcmp (kind_str, "push") == 0)
        pd_kind = PK_PUSH;
      else if (strcmp (kind_str, "pop") == 0)
--- 808,814 ----
      kind_str = kind_string;
  
      pd_kind = PK_INVALID;
!     diagnostic_kind = diagnostics::kind::unspecified;
      if (strcmp (kind_str, "push") == 0)
        pd_kind = PK_PUSH;
      else if (strcmp (kind_str, "pop") == 0)
*************** public:
*** 818,834 ****
      else if (strcmp (kind_str, "error") == 0)
        {
  	pd_kind = PK_DIAGNOSTIC;
! 	diagnostic_kind = DK_ERROR;
        }
      else if (strcmp (kind_str, "warning") == 0)
        {
  	pd_kind = PK_DIAGNOSTIC;
! 	diagnostic_kind = DK_WARNING;
        }
      else if (strcmp (kind_str, "ignored") == 0)
        {
  	pd_kind = PK_DIAGNOSTIC;
! 	diagnostic_kind = DK_IGNORED;
        }
    }
  
--- 818,834 ----
      else if (strcmp (kind_str, "error") == 0)
        {
  	pd_kind = PK_DIAGNOSTIC;
! 	diagnostic_kind = diagnostics::kind::error;
        }
      else if (strcmp (kind_str, "warning") == 0)
        {
  	pd_kind = PK_DIAGNOSTIC;
! 	diagnostic_kind = diagnostics::kind::warning;
        }
      else if (strcmp (kind_str, "ignored") == 0)
        {
  	pd_kind = PK_DIAGNOSTIC;
! 	diagnostic_kind = diagnostics::kind::ignored;
        }
    }
  
*************** handle_pragma_diagnostic_impl ()
*** 1016,1022 ****
       what we used to do here before and changing it breaks e.g.
       PR69543 and PR69558.  */
    control_warning_option (option_index, (int) data.diagnostic_kind,
! 			  arg, data.diagnostic_kind != DK_IGNORED,
  			  input_location, lang_mask, &handlers,
  			  &global_options, &global_options_set,
  			  global_dc);
--- 1016,1023 ----
       what we used to do here before and changing it breaks e.g.
       PR69543 and PR69558.  */
    control_warning_option (option_index, (int) data.diagnostic_kind,
! 			  arg,
! 			  data.diagnostic_kind != diagnostics::kind::ignored,
  			  input_location, lang_mask, &handlers,
  			  &global_options, &global_options_set,
  			  global_dc);
diff -Nrcpad gcc-16-20250720/gcc/c-family/c-warn.cc gcc-16-20250727/gcc/c-family/c-warn.cc
*** gcc-16-20250720/gcc/c-family/c-warn.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/c-warn.cc	Sun Jul 27 22:32:08 2025
*************** do_warn_array_compare (location_t locati
*** 3835,3841 ****
      op1 = TREE_OPERAND (op1, 0);
  
    auto_diagnostic_group d;
!   diagnostic_t kind = DK_WARNING;
    const char *msg;
    if (c_dialect_cxx () && cxx_dialect >= cxx20)
      {
--- 3835,3841 ----
      op1 = TREE_OPERAND (op1, 0);
  
    auto_diagnostic_group d;
!   enum diagnostics::kind kind = diagnostics::kind::warning;
    const char *msg;
    if (c_dialect_cxx () && cxx_dialect >= cxx20)
      {
*************** do_warn_array_compare (location_t locati
*** 3843,3849 ****
        if (cxx_dialect >= cxx26)
  	{
  	  msg = G_("comparison between two arrays is not allowed in C++26");
! 	  kind = DK_PERMERROR;
  	}
        else
  	msg = G_("comparison between two arrays is deprecated in C++20");
--- 3843,3849 ----
        if (cxx_dialect >= cxx26)
  	{
  	  msg = G_("comparison between two arrays is not allowed in C++26");
! 	  kind = diagnostics::kind::permerror;
  	}
        else
  	msg = G_("comparison between two arrays is deprecated in C++20");
diff -Nrcpad gcc-16-20250720/gcc/c-family/known-headers.cc gcc-16-20250727/gcc/c-family/known-headers.cc
*** gcc-16-20250720/gcc/c-family/known-headers.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/known-headers.cc	Sun Jul 27 22:32:08 2025
*************** suggest_missing_header::~suggest_missing
*** 329,337 ****
  
  /* suggest_missing_option's ctor.  */
  
! suggest_missing_option::suggest_missing_option (location_t loc,
! 						const char *macro_name,
! 						diagnostic_option_id option_id)
  : deferred_diagnostic (loc), m_name_str (macro_name), m_option_id (option_id)
  {
    gcc_assert (macro_name);
--- 329,338 ----
  
  /* suggest_missing_option's ctor.  */
  
! suggest_missing_option::
! suggest_missing_option (location_t loc,
! 			const char *macro_name,
! 			diagnostics::option_id option_id)
  : deferred_diagnostic (loc), m_name_str (macro_name), m_option_id (option_id)
  {
    gcc_assert (macro_name);
diff -Nrcpad gcc-16-20250720/gcc/c-family/known-headers.h gcc-16-20250727/gcc/c-family/known-headers.h
*** gcc-16-20250720/gcc/c-family/known-headers.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/c-family/known-headers.h	Sun Jul 27 22:32:08 2025
*************** class suggest_missing_option : public de
*** 48,59 ****
  {
   public:
    suggest_missing_option (location_t loc, const char *name,
! 			  diagnostic_option_id option_id);
    ~suggest_missing_option ();
  
   private:
    const char *m_name_str;
!   diagnostic_option_id m_option_id;
  };
  
  #endif /* GCC_KNOWN_HEADERS_H */
--- 48,59 ----
  {
   public:
    suggest_missing_option (location_t loc, const char *name,
! 			  diagnostics::option_id option_id);
    ~suggest_missing_option ();
  
   private:
    const char *m_name_str;
!   diagnostics::option_id m_option_id;
  };
  
  #endif /* GCC_KNOWN_HEADERS_H */
diff -Nrcpad gcc-16-20250720/gcc/cfgexpand.cc gcc-16-20250727/gcc/cfgexpand.cc
*** gcc-16-20250720/gcc/cfgexpand.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cfgexpand.cc	Sun Jul 27 22:32:08 2025
*************** expand_asm_loc (tree string, int vol, lo
*** 3275,3318 ****
    emit_insn (body);
  }
  
- /* Return the number of times character C occurs in string S.  */
- static int
- n_occurrences (int c, const char *s)
- {
-   int n = 0;
-   while (*s)
-     n += (*s++ == c);
-   return n;
- }
- 
- /* A subroutine of expand_asm_operands.  Check that all operands have
-    the same number of alternatives.  Return true if so.  */
- 
- static bool
- check_operand_nalternatives (const vec<const char *> &constraints)
- {
-   unsigned len = constraints.length();
-   if (len > 0)
-     {
-       int nalternatives = n_occurrences (',', constraints[0]);
- 
-       if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
- 	{
- 	  error ("too many alternatives in %<asm%>");
- 	  return false;
- 	}
- 
-       for (unsigned i = 1; i < len; ++i)
- 	if (n_occurrences (',', constraints[i]) != nalternatives)
- 	  {
- 	    error ("operand constraints for %<asm%> differ "
- 		   "in number of alternatives");
- 	    return false;
- 	  }
-     }
-   return true;
- }
- 
  /* Check for overlap between registers marked in CLOBBERED_REGS and
     anything inappropriate in T.  Emit error and return the register
     variable definition for error, NULL_TREE for ok.  */
--- 3275,3280 ----
*************** expand_asm_stmt (gasm *stmt)
*** 3478,3487 ****
  	= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
      }
  
-   /* ??? Diagnose during gimplification?  */
-   if (! check_operand_nalternatives (constraints))
-     return;
- 
    /* Count the number of meaningful clobbered registers, ignoring what
       we would ignore later.  */
    auto_vec<rtx> clobber_rvec;
--- 3440,3445 ----
*************** expand_asm_stmt (gasm *stmt)
*** 3555,3561 ****
  	 no point in going further.  */
        constraint = constraints[i];
        if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
! 				    &allows_mem, &allows_reg, &is_inout))
  	return;
  
        /* If the output is a hard register, verify it doesn't conflict with
--- 3513,3520 ----
  	 no point in going further.  */
        constraint = constraints[i];
        if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
! 				    &allows_mem, &allows_reg, &is_inout,
! 				    nullptr))
  	return;
  
        /* If the output is a hard register, verify it doesn't conflict with
*************** expand_asm_stmt (gasm *stmt)
*** 3633,3640 ****
  
        constraint = constraints[i + noutputs];
        if (! parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 				    constraints.address (),
! 				    &allows_mem, &allows_reg))
  	return;
  
        if (! allows_reg && allows_mem)
--- 3592,3599 ----
  
        constraint = constraints[i + noutputs];
        if (! parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 				    constraints.address (), &allows_mem,
! 				    &allows_reg, nullptr))
  	return;
  
        if (! allows_reg && allows_mem)
*************** expand_asm_stmt (gasm *stmt)
*** 3664,3670 ****
  
        ok = parse_output_constraint (&constraints[i], i, ninputs,
  				    noutputs, &allows_mem, &allows_reg,
! 				    &is_inout);
        gcc_assert (ok);
  
        /* If an output operand is not a decl or indirect ref and our constraint
--- 3623,3629 ----
  
        ok = parse_output_constraint (&constraints[i], i, ninputs,
  				    noutputs, &allows_mem, &allows_reg,
! 				    &is_inout, nullptr);
        gcc_assert (ok);
  
        /* If an output operand is not a decl or indirect ref and our constraint
*************** expand_asm_stmt (gasm *stmt)
*** 3769,3775 ****
        constraint = constraints[i + noutputs];
        ok = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
  				   constraints.address (),
! 				   &allows_mem, &allows_reg);
        gcc_assert (ok);
  
        /* EXPAND_INITIALIZER will not generate code for valid initializer
--- 3728,3734 ----
        constraint = constraints[i + noutputs];
        ok = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
  				   constraints.address (),
! 				   &allows_mem, &allows_reg, nullptr);
        gcc_assert (ok);
  
        /* EXPAND_INITIALIZER will not generate code for valid initializer
diff -Nrcpad gcc-16-20250720/gcc/cgraphunit.cc gcc-16-20250727/gcc/cgraphunit.cc
*** gcc-16-20250720/gcc/cgraphunit.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cgraphunit.cc	Sun Jul 27 22:32:08 2025
*************** symbol_table::compile (void)
*** 2400,2408 ****
      if (node->alias
  	&& lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl)))
        {
! 	IDENTIFIER_TRANSPARENT_ALIAS
! 	   (DECL_ASSEMBLER_NAME (node->decl)) = 1;
! 	TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl))
  	   = (node->alias_target ? node->alias_target
  	      : DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl));
        }
--- 2400,2409 ----
      if (node->alias
  	&& lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl)))
        {
! 	tree id = DECL_ASSEMBLER_NAME (node->decl);
! 	gcc_assert (!IDENTIFIER_INTERNAL_P (id));
! 	IDENTIFIER_TRANSPARENT_ALIAS (id) = 1;
! 	TREE_CHAIN (id)
  	   = (node->alias_target ? node->alias_target
  	      : DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl));
        }
diff -Nrcpad gcc-16-20250720/gcc/cobol/ChangeLog gcc-16-20250727/gcc/cobol/ChangeLog
*** gcc-16-20250720/gcc/cobol/ChangeLog	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/ChangeLog	Sun Jul 27 22:32:08 2025
***************
*** 1,3 ****
--- 1,168 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* util.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* util.cc: Update for renaming of diagnostic_option_id to
+ 	diagnostics::option_id.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* util.cc: Remove redundant #includes
+ 
+ 2025-07-24  Robert Dubner  <rdubner@symas.com>
+ 
+ 	PR cobol/119231
+ 	* gcobolspec.cc: (lang_specific_driver): Pass OPT_static through.
+ 	Handle -static and -static-libgcobol properly.
+ 
+ 2025-07-23  Robert Dubner  <rdubner@symas.com>
+ 
+ 	* genapi.cc (leave_procedure): Adjust location_t for PERFORM.
+ 	(parser_perform_times): Likewise.
+ 	(internal_perform_through_times): Likewise.
+ 	(perform_outofline_before_until): Likewise.
+ 	(perform_outofline_after_until): Likewise.
+ 	(perform_outofline_testafter_varying): Likewise.
+ 	(perform_outofline_before_varying): Likewise.
+ 
+ 2025-07-21  Robert Dubner  <rdubner@symas.com>
+ 	    James K. Lowden  <jklowden@cobolworx.com>
+ 
+ 	PR cobol/120402
+ 	* Make-lang.in: Elminate commented-out scripting.
+ 	* cbldiag.h (_CBLDIAG_H): Change #if 0 to #if GCOBOL_GETENV
+ 	(warn_msg): Add printf attributes.
+ 	(location_dump): Add debugging message.
+ 	* cdf.y: Improved linemap tracking.
+ 	* genapi.cc (treeplet_fill_source): const attribute for formal parameter.
+ 	(insert_nop): Created to consolidate var_decl_nop writes.
+ 	(build_main_that_calls_something): Move generation to the end of executable.
+ 	(level_88_helper): Formatting.
+ 	(parser_call_targets_dump): Formatting.
+ 	(function_pointer_from_name): const attribute for formal parameter.
+ 	(parser_initialize_programs): const attribute for formal parameter.
+ 	(parser_statement_begin): Improved linemap handling.
+ 	(section_label):  Improved linemap handling.
+ 	(paragraph_label): Improved linemap handling.
+ 	(pseudo_return_pop): Improved linemap handling.
+ 	(leave_procedure): Formatting.
+ 	(parser_enter_section):  Improved linemap handling.
+ 	(parser_enter_paragraph): Improved linemap handling.
+ 	(parser_perform): Formatting.
+ 	(parser_leave_file): Move creation of main() to this routine.
+ 	(parser_enter_program): Move creation of main from here to leave_file.
+ 	(parser_accept): Formatting. const attribute for formal parameter.
+ 	(parser_accept_command_line): const attribute for formal parameter.
+ 	(parser_accept_command_line_count): const attribute for formal parameter.
+ 	(parser_accept_envar): Likewise.
+ 	(parser_set_envar): Likewise.
+ 	(parser_display): Likewise.
+ 	(get_exhibit_name): Implement EXHIBIT verb.
+ 	(parser_exhibit): Likewise.
+ 	(parser_sleep): const attribute for formal parameter.
+ 	(parser_division): Improved linemap handling.
+ 	(parser_classify): const attribute for formal parameter.
+ 	(create_iline_address_pairs): Improved linemap handling.
+ 	(parser_perform_start): Likewise.
+ 	(perform_inline_until): Likewise.
+ 	(perform_inline_testbefore_varying): Likewise.
+ 	(parser_perform_until): Likewise.
+ 	(parser_perform_inline_times): Likewise.
+ 	(parser_intrinsic_subst): const attribute for formal parameter.
+ 	(parser_file_merge): Formatting.
+ 	(create_and_call): Improved linemap handling.
+ 	(mh_identical): const attribute for formal parameter.
+ 	(mh_numeric_display): const attribute for formal parameter.
+ 	(mh_little_endian): Likewise.
+ 	(mh_source_is_group): Likewise.
+ 	(psa_FldLiteralA): Formatting.
+ 	* genapi.h (parser_accept): const attribute for formal parameter.
+ 	(parser_accept_envar): Likewise.
+ 	(parser_set_envar): Likewise.
+ 	(parser_accept_command_line): Likewise.
+ 	(parser_accept_command_line_count): Likewise.
+ 	(parser_add): Likewise.
+ 	(parser_classify): Likewise.
+ 	(parser_sleep): Likewise.
+ 	(parser_exhibit): Likewise.
+ 	(parser_display): Likewise.
+ 	(parser_initialize_programs): Likewise.
+ 	(parser_intrinsic_subst): Likewise.
+ 	* gengen.cc (gg_assign): Improved linemap handling.
+ 	(gg_add_field_to_structure): Likewise.
+ 	(gg_define_from_declaration): Likewise.
+ 	(gg_build_relational_expression): Likewise.
+ 	(gg_goto_label_decl): Likewise.
+ 	(gg_goto): Likewise.
+ 	(gg_printf): Likewise.
+ 	(gg_fprintf): Likewise.
+ 	(gg_memset): Likewise.
+ 	(gg_memchr): Likewise.
+ 	(gg_memcpy): Likewise.
+ 	(gg_memmove): Likewise.
+ 	(gg_strcpy): Likewise.
+ 	(gg_strcmp): Likewise.
+ 	(gg_strncmp): Likewise.
+ 	(gg_return): Likewise.
+ 	(chain_parameter_to_function): Likewise.
+ 	(gg_define_function): Likewise.
+ 	(gg_get_function_decl): Likewise.
+ 	(gg_call_expr): Likewise.
+ 	(gg_call): Likewise.
+ 	(gg_call_expr_list): Likewise.
+ 	(gg_exit): Likewise.
+ 	(gg_abort): Likewise.
+ 	(gg_strlen): Likewise.
+ 	(gg_strdup): Likewise.
+ 	(gg_malloc): Likewise.
+ 	(gg_realloc): Likewise.
+ 	(gg_free): Likewise.
+ 	(gg_set_current_line_number): Likewise.
+ 	(gg_get_current_line_number): Likewise.
+ 	(gg_insert_into_assembler): Likewise.
+ 	(token_location_override): Likewise.
+ 	(gg_token_location): Likewise.
+ 	* gengen.h (location_from_lineno): Likewise.
+ 	(gg_set_current_line_number): Likewise.
+ 	(gg_get_current_line_number): Likewise.
+ 	(gg_token_location): Likewise.
+ 	(current_token_location): Likewise.
+ 	(current_location_minus_one): Likewise.
+ 	(current_location_minus_one_clear): Likewise.
+ 	(token_location_override): Likewise.
+ 	* genmath.cc (fast_divide):  const attribute for formal parameter.
+ 	* genutil.cc (get_and_check_refstart_and_reflen): Likewise.
+ 	(get_data_offset): Likewise.
+ 	(refer_refmod_length): Likewise.
+ 	(refer_offset): Likewise.
+ 	(refer_size): Likewise.
+ 	(refer_size_dest): Likewise.
+ 	(refer_size_source): Likewise.
+ 	(qualified_data_location): Likewise.
+ 	* genutil.h (refer_offset): Likewise.
+ 	(refer_size_source): Likewise.
+ 	(refer_size_dest): Likewise.
+ 	(qualified_data_location): Likewise.
+ 	* parse.y: EVALUATE token; Implement EXHIBIT verb;
+ 	Improved linemap handling.
+ 	* parse_ante.h (input_file_status_notify): Improved linemap handling.
+ 	(location_set): Likewise.
+ 	* scan.l: PICTURE string validation.
+ 	* scan_ante.h (class picture_t): PICTURE string validation.
+ 	(validate_picture): Likewise.
+ 	* symbols.cc (symbol_currency): Revised default currency handling.
+ 	* symbols.h (symbol_currency): Likewise.
+ 	* util.cc (location_from_lineno): Improved linemap handling.
+ 	(current_token_location): Improved linemap handling.
+ 	(current_location_minus_one): Improved linemap handling.
+ 	(current_location_minus_one_clear): Improved linemap handling.
+ 	(gcc_location_set_impl): Improved linemap handling.
+ 	(warn_msg): Improved linemap handling.
+ 	* util.h (cobol_lineno): Improved linemap handling.
+ 
  2025-07-15  Jakub Jelinek  <jakub@redhat.com>
  	    Jason Merrill  <jason@redhat.com>
  
diff -Nrcpad gcc-16-20250720/gcc/cobol/Make-lang.in gcc-16-20250727/gcc/cobol/Make-lang.in
*** gcc-16-20250720/gcc/cobol/Make-lang.in	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/Make-lang.in	Sun Jul 27 22:32:08 2025
*************** selftest-cobol:
*** 385,396 ****
  
  lang_checks += check-cobol
  
- ###
- ### Note that the process environment variable CXXFLAGS_FOR_COBOL is applied to
- ### gcc/cobol compilations.  This is not a configuration-level variable.
- ###
- ##
- ##cobol/%.o: cobol/%.cc
- ##	@echo $(COMPILE) $(CXXFLAGS_FOR_COBOL) $<
- ##	$(COMPILE) $(CXXFLAGS_FOR_COBOL) $<
- ##	$(POSTCOMPILE)
--- 385,387 ----
diff -Nrcpad gcc-16-20250720/gcc/cobol/cbldiag.h gcc-16-20250727/gcc/cobol/cbldiag.h
*** gcc-16-20250720/gcc/cobol/cbldiag.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/cbldiag.h	Sun Jul 27 22:32:08 2025
***************
*** 33,39 ****
  #else
  #define _CBLDIAG_H
  
! #if 0
  #define gcobol_getenv(x) getenv(x)
  #else
  #define gcobol_getenv(x) ((char *)nullptr)
--- 33,39 ----
  #else
  #define _CBLDIAG_H
  
! #if GCOBOL_GETENV
  #define gcobol_getenv(x) getenv(x)
  #else
  #define gcobol_getenv(x) ((char *)nullptr)
*************** struct YDFLTYPE
*** 78,87 ****
--- 78,92 ----
  
  #endif
  
+ // Diagnostic format specifiers are documented in gcc/pretty-print.cc
  // an error at a location, called from the parser for semantic errors
  void error_msg( const YYLTYPE& loc, const char gmsgid[], ... )
    ATTRIBUTE_GCOBOL_DIAG(2, 3);
  
+ bool
+ warn_msg( const YYLTYPE& loc, const char gmsgid[], ... )
+   ATTRIBUTE_GCOBOL_DIAG(2, 3);
+ 
  // an error that uses token_location, not yylloc
  void error_msg_direct( const char gmsgid[], ... )
    ATTRIBUTE_GCOBOL_DIAG(1, 2);
*************** template <typename LOC>
*** 116,126 ****
  static void
  location_dump( const char func[], int line, const char tag[], const LOC& loc) {
    extern int yy_flex_debug; // cppcheck-suppress shadowVariable
!   if( yy_flex_debug && gcobol_getenv("update_location") ) {
!     fprintf(stderr, "%s:%d: %s location (%d,%d) to (%d,%d)\n",
!             func, line, tag,
!             loc.first_line, loc.first_column, loc.last_line, loc.last_column);
!     gcc_location_dump();
    }
  }
  #endif // defined(yy_flex_debug)
--- 121,134 ----
  static void
  location_dump( const char func[], int line, const char tag[], const LOC& loc) {
    extern int yy_flex_debug; // cppcheck-suppress shadowVariable
!   if( yy_flex_debug ) {
!     const char *detail = gcobol_getenv("update_location");
!     if( detail ) {
!       fprintf(stderr, "%s:%d: %s location (%d,%d) to (%d,%d)\n",
!               func, line, tag,
!               loc.first_line, loc.first_column, loc.last_line, loc.last_column);
!       if( *detail == '2' ) gcc_location_dump();
!     }
    }
  }
  #endif // defined(yy_flex_debug)
diff -Nrcpad gcc-16-20250720/gcc/cobol/cdf.y gcc-16-20250727/gcc/cobol/cdf.y
*** gcc-16-20250720/gcc/cobol/cdf.y	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/cdf.y	Sun Jul 27 22:32:08 2025
*************** void input_file_status_notify();
*** 95,101 ****
          }                                                               \
        location_dump("cdf.c", __LINE__, "current", (Current));		\
        input_file_status_notify();					\
!       gcc_location_set( location_set(Current) );			\
    } while (0)
  
  %}
--- 95,101 ----
          }                                                               \
        location_dump("cdf.c", __LINE__, "current", (Current));		\
        input_file_status_notify();					\
!       location_set(Current);                                            \
    } while (0)
  
  %}
diff -Nrcpad gcc-16-20250720/gcc/cobol/gcobolspec.cc gcc-16-20250727/gcc/cobol/gcobolspec.cc
*** gcc-16-20250720/gcc/cobol/gcobolspec.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/gcobolspec.cc	Sun Jul 27 22:32:08 2025
*************** lang_specific_driver (struct cl_decoded_
*** 470,476 ****
--- 470,479 ----
  ////        break;
  ////#endif
        case OPT_static:
+ #if defined (HAVE_LD_STATIC_DYNAMIC)
+         append_arg(decoded_options[i]);
          static_in_general = true;
+ #endif        
          break;
  
        default:
*************** lang_specific_driver (struct cl_decoded_
*** 498,514 ****
      need_libgcobol = false;
      }
  
    if( need_libgcobol )
      {
      add_arg_lib(COBOL_LIBRARY, static_libgcobol);
      }
    if( need_libdl )
      {
!     add_arg_lib(DL_LIBRARY, static_in_general);
      }
    if( need_libstdc )
      {
!     add_arg_lib(STDCPP_LIBRARY, static_in_general);
      }
  
    if( prior_main )
--- 501,523 ----
      need_libgcobol = false;
      }
  
+   if( static_in_general )
+     {
+     // These two options interfere with each other.
+     static_libgcobol = false;
+     }
+ 
    if( need_libgcobol )
      {
      add_arg_lib(COBOL_LIBRARY, static_libgcobol);
      }
    if( need_libdl )
      {
!     add_arg_lib(DL_LIBRARY, false);
      }
    if( need_libstdc )
      {
!     add_arg_lib(STDCPP_LIBRARY, false);
      }
  
    if( prior_main )
diff -Nrcpad gcc-16-20250720/gcc/cobol/genapi.cc gcc-16-20250727/gcc/cobol/genapi.cc
*** gcc-16-20250720/gcc/cobol/genapi.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/genapi.cc	Sun Jul 27 22:32:08 2025
*************** typedef struct TREEPLET
*** 118,124 ****
  
  static
  void
! treeplet_fill_source(TREEPLET &treeplet, cbl_refer_t &refer)
    {
    treeplet.pfield = gg_get_address_of(refer.field->var_decl_node);
    treeplet.offset = refer_offset(refer);
--- 118,124 ----
  
  static
  void
! treeplet_fill_source(TREEPLET &treeplet, const cbl_refer_t &refer)
    {
    treeplet.pfield = gg_get_address_of(refer.field->var_decl_node);
    treeplet.offset = refer_offset(refer);
*************** trace1_init()
*** 233,238 ****
--- 233,245 ----
      }
    }
  
+ static
+ void
+ insert_nop(int n)
+   {
+   gg_assign(var_decl_nop, build_int_cst_type(INT, n));
+   }
+ 
  static void
  create_cblc_string_variable(const char *var_name, const char *var_contents)
    {
*************** build_main_that_calls_something(const ch
*** 270,277 ****
      SHOW_PARSE_END
      }
  
-   gg_set_current_line_number(DEFAULT_LINE_NUMBER);
- 
    tree function_decl = gg_define_function( INT,
                                             "main",
                                             "main",
--- 277,282 ----
*************** build_main_that_calls_something(const ch
*** 325,331 ****
                                         argc,
                                         argv,
                                         NULL_TREE)));
-   strncpy(ach_cobol_entry_point, psz, sizeof(ach_cobol_entry_point)-1);
    free(psz);
    gg_finalize_function();
    }
--- 330,335 ----
*************** level_88_helper(size_t parent_capacity,
*** 369,375 ****
    gcc_assert(retval);
    char *builder = static_cast<char *>(xmalloc(parent_capacity + 64));
    gcc_assert(builder);
!   
    size_t nbuild = 0;
  
    cbl_figconst_t figconst = cbl_figconst_of( elem.name());
--- 373,379 ----
    gcc_assert(retval);
    char *builder = static_cast<char *>(xmalloc(parent_capacity + 64));
    gcc_assert(builder);
! 
    size_t nbuild = 0;
  
    cbl_figconst_t figconst = cbl_figconst_of( elem.name());
*************** parser_call_targets_dump()
*** 788,794 ****
        }
        fprintf(stderr, " ]\n");
      }
! #endif    
    }
  
  size_t
--- 792,798 ----
        }
        fprintf(stderr, " ]\n");
      }
! #endif
    }
  
  size_t
*************** parser_call_target_update( size_t caller
*** 816,823 ****
    }
  
  static tree
! function_pointer_from_name(cbl_refer_t &name,
!                           tree function_return_type)
    {
    Analyze();
  
--- 820,827 ----
    }
  
  static tree
! function_pointer_from_name(const cbl_refer_t &name,
!                            tree function_return_type)
    {
    Analyze();
  
*************** function_pointer_from_name(cbl_refer_t &
*** 893,899 ****
    }
  
  void
! parser_initialize_programs(size_t nprogs, struct cbl_refer_t *progs)
    {
    Analyze();
    SHOW_PARSE
--- 897,904 ----
    }
  
  void
! parser_initialize_programs( size_t nprogs,
!                             const struct cbl_refer_t *progs)
    {
    Analyze();
    SHOW_PARSE
*************** parser_statement_begin( const cbl_name_t
*** 1178,1191 ****
      exception_processing = file_ops.find(statement_name) != file_ops.end();
      }
  
-   if( gg_get_current_line_number() == DEFAULT_LINE_NUMBER )
-     {
-     // This code is intended to prevert GDB anomalies when the first line of a
-     // program is a PERFORM <proc> ... TEST AFTER ... UNTIL ...
-     gg_set_current_line_number(CURRENT_LINE_NUMBER-1);
-     gg_assign(var_decl_nop, build_int_cst_type(INT, 106));
-     }
- 
    // At this point, if any exception is enabled, we store the location stuff.
    // Each file I-O routine calls store_location_stuff explicitly, because
    // those exceptions can't be defeated.
--- 1183,1188 ----
*************** parser_statement_begin( const cbl_name_t
*** 1195,1202 ****
      store_location_stuff(statement_name);
      }
  
-   gg_set_current_line_number(CURRENT_LINE_NUMBER);
- 
    if( exception_processing )
      {
      set_exception_environment(ecs, dcls);
--- 1192,1197 ----
*************** section_label(struct cbl_proc_t *procedu
*** 2666,2673 ****
    // With nested programs, you can have multiple program/section pairs with the
    // the same names; we use a deconflictor to avoid collisions
  
-   gg_set_current_line_number(CURRENT_LINE_NUMBER);
- 
    size_t deconflictor = symbol_label_id(procedure->label);
  
    cbl_label_t *label = procedure->label;
--- 2661,2666 ----
*************** section_label(struct cbl_proc_t *procedu
*** 2692,2698 ****
      }
    assembler_label(psz2);
    free(psz2);
!   gg_assign(var_decl_nop, build_int_cst_type(INT, 108));
    }
  
  static void
--- 2685,2691 ----
      }
    assembler_label(psz2);
    free(psz2);
!   insert_nop(108);
    }
  
  static void
*************** paragraph_label(struct cbl_proc_t *proce
*** 2707,2714 ****
    //      are not referenced by the program.  We provide a deconflictor to
    //      separate such labels.
  
-   gg_set_current_line_number(CURRENT_LINE_NUMBER);
- 
    cbl_label_t *paragraph  = procedure->label;
    cbl_label_t *section    = nullptr;
  
--- 2700,2705 ----
*************** paragraph_label(struct cbl_proc_t *proce
*** 2730,2735 ****
--- 2721,2729 ----
            section_name ? section_name: "(null)" ,
            current_function->our_unmangled_name ? current_function->our_unmangled_name: "" ,
            (fmt_size_t)deconflictor );
+ 
+   // (0) is wrong, so back up one
+ 
    gg_insert_into_assembler(psz1);
  
    SHOW_PARSE
*************** paragraph_label(struct cbl_proc_t *proce
*** 2746,2752 ****
                            combined_name(procedure->label));
    assembler_label(psz2);
    free(psz2);
!   gg_assign(var_decl_nop, build_int_cst_type(INT, 109));
    }
  
  static void
--- 2740,2764 ----
                            combined_name(procedure->label));
    assembler_label(psz2);
    free(psz2);
! 
!   // We are inserting a NOP after having created a label for the procedure.
!   // This means that when using GDC_COBOL to step into a procedure, the
!   // execution will stop there and show "123 para-name." at the stopped point.
!   //
!   // Note that because there is no user-specified executable code at that point
!   // the user can't set a working breakpoint with "break 123".  But because
!   // GDB will pick up the psz2 text and set a breakpoint there (which is the
!   // location of the NOP) "break para-name" will actually stop and show line
!   // 123.
!   //
!   // This really only makes sense when you look at the assembly language. Keep
!   // in mind as you read it that issuing a "break 123" causes GDB to set a
!   // breakpoint at the first executable machine language code following the
!   // first ".loc 123" directive.
!   //
!   // Yes, trying to understand this causes headaches for many people who read
!   // this.  Take an aspirin.
!   insert_nop(109);
    }
  
  static void
*************** pseudo_return_pop(cbl_proc_t *procedure)
*** 2790,2795 ****
--- 2802,2808 ----
                NULL_TREE);
      }
  
+   token_location_override(current_location_minus_one());
    IF( var_decl_exit_address, eq_op, procedure->exit.addr )
      {
      TRACE1
*************** pseudo_return_pop(cbl_proc_t *procedure)
*** 2799,2809 ****
--- 2812,2824 ----
      // The top of the stack is us!
  
      // Pick up the return address from the pseudo_return stack:
+     token_location_override(current_location_minus_one());
      gg_assign(current_function->void_star_temp,
                gg_call_expr( VOID_P,
                              "__gg__pseudo_return_pop",
                              NULL_TREE));
      // And do the return:
+     token_location_override(current_location_minus_one());
      gg_goto(current_function->void_star_temp);
      }
    ELSE
*************** leave_procedure(struct cbl_proc_t *proce
*** 2837,2847 ****
--- 2852,2864 ----
      // procedure->bottom.label);
      // Procedure can be null, for example at the beginning of a
      // new program, or after somebody else has cleared it out.
+ 
      gg_append_statement(procedure->exit.label);
  
      char *psz;
      psz = xasprintf("_procret." HOST_SIZE_T_PRINT_DEC ":",
                      (fmt_size_t)symbol_label_id(procedure->label));
+     token_location_override(current_location_minus_one());
      gg_insert_into_assembler(psz);
      free(psz);
      pseudo_return_pop(procedure);
*************** parser_enter_section(cbl_label_t *label)
*** 3012,3017 ****
--- 3029,3036 ----
      {
      SHOW_PARSE_HEADER
      SHOW_PARSE_LABEL(" ", label)
+     SHOW_PARSE_INDENT
+     linemap_dump_location( line_table, current_token_location(), stderr );
      SHOW_PARSE_END
      }
  
*************** parser_enter_section(cbl_label_t *label)
*** 3019,3026 ****
  
    // This NOP is needed to give GDB a line number for the entry point of
    // paragraphs
!   gg_set_current_line_number(CURRENT_LINE_NUMBER);
!   gg_assign(var_decl_nop, build_int_cst_type(INT, 101));
  
    struct cbl_proc_t *procedure = find_procedure(label);
    gg_append_statement(procedure->top.label);
--- 3038,3044 ----
  
    // This NOP is needed to give GDB a line number for the entry point of
    // paragraphs
!   insert_nop(101);
  
    struct cbl_proc_t *procedure = find_procedure(label);
    gg_append_statement(procedure->top.label);
*************** parser_enter_paragraph(cbl_label_t *labe
*** 3047,3052 ****
--- 3065,3072 ----
      {
      SHOW_PARSE_HEADER
      SHOW_PARSE_LABEL(" ", label)
+     SHOW_PARSE_INDENT
+     linemap_dump_location( line_table, current_token_location(), stderr );
      SHOW_PARSE_END
      }
  
*************** parser_perform(cbl_label_t *label, bool
*** 3272,3278 ****
      SHOW_PARSE_TEXT(ach)
      if( label )
        {
!       sprintf(ach, 
                " label->proc is %p",
                static_cast<void*>(label->structs.proc));
        }
--- 3292,3298 ----
      SHOW_PARSE_TEXT(ach)
      if( label )
        {
!       sprintf(ach,
                " label->proc is %p",
                static_cast<void*>(label->structs.proc));
        }
*************** parser_perform_times( cbl_label_t *proc_
*** 3426,3431 ****
--- 3446,3452 ----
    sprintf(ach,
            "_procretb." HOST_SIZE_T_PRINT_DEC ":",
            (fmt_size_t)our_pseudo_label);
+   token_location_override(current_location_minus_one());
    gg_insert_into_assembler(ach);
    }
  
*************** internal_perform_through_times(   cbl_la
*** 3579,3584 ****
--- 3600,3606 ----
    sprintf(ach,
            "_procretb." HOST_SIZE_T_PRINT_DEC ":",
            (fmt_size_t)our_pseudo_label);
+   token_location_override(current_location_minus_one());
    gg_insert_into_assembler( ach );
    }
  
*************** parser_leave_file()
*** 3770,3775 ****
--- 3792,3813 ----
      {
      // We are leaving the top-level file, which means this compilation is
      // done, done, done.
+ 
+     // There is, however, one thing left to do.  If the command line says
+     // that this module needs a main entry point, then this is where
+     // we create a main() function.  We build it at the end, so that all of
+     // the .loc directives associated with it appear at the end of the
+     // source code.  We used to create the main() entry point at the beginning,
+     // but that created confusion for GDB when trying to debug the generated
+     // executable.
+     if( main_entry_point )
+       {
+       next_program_is_main = false;
+       build_main_that_calls_something(main_entry_point);
+       free(main_entry_point);
+       main_entry_point = NULL;
+       }
+ 
      gg_leaving_the_source_code_file();
      }
    }
*************** parser_enter_program( const char *funcna
*** 3879,3895 ****
    // The first thing we have to do is mangle this name.  This is safe even
    // though the end result will be mangled again, because the mangler doesn't
    // change a mangled name.
!    
!   char *mangled_name;
!  
!   if( current_call_convention() == cbl_call_cobol_e )
!     {
!     mangled_name = cobol_name_mangler(funcname_);
!     }
!   else
!     {
!     mangled_name = xstrdup(funcname_);
!     }
  
    size_t parent_index = current_program_index();
    char *funcname;
--- 3917,3924 ----
    // The first thing we have to do is mangle this name.  This is safe even
    // though the end result will be mangled again, because the mangler doesn't
    // change a mangled name.
! 
!   char *mangled_name = cobol_name_mangler(funcname_);
  
    size_t parent_index = current_program_index();
    char *funcname;
*************** parser_enter_program( const char *funcna
*** 3917,3944 ****
  
    if( !is_function && !parent_index )
      {
!     // This is a top_level program, and not a function
      if( next_program_is_main )
        {
        next_program_is_main = false;
!       if(main_entry_point)
!         {
!         build_main_that_calls_something(main_entry_point);
!         free(main_entry_point);
!         main_entry_point = NULL;
!         }
!       else
          {
!         build_main_that_calls_something(funcname);
          }
        }
      }
  
-   // Call this after build_main_that_calls_something, because it manipulates
-   // the current line number to DEFAULT_LINE_NUMBER.  We have to manipulate it
-   // back afterward.
-   gg_set_current_line_number(CURRENT_LINE_NUMBER);
- 
    if( strcmp(funcname_, "main") == 0 && this_module_has_main )
      {
      // setting 'retval' to 1 let's the caller know that we are being told
--- 3946,3970 ----
  
    if( !is_function && !parent_index )
      {
!     // This is a top_level program-id, and not a function
      if( next_program_is_main )
        {
+       // This is the first top-level program-id.
        next_program_is_main = false;
!       if( !main_entry_point )
          {
!         // Because no explicit main_entry_point was specified, this program-id,
!         // the first in the file, becomes the target of the main() function
!         // that will be created at parser_leave_file time.
!         main_entry_point = xstrdup(funcname);
! 
!         char *psz = cobol_name_mangler(main_entry_point);
!         strncpy(ach_cobol_entry_point, psz, sizeof(ach_cobol_entry_point)-1);
!         free(psz);
          }
        }
      }
  
    if( strcmp(funcname_, "main") == 0 && this_module_has_main )
      {
      // setting 'retval' to 1 let's the caller know that we are being told
*************** psa_FldBlob(struct cbl_field_t *var )
*** 4361,4367 ****
    }
  
  void
! parser_accept(struct cbl_refer_t tgt,
                special_name_t special_e,
                cbl_label_t *error,
                cbl_label_t *not_error )
--- 4387,4393 ----
    }
  
  void
! parser_accept(const struct cbl_refer_t &tgt,
                special_name_t special_e,
                cbl_label_t *error,
                cbl_label_t *not_error )
*************** parser_accept(struct cbl_refer_t tgt,
*** 4464,4470 ****
  
      case ARG_VALUE_e:
        // We are fetching the variable whose index was established by a prior
!       // DISPLAY UPON ARGUMENT-NUMBER.  After the fetch, the value will be 
        // incremented by one.
        function_to_call = "__gg__accept_arg_value";
        break;
--- 4490,4496 ----
  
      case ARG_VALUE_e:
        // We are fetching the variable whose index was established by a prior
!       // DISPLAY UPON ARGUMENT-NUMBER.  After the fetch, the value will be
        // incremented by one.
        function_to_call = "__gg__accept_arg_value";
        break;
*************** parser_accept_exception_end( cbl_label_t
*** 4600,4607 ****
    }
  
  void
! parser_accept_command_line( cbl_refer_t tgt,
!                             cbl_refer_t source,
                              cbl_label_t *error,
                              cbl_label_t *not_error )
    {
--- 4626,4633 ----
    }
  
  void
! parser_accept_command_line( const cbl_refer_t &tgt,
!                             const cbl_refer_t &source,
                              cbl_label_t *error,
                              cbl_label_t *not_error )
    {
*************** parser_accept_command_line( cbl_refer_t
*** 4743,4749 ****
    }
  
  void
! parser_accept_command_line_count( cbl_refer_t tgt )
    {
    Analyze();
    SHOW_PARSE
--- 4769,4775 ----
    }
  
  void
! parser_accept_command_line_count( const cbl_refer_t &tgt )
    {
    Analyze();
    SHOW_PARSE
*************** parser_accept_command_line_count( cbl_re
*** 4765,4774 ****
    }
  
  void
! parser_accept_envar(struct cbl_refer_t tgt,
!                     struct cbl_refer_t envar,
!                     cbl_label_t *error,
!                     cbl_label_t *not_error )
    {
    Analyze();
  
--- 4791,4800 ----
    }
  
  void
! parser_accept_envar(const struct cbl_refer_t &tgt,
!                     const struct cbl_refer_t &envar,
!                           cbl_label_t *error,
!                           cbl_label_t *not_error )
    {
    Analyze();
  
*************** parser_accept_envar(struct cbl_refer_t t
*** 4851,4857 ****
    }
  
  void
! parser_set_envar( struct cbl_refer_t name, struct cbl_refer_t value )
    {
    Analyze();
    SHOW_PARSE
--- 4877,4884 ----
    }
  
  void
! parser_set_envar( const struct cbl_refer_t &name,
!                   const struct cbl_refer_t &value )
    {
    Analyze();
    SHOW_PARSE
*************** parser_display_field(cbl_field_t *field)
*** 5392,5400 ****
  
  void
  parser_display( const struct cbl_special_name_t *upon,
!                 std::vector<cbl_refer_t> refs, 
!                 bool advance, 
!           const cbl_label_t *not_error, 
            const cbl_label_t *error )
    {
    const size_t n = refs.size();
--- 5419,5427 ----
  
  void
  parser_display( const struct cbl_special_name_t *upon,
!           const std::vector<cbl_refer_t> &refs,
!                 bool advance,
!           const cbl_label_t *not_error,
            const cbl_label_t *error )
    {
    const size_t n = refs.size();
*************** parser_display( const struct cbl_special
*** 5569,5574 ****
--- 5596,5701 ----
    cursor_at_sol = advance;
    }
  
+ static
+ bool  // Returns false for literals; true for named variables
+ get_exhibit_name(tree file_descriptor, const cbl_refer_t &arg)
+   {
+   bool retval;
+   if( is_literal(arg.field) )
+     {
+     // If something is a literal, we just display the literal value
+     parser_display_internal(file_descriptor,
+                             arg,
+                             DISPLAY_NO_ADVANCE);
+     retval = false;
+     }
+   else
+     {
+     // It's not a literal, so we show its name, and the names or literal
+     // values) of any qualifier subscripts or refmods
+     gg_write( file_descriptor,
+               gg_string_literal(arg.field->name),
+               build_int_cst_type(SIZE_T, strlen(arg.field->name)) );
+ 
+     if( arg.subscripts.size() )
+       {
+       // This refer has subscripts:
+       gg_write( file_descriptor,
+                 gg_string_literal("("),
+                 integer_one_node );
+       for(size_t i=0; i<arg.subscripts.size(); i++)
+         {
+         if( i > 0 )
+           {
+           gg_write( file_descriptor,
+                     gg_string_literal(","),
+                     integer_one_node );
+           }
+         get_exhibit_name(file_descriptor, arg.subscripts[i]);
+         }
+       gg_write( file_descriptor,
+                 gg_string_literal(")"),
+                 integer_one_node );
+       }
+     if( arg.refmod.from || arg.refmod.len )
+       {
+       gg_write( file_descriptor,
+                 gg_string_literal("("),
+                 integer_one_node );
+       if( arg.refmod.from )
+         {
+         get_exhibit_name(file_descriptor, *(arg.refmod.from));
+         }
+       gg_write( file_descriptor,
+                 gg_string_literal(":"),
+                 integer_one_node );
+       if( arg.refmod.len )
+         {
+         get_exhibit_name(file_descriptor, *(arg.refmod.len));
+         }
+       gg_write( file_descriptor,
+                 gg_string_literal(")"),
+                 integer_one_node );
+       }
+     retval = true;
+     }
+   return retval;
+   }
+ 
+ void
+ parser_exhibit( bool /*changed*/, bool /*named*/,
+                 const std::vector<cbl_refer_t> &args )
+   {
+   tree file_descriptor = gg_define_int();
+   gg_assign(file_descriptor, integer_one_node);   // stdout is file descriptor 1.
+ 
+   for(size_t i=0; i<args.size(); i++)
+     {
+     CHECK_FIELD(args[i].field);
+     if(i > 0)
+       {
+       // When there more than one argument, the second through Nth get a space
+       // in front of them.
+       gg_write( file_descriptor,
+                 gg_string_literal(" "),
+                 integer_one_node);
+       }
+     if( get_exhibit_name(file_descriptor, args[i]) )
+       {
+       gg_write( file_descriptor,
+                 gg_string_literal("="),
+                 integer_one_node);
+       parser_display_internal(file_descriptor,
+                               args[i],
+                               DISPLAY_NO_ADVANCE);
+       }
+     }
+   gg_write( file_descriptor,
+             gg_string_literal("\n"),
+             integer_one_node);
+   cursor_at_sol = true;
+   }
+ 
  static tree
  get_literalN_value(cbl_field_t *var)
    {
*************** is_valuable( cbl_field_type_t type ) {
*** 6344,6350 ****
    return false;
  }
  
! void parser_sleep(cbl_refer_t seconds)
    {
    if( seconds.field )
      {
--- 6471,6477 ----
    return false;
  }
  
! void parser_sleep(const cbl_refer_t &seconds)
    {
    if( seconds.field )
      {
*************** void parser_sleep(cbl_refer_t seconds)
*** 6364,6370 ****
      // This is a naked place-holding CONTINUE.  Generate some do-nothing
      // code that will stick some .LOC information into the assembly language,
      // so that GDB-COBOL can display the CONTINUE statement.
!     gg_assign(var_decl_nop, build_int_cst_type(INT, 103));
      }
    }
  
--- 6491,6497 ----
      // This is a naked place-holding CONTINUE.  Generate some do-nothing
      // code that will stick some .LOC information into the assembly language,
      // so that GDB-COBOL can display the CONTINUE statement.
!     insert_nop(103);
      }
    }
  
*************** parser_division(cbl_division_t division,
*** 6935,6942 ****
      SHOW_PARSE_END
      }
  
-   gg_set_current_line_number(CURRENT_LINE_NUMBER);
- 
    if( division == data_div_e )
      {
      Analyze();
--- 7062,7067 ----
*************** parser_division(cbl_division_t division,
*** 7394,7399 ****
--- 7519,7529 ----
          ENDIF
        }
        ENDIF
+     // The first token_location that the parser establishes is caused by the
+     // parser scanning all of the lines in the source code.  This messes up the
+     // logic for backing up one line, which is needed to correctly step through
+     // COBOL code with GDB-COBOL.  So, we clear it here.
+     current_location_minus_one_clear();
      }
    }
  
*************** parser_setop( struct cbl_field_t *tgt,
*** 8002,8008 ****
  
  void
  parser_classify(    cbl_field_t *tgt,
!                     cbl_refer_t  candidate,
                      enum classify_t type )
    {
    Analyze();
--- 8132,8138 ----
  
  void
  parser_classify(    cbl_field_t *tgt,
!                const cbl_refer_t  &candidate,
                      enum classify_t type )
    {
    Analyze();
*************** create_iline_address_pairs(struct cbl_pe
*** 8099,8112 ****
  
    gg_create_goto_pair(&tgt->addresses.setup.go_to,
                        &tgt->addresses.setup.label);
- 
-   // Even in -O0 compilations, the compiler does some elementary optimizations
-   // around JMP instructions.  We have the SETUP code for in-line performats
-   // in an island at the end of the loop code.  With this intervention, NEXTing
-   // through the code shows you the final statement of the loop before the
-   // loop actually starts.
- 
-   tgt->addresses.line_number_of_setup_code = gg_get_current_line_number();
    }
  
  void
--- 8229,8234 ----
*************** parser_perform_start( struct cbl_perform
*** 8169,8175 ****
    // Give GDB-COBOL something to chew on when NEXTing.  This instruction will
    // get the line number of the PERFORM N TIMES code.
    gg_append_statement(tgt->addresses.top.label);
!   gg_assign(var_decl_nop, build_int_cst_type(INT, 104));
    }
  
  void
--- 8291,8297 ----
    // Give GDB-COBOL something to chew on when NEXTing.  This instruction will
    // get the line number of the PERFORM N TIMES code.
    gg_append_statement(tgt->addresses.top.label);
!   insert_nop(104);
    }
  
  void
*************** perform_outofline_before_until(struct cb
*** 8321,8326 ****
--- 8443,8449 ----
    sprintf(ach,
            "_procretb." HOST_SIZE_T_PRINT_DEC ":",
            (fmt_size_t)our_pseudo_label);
+   token_location_override(current_location_minus_one());
    gg_insert_into_assembler( ach );
    }
  
*************** perform_outofline_after_until(struct cbl
*** 8384,8389 ****
--- 8507,8513 ----
    sprintf(ach,
            "_procretb." HOST_SIZE_T_PRINT_DEC ":",
            (fmt_size_t)our_pseudo_label);
+   token_location_override(current_location_minus_one());
    gg_insert_into_assembler( ach );
    }
  
*************** perform_outofline_testafter_varying(stru
*** 8504,8509 ****
--- 8628,8634 ----
    sprintf(ach,
            "_procretb." HOST_SIZE_T_PRINT_DEC ":",
            (fmt_size_t)our_pseudo_label);
+   token_location_override(current_location_minus_one());
    gg_insert_into_assembler( ach );
    }
  
*************** perform_outofline_before_varying(   stru
*** 8647,8652 ****
--- 8772,8778 ----
    sprintf(ach,
            "_procretb." HOST_SIZE_T_PRINT_DEC ":",
            (fmt_size_t)our_pseudo_label);
+   token_location_override(current_location_minus_one());
    gg_insert_into_assembler( ach );
    }
  
*************** perform_inline_until(   struct cbl_perfo
*** 8726,8733 ****
                    GOTO TOP
        EXIT:
    */
-   gg_set_current_line_number(cobol_location().last_line);
- 
    gg_append_statement(tgt->addresses.test.label);
  
    // Go to where the conditional is recalculated....
--- 8852,8857 ----
*************** perform_inline_testbefore_varying(  stru
*** 8842,8849 ****
      parser_move(varys[i].varying, varys[i].from);
      }
  
-   gg_set_current_line_number(cobol_location().last_line);
- 
    // Lay down the testing cycle:
    for(size_t i=0; i<N; i++)
      {
--- 8966,8971 ----
*************** parser_perform_until(   struct cbl_perfo
*** 9165,9173 ****
      SHOW_PARSE_END
      }
  
-   gg_set_current_line_number(cobol_location().last_line);
-   gg_assign(var_decl_nop, build_int_cst_type(INT, 105));
- 
    if( tgt->from()->type != LblLoop )
      {
      perform_outofline( tgt, test_before, N, varys);
--- 9287,9292 ----
*************** parser_perform_inline_times(struct cbl_p
*** 9234,9243 ****
    gg_append_statement( tgt->addresses.testA.label );
    gg_append_statement( tgt->addresses.test.label );
  
-   // AT this point, we want to set the line_number to the location of the
-   // END-PERFORM statement.
-   gg_set_current_line_number(cobol_location().last_line);
- 
    gg_decrement(counter);
    // Do the test:
    IF( counter, gt_op, gg_cast(LONG, integer_zero_node) )
--- 9353,9358 ----
*************** parser_perform_inline_times(struct cbl_p
*** 9268,9275 ****
      SHOW_PARSE_END
      }
  
-   int stash = gg_get_current_line_number();
-   gg_set_current_line_number(tgt->addresses.line_number_of_setup_code);
    gg_append_statement( tgt->addresses.setup.label );
  
    // Get the count:
--- 9383,9388 ----
*************** parser_perform_inline_times(struct cbl_p
*** 9300,9307 ****
      gg_append_statement( tgt->addresses.exit.go_to );
      ENDIF
  
-   gg_set_current_line_number(stash);
- 
    SHOW_PARSE
      {
      SHOW_PARSE_INDENT
--- 9413,9418 ----
*************** parser_intrinsic_numval_c( cbl_field_t *
*** 10740,10746 ****
  
  void
  parser_intrinsic_subst( cbl_field_t *f,
!                         cbl_refer_t& ref1,
                          size_t argc,
                          cbl_substitute_t * argv )
    {
--- 10851,10857 ----
  
  void
  parser_intrinsic_subst( cbl_field_t *f,
!                   const cbl_refer_t& ref1,
                          size_t argc,
                          cbl_substitute_t * argv )
    {
*************** parser_file_merge(  cbl_file_t *workfile
*** 12317,12323 ****
  
    const cbl_enabled_exceptions_t&
                                  enabled_exceptions( cdf_enabled_exceptions() );
!   
    for(size_t i=0; i<ninputs; i++)
      {
      if( process_this_exception(ec_sort_merge_file_open_e) )
--- 12428,12434 ----
  
    const cbl_enabled_exceptions_t&
                                  enabled_exceptions( cdf_enabled_exceptions() );
! 
    for(size_t i=0; i<ninputs; i++)
      {
      if( process_this_exception(ec_sort_merge_file_open_e) )
*************** create_and_call(size_t narg,
*** 13016,13022 ****
      // Fetch the FUNCTION_DECL for that FUNCTION_TYPE
      tree function_decl = gg_build_fn_decl(funcname, fndecl_type);
      set_call_convention(function_decl, current_call_convention());
!     
      // Take the address of the function decl:
      tree address_of_function = gg_get_address_of(function_decl);
  
--- 13127,13133 ----
      // Fetch the FUNCTION_DECL for that FUNCTION_TYPE
      tree function_decl = gg_build_fn_decl(funcname, fndecl_type);
      set_call_convention(function_decl, current_call_convention());
! 
      // Take the address of the function decl:
      tree address_of_function = gg_get_address_of(function_decl);
  
*************** create_and_call(size_t narg,
*** 13028,13034 ****
      parser_call_target( funcname, assigment );
  
      // Create the call_expr from that address
!     call_expr = build_call_array_loc( location_from_lineno(),
                                        returned_value_type,
                                        address_of_function,
                                        narg,
--- 13139,13145 ----
      parser_call_target( funcname, assigment );
  
      // Create the call_expr from that address
!     call_expr = build_call_array_loc( gg_token_location(),
                                        returned_value_type,
                                        address_of_function,
                                        narg,
*************** conditional_abs(tree source, const cbl_f
*** 14140,14148 ****
    }
  
  static bool
! mh_identical(cbl_refer_t &destref,
!        const cbl_refer_t &sourceref,
!        const TREEPLET    &tsource)
    {
    // Check to see if the two variables are identical types, thus allowing
    // for a simple byte-for-byte copy of the data areas:
--- 14251,14259 ----
    }
  
  static bool
! mh_identical(const cbl_refer_t &destref,
!              const cbl_refer_t &sourceref,
!              const TREEPLET    &tsource)
    {
    // Check to see if the two variables are identical types, thus allowing
    // for a simple byte-for-byte copy of the data areas:
*************** picky_memcpy(tree &dest_p, const tree &s
*** 14733,14742 ****
    }
  
  static bool
! mh_numeric_display( cbl_refer_t &destref,
!               const cbl_refer_t &sourceref,
!               const TREEPLET    &tsource,
!                     tree size_error)
    {
    bool moved = false;
  
--- 14844,14853 ----
    }
  
  static bool
! mh_numeric_display( const cbl_refer_t &destref,
!                     const cbl_refer_t &sourceref,
!                     const TREEPLET    &tsource,
!                           tree size_error)
    {
    bool moved = false;
  
*************** mh_numeric_display( cbl_refer_t &destref
*** 15222,15232 ****
    }
  
  static bool
! mh_little_endian( cbl_refer_t &destref,
!             const cbl_refer_t &sourceref,
!             const TREEPLET    &tsource,
!                   bool check_for_error,
!                   tree size_error)
    {
    bool moved = false;
  
--- 15333,15343 ----
    }
  
  static bool
! mh_little_endian( const cbl_refer_t &destref,
!                   const cbl_refer_t &sourceref,
!                   const TREEPLET    &tsource,
!                         bool check_for_error,
!                         tree size_error)
    {
    bool moved = false;
  
*************** mh_little_endian( cbl_refer_t &destref,
*** 15294,15302 ****
    }
  
  static bool
! mh_source_is_group( cbl_refer_t &destref,
!               const cbl_refer_t &sourceref,
!               const TREEPLET    &tsrc)
    {
    bool retval = false;
    if( sourceref.field->type == FldGroup && !(destref.field->attr & rjust_e) )
--- 15405,15413 ----
    }
  
  static bool
! mh_source_is_group( const cbl_refer_t &destref,
!                     const cbl_refer_t &sourceref,
!                     const TREEPLET    &tsrc)
    {
    bool retval = false;
    if( sourceref.field->type == FldGroup && !(destref.field->attr & rjust_e) )
*************** psa_FldLiteralA(struct cbl_field_t *fiel
*** 16640,16646 ****
                                                    vs_file_static);
      }
    else
! #endif    
      {
      // We have not seen that string before
      static int nvar = 0;
--- 16751,16757 ----
                                                    vs_file_static);
      }
    else
! #endif
      {
      // We have not seen that string before
      static int nvar = 0;
diff -Nrcpad gcc-16-20250720/gcc/cobol/genapi.h gcc-16-20250727/gcc/cobol/genapi.h
*** gcc-16-20250720/gcc/cobol/genapi.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/genapi.h	Sun Jul 27 22:32:08 2025
*************** void parser_division( cbl_division_t div
*** 52,71 ****
  void parser_enter_program(const char *funcname, bool is_function, int *retval);
  void parser_leave_program();
  
! void parser_accept( cbl_refer_t refer, special_name_t special_e, 
!                     cbl_label_t *error, cbl_label_t *not_error );
  void parser_accept_exception( cbl_label_t *name );
  void parser_accept_exception_end( cbl_label_t *name );
  
  void parser_accept_under_discussion(struct cbl_refer_t tgt, special_name_t special,
                                      cbl_label_t *error, cbl_label_t *not_error );
! void parser_accept_envar( cbl_refer_t refer, cbl_refer_t envar,
!                           cbl_label_t *error, cbl_label_t *not_error );
! void parser_set_envar( cbl_refer_t envar, cbl_refer_t refer );
  
! void parser_accept_command_line( cbl_refer_t tgt, cbl_refer_t src,
!                           cbl_label_t *error, cbl_label_t *not_error );
! void parser_accept_command_line_count( cbl_refer_t tgt );
  
  void parser_accept_date_yymmdd( cbl_field_t *tgt );
  void parser_accept_date_yyyymmdd( cbl_field_t *tgt );
--- 52,77 ----
  void parser_enter_program(const char *funcname, bool is_function, int *retval);
  void parser_leave_program();
  
! void parser_accept( const cbl_refer_t &refer,
!                     special_name_t special_e,
!                     cbl_label_t *error,
!                     cbl_label_t *not_error );
  void parser_accept_exception( cbl_label_t *name );
  void parser_accept_exception_end( cbl_label_t *name );
  
  void parser_accept_under_discussion(struct cbl_refer_t tgt, special_name_t special,
                                      cbl_label_t *error, cbl_label_t *not_error );
! void parser_accept_envar( const cbl_refer_t &refer,
!                           const cbl_refer_t &envar,
!                           cbl_label_t *error,
!                           cbl_label_t *not_error );
! void parser_set_envar( const cbl_refer_t &envar, const cbl_refer_t &refer );
  
! void parser_accept_command_line(const cbl_refer_t &tgt,
!                                 const cbl_refer_t &src,
!                                 cbl_label_t *error,
!                                 cbl_label_t *not_error );
! void parser_accept_command_line_count( const cbl_refer_t &tgt );
  
  void parser_accept_date_yymmdd( cbl_field_t *tgt );
  void parser_accept_date_yyyymmdd( cbl_field_t *tgt );
*************** parser_add( size_t nC, cbl_num_result_t
*** 89,96 ****
              size_t nA, cbl_refer_t *A,
              cbl_arith_format_t format,
              cbl_label_t *error,
!             cbl_label_t *not_error,
!             void *compute_error = NULL);  // This has to be cast to a tree pointer to int
  
  void parser_arith_error( cbl_label_t *name );
  void parser_arith_error_end( cbl_label_t *name );
--- 95,101 ----
              size_t nA, cbl_refer_t *A,
              cbl_arith_format_t format,
              cbl_label_t *error,
!             cbl_label_t *not_error,            void *compute_error = NULL);  // This has to be cast to a tree pointer to int
  
  void parser_arith_error( cbl_label_t *name );
  void parser_arith_error_end( cbl_label_t *name );
*************** parser_bitwise_op(struct cbl_field_t *tg
*** 177,183 ****
  
  void
  parser_classify( struct cbl_field_t *tgt,
!                  struct cbl_refer_t  srca,  enum classify_t type );
  
  void
  parser_op( struct cbl_refer_t cref,
--- 182,189 ----
  
  void
  parser_classify( struct cbl_field_t *tgt,
!            const struct cbl_refer_t &srca,
!                  enum                classify_t type );
  
  void
  parser_op( struct cbl_refer_t cref,
*************** parser_program_hierarchy( const struct c
*** 256,262 ****
  void
  parser_end_program(const char *name=NULL);
  
! void parser_sleep(cbl_refer_t seconds);
  
  void parser_exit( const cbl_refer_t& refer, ec_type_t = ec_none_e );
  void parser_exit_section(void);
--- 262,268 ----
  void
  parser_end_program(const char *name=NULL);
  
! void parser_sleep(const cbl_refer_t &seconds);
  
  void parser_exit( const cbl_refer_t& refer, ec_type_t = ec_none_e );
  void parser_exit_section(void);
*************** void parser_exit_perform( struct cbl_per
*** 265,273 ****
  void parser_exit_program(void); // exits back to COBOL only, else continue
  
  void
  parser_display( const struct cbl_special_name_t *upon,
!                 std::vector<cbl_refer_t> args, 
!                 bool advance = DISPLAY_ADVANCE, 
            const cbl_label_t *not_error = nullptr,
            const cbl_label_t *compute_error = nullptr );
  
--- 271,282 ----
  void parser_exit_program(void); // exits back to COBOL only, else continue
  
  void
+ parser_exhibit( bool changed, bool named,
+                 const std::vector<cbl_refer_t> &args );
+ void
  parser_display( const struct cbl_special_name_t *upon,
!                 const std::vector<cbl_refer_t> &args,
!                 bool advance = DISPLAY_ADVANCE,
            const cbl_label_t *not_error = nullptr,
            const cbl_label_t *compute_error = nullptr );
  
*************** void
*** 305,311 ****
  parser_initialize(const cbl_refer_t& refer, bool like_parser_symbol_add=false);
  
  void
! parser_initialize_programs(size_t nprog, struct cbl_refer_t *progs);
  
  void
  parser_label_label( struct cbl_label_t *label );
--- 314,320 ----
  parser_initialize(const cbl_refer_t& refer, bool like_parser_symbol_add=false);
  
  void
! parser_initialize_programs(size_t nprog, const struct cbl_refer_t *progs);
  
  void
  parser_label_label( struct cbl_label_t *label );
*************** parser_intrinsic_numval_c( cbl_field_t *
*** 452,458 ****
  
  void
  parser_intrinsic_subst( cbl_field_t *f,
!                         cbl_refer_t& ref1,
                          size_t argc,
                          cbl_substitute_t * argv );
  
--- 461,467 ----
  
  void
  parser_intrinsic_subst( cbl_field_t *f,
!                   const cbl_refer_t& ref1,
                          size_t argc,
                          cbl_substitute_t * argv );
  
diff -Nrcpad gcc-16-20250720/gcc/cobol/gengen.cc gcc-16-20250727/gcc/cobol/gengen.cc
*** gcc-16-20250720/gcc/cobol/gengen.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/gengen.cc	Sun Jul 27 22:32:08 2025
***************
*** 107,114 ****
  // Don't like it?  Cry me a river.
  static const int ARG_LIMIT = 512;
  
- static int sv_current_line_number;
- 
  // These are globally useful constants
  tree char_nodes[256];
  
--- 107,112 ----
*************** gg_assign(tree dest, const tree source)
*** 452,458 ****
  
    if( okay )
      {
!     stmt = build2_loc(location_from_lineno(),
                        MODIFY_EXPR,
                        TREE_TYPE(dest),
                        dest,
--- 450,456 ----
  
    if( okay )
      {
!     stmt = build2_loc(gg_token_location(),
                        MODIFY_EXPR,
                        TREE_TYPE(dest),
                        dest,
*************** gg_add_field_to_structure(const tree typ
*** 616,622 ****
    tree id_of_field = get_identifier (name_of_field);
  
    // Create the new field:
!   tree new_field_decl = build_decl(   location_from_lineno(),
                                        FIELD_DECL,
                                        id_of_field,
                                        type_of_field);
--- 614,620 ----
    tree id_of_field = get_identifier (name_of_field);
  
    // Create the new field:
!   tree new_field_decl = build_decl(   gg_token_location(),
                                        FIELD_DECL,
                                        id_of_field,
                                        type_of_field);
*************** gg_define_from_declaration(tree var_decl
*** 1043,1049 ****
      {
      // Having made sure the chain of variable declarations is nicely started,
      // it's time to actually define the storage with a decl_expression:
!     tree stmt = build1_loc (location_from_lineno(),
                              DECL_EXPR,
                              TREE_TYPE(var_decl),
                              var_decl);
--- 1041,1047 ----
      {
      // Having made sure the chain of variable declarations is nicely started,
      // it's time to actually define the storage with a decl_expression:
!     tree stmt = build1_loc (gg_token_location(),
                              DECL_EXPR,
                              TREE_TYPE(var_decl),
                              var_decl);
*************** gg_build_relational_expression(tree oper
*** 1774,1780 ****
        compare = LE_EXPR;
        break;
      }
!   tree relational_expression = build2_loc(location_from_lineno(),
                                            compare,
                                            boolean_type_node,
                                            operand_a,
--- 1772,1778 ----
        compare = LE_EXPR;
        break;
      }
!   tree relational_expression = build2_loc(gg_token_location(),
                                            compare,
                                            boolean_type_node,
                                            operand_a,
*************** gg_create_goto_pair(tree *goto_expr,
*** 1891,1897 ****
  void
  gg_goto_label_decl(tree label_decl)
    {
!   tree goto_expr  = build1_loc( location_from_lineno(),
                                  GOTO_EXPR,
                                  void_type_node,
                                  label_decl);
--- 1889,1895 ----
  void
  gg_goto_label_decl(tree label_decl)
    {
!   tree goto_expr  = build1_loc( gg_token_location(),
                                  GOTO_EXPR,
                                  void_type_node,
                                  label_decl);
*************** gg_create_goto_pair(tree *goto_expr, tre
*** 1938,1944 ****
  void
  gg_goto(tree var_decl_pointer)
    {
!   tree go_to = build1_loc(location_from_lineno(),
                            GOTO_EXPR,
                            void_type_node,
                            var_decl_pointer);
--- 1936,1942 ----
  void
  gg_goto(tree var_decl_pointer)
    {
!   tree go_to = build1_loc(gg_token_location(),
                            GOTO_EXPR,
                            void_type_node,
                            var_decl_pointer);
*************** gg_printf(const char *format_string, ...
*** 2186,2192 ****
      function = gg_get_function_address(INT, "__gg__fprintf_stderr");
      }
  
!   tree stmt = build_call_array_loc (location_from_lineno(),
                                      INT,
                                      function,
                                      nargs,
--- 2184,2190 ----
      function = gg_get_function_address(INT, "__gg__fprintf_stderr");
      }
  
!   tree stmt = build_call_array_loc (gg_token_location(),
                                      INT,
                                      function,
                                      nargs,
*************** gg_fprintf(tree fd, int nargs, const cha
*** 2233,2239 ****
      function = gg_get_function_address(INT, "sprintf");
      }
  
!   tree stmt = build_call_array_loc (location_from_lineno(),
                                      INT,
                                      function,
                                      argc,
--- 2231,2237 ----
      function = gg_get_function_address(INT, "sprintf");
      }
  
!   tree stmt = build_call_array_loc (gg_token_location(),
                                      INT,
                                      function,
                                      argc,
*************** void
*** 2280,2286 ****
  gg_memset(tree dest, const tree value, tree size)
    {
    tree the_call =
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_MEMSET),
                            3,
                            dest,
--- 2278,2284 ----
  gg_memset(tree dest, const tree value, tree size)
    {
    tree the_call =
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_MEMSET),
                            3,
                            dest,
*************** gg_memchr(tree buf, tree ch, tree length
*** 2294,2300 ****
    {
    tree the_call = fold_convert(
        pvoid_type_node,
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_MEMCHR),
                            3,
                            buf,
--- 2292,2298 ----
    {
    tree the_call = fold_convert(
        pvoid_type_node,
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_MEMCHR),
                            3,
                            buf,
*************** void
*** 2309,2315 ****
  gg_memcpy(tree dest, const tree src, tree size)
    {
    tree the_call = build_call_expr_loc(
!         location_from_lineno(),
          builtin_decl_explicit (BUILT_IN_MEMCPY),
          3,
          dest,
--- 2307,2313 ----
  gg_memcpy(tree dest, const tree src, tree size)
    {
    tree the_call = build_call_expr_loc(
!         gg_token_location(),
          builtin_decl_explicit (BUILT_IN_MEMCPY),
          3,
          dest,
*************** void
*** 2324,2330 ****
  gg_memmove(tree dest, const tree src, tree size)
    {
    tree the_call = build_call_expr_loc(
!         location_from_lineno(),
          builtin_decl_explicit (BUILT_IN_MEMMOVE),
          3,
          dest,
--- 2322,2328 ----
  gg_memmove(tree dest, const tree src, tree size)
    {
    tree the_call = build_call_expr_loc(
!         gg_token_location(),
          builtin_decl_explicit (BUILT_IN_MEMMOVE),
          3,
          dest,
*************** void
*** 2357,2363 ****
  gg_strcpy(tree dest, tree src)
    {
    tree the_call =
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_STRCPY),
                            2,
                            dest,
--- 2355,2361 ----
  gg_strcpy(tree dest, tree src)
    {
    tree the_call =
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_STRCPY),
                            2,
                            dest,
*************** gg_strcmp(tree A, tree B)
*** 2370,2376 ****
    {
    tree the_call = fold_convert(
        integer_type_node,
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_STRCMP),
                            2,
                            A,
--- 2368,2374 ----
    {
    tree the_call = fold_convert(
        integer_type_node,
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_STRCMP),
                            2,
                            A,
*************** gg_strncmp(tree char_star_A, tree char_s
*** 2402,2408 ****
    {
    tree the_call = fold_convert(
        integer_type_node,
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_STRNCMP),
                            3,
                            char_star_A,
--- 2400,2406 ----
    {
    tree the_call = fold_convert(
        integer_type_node,
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_STRNCMP),
                            3,
                            char_star_A,
*************** gg_return(tree operand)
*** 2433,2439 ****
      {
      // When there is no operand, or if the function result is void, then
      // we just generate a return_expr.
!     stmt = build1_loc(location_from_lineno(), RETURN_EXPR, void_type_node, NULL_TREE);
      }
    else
      {
--- 2431,2437 ----
      {
      // When there is no operand, or if the function result is void, then
      // we just generate a return_expr.
!     stmt = build1_loc(gg_token_location(), RETURN_EXPR, void_type_node, NULL_TREE);
      }
    else
      {
*************** gg_return(tree operand)
*** 2443,2449 ****
                              function_type,
                              DECL_RESULT(current_function->function_decl),
                              gg_cast(function_type, operand));
!     stmt = build1_loc(location_from_lineno(), RETURN_EXPR, void_type_node, modify);
      }
    gg_append_statement(stmt);
    }
--- 2441,2447 ----
                              function_type,
                              DECL_RESULT(current_function->function_decl),
                              gg_cast(function_type, operand));
!     stmt = build1_loc(gg_token_location(), RETURN_EXPR, void_type_node, modify);
      }
    gg_append_statement(stmt);
    }
*************** gg_return(tree operand)
*** 2451,2457 ****
  void
  chain_parameter_to_function(tree function_decl, const tree param_type,  const char *name)
    {
!   tree parm = build_decl (location_from_lineno(),
                            PARM_DECL,
                            get_identifier (name),
                            param_type);
--- 2449,2455 ----
  void
  chain_parameter_to_function(tree function_decl, const tree param_type,  const char *name)
    {
!   tree parm = build_decl (gg_token_location(),
                            PARM_DECL,
                            get_identifier (name),
                            param_type);
*************** gg_define_function( tree return_type,
*** 2686,2692 ****
      }
  
    // Establish the RESULT_DECL for the function:
!   tree resdecl = build_decl (location_from_lineno(), RESULT_DECL, NULL_TREE, return_type);
    DECL_CONTEXT (resdecl) = function_decl;
    DECL_RESULT (function_decl) = resdecl;
  
--- 2684,2690 ----
      }
  
    // Establish the RESULT_DECL for the function:
!   tree resdecl = build_decl (gg_token_location(), RESULT_DECL, NULL_TREE, return_type);
    DECL_CONTEXT (resdecl) = function_decl;
    DECL_RESULT (function_decl) = resdecl;
  
*************** gg_get_function_decl(tree return_type, c
*** 2818,2824 ****
      }
  
    // Establish the RESULT_DECL for the function:
!   tree resdecl = build_decl (location_from_lineno(), RESULT_DECL, NULL_TREE, return_type);
    DECL_CONTEXT (resdecl) = function_decl;
    DECL_RESULT (function_decl) = resdecl;
  
--- 2816,2822 ----
      }
  
    // Establish the RESULT_DECL for the function:
!   tree resdecl = build_decl (gg_token_location(), RESULT_DECL, NULL_TREE, return_type);
    DECL_CONTEXT (resdecl) = function_decl;
    DECL_RESULT (function_decl) = resdecl;
  
*************** gg_call_expr(tree return_type, const cha
*** 3076,3082 ****
    tree the_func_addr = build1(ADDR_EXPR,
                                build_pointer_type (TREE_TYPE(function_decl)),
                                function_decl);
!   tree the_call = build_call_array_loc(location_from_lineno(),
                                         return_type,
                                         the_func_addr,
                                         nargs,
--- 3074,3080 ----
    tree the_func_addr = build1(ADDR_EXPR,
                                build_pointer_type (TREE_TYPE(function_decl)),
                                function_decl);
!   tree the_call = build_call_array_loc(gg_token_location(),
                                         return_type,
                                         the_func_addr,
                                         nargs,
*************** gg_call(tree return_type, const char *fu
*** 3132,3138 ****
    tree the_func_addr = build1(ADDR_EXPR,
                                build_pointer_type (TREE_TYPE(function_decl)),
                                function_decl);
!   tree the_call = build_call_array_loc(location_from_lineno(),
                                         return_type,
                                         the_func_addr,
                                         nargs,
--- 3130,3136 ----
    tree the_func_addr = build1(ADDR_EXPR,
                                build_pointer_type (TREE_TYPE(function_decl)),
                                function_decl);
!   tree the_call = build_call_array_loc(gg_token_location(),
                                         return_type,
                                         the_func_addr,
                                         nargs,
*************** gg_call_expr_list(tree return_type, tree
*** 3157,3163 ****
    // Avoid that with something like
    //      gg_assign( dest, gg_call_expr_list(...) );
  
!   tree the_call = build_call_array_loc(location_from_lineno(),
                                         return_type,
                                         function_pointer,
                                         param_count,
--- 3155,3161 ----
    // Avoid that with something like
    //      gg_assign( dest, gg_call_expr_list(...) );
  
!   tree the_call = build_call_array_loc(gg_token_location(),
                                         return_type,
                                         function_pointer,
                                         param_count,
*************** void
*** 3192,3198 ****
  gg_exit(tree exit_code)
    {
    tree the_call =
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_EXIT),
                            1,
                            exit_code);
--- 3190,3196 ----
  gg_exit(tree exit_code)
    {
    tree the_call =
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_EXIT),
                            1,
                            exit_code);
*************** void
*** 3203,3209 ****
  gg_abort()
    {
    tree the_call =
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_ABORT),
                            0);
    gg_append_statement(the_call);
--- 3201,3207 ----
  gg_abort()
    {
    tree the_call =
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_ABORT),
                            0);
    gg_append_statement(the_call);
*************** gg_strlen(tree psz)
*** 3214,3220 ****
    {
    tree the_call = fold_convert(
        size_type_node,
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_STRLEN),
                            1,
                            psz));
--- 3212,3218 ----
    {
    tree the_call = fold_convert(
        size_type_node,
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_STRLEN),
                            1,
                            psz));
*************** gg_strdup(tree psz)
*** 3226,3232 ****
    {
    tree the_call = fold_convert(
        build_pointer_type(char_type_node),
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_STRDUP),
                            1,
                            psz));
--- 3224,3230 ----
    {
    tree the_call = fold_convert(
        build_pointer_type(char_type_node),
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_STRDUP),
                            1,
                            psz));
*************** gg_malloc(tree size)
*** 3240,3246 ****
    {
    tree the_call = fold_convert(
        pvoid_type_node,
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_MALLOC),
                            1,
                            size));
--- 3238,3244 ----
    {
    tree the_call = fold_convert(
        pvoid_type_node,
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_MALLOC),
                            1,
                            size));
*************** gg_realloc(tree base, tree size)
*** 3252,3258 ****
    {
    tree the_call = fold_convert(
        pvoid_type_node,
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_REALLOC),
                            2,
                            base,
--- 3250,3256 ----
    {
    tree the_call = fold_convert(
        pvoid_type_node,
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_REALLOC),
                            2,
                            base,
*************** void
*** 3276,3282 ****
  gg_free(tree pointer)
    {
    tree the_call =
!       build_call_expr_loc(location_from_lineno(),
                            builtin_decl_explicit (BUILT_IN_FREE),
                            1,
                            pointer);
--- 3274,3280 ----
  gg_free(tree pointer)
    {
    tree the_call =
!       build_call_expr_loc(gg_token_location(),
                            builtin_decl_explicit (BUILT_IN_FREE),
                            1,
                            pointer);
*************** gg_string_literal(const char *string)
*** 3377,3394 ****
    return build_string_literal(strlen(string)+1, string);
    }
  
- void
- gg_set_current_line_number(int line_number)
-   {
-   sv_current_line_number = line_number;
-   }
- 
- int
- gg_get_current_line_number()
-   {
-   return sv_current_line_number;
-   }
- 
  tree
  gg_trans_unit_var_decl(const char *var_name)
    {
--- 3375,3380 ----
*************** gg_insert_into_assembler(const char ach[
*** 3410,3416 ****
    if( !optimize )
      {
      // Create the required generic tag
!     tree asm_expr = build5_loc( location_from_lineno(),
                              ASM_EXPR,
                              VOID,
                              build_string(strlen(ach), ach),
--- 3396,3402 ----
    if( !optimize )
      {
      // Create the required generic tag
!     tree asm_expr = build5_loc( gg_token_location(),
                              ASM_EXPR,
                              VOID,
                              build_string(strlen(ach), ach),
*************** gg_insert_into_assemblerf(const char *fo
*** 3447,3451 ****
      gg_insert_into_assembler(ach);
      }
    }
  
! #pragma GCC diagnostic pop
\ No newline at end of file
--- 3433,3460 ----
      gg_insert_into_assembler(ach);
      }
    }
+ #pragma GCC diagnostic pop
  
! static location_t sv_token_location_override = 0;
! 
! void
! token_location_override(location_t loc)
!   {
!   sv_token_location_override = loc;
!   }
! 
! location_t
! gg_token_location()
!   {
!   location_t retval;
!   if( sv_token_location_override )
!     {
!     retval = sv_token_location_override;
!     sv_token_location_override = 0;
!     }
!   else
!     {
!     retval = current_token_location();
!     }
!   return retval;
!   }
diff -Nrcpad gcc-16-20250720/gcc/cobol/gengen.h gcc-16-20250727/gcc/cobol/gengen.h
*** gcc-16-20250720/gcc/cobol/gengen.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/gengen.h	Sun Jul 27 22:32:08 2025
*************** extern tree gg_indirect(tree pointer, tr
*** 525,535 ****
  extern tree gg_string_literal(const char *string);
  
  #define CURRENT_LINE_NUMBER (cobol_location().first_line)
! extern location_t location_from_lineno();
! 
! // When set to true, use UNKNOWN_LOCATION instead of CURRENT_LINE_NUMBER
! extern void gg_set_current_line_number(int line_number);
! extern int  gg_get_current_line_number();
  
  extern tree gg_trans_unit_var_decl(const char *var_name);
  
--- 525,535 ----
  extern tree gg_string_literal(const char *string);
  
  #define CURRENT_LINE_NUMBER (cobol_location().first_line)
! extern location_t gg_token_location();
! extern location_t current_token_location();
! extern location_t current_location_minus_one();
! extern void current_location_minus_one_clear();
! extern void token_location_override(location_t loc);
  
  extern tree gg_trans_unit_var_decl(const char *var_name);
  
diff -Nrcpad gcc-16-20250720/gcc/cobol/genmath.cc gcc-16-20250727/gcc/cobol/genmath.cc
*** gcc-16-20250720/gcc/cobol/genmath.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/genmath.cc	Sun Jul 27 22:32:08 2025
*************** static bool
*** 610,616 ****
  fast_divide(size_t nC, cbl_num_result_t *C,
              size_t nA, cbl_refer_t *A,
              size_t nB, cbl_refer_t *B,
!             cbl_refer_t             remainder)
    {
    bool retval = false;
    if( all_results_binary(nC, C) )
--- 610,616 ----
  fast_divide(size_t nC, cbl_num_result_t *C,
              size_t nA, cbl_refer_t *A,
              size_t nB, cbl_refer_t *B,
!       const cbl_refer_t             &remainder)
    {
    bool retval = false;
    if( all_results_binary(nC, C) )
diff -Nrcpad gcc-16-20250720/gcc/cobol/genutil.cc gcc-16-20250727/gcc/cobol/genutil.cc
*** gcc-16-20250720/gcc/cobol/genutil.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/genutil.cc	Sun Jul 27 22:32:08 2025
*************** static
*** 305,311 ****
  void
  get_and_check_refstart_and_reflen(  tree         refstart,// LONG returned value
                                      tree         reflen,  // LONG returned value
!                                     cbl_refer_t &refer)
    {
    const cbl_enabled_exceptions_t&
                                  enabled_exceptions( cdf_enabled_exceptions() );
--- 305,311 ----
  void
  get_and_check_refstart_and_reflen(  tree         refstart,// LONG returned value
                                      tree         reflen,  // LONG returned value
!                               const cbl_refer_t &refer)
    {
    const cbl_enabled_exceptions_t&
                                  enabled_exceptions( cdf_enabled_exceptions() );
*************** get_depending_on_value(tree retval, cons
*** 542,549 ****
  
  static
  tree
! get_data_offset(cbl_refer_t &refer,
!                 int *pflags = NULL)
    {
    Analyze();
    // This routine returns a tree which is the size_t offset to the data in the
--- 542,549 ----
  
  static
  tree
! get_data_offset(const cbl_refer_t &refer,
!                       int *pflags = NULL)
    {
    Analyze();
    // This routine returns a tree which is the size_t offset to the data in the
*************** refer_is_clean(const cbl_refer_t &refer)
*** 1974,1980 ****
      */
  static
  tree  // size_t
! refer_refmod_length(cbl_refer_t &refer)
    {
    Analyze();
    REFER("refstart and reflen");
--- 1974,1980 ----
      */
  static
  tree  // size_t
! refer_refmod_length(const cbl_refer_t &refer)
    {
    Analyze();
    REFER("refstart and reflen");
*************** refer_fill_depends(const cbl_refer_t &re
*** 2017,2024 ****
    }
  
  tree  // size_t
! refer_offset(cbl_refer_t &refer,
!                     int *pflags)
    {
    // This routine calculates the effect of a refer offset on the
    // refer.field->data location.  When there are subscripts, the data location
--- 2017,2024 ----
    }
  
  tree  // size_t
! refer_offset(const cbl_refer_t &refer,
!                    int *pflags)
    {
    // This routine calculates the effect of a refer offset on the
    // refer.field->data location.  When there are subscripts, the data location
*************** refer_offset(cbl_refer_t &refer,
*** 2045,2051 ****
  
  static
  tree   // size_t
! refer_size(cbl_refer_t &refer, refer_type_t refer_type)
    {
    Analyze();
    static tree retval = gg_define_variable(SIZE_T, "..rs_retval", vs_file_static);
--- 2045,2051 ----
  
  static
  tree   // size_t
! refer_size(const cbl_refer_t &refer, refer_type_t refer_type)
    {
    Analyze();
    static tree retval = gg_define_variable(SIZE_T, "..rs_retval", vs_file_static);
*************** refer_size(cbl_refer_t &refer, refer_typ
*** 2086,2098 ****
    }
  
  tree  // size_t
! refer_size_dest(cbl_refer_t &refer)
    {
    return refer_size(refer, refer_dest);
    }
  
  tree  // size_t
! refer_size_source(cbl_refer_t &refer)
    {
    /*  There are oddities involved with refer_size_source and refer_size_dest.
        See the comments in refer_has_depends for some explanation.  There are
--- 2086,2098 ----
    }
  
  tree  // size_t
! refer_size_dest(const cbl_refer_t &refer)
    {
    return refer_size(refer, refer_dest);
    }
  
  tree  // size_t
! refer_size_source(const cbl_refer_t &refer)
    {
    /*  There are oddities involved with refer_size_source and refer_size_dest.
        See the comments in refer_has_depends for some explanation.  There are
*************** refer_size_source(cbl_refer_t &refer)
*** 2129,2135 ****
    }
  
  tree
! qualified_data_location(cbl_refer_t &refer)
    {
    return gg_add(member(refer.field->var_decl_node, "data"),
                  refer_offset(refer));
--- 2129,2135 ----
    }
  
  tree
! qualified_data_location(const cbl_refer_t &refer)
    {
    return gg_add(member(refer.field->var_decl_node, "data"),
                  refer_offset(refer));
diff -Nrcpad gcc-16-20250720/gcc/cobol/genutil.h gcc-16-20250727/gcc/cobol/genutil.h
*** gcc-16-20250720/gcc/cobol/genutil.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/genutil.h	Sun Jul 27 22:32:08 2025
*************** char     *get_literal_string(cbl_field_t
*** 140,151 ****
  
  bool      refer_is_clean(const cbl_refer_t &refer);
  
! tree      refer_offset(cbl_refer_t &refer,
                         int *pflags=NULL);
! tree      refer_size_source(cbl_refer_t &refer);
! tree      refer_size_dest(cbl_refer_t &refer);
  
! tree      qualified_data_location(cbl_refer_t &refer);
  
  void      build_array_of_treeplets( int ngroup,
                                      size_t N,
--- 140,151 ----
  
  bool      refer_is_clean(const cbl_refer_t &refer);
  
! tree      refer_offset(const cbl_refer_t &refer,
                         int *pflags=NULL);
! tree      refer_size_source(const cbl_refer_t &refer);
! tree      refer_size_dest(const cbl_refer_t &refer);
  
! tree      qualified_data_location(const cbl_refer_t &refer);
  
  void      build_array_of_treeplets( int ngroup,
                                      size_t N,
diff -Nrcpad gcc-16-20250720/gcc/cobol/parse.y gcc-16-20250727/gcc/cobol/parse.y
*** gcc-16-20250720/gcc/cobol/parse.y	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/parse.y	Sun Jul 27 22:32:08 2025
***************
*** 801,806 ****
--- 801,807 ----
  %type   <boolean>       io_invalid  read_eof  write_eop
                          global is_global anycase backward
                          end_display
+                         exh_changed exh_named
  %type   <number>        mistake globally first_last
  %type   <io_mode>   io_mode
  
***************
*** 1012,1018 ****
  %right                  IF THEN ELSE
                          SENTENCE
                          ACCEPT ADD ALTER CALL CANCEL CLOSE COMPUTE CONTINUE
!                         DELETE DISPLAY DIVIDE EVALUATE END EOP EXIT FILLER_kw
                          GOBACK GOTO
                          INITIALIZE INSPECT
                          MERGE MOVE MULTIPLY OPEN OVERFLOW_kw PARAGRAPH PERFORM
--- 1013,1021 ----
  %right                  IF THEN ELSE
                          SENTENCE
                          ACCEPT ADD ALTER CALL CANCEL CLOSE COMPUTE CONTINUE
!                         DELETE DISPLAY DIVIDE
!                         EVALUATE END EOP EXIT
!                         FILLER_kw
                          GOBACK GOTO
                          INITIALIZE INSPECT
                          MERGE MOVE MULTIPLY OPEN OVERFLOW_kw PARAGRAPH PERFORM
*************** statement:      error {
*** 5052,5057 ****
--- 5055,5061 ----
          |       divide          { $$ =  DIVIDE; }
          |       entry           { $$ =  ENTRY; }
          |       evaluate        { $$ =  EVALUATE; }
+         |       exhibit_stmt    { $$ =  EXHIBIT; }
          |       exit            { $$ =  EXIT; }
          |       free            { $$ =  FREE; }
          |       go_to           { $$ =  GOTO; }
*************** disp_upon:    	device_name {
*** 5687,5692 ****
--- 5691,5710 ----
                  }
                  ;
  
+ exhibit_stmt:   EXHIBIT exh_changed exh_named vargs {
+                   statement_begin(@1, EXHIBIT);
+                   std::vector<cbl_refer_t> args( $vargs->args.begin(),
+                                                  $vargs->args.end() );
+                   parser_exhibit( $exh_changed, $exh_named, args );
+                 }
+                 ;
+ exh_changed:    %empty  { $$ = false; }
+         |       CHANGED { $$ = true; }
+                 ;
+ exh_named:      %empty  { $$ = false; }
+         |       NAMED   { $$ = true; }
+                 ;
+ 
  divide:         divide_impl end_divide { ast_divide($1); }
          |       divide_cond end_divide { ast_divide($1); }
                  ;
*************** perform_cond:   UNTIL { parser_perform_c
*** 7636,7641 ****
--- 7654,7660 ----
  perform_inline: perform_start statements END_PERFORM
                  {
  		  location_set(@END_PERFORM);
+ 		  parser_sleep(*cbl_refer_t::empty());
  		  $$ = perform_current();
  		  if( $perform_start == LOCATION ) {
  		    error_msg(@1, "LOCATION not valid with PERFORM Format 2");
*************** perform_inline: perform_start statements
*** 7644,7649 ****
--- 7663,7669 ----
          |       perform_start END_PERFORM
                  {
  		  location_set(@END_PERFORM);
+ 		  parser_sleep(*cbl_refer_t::empty());
  		  $$ = perform_current();
  		  if( $perform_start == LOCATION ) {
  		    error_msg(@1, "LOCATION not valid with PERFORM Format 2");
*************** label_add( const YYLTYPE& loc,
*** 11788,11794 ****
                  name, cbl_label_of(p)->name, cbl_label_of(p)->line);
      }
    }
!   struct cbl_label_t label = { type, parent, loc.last_line };
  
    if( !namcpy(loc, label.name, name) ) return NULL;
    auto p =  symbol_label_add(PROGRAM, &label);
--- 11808,11814 ----
                  name, cbl_label_of(p)->name, cbl_label_of(p)->line);
      }
    }
!   struct cbl_label_t label = { type, parent, loc.first_line };
  
    if( !namcpy(loc, label.name, name) ) return NULL;
    auto p =  symbol_label_add(PROGRAM, &label);
diff -Nrcpad gcc-16-20250720/gcc/cobol/parse_ante.h gcc-16-20250727/gcc/cobol/parse_ante.h
*** gcc-16-20250720/gcc/cobol/parse_ante.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/parse_ante.h	Sun Jul 27 22:32:08 2025
*************** void input_file_status_notify();
*** 103,109 ****
          }                                                               \
        location_dump("parse.c", __LINE__, "current", (Current));         \
        input_file_status_notify();                                       \
!       gcc_location_set( location_set(Current) );                        \
    } while (0)
  
  int yylex(void);
--- 103,109 ----
          }                                                               \
        location_dump("parse.c", __LINE__, "current", (Current));         \
        input_file_status_notify();                                       \
!       location_set(Current);                                            \
    } while (0)
  
  int yylex(void);
*************** goodnight_gracie() {
*** 3493,3510 ****
  
  // false after USE statement, to enter Declarative with EC intact. 
  static bool statement_cleanup = true;
  
  static void statement_epilog( int token );
  
  const char * keyword_str( int token );
  
- static YYLTYPE current_location;
- 
  const YYLTYPE& cobol_location() { return current_location; }
  
! static inline YYLTYPE
  location_set( const YYLTYPE& loc ) {
!   return current_location = loc;
  }
  
  static void statement_begin( const YYLTYPE& loc, int token );
--- 3493,3510 ----
  
  // false after USE statement, to enter Declarative with EC intact. 
  static bool statement_cleanup = true;
+ static YYLTYPE current_location;
  
  static void statement_epilog( int token );
  
  const char * keyword_str( int token );
  
  const YYLTYPE& cobol_location() { return current_location; }
  
! static inline void
  location_set( const YYLTYPE& loc ) {
!   current_location = loc;
!   gcc_location_set(loc);
  }
  
  static void statement_begin( const YYLTYPE& loc, int token );
diff -Nrcpad gcc-16-20250720/gcc/cobol/scan.l gcc-16-20250727/gcc/cobol/scan.l
*** gcc-16-20250720/gcc/cobol/scan.l	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/scan.l	Sun Jul 27 22:32:08 2025
*************** EOL  \r?\n
*** 89,94 ****
--- 89,95 ----
  BLANK_EOL   [[:blank:]]*{EOL}
  BLANK_OEOL  [[:blank:]]*{EOL}?
  
+ PICTURE   [^[:space:]]+
  
  DOTSEP    [.]+[[:space:]]
  DOTEOL    [[:blank:]]*[.]{BLANK_EOL}
*************** SIZE_ERROR (ON[[[:space:]]+)?SIZE[[:spac
*** 176,182 ****
  VARTYPE  NUMERIC|ALPHABETIC|ALPHABETIC_LOWER|ALPHABETIC_UPPER|DBCS|KANJI
  NAMTYP   {NAME}|{VARTYPE}
  
! NL       [[:blank:]]*\r?\n[[:blank:]]*
  
  PUSH_FILE \f?[#]FILE{SPC}PUSH{SPC}[^\f]+\f
  POP_FILE  \f?[#]FILE{SPC}POP\f
--- 177,183 ----
  VARTYPE  NUMERIC|ALPHABETIC|ALPHABETIC_LOWER|ALPHABETIC_UPPER|DBCS|KANJI
  NAMTYP   {NAME}|{VARTYPE}
  
! NL       [[:blank:]]*{EOL}[[:blank:]]*
  
  PUSH_FILE \f?[#]FILE{SPC}PUSH{SPC}[^\f]+\f
  POP_FILE  \f?[#]FILE{SPC}POP\f
*************** USE({SPC}FOR)?		{ return USE; }
*** 965,971 ****
                                return NUMSTR;
                             }
  
!   PIC(TURE)?({SPC}IS)?[[:space:]]{BLANK_OEOL} {
  				  yy_push_state(picture); return PIC; }
  
    ANY				{ return ANY; }
--- 966,974 ----
                                return NUMSTR;
                             }
  
!   PIC(TURE)?({SPC}IS)?{SPC}{PICTURE} {
! 				  auto pos = validate_picture();
! 				  myless(pos);
  				  yy_push_state(picture); return PIC; }
  
    ANY				{ return ANY; }
*************** USE({SPC}FOR)?		{ return USE; }
*** 1147,1153 ****
  	    		  yy_push_state(hex_state); }
    N?X{nonseq}		{ dbgmsg("invalid hexadecimal value: %s", yytext);
  			  return NO_CONDITION; }
!   [[:blank:]]*\r?\n     {}
  
    WORKING-STORAGE{SPC}SECTION { return WORKING_STORAGE_SECT; }
    LOCAL-STORAGE{SPC}SECTION   { return LOCAL_STORAGE_SECT; }
--- 1150,1156 ----
  	    		  yy_push_state(hex_state); }
    N?X{nonseq}		{ dbgmsg("invalid hexadecimal value: %s", yytext);
  			  return NO_CONDITION; }
!   [[:blank:]]*{EOL}     {}
  
    WORKING-STORAGE{SPC}SECTION { return WORKING_STORAGE_SECT; }
    LOCAL-STORAGE{SPC}SECTION   { return LOCAL_STORAGE_SECT; }
*************** USE({SPC}FOR)?		{ return USE; }
*** 1217,1223 ****
    {NP}V?/[,.]?     { yylval.number = ndigit(yyleng);     return picset(PIC_P); }
    {N9}*V/{N9}*     { yylval.number = ndigit(yyleng - 1); return picset(NINEV); }
    {N9}/{N9}*[,.]?  { yylval.number = ndigit(yyleng);     return picset(NINES); }
!   P+/[,.]?\r?\n    { yylval.number = yyleng;             return picset(PIC_P); }
  
    1{1,31}/({COUNT}|[(]{NAME}[)]) {
                           yy_push_state(picture_count);
--- 1220,1226 ----
    {NP}V?/[,.]?     { yylval.number = ndigit(yyleng);     return picset(PIC_P); }
    {N9}*V/{N9}*     { yylval.number = ndigit(yyleng - 1); return picset(NINEV); }
    {N9}/{N9}*[,.]?  { yylval.number = ndigit(yyleng);     return picset(NINES); }
!   P+/[,.]?{EOL}    { yylval.number = yyleng;             return picset(PIC_P); }
  
    1{1,31}/({COUNT}|[(]{NAME}[)]) {
                           yy_push_state(picture_count);
*************** USE({SPC}FOR)?		{ return USE; }
*** 1316,1322 ****
    [""]{SPC}[&]{SPC}[""''] {
  		        if( yytext[yyleng - 1] == '\'' ) BEGIN(quoted1);
  		      }
!   [""]-{OSPC}(\r?\n{OSPC})+[""] /* continue ...  */
    [""]                {
        			char *s = xstrdup(tmpstring? tmpstring : "\0");
                          yylval.literal.set_data(strlen(s), s);
--- 1319,1325 ----
    [""]{SPC}[&]{SPC}[""''] {
  		        if( yytext[yyleng - 1] == '\'' ) BEGIN(quoted1);
  		      }
!   [""]-{OSPC}({EOL}{OSPC})+[""] /* continue ...  */
    [""]                {
        			char *s = xstrdup(tmpstring? tmpstring : "\0");
                          yylval.literal.set_data(strlen(s), s);
*************** USE({SPC}FOR)?		{ return USE; }
*** 1333,1339 ****
    ['']{SPC}[&]{SPC}[""''] {
  		        if( yytext[yyleng - 1] == '"' ) BEGIN(quoted2);
  		      }
!   ['']-{OSPC}(\r?\n{OSPC})+[''] /* continue ...  */
    ['']                {
        			char *s = xstrdup(tmpstring? tmpstring : "\0");
                          yylval.literal.set_data(strlen(s), s);
--- 1336,1342 ----
    ['']{SPC}[&]{SPC}[""''] {
  		        if( yytext[yyleng - 1] == '"' ) BEGIN(quoted2);
  		      }
!   ['']-{OSPC}({EOL}{OSPC})+[''] /* continue ...  */
    ['']                {
        			char *s = xstrdup(tmpstring? tmpstring : "\0");
                          yylval.literal.set_data(strlen(s), s);
*************** BASIS		{ yy_push_state(basis); return BA
*** 2040,2046 ****
  		  return symbol_file(PROGRAM, yytext)? FILENAME : NAME;
  		}
    [[:blank:]]+
!   \r?\n		{ yy_pop_state(); }
  }
  
  <raising>{
--- 2043,2049 ----
  		  return symbol_file(PROGRAM, yytext)? FILENAME : NAME;
  		}
    [[:blank:]]+
!   {EOL}		{ yy_pop_state(); }
  }
  
  <raising>{
*************** BASIS		{ yy_push_state(basis); return BA
*** 2169,2175 ****
  <*>{DOTSEP}			{ return '.'; }
  <*>[().=*/+&-]			{ return *yytext; }
  <*>[[:blank:]]+
! <*>\r?\n
  
  <*>{
    {COMMA}
--- 2172,2178 ----
  <*>{DOTSEP}			{ return '.'; }
  <*>[().=*/+&-]			{ return *yytext; }
  <*>[[:blank:]]+
! <*>{EOL}
  
  <*>{
    {COMMA}
diff -Nrcpad gcc-16-20250720/gcc/cobol/scan_ante.h gcc-16-20250727/gcc/cobol/scan_ante.h
*** gcc-16-20250720/gcc/cobol/scan_ante.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/scan_ante.h	Sun Jul 27 22:32:08 2025
*************** picset( int token ) {
*** 694,699 ****
--- 694,1080 ----
    return token;
  }
  
+ /**
+ ## Script and data to produce picture_t::followers.
+ ## Based on ISO Table 10. 
+ #! /usr/bin/awk -f
+ 
+ BEGIN  {
+   str = "B0/ , . + +- +- CR/DB cs cs Z* Z* + + cs cs 9 AX S V P P 1 N E"
+   split(str, cols)
+ }
+ 
+ $1 ~ /CR|DB|cs/ { next }
+ 
+ 0 && !nlines++ {
+   for( i=0; i < length(cols); i++ ) {
+     print i, cols[i], "'" $i "'"
+   }
+ }
+ 
+ $field == "x" {
+   if( ! nout++ ) {
+     printf "%2d: %5s: \"", field, cols[field - 1]
+   }
+ 
+   gsub(/^ +| +$/, "", $1) 
+   printf "%s", $1
+ }
+ 
+ END {
+   if( ! nout++ ) {
+     printf "%2d: %5s: \"", field, cols[field - 1]
+   }
+   print "\""
+ }
+ 
+ B  x x x - x - - x - x x x x x x x x - x - x - x
+ 0  x x x - x - - x - x x x x x x x x - x - x - x
+ /  x x x - x - - x - x x x x x x x x - x - x - x
+ ,  x x x - x - - x - x x x x x x x - - x - x
+ .  x x - - x - - x - x - x - x - x
+ +  - - - - - - - - - - - - - - - - - - - - - - - x
+ +
+ –
+ +  x x x - - - - x x x x - - x x x - - x x x
+ CR x x x - - - - x x x x - - x x x - - x x x
+ DB x x x - - - - x x x x - - x x x - - x x x
+ cs - - - - x
+ cs x x x - x - - - - x x - - - - x - - x x x
+ 
+ Z  x x - - x - - x - x
+ *  x x - - x - - x - x
+ Z  x x x - x - - x - x x - - - - - - - x - x
+ *  x x x - x - - x - x x - - - - - - - x - x
+ +  x x - - - - - x - - - x
+ –  x x - - - - - x - - - x
+ +  x x x - - - - x - - - x x - - - - - x
+ –  x x x - - - - x - - - x x - - - - - x
+ cs x x - - x - - - - - - - - x
+ cs x x x - x - - - - - - - - x x - - - x
+ 
+ 9  x x x x x - - x - x - x - x - x x x x - x - - x
+ A  x - - - - - - - - - - - - - - x x
+ X  x - - - - - - - - - - - - - - x x
+ S 
+ V  x x - - x - - x - x - x - x - x - x - x
+ P  x x - - x - - x - x - x - x - x - x - x
+ P  - - - - x - - x - - - - - - - - - x x - x
+ 1  - - - - - - - - - - - - - - - - - - - - - x
+ N  x - - - - - - - - - - - - - - - - - - - - - x
+ E  x x x - x - - - - - - - - - - x
+ **/
+ 
+ class picture_t {
+   static const char dot = '.', comma = ',';
+ 
+   typedef std::vector<std::string> followings_t;
+   static const std::map <char, followings_t> followers;
+   
+   const char * const begin;
+   const char *p, *pend; 
+   size_t pos;
+   struct exclusions_t { // Nonzero if set, > 1 is false.
+     // crdb means CR/DB or +/-.
+     // pluses means 2 or more consecutive '+'.
+     // minuses means 2 or more consecutive '-'.
+     // "21) The symbol 'Z' and the symbol '*' are mutually exclusive "
+     // stars means '*' or Z.
+     unsigned short int crdb, currency, dot, pluses, minuses, stars, zzz;
+     exclusions_t()
+       : crdb(0), currency(0), dot(0), pluses(0), minuses(0), stars(0)
+     {}
+   } exclusions;
+   YYLTYPE loc;
+   
+   bool is_crdb() const { // input must be uppercase for CR/DB
+     if( p[0] == 'C' || p[0] == 'D' ) {
+       char input[3] = { p[0], p[1] };
+       return ( 0 == strcmp(input, "CR") || 0 == strcmp(input, "DB") );
+     }
+     return false;
+   }
+ 
+   const char * match_paren( const char *paren ) const {
+     gcc_assert(paren[0] == '(');  // start with opening paren
+     paren = std::find_if( paren, pend,
+                           []( char ch ) {
+                             return ch == '(' || ch == ')';
+                           } );
+     if( *paren == '(' ) return nullptr; // no nesting
+     if( paren == pend ) return nullptr;
+     return ++paren;
+   }
+ 
+   const char * next_not( char ch ) const {
+     return std::find_if( p, pend,
+                          [ch = TOUPPER(ch)]( char next ) {
+                            return ch != next;
+                          } );
+   }
+ 
+   const char * valid_next( const char *p, const std::string& valid ) const {
+     if( p == pend || p + 1 == pend ) return pend;
+     if( p[1] == '(' ) {
+       return match_paren(++p);
+     }
+     auto pv = std::find(valid.begin(), valid.end(), TOUPPER(p[1]));
+     return pv != valid.end()? ++p : nullptr;
+   }
+   const char * valid_next( const char *p,
+                            bool first = true, char ch = '\0' ) const {
+     if( p == pend || p + 1 == pend ) return pend;
+     if( p[0] == '(' ) {
+       if( (p = match_paren(p)) == nullptr ) return nullptr;
+     }
+     if( p[0] == '(' ) return nullptr;  // consecutive parentheses
+     
+     int index = first? 0 : 1;
+     if( !ch ) ch = *p;   // use current character unless overridden
+     auto valid = followers.find(TOUPPER(ch));
+     if( valid == followers.end() ) {
+       YYLTYPE loc(yylloc);
+       loc.first_column += int(p - begin);
+       error_msg( loc, "PICTURE: strange character %qc, giving up", ch );
+       return nullptr;
+     }
+     return valid_next(p, valid->second[index]);
+   }
+ 
+   const char * start() { // start modifies exclusions, but not p
+     auto pnext = p;
+ 
+     switch(TOUPPER(p[0])) {
+     case comma: case dot:
+       // use decimal_is_comma()
+       //  4:     .: "B0/,+Z*+-9E"
+       exclusions.dot++;
+       pnext = valid_next(p, "B0/,+Z*+-9E");
+       break;
+     case '+': case '-':
+       //  6:    +-: "B0/,.Z*Z*9VPPE"
+       exclusions.crdb++;
+       pnext = next_not(p[0]);
+       if( p + 1 < pnext ) {
+         exclusions.pluses++;
+       }
+       pnext = valid_next(--pnext, "B0/,.Z*Z*9VPPE");
+       break;
+     case 'Z': case '*': 
+       exclusions.stars++;
+       pnext = next_not(p[0]);
+       break;
+     case 'S':
+       // 19:     S: "9VP"
+       pnext = valid_next(p, "9VP");
+       break;
+     }
+ 
+     /*
+      * "For fixed editing sign control, the currency symbol, when used, shall
+      * be either the leftmost symbol in character-string-1, optionally preceded
+      * by one of the symbols '+' or '-' "
+      */
+     if( pnext ) {
+       if( p == pnext || p[0] == '+' || p[0] == '-' ) {
+         if( symbol_currency(*pnext) ) {
+           exclusions.currency++;
+           pnext = next_not(*pnext);
+           pnext = valid_next(--pnext, true, '$');
+         }
+       }
+     }
+     
+     return pnext;
+   }
+ 
+   const char * next() { // modify state; do not modify position
+     auto pnext = p;
+     auto loc(picture_t::loc);
+     loc.first_column += int(p - begin);
+ 
+     if( is_crdb() ) {
+       if( exclusions.crdb++ ) {
+         error_msg( loc, "PICTURE: CR/DB and %c/%c may appear only once", '+', '-' );
+         return nullptr;
+       }
+       if( p + 2 != pend ) { 
+         error_msg( loc, "PICTURE: CR/DB must appear at the end" );
+         return nullptr;
+       }
+       return pend;
+     }
+ 
+     if( symbol_currency(p[0]) ) {
+       if( false && exclusions.currency++ ) { // not enforced
+         error_msg( loc, "PICTURE: CURRENCY SYMBOL sequence may appear at most once" );
+         return nullptr;
+       }
+       return valid_next(p, ! exclusions.dot, '$');
+     }
+ 
+     switch(TOUPPER(p[0])) {
+     case '(':
+       return match_paren(p);
+       break;
+     case 'B': case '0': case '/':
+       pnext = valid_next(p);
+       break;
+     case comma: 
+       if( decimal_is_comma() ) {
+         if( exclusions.dot++ ) {
+           error_msg( loc, "PICTURE: %qc: may appear at most once", p[0] );
+           return nullptr;
+         }
+         pnext = valid_next(p, true, dot);
+       } else {
+         pnext = valid_next(p);
+       }
+       break;
+     case dot: 
+       if( p + 1 == pend ) {
+         pnext = pend;
+       } else {
+         if( decimal_is_comma() ) {
+           pnext = valid_next(p, true, comma );
+         } else {
+           if( exclusions.dot++ ) {
+             error_msg( loc, "PICTURE: %qc: may appear at most once", p[0] );
+             return nullptr;
+           }
+           pnext = valid_next(p);
+         }
+       }
+       break;
+ 
+     case '+': case '-':
+       // 7 is trailing sign; 13 & 14 are numeric.  Leading sign handled by start(). 
+       if( p + 1 == pend ) {
+         if( exclusions.crdb++ ) {
+           error_msg( loc, "PICTURE: %c/%c may appear at most once as a sign", '+', '-' );
+           return nullptr;
+         }
+         pnext = pend;
+       } else {
+         pnext = next_not(p[0]);
+         if( p + 1 < pnext ) {
+           if( false && exclusions.pluses++ )  { // not enforced
+             error_msg( loc, "PICTURE: %qc: sequence may appear at most once", p[0] );
+             return nullptr;
+           }
+         }
+         pnext = valid_next(pnext, ! exclusions.dot);
+       }
+       break;
+ 
+     case 'Z': case '*':
+       if( false && exclusions.stars++ ) { // not enforced 
+         error_msg( loc, "PICTURE: %qc: sequence may appear at most once", p[0] );
+         return nullptr;
+       }
+       if( (pnext = next_not(p[0])) == nullptr ) return pnext;
+       pnext = valid_next(pnext, ! exclusions.dot);
+       break;
+     case 'P':
+       pnext = valid_next(pnext, ! exclusions.dot);
+       break;
+     case '9':
+     case 'A': case 'X':
+     case 'V':
+     case '1':
+     case 'N':
+       pnext = valid_next(p);
+       break;
+     case 'E':
+       pnext = valid_next(p, "+9");
+       if( pnext && *pnext == '+' ) {
+         pnext = valid_next(p, "9");
+       }
+       break;
+     default:
+       error_msg( loc, "PICTURE: %qc: invalid character", p[0] );
+       return nullptr;
+     }
+     return pnext;
+   }
+   
+  public:
+   picture_t( const char *p, int len )
+     : begin(p)
+     , p(p), pend(p + len)
+     , loc(yylloc)
+   { 
+     assert(TOUPPER(*p) == 'P'); // as in PICTURE (or PICTURE IS)
+     // move p to start of picture string
+     while( (p = std::find_if(p, pend, fisspace)) != pend ) {
+       this->p = p = std::find_if(p, pend,
+                                  []( char ch ) { return ! fisspace(ch); } );
+     }
+     assert(this->p != pend);
+     pos = this->p - begin;
+   }
+ 
+   bool is_valid() {
+     if( !p ) return false;
+     if( (p = start()) == nullptr ) {
+       return false;
+     }
+ 
+     while( p && p < pend) {
+       p = next();
+     }
+     return p == pend;
+   }
+ 
+   int starts_at() const { return pos; }
+ };
+ 
+ /*
+  * The Followers map gives 1 or 2 lists of valid characters following a
+  * character, the one in the key. If there are two lists, the correct one is
+  * determined by the caller based on the state of the picture string, i.e.,
+  * what has been seen before.
+  */
+ const std::map <char, picture_t::followings_t> picture_t::followers {
+   /*   B0/ */ { 'B', {"B0/,.Z*+-9AXVPNE" } },
+   /*   B0/ */ { '0', {"B0/,.Z*+-9AXVPNE" } },
+   /*   B0/ */ { '/', {"B0/,.Z*+-9AXVPNE" } },
+   /*     , */ { ',', {"B0/,.Z*+-9VPE"} },
+   /*     . */ { '.', {"B0/,Z*+-9E"} },
+   /*     +    { '+', "9" }, */
+   /*    +- */ { '+', {"B0/,.Z*9VPE", "" } },
+   /*    +- */ { '-', {"B0/,.Z*9VPE", "" } },
+   /* CR/DB    { 'C', "" }, */
+   /*    cs    { 'c', "B0/,.Z*+-9VP" }, */
+   /*    cs    { 'c', "+" }, */
+   /*    Z* */ { 'Z', {"B0/,.+Z*9VP", "B0/,+Z*"} },
+   /*    Z* */ { '*', {"B0/,.+Z*9VP", "B0/,+Z*"} },
+   /*     + */ { '+', {"B0/,.+-9VP",  "B0/,+-"} },
+   /*    cs */ { '$', {"B0/,.+9VP",   "B0/,+"} },
+   /*     9 */ { '9', {"B0/,.+9AXVPE"} },
+   /*    AX */ { 'A', {"B0/9AX"} },
+   /*    AX */ { 'X', {"B0/9AX"} },
+   /*     S */ { 'S', {"9VP"} },
+   /*     V */ { 'V', {"B0/,+Z*+-9P"} },
+   /*     P */ { 'P', {"+VP", "B0/,+Z*9P"} },
+   /*     1 */ { '1', {"1"} },
+   /*     N */ { 'N', {"B0/N"} },
+   /*     E */ { 'E', {"+9"} },
+ };
+ 
+ /*
+  * Although picture_t::is_valid return a bool, it's not used. The validation
+  * routines emit messages where the error is detected. The entire string is
+  * subsequently parsed by the parser, which might otherwise accept an invalid
+  * string, but will usually emit a message of its own.
+  */
+ static int 
+ validate_picture() {
+   picture_t picture(yytext, yyleng);
+   picture.is_valid();
+   return  picture.starts_at();
+ }
+ 
  static inline bool
  is_integer_token( int *pvalue = NULL ) {
    int v, n = 0;
diff -Nrcpad gcc-16-20250720/gcc/cobol/symbols.cc gcc-16-20250727/gcc/cobol/symbols.cc
*** gcc-16-20250720/gcc/cobol/symbols.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/symbols.cc	Sun Jul 27 22:32:08 2025
*************** symbol_currency( char sign ) {
*** 4249,4254 ****
--- 4249,4259 ----
    if( currencies.size() == 0 ) {
      currencies['$'] = "$";
    }
+   if( sign == '\0' ) { // default
+     auto result = currencies.begin();
+     gcc_assert(result != currencies.end());
+     return result->second;
+   }
    auto result = currencies.find(sign);
    return result == currencies.end()? NULL : result->second;
  }
diff -Nrcpad gcc-16-20250720/gcc/cobol/symbols.h gcc-16-20250727/gcc/cobol/symbols.h
*** gcc-16-20250720/gcc/cobol/symbols.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/symbols.h	Sun Jul 27 22:32:08 2025
*************** symbol_field_same_as( cbl_field_t *tgt,
*** 2613,2619 ****
  size_t symbol_file_same_record_area( std::list<cbl_file_t*>& files );
  
  bool symbol_currency_add( const char symbol[], const char sign[] = NULL );
! const char * symbol_currency( char symbol );
  
  const char * symbol_type_str( enum symbol_type_t type );
  const char * cbl_field_type_str( enum cbl_field_type_t type );
--- 2613,2619 ----
  size_t symbol_file_same_record_area( std::list<cbl_file_t*>& files );
  
  bool symbol_currency_add( const char symbol[], const char sign[] = NULL );
! const char * symbol_currency( char symbol = '\0' );
  
  const char * symbol_type_str( enum symbol_type_t type );
  const char * cbl_field_type_str( enum cbl_field_type_t type );
diff -Nrcpad gcc-16-20250720/gcc/cobol/util.cc gcc-16-20250727/gcc/cobol/util.cc
*** gcc-16-20250720/gcc/cobol/util.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/util.cc	Sun Jul 27 22:32:08 2025
***************
*** 47,61 ****
  #include <intl.h>
  #include <backtrace.h>
  #include <diagnostic.h>
- #include <diagnostic-color.h>
- #include <diagnostic-url.h>
- #include <diagnostic-metadata.h>
- #include <diagnostic-path.h>
- #include <edit-context.h>
- #include <selftest.h>
- #include <selftest-diagnostic.h>
  #include <opts.h>
- 
  #include "util.h"
  
  #include "cbldiag.h"
--- 47,53 ----
*************** cobol_filename_restore() {
*** 2078,2093 ****
    linemap_add(line_table, LC_LEAVE, sysp, NULL, 0);
  }
  
! static location_t token_location;
  
! location_t location_from_lineno() { return token_location; }
  
  template <typename LOC>
  static void
  gcc_location_set_impl( const LOC& loc ) {
    // Set the position to the first line & column in the location.
    token_location = linemap_line_start( line_table, loc.first_line, 80 );
    token_location = linemap_position_for_column( line_table, loc.first_column);
    location_dump(__func__, __LINE__, "parser", loc);
  }
  
--- 2070,2114 ----
    linemap_add(line_table, LC_LEAVE, sysp, NULL, 0);
  }
  
! static int first_line_minus_1 = 0;
! static location_t token_location_minus_1 = 0;
! static location_t token_location = 0;
  
! location_t current_token_location() { return token_location; }
! location_t current_location_minus_one() { return token_location_minus_1; }
! void current_location_minus_one_clear()
!   {
!   first_line_minus_1 = 0;
!   }
  
  template <typename LOC>
  static void
  gcc_location_set_impl( const LOC& loc ) {
    // Set the position to the first line & column in the location.
+   if( getenv("KILROY") )
+     {
+     fprintf(stderr, "********** KILROY %d\n", loc.first_line);
+     }
+ 
+  static location_t loc_m_1 = 0;
+ 
    token_location = linemap_line_start( line_table, loc.first_line, 80 );
    token_location = linemap_position_for_column( line_table, loc.first_column);
+ 
+   if( loc.first_line > first_line_minus_1 )
+     {
+     // In order for GDB-COBOL to be able to step through COBOL code properly,
+     // it is sometimes necessary for the code at the beginning of a COBOL
+     // line to be using the location_t of the previous line.  This is true, for
+     // example, when laying down the infrastructure code between the last
+     // statement of a paragraph and the code created at the beginning of the
+     // following paragragh.  This code assumes that token_location values of
+     // interest are monotonic, and stores that prior value.
+     first_line_minus_1 = loc.first_line;
+     token_location_minus_1 = loc_m_1;
+     loc_m_1 = token_location;
+     }
+ 
    location_dump(__func__, __LINE__, "parser", loc);
  }
  
*************** verify_format( const char gmsgid[] ) {
*** 2128,2134 ****
  }
  #endif
  
! static const diagnostic_option_id option_zero;
  size_t parse_error_inc();
  
  void gcc_location_dump() {
--- 2149,2155 ----
  }
  #endif
  
! static const diagnostics::option_id option_zero;
  size_t parse_error_inc();
  
  void gcc_location_dump() {
*************** ydferror( const char gmsgid[], ... ) {
*** 2147,2153 ****
    va_start (ap, gmsgid);
    rich_location richloc (line_table, token_location);
    /*bool ret =*/ global_dc->diagnostic_impl (&richloc, nullptr, option_zero,
!                                              gmsgid, &ap, DK_ERROR);
    va_end (ap);
  }
  
--- 2168,2175 ----
    va_start (ap, gmsgid);
    rich_location richloc (line_table, token_location);
    /*bool ret =*/ global_dc->diagnostic_impl (&richloc, nullptr, option_zero,
!                                              gmsgid, &ap,
!                                              diagnostics::kind::error);
    va_end (ap);
  }
  
*************** class temp_loc_t {
*** 2202,2208 ****
    va_start (ap, gmsgid);                                                \
    rich_location richloc (line_table, token_location);                   \
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_zero,        \
!                                          gmsgid, &ap, DK_ERROR);        \
    va_end (ap);                                                          \
    global_dc->end_group();
  
--- 2224,2231 ----
    va_start (ap, gmsgid);                                                \
    rich_location richloc (line_table, token_location);                   \
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_zero,        \
!                                          gmsgid, &ap,                   \
!                                          diagnostics::kind::error);     \
    va_end (ap);                                                          \
    global_dc->end_group();
  
*************** void error_msg( const YDFLTYPE& loc, con
*** 2218,2230 ****
    ERROR_MSG_BODY
  }
  
  void error_msg_direct( const char gmsgid[], ... ) {
    verify_format(gmsgid);
    parse_error_inc();
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   /*auto ret = */emit_diagnostic_valist( DK_ERROR, token_location,
                                           option_zero, gmsgid, &ap );
    va_end (ap);
  }
--- 2241,2269 ----
    ERROR_MSG_BODY
  }
  
+ bool
+ warn_msg( const YYLTYPE& loc, const char gmsgid[], ... ) {
+   temp_loc_t looker(loc);
+   verify_format(gmsgid);
+   auto_diagnostic_group d;
+   va_list ap;
+   va_start (ap, gmsgid);
+   rich_location richloc (line_table, token_location);
+   auto ret = emit_diagnostic_valist( diagnostics::kind::warning,
+                                      token_location,
+                                      option_zero, gmsgid, &ap );
+   va_end (ap);
+   return ret;
+ }
+ 
  void error_msg_direct( const char gmsgid[], ... ) {
    verify_format(gmsgid);
    parse_error_inc();
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   /*auto ret = */emit_diagnostic_valist( diagnostics::kind::error,
!                                          token_location,
                                           option_zero, gmsgid, &ap );
    va_end (ap);
  }
*************** yyerror( const char gmsgid[], ... ) {
*** 2242,2248 ****
                                                nullptr,
                                                option_zero,
                                                gmsgid,
!                                               &ap, DK_ERROR);
    va_end (ap);
    global_dc->end_group();
  }
--- 2281,2287 ----
                                                nullptr,
                                                option_zero,
                                                gmsgid,
!                                               &ap, diagnostics::kind::error);
    va_end (ap);
    global_dc->end_group();
  }
*************** yywarn( const char gmsgid[], ... ) {
*** 2253,2259 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   auto ret = emit_diagnostic_valist( DK_WARNING, token_location,
                                       option_zero, gmsgid, &ap );
    va_end (ap);
    return ret;
--- 2292,2298 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   auto ret = emit_diagnostic_valist( diagnostics::kind::warning, token_location,
                                       option_zero, gmsgid, &ap );
    va_end (ap);
    return ret;
*************** cbl_internal_error(const char *gmsgid, .
*** 2451,2457 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( DK_ICE, token_location, option_zero, gmsgid, &ap );
    va_end(ap);
    abort();  // This unnecessary statement is needed so that [[noreturn]]
    //        // doesn't cause a warning.
--- 2490,2497 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( diagnostics::kind::ice,
! 			  token_location, option_zero, gmsgid, &ap );
    va_end(ap);
    abort();  // This unnecessary statement is needed so that [[noreturn]]
    //        // doesn't cause a warning.
*************** cbl_unimplementedw(const char *gmsgid, .
*** 2463,2469 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( DK_SORRY, token_location, option_zero, gmsgid, &ap );
    va_end(ap);
  }
  
--- 2503,2510 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( diagnostics::kind::sorry,
! 			  token_location, option_zero, gmsgid, &ap );
    va_end(ap);
  }
  
*************** cbl_unimplemented(const char *gmsgid, ..
*** 2473,2479 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( DK_SORRY, token_location, option_zero, gmsgid, &ap );
    va_end(ap);
  }
  
--- 2514,2521 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( diagnostics::kind::sorry,
! 			  token_location, option_zero, gmsgid, &ap );
    va_end(ap);
  }
  
*************** cbl_unimplemented_at( const YYLTYPE& loc
*** 2484,2490 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( DK_SORRY, token_location, option_zero, gmsgid, &ap );
    va_end(ap);
  }
  
--- 2526,2533 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( diagnostics::kind::sorry,
! 			  token_location, option_zero, gmsgid, &ap );
    va_end(ap);
  }
  
*************** cbl_err(const char *fmt, ...) {
*** 2501,2507 ****
    verify_format(gmsgid);
    va_list ap;
    va_start(ap, fmt);
!   emit_diagnostic_valist( DK_FATAL, token_location, option_zero, gmsgid, &ap );
    va_end(ap);
  }
  #pragma GCC diagnostic pop
--- 2544,2551 ----
    verify_format(gmsgid);
    va_list ap;
    va_start(ap, fmt);
!   emit_diagnostic_valist( diagnostics::kind::fatal,
! 			  token_location, option_zero, gmsgid, &ap );
    va_end(ap);
  }
  #pragma GCC diagnostic pop
*************** cbl_errx(const char *gmsgid, ...) {
*** 2512,2518 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( DK_FATAL, token_location, option_zero, gmsgid, &ap );
    va_end(ap);
    }
  
--- 2556,2563 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start(ap, gmsgid);
!   emit_diagnostic_valist( diagnostics::kind::fatal,
! 			  token_location, option_zero, gmsgid, &ap );
    va_end(ap);
    }
  
diff -Nrcpad gcc-16-20250720/gcc/cobol/util.h gcc-16-20250727/gcc/cobol/util.h
*** gcc-16-20250720/gcc/cobol/util.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/cobol/util.h	Sun Jul 27 22:32:08 2025
*************** void cobol_set_pp_option(int opt);
*** 49,55 ****
  
  void cobol_filename_restore();
  const char * cobol_lineno( int );
! int cobol_lineno();
  
  unsigned long gb4( size_t input );
  
--- 49,55 ----
  
  void cobol_filename_restore();
  const char * cobol_lineno( int );
! int cobol_lineno(void);
  
  unsigned long gb4( size_t input );
  
diff -Nrcpad gcc-16-20250720/gcc/common.opt gcc-16-20250727/gcc/common.opt
*** gcc-16-20250720/gcc/common.opt	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/common.opt	Sun Jul 27 22:32:08 2025
*************** Driver Common Joined RejectNegative Var(
*** 1447,1453 ****
  
  ; Required for these enum values.
  SourceInclude
! diagnostic-color.h
  
  Enum
  Name(diagnostic_color_rule) Type(int)
--- 1447,1453 ----
  
  ; Required for these enum values.
  SourceInclude
! diagnostics/color.h
  
  Enum
  Name(diagnostic_color_rule) Type(int)
*************** Driver Common Joined RejectNegative Var(
*** 1471,1477 ****
  
  ; Required for these enum values.
  SourceInclude
! diagnostic-url.h
  
  Enum
  Name(diagnostic_url_rule) Type(int)
--- 1471,1477 ----
  
  ; Required for these enum values.
  SourceInclude
! diagnostics/url.h
  
  Enum
  Name(diagnostic_url_rule) Type(int)
diff -Nrcpad gcc-16-20250720/gcc/config/aarch64/aarch64-cost-tables.h gcc-16-20250727/gcc/config/aarch64/aarch64-cost-tables.h
*** gcc-16-20250720/gcc/config/aarch64/aarch64-cost-tables.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config/aarch64/aarch64-cost-tables.h	Sun Jul 27 22:32:08 2025
*************** const struct cpu_cost_table qdf24xx_extr
*** 125,133 ****
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 125,133 ----
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table thunderx_ext
*** 233,241 ****
    {
      COSTS_N_INSNS (1),	/* Alu.  */
      COSTS_N_INSNS (4),	/* mult.  */
!     COSTS_N_INSNS (1),	/* movi.  */
!     COSTS_N_INSNS (2),	/* dup.  */
!     COSTS_N_INSNS (2)	/* extract.  */
    }
  };
  
--- 233,241 ----
    {
      COSTS_N_INSNS (1),	/* Alu.  */
      COSTS_N_INSNS (4),	/* mult.  */
!     COSTS_N_INSNS (0),	/* movi.  */
!     COSTS_N_INSNS (1),	/* dup.  */
!     COSTS_N_INSNS (1)	/* extract.  */
    }
  };
  
*************** const struct cpu_cost_table thunderx2t99
*** 340,348 ****
    {
      COSTS_N_INSNS (1),	/* Alu.  */
      COSTS_N_INSNS (4),	/* Mult.  */
!     COSTS_N_INSNS (1),	/* movi.  */
!     COSTS_N_INSNS (2),	/* dup.  */
!     COSTS_N_INSNS (2)	/* extract.  */
    }
  };
  
--- 340,348 ----
    {
      COSTS_N_INSNS (1),	/* Alu.  */
      COSTS_N_INSNS (4),	/* Mult.  */
!     COSTS_N_INSNS (0),	/* movi.  */
!     COSTS_N_INSNS (1),	/* dup.  */
!     COSTS_N_INSNS (1)	/* extract.  */
    }
  };
  
*************** const struct cpu_cost_table thunderx3t11
*** 447,455 ****
    {
      COSTS_N_INSNS (1),	/* Alu.  */
      COSTS_N_INSNS (4),	/* Mult.  */
!     COSTS_N_INSNS (1),	/* movi.  */
!     COSTS_N_INSNS (2),	/* dup.  */
!     COSTS_N_INSNS (2)	/* extract.  */
    }
  };
  
--- 447,455 ----
    {
      COSTS_N_INSNS (1),	/* Alu.  */
      COSTS_N_INSNS (4),	/* Mult.  */
!     COSTS_N_INSNS (0),	/* movi.  */
!     COSTS_N_INSNS (1),	/* dup.  */
!     COSTS_N_INSNS (1)	/* extract.  */
    }
  };
  
*************** const struct cpu_cost_table tsv110_extra
*** 555,563 ****
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 555,563 ----
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table a64fx_extra_
*** 662,670 ****
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 662,670 ----
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table ampere1_extr
*** 769,777 ****
    {
      COSTS_N_INSNS (3),  /* alu.  */
      COSTS_N_INSNS (3),  /* mult.  */
!     COSTS_N_INSNS (2),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 769,777 ----
    {
      COSTS_N_INSNS (3),  /* alu.  */
      COSTS_N_INSNS (3),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table ampere1a_ext
*** 876,884 ****
    {
      COSTS_N_INSNS (3),  /* alu.  */
      COSTS_N_INSNS (3),  /* mult.  */
!     COSTS_N_INSNS (2),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 876,884 ----
    {
      COSTS_N_INSNS (3),  /* alu.  */
      COSTS_N_INSNS (3),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table ampere1b_ext
*** 983,991 ****
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (2),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
--- 983,991 ----
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (2),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (0),  /* dup.  */
!     COSTS_N_INSNS (0)   /* extract.  */
    }
  };
  
diff -Nrcpad gcc-16-20250720/gcc/config/aarch64/aarch64-simd.md gcc-16-20250727/gcc/config/aarch64/aarch64-simd.md
*** gcc-16-20250720/gcc/config/aarch64/aarch64-simd.md	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config/aarch64/aarch64-simd.md	Sun Jul 27 22:32:08 2025
***************
*** 1190,1202 ****
    [(set_attr "type" "neon_ins<q>, neon_from_gp<q>, neon_load1_one_lane<q>")]
  )
  
  (define_insn "aarch64_simd_vec_set_zero<mode>"
    [(set (match_operand:VALL_F16 0 "register_operand" "=w")
  	(vec_merge:VALL_F16
  	    (match_operand:VALL_F16 1 "register_operand" "0")
  	    (match_operand:VALL_F16 3 "aarch64_simd_imm_zero" "")
  	    (match_operand:SI 2 "immediate_operand" "i")))]
!   "TARGET_SIMD && aarch64_exact_log2_inverse (<nunits>, operands[2]) >= 0"
    {
      int elt = ENDIAN_LANE_N (<nunits>,
  			     aarch64_exact_log2_inverse (<nunits>,
--- 1190,1205 ----
    [(set_attr "type" "neon_ins<q>, neon_from_gp<q>, neon_load1_one_lane<q>")]
  )
  
+ ;; Inserting from the zero register into a vector lane is treated as an
+ ;; expensive GP->FP move on all CPUs.  Avoid it when optimizing for speed.
  (define_insn "aarch64_simd_vec_set_zero<mode>"
    [(set (match_operand:VALL_F16 0 "register_operand" "=w")
  	(vec_merge:VALL_F16
  	    (match_operand:VALL_F16 1 "register_operand" "0")
  	    (match_operand:VALL_F16 3 "aarch64_simd_imm_zero" "")
  	    (match_operand:SI 2 "immediate_operand" "i")))]
!   "TARGET_SIMD && aarch64_exact_log2_inverse (<nunits>, operands[2]) >= 0
!    && optimize_function_for_size_p (cfun)"
    {
      int elt = ENDIAN_LANE_N (<nunits>,
  			     aarch64_exact_log2_inverse (<nunits>,
diff -Nrcpad gcc-16-20250720/gcc/config/aarch64/aarch64-sve.md gcc-16-20250727/gcc/config/aarch64/aarch64-sve.md
*** gcc-16-20250720/gcc/config/aarch64/aarch64-sve.md	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config/aarch64/aarch64-sve.md	Sun Jul 27 22:32:08 2025
***************
*** 3752,3760 ****
  
  ;; Unpredicated floating-point unary operations.
  (define_insn "@aarch64_sve_<optab><mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand" "=w")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:SVE_FULL_F 1 "register_operand" "w")]
  	  SVE_FP_UNARY))]
    "TARGET_SVE"
    "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>"
--- 3752,3760 ----
  
  ;; Unpredicated floating-point unary operations.
  (define_insn "@aarch64_sve_<optab><mode>"
!   [(set (match_operand:SVE_F 0 "register_operand" "=w")
! 	(unspec:SVE_F
! 	  [(match_operand:SVE_F 1 "register_operand" "w")]
  	  SVE_FP_UNARY))]
    "TARGET_SVE"
    "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>"
***************
*** 3762,3786 ****
  
  ;; Unpredicated floating-point unary operations.
  (define_expand "<optab><mode>2"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_dup 2)
! 	   (const_int SVE_RELAXED_GP)
! 	   (match_operand:SVE_FULL_F 1 "register_operand")]
  	  SVE_COND_FP_UNARY_OPTAB))]
    "TARGET_SVE"
    {
      operands[2] = aarch64_ptrue_reg (<VPRED>mode);
    }
  )
  
  ;; Predicated floating-point unary operations.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:<VPRED> 1 "register_operand")
  	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_FULL_F 2 "register_operand")]
  	  SVE_COND_FP_UNARY))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , 2 ; attrs: movprfx ]
--- 3762,3802 ----
  
  ;; Unpredicated floating-point unary operations.
  (define_expand "<optab><mode>2"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_dup 2)
! 	   (match_dup 3)
! 	   (match_operand:SVE_F 1 "register_operand")]
  	  SVE_COND_FP_UNARY_OPTAB))]
    "TARGET_SVE"
    {
+     operands[2] = aarch64_sve_fp_pred (<MODE>mode, &operands[3]);
+   }
+ )
+ 
+ ;; FABS and FNEG are non-trapping, so we can always expand with a <VPRED>
+ ;; predicate.  It doesn't matter whether the padding bits of a partial
+ ;; vector mode are active or inactive.
+ (define_expand "<optab><mode>2"
+   [(set (match_operand:SVE_F 0 "register_operand")
+ 	(unspec:SVE_F
+ 	  [(match_dup 2)
+ 	   (const_int SVE_RELAXED_GP)
+ 	   (match_operand:SVE_F 1 "register_operand")]
+ 	  SVE_COND_FP_UNARY_BITWISE))]
+   "TARGET_SVE"
+   {
      operands[2] = aarch64_ptrue_reg (<VPRED>mode);
    }
  )
  
  ;; Predicated floating-point unary operations.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
! 	  [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
  	   (match_operand:SI 3 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_F 2 "register_operand")]
  	  SVE_COND_FP_UNARY))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , 2 ; attrs: movprfx ]
***************
*** 3806,3818 ****
  
  ;; Predicated floating-point unary arithmetic, merging with the first input.
  (define_insn_and_rewrite "*cond_<optab><mode>_2_relaxed"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F
  	     [(match_operand 3)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F 2 "register_operand")]
  	     SVE_COND_FP_UNARY)
  	   (match_dup 2)]
  	  UNSPEC_SEL))]
--- 3822,3834 ----
  
  ;; Predicated floating-point unary arithmetic, merging with the first input.
  (define_insn_and_rewrite "*cond_<optab><mode>_2_relaxed"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F
  	     [(match_operand 3)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F 2 "register_operand")]
  	     SVE_COND_FP_UNARY)
  	   (match_dup 2)]
  	  UNSPEC_SEL))]
***************
*** 3854,3868 ****
  ;; as earlyclobber helps to make the instruction more regular to the
  ;; register allocator.
  (define_insn_and_rewrite "*cond_<optab><mode>_any_relaxed"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F 2 "register_operand")]
  	     SVE_COND_FP_UNARY)
! 	   (match_operand:SVE_FULL_F 3 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE && !rtx_equal_p (operands[2], operands[3])"
    {@ [ cons: =0 , 1   , 2 , 3  ; attrs: movprfx ]
--- 3870,3884 ----
  ;; as earlyclobber helps to make the instruction more regular to the
  ;; register allocator.
  (define_insn_and_rewrite "*cond_<optab><mode>_any_relaxed"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F 2 "register_operand")]
  	     SVE_COND_FP_UNARY)
! 	   (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE && !rtx_equal_p (operands[2], operands[3])"
    {@ [ cons: =0 , 1   , 2 , 3  ; attrs: movprfx ]
***************
*** 5495,5521 ****
  ;; Split a predicated instruction whose predicate is unused into an
  ;; unpredicated instruction.
  (define_split
!   [(set (match_operand:SVE_FULL_F_B16B16 0 "register_operand")
! 	(unspec:SVE_FULL_F_B16B16
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_FULL_F_B16B16 2 "register_operand")
! 	   (match_operand:SVE_FULL_F_B16B16 3 "register_operand")]
  	  <SVE_COND_FP>))]
!   "TARGET_SVE
!    && reload_completed
!    && INTVAL (operands[4]) == SVE_RELAXED_GP"
    [(set (match_dup 0)
! 	(SVE_UNPRED_FP_BINARY:SVE_FULL_F_B16B16 (match_dup 2) (match_dup 3)))]
  )
  
  ;; Unpredicated floating-point binary operations (post-RA only).
  ;; These are generated by the split above.
  (define_insn "*post_ra_<sve_fp_op><mode>3"
!   [(set (match_operand:SVE_FULL_F_B16B16 0 "register_operand" "=w")
! 	(SVE_UNPRED_FP_BINARY:SVE_FULL_F_B16B16
! 	  (match_operand:SVE_FULL_F_B16B16 1 "register_operand" "w")
! 	  (match_operand:SVE_FULL_F_B16B16 2 "register_operand" "w")))]
    "TARGET_SVE && reload_completed"
    "<b><sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>")
  
--- 5511,5535 ----
  ;; Split a predicated instruction whose predicate is unused into an
  ;; unpredicated instruction.
  (define_split
!   [(set (match_operand:SVE_F_B16B16 0 "register_operand")
! 	(unspec:SVE_F_B16B16
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (const_int SVE_RELAXED_GP)
! 	   (match_operand:SVE_F_B16B16 2 "register_operand")
! 	   (match_operand:SVE_F_B16B16 3 "register_operand")]
  	  <SVE_COND_FP>))]
!   "TARGET_SVE && reload_completed"
    [(set (match_dup 0)
! 	(SVE_UNPRED_FP_BINARY:SVE_F_B16B16 (match_dup 2) (match_dup 3)))]
  )
  
  ;; Unpredicated floating-point binary operations (post-RA only).
  ;; These are generated by the split above.
  (define_insn "*post_ra_<sve_fp_op><mode>3"
!   [(set (match_operand:SVE_F_B16B16 0 "register_operand" "=w")
! 	(SVE_UNPRED_FP_BINARY:SVE_F_B16B16
! 	  (match_operand:SVE_F_B16B16 1 "register_operand" "w")
! 	  (match_operand:SVE_F_B16B16 2 "register_operand" "w")))]
    "TARGET_SVE && reload_completed"
    "<b><sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>")
  
***************
*** 5547,5556 ****
  
  ;; Unpredicated floating-point binary operations.
  (define_insn "@aarch64_sve_<optab><mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand" "=w")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:SVE_FULL_F 1 "register_operand" "w")
! 	   (match_operand:SVE_FULL_F 2 "register_operand" "w")]
  	  SVE_FP_BINARY))]
    "TARGET_SVE"
    "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
--- 5561,5570 ----
  
  ;; Unpredicated floating-point binary operations.
  (define_insn "@aarch64_sve_<optab><mode>"
!   [(set (match_operand:SVE_F 0 "register_operand" "=w")
! 	(unspec:SVE_F
! 	  [(match_operand:SVE_F 1 "register_operand" "w")
! 	   (match_operand:SVE_F 2 "register_operand" "w")]
  	  SVE_FP_BINARY))]
    "TARGET_SVE"
    "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
***************
*** 5559,5585 ****
  ;; Unpredicated floating-point binary operations that need to be predicated
  ;; for SVE.
  (define_expand "<optab><mode>3"
!   [(set (match_operand:SVE_FULL_F_B16B16 0 "register_operand")
! 	(unspec:SVE_FULL_F_B16B16
  	  [(match_dup 3)
! 	   (const_int SVE_RELAXED_GP)
! 	   (match_operand:SVE_FULL_F_B16B16 1 "<sve_pred_fp_rhs1_operand>")
! 	   (match_operand:SVE_FULL_F_B16B16 2 "<sve_pred_fp_rhs2_operand>")]
  	  SVE_COND_FP_BINARY_OPTAB))]
    "TARGET_SVE && (<supports_bf16> || !<is_bf16>)"
    {
!     operands[3] = aarch64_ptrue_reg (<VPRED>mode);
    }
  )
  
  ;; Predicated floating-point binary operations that have no immediate forms.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:<VPRED> 1 "register_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_FULL_F 2 "register_operand")
! 	   (match_operand:SVE_FULL_F 3 "register_operand")]
  	  SVE_COND_FP_BINARY_REG))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx ]
--- 5573,5599 ----
  ;; Unpredicated floating-point binary operations that need to be predicated
  ;; for SVE.
  (define_expand "<optab><mode>3"
!   [(set (match_operand:SVE_F_B16B16 0 "register_operand")
! 	(unspec:SVE_F_B16B16
  	  [(match_dup 3)
! 	   (match_dup 4)
! 	   (match_operand:SVE_F_B16B16 1 "<sve_pred_fp_rhs1_operand>")
! 	   (match_operand:SVE_F_B16B16 2 "<sve_pred_fp_rhs2_operand>")]
  	  SVE_COND_FP_BINARY_OPTAB))]
    "TARGET_SVE && (<supports_bf16> || !<is_bf16>)"
    {
!     operands[3] = aarch64_sve_fp_pred (<MODE>mode, &operands[4]);
    }
  )
  
  ;; Predicated floating-point binary operations that have no immediate forms.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
! 	  [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_F 2 "register_operand")
! 	   (match_operand:SVE_F 3 "register_operand")]
  	  SVE_COND_FP_BINARY_REG))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx ]
***************
*** 5607,5620 ****
  
  ;; Predicated floating-point operations, merging with the first input.
  (define_insn_and_rewrite "*cond_<optab><mode>_2_relaxed"
!   [(set (match_operand:SVE_FULL_F_B16B16 0 "register_operand")
! 	(unspec:SVE_FULL_F_B16B16
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F_B16B16
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F_B16B16 2 "register_operand")
! 	      (match_operand:SVE_FULL_F_B16B16 3 "register_operand")]
  	     SVE_COND_FP_BINARY)
  	   (match_dup 2)]
  	  UNSPEC_SEL))]
--- 5621,5634 ----
  
  ;; Predicated floating-point operations, merging with the first input.
  (define_insn_and_rewrite "*cond_<optab><mode>_2_relaxed"
!   [(set (match_operand:SVE_F_B16B16 0 "register_operand")
! 	(unspec:SVE_F_B16B16
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F_B16B16
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F_B16B16 2 "register_operand")
! 	      (match_operand:SVE_F_B16B16 3 "register_operand")]
  	     SVE_COND_FP_BINARY)
  	   (match_dup 2)]
  	  UNSPEC_SEL))]
***************
*** 5650,5663 ****
  
  ;; Same for operations that take a 1-bit constant.
  (define_insn_and_rewrite "*cond_<optab><mode>_2_const_relaxed"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F 2 "register_operand")
! 	      (match_operand:SVE_FULL_F 3 "<sve_pred_fp_rhs2_immediate>")]
  	     SVE_COND_FP_BINARY_I1)
  	   (match_dup 2)]
  	  UNSPEC_SEL))]
--- 5664,5677 ----
  
  ;; Same for operations that take a 1-bit constant.
  (define_insn_and_rewrite "*cond_<optab><mode>_2_const_relaxed"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F 2 "register_operand")
! 	      (match_operand:SVE_F 3 "<sve_pred_fp_rhs2_immediate>")]
  	     SVE_COND_FP_BINARY_I1)
  	   (match_dup 2)]
  	  UNSPEC_SEL))]
***************
*** 5693,5706 ****
  
  ;; Predicated floating-point operations, merging with the second input.
  (define_insn_and_rewrite "*cond_<optab><mode>_3_relaxed"
!   [(set (match_operand:SVE_FULL_F_B16B16 0 "register_operand")
! 	(unspec:SVE_FULL_F_B16B16
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F_B16B16
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F_B16B16 2 "register_operand")
! 	      (match_operand:SVE_FULL_F_B16B16 3 "register_operand")]
  	     SVE_COND_FP_BINARY)
  	   (match_dup 3)]
  	  UNSPEC_SEL))]
--- 5707,5720 ----
  
  ;; Predicated floating-point operations, merging with the second input.
  (define_insn_and_rewrite "*cond_<optab><mode>_3_relaxed"
!   [(set (match_operand:SVE_F_B16B16 0 "register_operand")
! 	(unspec:SVE_F_B16B16
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F_B16B16
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F_B16B16 2 "register_operand")
! 	      (match_operand:SVE_F_B16B16 3 "register_operand")]
  	     SVE_COND_FP_BINARY)
  	   (match_dup 3)]
  	  UNSPEC_SEL))]
***************
*** 5736,5751 ****
  
  ;; Predicated floating-point operations, merging with an independent value.
  (define_insn_and_rewrite "*cond_<optab><mode>_any_relaxed"
!   [(set (match_operand:SVE_FULL_F_B16B16 0 "register_operand")
! 	(unspec:SVE_FULL_F_B16B16
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F_B16B16
  	     [(match_operand 5)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F_B16B16 2 "register_operand")
! 	      (match_operand:SVE_FULL_F_B16B16 3 "register_operand")]
  	     SVE_COND_FP_BINARY)
! 	   (match_operand:SVE_FULL_F_B16B16 4 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE
     && (<supports_bf16> || !<is_bf16>)
--- 5750,5765 ----
  
  ;; Predicated floating-point operations, merging with an independent value.
  (define_insn_and_rewrite "*cond_<optab><mode>_any_relaxed"
!   [(set (match_operand:SVE_F_B16B16 0 "register_operand")
! 	(unspec:SVE_F_B16B16
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F_B16B16
  	     [(match_operand 5)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F_B16B16 2 "register_operand")
! 	      (match_operand:SVE_F_B16B16 3 "register_operand")]
  	     SVE_COND_FP_BINARY)
! 	   (match_operand:SVE_F_B16B16 4 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE
     && (<supports_bf16> || !<is_bf16>)
***************
*** 5818,5833 ****
  
  ;; Same for operations that take a 1-bit constant.
  (define_insn_and_rewrite "*cond_<optab><mode>_any_const_relaxed"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F
  	     [(match_operand 5)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F 2 "register_operand")
! 	      (match_operand:SVE_FULL_F 3 "<sve_pred_fp_rhs2_immediate>")]
  	     SVE_COND_FP_BINARY_I1)
! 	   (match_operand:SVE_FULL_F 4 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE && !rtx_equal_p (operands[2], operands[4])"
    {@ [ cons: =0 , 1   , 2 , 4   ]
--- 5832,5847 ----
  
  ;; Same for operations that take a 1-bit constant.
  (define_insn_and_rewrite "*cond_<optab><mode>_any_const_relaxed"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F
  	     [(match_operand 5)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F 2 "register_operand")
! 	      (match_operand:SVE_F 3 "<sve_pred_fp_rhs2_immediate>")]
  	     SVE_COND_FP_BINARY_I1)
! 	   (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE && !rtx_equal_p (operands[2], operands[4])"
    {@ [ cons: =0 , 1   , 2 , 4   ]
***************
*** 5892,5903 ****
  
  ;; Predicated floating-point addition.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:<VPRED> 1 "register_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_FULL_F 2 "register_operand")
! 	   (match_operand:SVE_FULL_F 3 "aarch64_sve_float_arith_with_sub_operand")]
  	  SVE_COND_FP_ADD))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , %2 , 3   , 4   ; attrs: movprfx ]
--- 5906,5917 ----
  
  ;; Predicated floating-point addition.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
! 	  [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_F 2 "register_operand")
! 	   (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_operand")]
  	  SVE_COND_FP_ADD))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , %2 , 3   , 4   ; attrs: movprfx ]
***************
*** 5914,5927 ****
  ;; Predicated floating-point addition of a constant, merging with the
  ;; first input.
  (define_insn_and_rewrite "*cond_add<mode>_2_const_relaxed"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F 2 "register_operand")
! 	      (match_operand:SVE_FULL_F 3 "aarch64_sve_float_arith_with_sub_immediate")]
  	     UNSPEC_COND_FADD)
  	   (match_dup 2)]
  	  UNSPEC_SEL))]
--- 5928,5941 ----
  ;; Predicated floating-point addition of a constant, merging with the
  ;; first input.
  (define_insn_and_rewrite "*cond_add<mode>_2_const_relaxed"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F 2 "register_operand")
! 	      (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_immediate")]
  	     UNSPEC_COND_FADD)
  	   (match_dup 2)]
  	  UNSPEC_SEL))]
***************
*** 5962,5977 ****
  ;; Predicated floating-point addition of a constant, merging with an
  ;; independent value.
  (define_insn_and_rewrite "*cond_add<mode>_any_const_relaxed"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F
  	     [(match_operand 5)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F 2 "register_operand")
! 	      (match_operand:SVE_FULL_F 3 "aarch64_sve_float_arith_with_sub_immediate")]
  	     UNSPEC_COND_FADD)
! 	   (match_operand:SVE_FULL_F 4 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE && !rtx_equal_p (operands[2], operands[4])"
    {@ [ cons: =0 , 1   , 2 , 3   , 4   ]
--- 5976,5991 ----
  ;; Predicated floating-point addition of a constant, merging with an
  ;; independent value.
  (define_insn_and_rewrite "*cond_add<mode>_any_const_relaxed"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F
  	     [(match_operand 5)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F 2 "register_operand")
! 	      (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_immediate")]
  	     UNSPEC_COND_FADD)
! 	   (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE && !rtx_equal_p (operands[2], operands[4])"
    {@ [ cons: =0 , 1   , 2 , 3   , 4   ]
***************
*** 6208,6219 ****
  
  ;; Predicated floating-point subtraction.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:<VPRED> 1 "register_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_FULL_F 2 "aarch64_sve_float_arith_operand")
! 	   (match_operand:SVE_FULL_F 3 "register_operand")]
  	  SVE_COND_FP_SUB))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , 2   , 3 , 4   ; attrs: movprfx ]
--- 6222,6233 ----
  
  ;; Predicated floating-point subtraction.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
! 	  [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_F 2 "aarch64_sve_float_arith_operand")
! 	   (match_operand:SVE_F 3 "register_operand")]
  	  SVE_COND_FP_SUB))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , 2   , 3 , 4   ; attrs: movprfx ]
***************
*** 6229,6242 ****
  ;; Predicated floating-point subtraction from a constant, merging with the
  ;; second input.
  (define_insn_and_rewrite "*cond_sub<mode>_3_const_relaxed"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F 2 "aarch64_sve_float_arith_immediate")
! 	      (match_operand:SVE_FULL_F 3 "register_operand")]
  	     UNSPEC_COND_FSUB)
  	   (match_dup 3)]
  	  UNSPEC_SEL))]
--- 6243,6256 ----
  ;; Predicated floating-point subtraction from a constant, merging with the
  ;; second input.
  (define_insn_and_rewrite "*cond_sub<mode>_3_const_relaxed"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F
  	     [(match_operand 4)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F 2 "aarch64_sve_float_arith_immediate")
! 	      (match_operand:SVE_F 3 "register_operand")]
  	     UNSPEC_COND_FSUB)
  	   (match_dup 3)]
  	  UNSPEC_SEL))]
***************
*** 6273,6288 ****
  ;; Predicated floating-point subtraction from a constant, merging with an
  ;; independent value.
  (define_insn_and_rewrite "*cond_sub<mode>_const_relaxed"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_FULL_F
  	     [(match_operand 5)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_FULL_F 2 "aarch64_sve_float_arith_immediate")
! 	      (match_operand:SVE_FULL_F 3 "register_operand")]
  	     UNSPEC_COND_FSUB)
! 	   (match_operand:SVE_FULL_F 4 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE && !rtx_equal_p (operands[3], operands[4])"
    {@ [ cons: =0 , 1   , 3 , 4   ]
--- 6287,6302 ----
  ;; Predicated floating-point subtraction from a constant, merging with an
  ;; independent value.
  (define_insn_and_rewrite "*cond_sub<mode>_const_relaxed"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_operand:<VPRED> 1 "register_operand")
! 	   (unspec:SVE_F
  	     [(match_operand 5)
  	      (const_int SVE_RELAXED_GP)
! 	      (match_operand:SVE_F 2 "aarch64_sve_float_arith_immediate")
! 	      (match_operand:SVE_F 3 "register_operand")]
  	     UNSPEC_COND_FSUB)
! 	   (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
  	  UNSPEC_SEL))]
    "TARGET_SVE && !rtx_equal_p (operands[3], operands[4])"
    {@ [ cons: =0 , 1   , 3 , 4   ]
***************
*** 6631,6642 ****
  
  ;; Predicated floating-point multiplication.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:<VPRED> 1 "register_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_FULL_F 2 "register_operand")
! 	   (match_operand:SVE_FULL_F 3 "aarch64_sve_float_mul_operand")]
  	  SVE_COND_FP_MUL))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , %2 , 3   , 4   ; attrs: movprfx ]
--- 6645,6656 ----
  
  ;; Predicated floating-point multiplication.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
! 	  [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_F 2 "register_operand")
! 	   (match_operand:SVE_F 3 "aarch64_sve_float_mul_operand")]
  	  SVE_COND_FP_MUL))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , %2 , 3   , 4   ; attrs: movprfx ]
***************
*** 6671,6682 ****
  ;; -------------------------------------------------------------------------
  
  (define_expand "div<mode>3"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
  	  [(match_dup 3)
! 	   (const_int SVE_RELAXED_GP)
! 	   (match_operand:SVE_FULL_F 1 "nonmemory_operand")
! 	   (match_operand:SVE_FULL_F 2 "register_operand")]
  	  UNSPEC_COND_FDIV))]
    "TARGET_SVE"
    {
--- 6685,6696 ----
  ;; -------------------------------------------------------------------------
  
  (define_expand "div<mode>3"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
  	  [(match_dup 3)
! 	   (match_dup 4)
! 	   (match_operand:SVE_F 1 "nonmemory_operand")
! 	   (match_operand:SVE_F 2 "register_operand")]
  	  UNSPEC_COND_FDIV))]
    "TARGET_SVE"
    {
***************
*** 6684,6706 ****
        DONE;
  
      operands[1] = force_reg (<MODE>mode, operands[1]);
!     operands[3] = aarch64_ptrue_reg (<VPRED>mode);
    }
  )
  
  (define_expand "@aarch64_frecpe<mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:SVE_FULL_F 1 "register_operand")]
  	  UNSPEC_FRECPE))]
    "TARGET_SVE"
  )
  
  (define_expand "@aarch64_frecps<mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:SVE_FULL_F 1 "register_operand")
! 	   (match_operand:SVE_FULL_F 2 "register_operand")]
  	  UNSPEC_FRECPS))]
    "TARGET_SVE"
  )
--- 6698,6720 ----
        DONE;
  
      operands[1] = force_reg (<MODE>mode, operands[1]);
!     operands[3] = aarch64_sve_fp_pred (<MODE>mode, &operands[4]);
    }
  )
  
  (define_expand "@aarch64_frecpe<mode>"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
! 	  [(match_operand:SVE_F 1 "register_operand")]
  	  UNSPEC_FRECPE))]
    "TARGET_SVE"
  )
  
  (define_expand "@aarch64_frecps<mode>"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
! 	  [(match_operand:SVE_F 1 "register_operand")
! 	   (match_operand:SVE_F 2 "register_operand")]
  	  UNSPEC_FRECPS))]
    "TARGET_SVE"
  )
***************
*** 6865,6876 ****
  
  ;; Predicated floating-point maximum/minimum.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_FULL_F 0 "register_operand")
! 	(unspec:SVE_FULL_F
! 	  [(match_operand:<VPRED> 1 "register_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_FULL_F 2 "register_operand")
! 	   (match_operand:SVE_FULL_F 3 "aarch64_sve_float_maxmin_operand")]
  	  SVE_COND_FP_MAXMIN))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , %2 , 3   ; attrs: movprfx ]
--- 6879,6890 ----
  
  ;; Predicated floating-point maximum/minimum.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_F 0 "register_operand")
! 	(unspec:SVE_F
! 	  [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_F 2 "register_operand")
! 	   (match_operand:SVE_F 3 "aarch64_sve_float_maxmin_operand")]
  	  SVE_COND_FP_MAXMIN))]
    "TARGET_SVE"
    {@ [ cons: =0 , 1   , %2 , 3   ; attrs: movprfx ]
***************
*** 9653,9658 ****
--- 9667,9697 ----
    }
  )
  
+ ;; As above, for pairs that are used by the auto-vectorizer only.
+ (define_insn_and_rewrite "*cond_<optab>_nontrunc<SVE_PARTIAL_F:mode><SVE_HSDI:mode>_relaxed"
+   [(set (match_operand:SVE_HSDI 0 "register_operand")
+ 	(unspec:SVE_HSDI
+ 	  [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand")
+ 	   (unspec:SVE_HSDI
+ 	     [(match_operand 4)
+ 	      (const_int SVE_RELAXED_GP)
+ 	      (match_operand:SVE_PARTIAL_F 2 "register_operand")]
+ 	     SVE_COND_FCVTI)
+ 	   (match_operand:SVE_HSDI 3 "aarch64_simd_reg_or_zero")]
+ 	  UNSPEC_SEL))]
+   "TARGET_SVE
+   && (~(<SVE_HSDI:self_mask> | <SVE_HSDI:narrower_mask>) & <SVE_PARTIAL_F:self_mask>) == 0"
+   {@ [ cons: =0 , 1   , 2 , 3  ; attrs: movprfx ]
+      [ &w       , Upl , w , 0  ; *              ] fcvtz<su>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_PARTIAL_F:Vetype>
+      [ &w       , Upl , w , Dz ; yes            ] movprfx\t%0.<SVE_HSDI:Vetype>, %1/z, %2.<SVE_HSDI:Vetype>\;fcvtz<su>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_PARTIAL_F:Vetype>
+      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;fcvtz<su>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_PARTIAL_F:Vetype>
+   }
+   "&& !rtx_equal_p (operands[1], operands[4])"
+   {
+     operands[4] = copy_rtx (operands[1]);
+   }
+ )
+ 
  (define_insn "*cond_<optab>_nontrunc<SVE_FULL_F:mode><SVE_FULL_HSDI:mode>_strict"
    [(set (match_operand:SVE_FULL_HSDI 0 "register_operand")
  	(unspec:SVE_FULL_HSDI
***************
*** 9706,9711 ****
--- 9745,9773 ----
    }
  )
  
+ (define_insn_and_rewrite "*cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx2SI_ONLY:mode>_relaxed"
+   [(set (match_operand:VNx2SI_ONLY 0 "register_operand")
+ 	(unspec:VNx2SI_ONLY
+ 	  [(match_operand:VNx2BI 1 "register_operand")
+ 	   (unspec:VNx2SI_ONLY
+ 	     [(match_operand 4)
+ 	      (const_int SVE_RELAXED_GP)
+ 	      (match_operand:VNx2DF_ONLY 2 "register_operand")]
+ 	     SVE_COND_FCVTI)
+ 	   (match_operand:VNx2SI_ONLY 3 "aarch64_simd_reg_or_zero")]
+ 	  UNSPEC_SEL))]
+   "TARGET_SVE"
+   {@ [ cons: =0 , 1   , 2 , 3  ; attrs: movprfx ]
+      [ &w       , Upl , w , 0  ; *              ] fcvtz<su>\t%0.<VNx2SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
+      [ &w       , Upl , w , Dz ; yes            ] movprfx\t%0.<VNx2DF_ONLY:Vetype>, %1/z, %2.<VNx2DF_ONLY:Vetype>\;fcvtz<su>\t%0.<VNx2SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
+      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;fcvtz<su>\t%0.<VNx2SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
+   }
+   "&& !rtx_equal_p (operands[1], operands[4])"
+   {
+     operands[4] = copy_rtx (operands[1]);
+   }
+ )
+ 
  ;; -------------------------------------------------------------------------
  ;; ---- [INT<-FP] Packs
  ;; -------------------------------------------------------------------------
***************
*** 9857,9862 ****
--- 9919,9949 ----
    }
  )
  
+ ;; As above, for pairs that are used by the auto-vectorizer only.
+ (define_insn_and_rewrite "*cond_<optab>_nonextend<SVE_HSDI:mode><SVE_PARTIAL_F:mode>_relaxed"
+   [(set (match_operand:SVE_PARTIAL_F 0 "register_operand")
+ 	(unspec:SVE_PARTIAL_F
+ 	  [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand")
+ 	   (unspec:SVE_PARTIAL_F
+ 	     [(match_operand 4)
+ 	      (const_int SVE_RELAXED_GP)
+ 	      (match_operand:SVE_HSDI 2 "register_operand")]
+ 	     SVE_COND_ICVTF)
+ 	   (match_operand:SVE_PARTIAL_F 3 "aarch64_simd_reg_or_zero")]
+ 	  UNSPEC_SEL))]
+   "TARGET_SVE
+    && (~(<SVE_HSDI:self_mask> | <SVE_HSDI:narrower_mask>) & <SVE_PARTIAL_F:self_mask>) == 0"
+   {@ [ cons: =0 , 1   , 2 , 3  ; attrs: movprfx ]
+      [ &w       , Upl , w , 0  ; *              ] <su>cvtf\t%0.<SVE_PARTIAL_F:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
+      [ &w       , Upl , w , Dz ; yes            ] movprfx\t%0.<SVE_HSDI:Vetype>, %1/z, %2.<SVE_HSDI:Vetype>\;<su>cvtf\t%0.<SVE_PARTIAL_F:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
+      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;<su>cvtf\t%0.<SVE_PARTIAL_F:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
+   }
+   "&& !rtx_equal_p (operands[1], operands[4])"
+   {
+     operands[4] = copy_rtx (operands[1]);
+   }
+ )
+ 
  (define_insn "*cond_<optab>_nonextend<SVE_FULL_HSDI:mode><SVE_FULL_F:mode>_strict"
    [(set (match_operand:SVE_FULL_F 0 "register_operand")
  	(unspec:SVE_FULL_F
***************
*** 10066,10071 ****
--- 10153,10182 ----
    }
  )
  
+ ;; As above, for pairs that are used by the auto-vectorizer only.
+ (define_insn_and_rewrite "*cond_<optab>_trunc<SVE_SDF:mode><SVE_PARTIAL_HSF:mode>"
+   [(set (match_operand:SVE_PARTIAL_HSF 0 "register_operand")
+ 	(unspec:SVE_PARTIAL_HSF
+ 	  [(match_operand:<SVE_SDF:VPRED> 1 "register_operand")
+ 	   (unspec:SVE_PARTIAL_HSF
+ 	     [(match_operand 4)
+ 	      (const_int SVE_RELAXED_GP)
+ 	      (match_operand:SVE_SDF 2 "register_operand")]
+ 	     SVE_COND_FCVT)
+ 	   (match_operand:SVE_PARTIAL_HSF 3 "aarch64_simd_reg_or_zero")]
+ 	  UNSPEC_SEL))]
+   "TARGET_SVE && (~<SVE_SDF:narrower_mask> & <SVE_PARTIAL_HSF:self_mask>) == 0"
+   {@ [ cons: =0 , 1   , 2 , 3  ; attrs: movprfx ]
+      [ w        , Upl , w , 0  ; *              ] fcvt\t%0.<SVE_PARTIAL_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>
+      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<SVE_SDF:Vetype>, %1/z, %2.<SVE_SDF:Vetype>\;fcvt\t%0.<SVE_PARTIAL_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>
+      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;fcvt\t%0.<SVE_PARTIAL_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>
+   }
+   "&& !rtx_equal_p (operands[1], operands[4])"
+   {
+     operands[4] = copy_rtx (operands[1]);
+   }
+ )
+ 
  ;; -------------------------------------------------------------------------
  ;; ---- [FP<-FP] Packs (bfloat16)
  ;; -------------------------------------------------------------------------
***************
*** 10259,10264 ****
--- 10370,10399 ----
    }
  )
  
+ ;; As above, for pairs that are used by the auto-vectorizer only.
+ (define_insn_and_rewrite "*cond_<optab>_nontrunc<SVE_PARTIAL_HSF:mode><SVE_SDF:mode>_relaxed"
+   [(set (match_operand:SVE_SDF 0 "register_operand")
+ 	(unspec:SVE_SDF
+ 	  [(match_operand:<SVE_SDF:VPRED> 1 "register_operand")
+ 	   (unspec:SVE_SDF
+ 	     [(match_operand 4)
+ 	      (const_int SVE_RELAXED_GP)
+ 	      (match_operand:SVE_PARTIAL_HSF 2 "register_operand")]
+ 	     SVE_COND_FCVT)
+ 	   (match_operand:SVE_SDF 3 "aarch64_simd_reg_or_zero")]
+ 	  UNSPEC_SEL))]
+   "TARGET_SVE && (~<SVE_SDF:narrower_mask> & <SVE_PARTIAL_HSF:self_mask>) == 0"
+   {@ [ cons: =0 , 1   , 2 , 3  ; attrs: movprfx ]
+      [ w        , Upl , w , 0  ; *              ] fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_PARTIAL_HSF:Vetype>
+      [ ?&w      , Upl , w , Dz ; yes            ] movprfx\t%0.<SVE_SDF:Vetype>, %1/z, %2.<SVE_SDF:Vetype>\;fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_PARTIAL_HSF:Vetype>
+      [ ?&w      , Upl , w , w  ; yes            ] movprfx\t%0, %3\;fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_PARTIAL_HSF:Vetype>
+   }
+   "&& !rtx_equal_p (operands[1], operands[4])"
+   {
+     operands[4] = copy_rtx (operands[1]);
+   }
+ )
+ 
  ;; -------------------------------------------------------------------------
  ;; ---- [PRED<-PRED] Packs
  ;; -------------------------------------------------------------------------
diff -Nrcpad gcc-16-20250720/gcc/config/aarch64/aarch64-sve2.md gcc-16-20250727/gcc/config/aarch64/aarch64-sve2.md
*** gcc-16-20250720/gcc/config/aarch64/aarch64-sve2.md	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config/aarch64/aarch64-sve2.md	Sun Jul 27 22:32:08 2025
***************
*** 1346,1357 ****
  
  ;; Predicated B16B16 binary operations.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:VNx8BF_ONLY 0 "register_operand")
! 	(unspec:VNx8BF_ONLY
! 	  [(match_operand:<VPRED> 1 "register_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:VNx8BF_ONLY 2 "register_operand")
! 	   (match_operand:VNx8BF_ONLY 3 "register_operand")]
  	  SVE_COND_FP_BINARY_OPTAB))]
    "TARGET_SSVE_B16B16 && <supports_bf16>"
    {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx , is_rev ]
--- 1346,1357 ----
  
  ;; Predicated B16B16 binary operations.
  (define_insn "@aarch64_pred_<optab><mode>"
!   [(set (match_operand:SVE_BF 0 "register_operand")
! 	(unspec:SVE_BF
! 	  [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
  	   (match_operand:SI 4 "aarch64_sve_gp_strictness")
! 	   (match_operand:SVE_BF 2 "register_operand")
! 	   (match_operand:SVE_BF 3 "register_operand")]
  	  SVE_COND_FP_BINARY_OPTAB))]
    "TARGET_SSVE_B16B16 && <supports_bf16>"
    {@ [ cons: =0 , 1   , 2 , 3 ; attrs: movprfx , is_rev ]
diff -Nrcpad gcc-16-20250720/gcc/config/aarch64/aarch64.cc gcc-16-20250727/gcc/config/aarch64/aarch64.cc
*** gcc-16-20250720/gcc/config/aarch64/aarch64.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config/aarch64/aarch64.cc	Sun Jul 27 22:32:08 2025
*************** static int aarch64_address_cost (rtx, ma
*** 356,362 ****
  static bool aarch64_builtin_support_vector_misalignment (machine_mode mode,
  							 const_tree type,
  							 int misalignment,
! 							 bool is_packed);
  static machine_mode aarch64_simd_container_mode (scalar_mode, poly_int64);
  static bool aarch64_print_address_internal (FILE*, machine_mode, rtx,
  					    aarch64_addr_query_type);
--- 356,363 ----
  static bool aarch64_builtin_support_vector_misalignment (machine_mode mode,
  							 const_tree type,
  							 int misalignment,
! 							 bool is_packed,
! 							 bool is_gather_scatter);
  static machine_mode aarch64_simd_container_mode (scalar_mode, poly_int64);
  static bool aarch64_print_address_internal (FILE*, machine_mode, rtx,
  					    aarch64_addr_query_type);
*************** cost_plus:
*** 15854,15864 ****
  	break;
      case CONST_VECTOR:
  	{
! 	  /* Load using MOVI/MVNI.  */
! 	  if (aarch64_simd_valid_mov_imm (x))
! 	    *cost = extra_cost->vect.movi;
! 	  else /* Load using constant pool.  */
! 	    *cost = extra_cost->ldst.load;
  	  break;
  	}
      case VEC_CONCAT:
--- 15855,15868 ----
  	break;
      case CONST_VECTOR:
  	{
! 	  if (speed)
! 	    {
! 	      /* Load using MOVI/MVNI.  */
! 	      if (aarch64_simd_valid_mov_imm (x))
! 		*cost += extra_cost->vect.movi;
! 	      else /* Load using constant pool.  */
! 		*cost += extra_cost->ldst.load;
! 	    }
  	  break;
  	}
      case VEC_CONCAT:
*************** cost_plus:
*** 15867,15873 ****
  	break;
      case VEC_DUPLICATE:
  	/* Load using a DUP.  */
! 	*cost = extra_cost->vect.dup;
  	return false;
      case VEC_SELECT:
  	{
--- 15871,15878 ----
  	break;
      case VEC_DUPLICATE:
  	/* Load using a DUP.  */
! 	if (speed)
! 	  *cost += extra_cost->vect.dup;
  	return false;
      case VEC_SELECT:
  	{
*************** cost_plus:
*** 15875,15887 ****
  	  *cost = rtx_cost (op0, GET_MODE (op0), VEC_SELECT, 0, speed);
  
  	  /* cost subreg of 0 as free, otherwise as DUP */
! 	  rtx op1 = XEXP (x, 1);
! 	  if (vec_series_lowpart_p (mode, GET_MODE (op1), op1))
! 	    ;
! 	  else if (vec_series_highpart_p (mode, GET_MODE (op1), op1))
! 	    *cost = extra_cost->vect.dup;
! 	  else
! 	    *cost = extra_cost->vect.extract;
  	  return true;
  	}
      default:
--- 15880,15895 ----
  	  *cost = rtx_cost (op0, GET_MODE (op0), VEC_SELECT, 0, speed);
  
  	  /* cost subreg of 0 as free, otherwise as DUP */
! 	  if (speed)
! 	    {
! 	      rtx op1 = XEXP (x, 1);
! 	      if (vec_series_lowpart_p (mode, GET_MODE (op1), op1))
! 		;
! 	      else if (vec_series_highpart_p (mode, GET_MODE (op1), op1))
! 		*cost += extra_cost->vect.dup;
! 	      else
! 		*cost += extra_cost->vect.extract;
! 	    }
  	  return true;
  	}
      default:
*************** aarch64_vector_costs::add_stmt_cost (int
*** 17969,17974 ****
--- 17977,17983 ----
  
        /* Check if we've seen an SVE gather/scatter operation and which size.  */
        if (kind == scalar_load
+ 	  && vectype
  	  && aarch64_sve_mode_p (TYPE_MODE (vectype))
  	  && vect_mem_access_type (stmt_info, node) == VMAT_GATHER_SCATTER)
  	{
*************** aarch64_process_one_target_attr (char *a
*** 19958,19965 ****
  	      if (valid)
  		{
  		  set_option (&global_options, NULL, p_attr->opt_num, value,
! 			      NULL, DK_UNSPECIFIED, input_location,
! 			      global_dc);
  		}
  	      else
  		{
--- 19967,19975 ----
  	      if (valid)
  		{
  		  set_option (&global_options, NULL, p_attr->opt_num, value,
! 			      NULL,
! 			      static_cast<int> (diagnostics::kind::unspecified),
! 			      input_location, global_dc);
  		}
  	      else
  		{
*************** aarch64_simd_vector_alignment_reachable
*** 24406,24415 ****
  static bool
  aarch64_builtin_support_vector_misalignment (machine_mode mode,
  					     const_tree type, int misalignment,
! 					     bool is_packed)
  {
    if (TARGET_SIMD && STRICT_ALIGNMENT)
      {
        /* Return if movmisalign pattern is not supported for this mode.  */
        if (optab_handler (movmisalign_optab, mode) == CODE_FOR_nothing)
          return false;
--- 24416,24429 ----
  static bool
  aarch64_builtin_support_vector_misalignment (machine_mode mode,
  					     const_tree type, int misalignment,
! 					     bool is_packed,
! 					     bool is_gather_scatter)
  {
    if (TARGET_SIMD && STRICT_ALIGNMENT)
      {
+       if (is_gather_scatter)
+ 	return true;
+ 
        /* Return if movmisalign pattern is not supported for this mode.  */
        if (optab_handler (movmisalign_optab, mode) == CODE_FOR_nothing)
          return false;
*************** aarch64_builtin_support_vector_misalignm
*** 24419,24425 ****
  	return false;
      }
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed);
  }
  
  /* If VALS is a vector constant that can be loaded into a register
--- 24433,24440 ----
  	return false;
      }
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed,
! 						      is_gather_scatter);
  }
  
  /* If VALS is a vector constant that can be loaded into a register
diff -Nrcpad gcc-16-20250720/gcc/config/aarch64/cortex-a57-fma-steering.cc gcc-16-20250727/gcc/config/aarch64/cortex-a57-fma-steering.cc
*** gcc-16-20250720/gcc/config/aarch64/cortex-a57-fma-steering.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config/aarch64/cortex-a57-fma-steering.cc	Sun Jul 27 22:32:08 2025
*************** func_fma_steering::analyze ()
*** 948,953 ****
--- 948,958 ----
  
  	  /* Search the chain where this instruction is (one of) the root.  */
  	  dest_op_info = insn_rr[INSN_UID (insn)].op_info;
+ 
+ 	  /* Register rename could fail. */
+ 	  if (!dest_op_info)
+ 	    continue;
+ 
  	  dest_regno = REGNO (SET_DEST (PATTERN (insn)));
  	  for (i = 0; i < dest_op_info->n_chains; i++)
  	    {
diff -Nrcpad gcc-16-20250720/gcc/config/aarch64/iterators.md gcc-16-20250727/gcc/config/aarch64/iterators.md
*** gcc-16-20250720/gcc/config/aarch64/iterators.md	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config/aarch64/iterators.md	Sun Jul 27 22:32:08 2025
***************
*** 463,468 ****
--- 463,469 ----
  (define_mode_iterator VNx8SI_ONLY [VNx8SI])
  (define_mode_iterator VNx8SF_ONLY [VNx8SF])
  (define_mode_iterator VNx8DI_ONLY [VNx8DI])
+ (define_mode_iterator VNx2SI_ONLY [VNx2SI])
  (define_mode_iterator VNx4SI_ONLY [VNx4SI])
  (define_mode_iterator VNx4SF_ONLY [VNx4SF])
  (define_mode_iterator VNx2DI_ONLY [VNx2DI])
***************
*** 3366,3371 ****
--- 3367,3376 ----
  (define_int_iterator SVE_INT_UNARY [UNSPEC_REVB
  				    UNSPEC_REVH UNSPEC_REVW])
  
+ ;; This iterator is currently only used for estimation instructions,
+ ;; which are never generated automatically when -ftrapping-math is true.
+ ;; The iterator is therefore applied unconditionally to partial FP modes.
+ ;; This might need to be revisited if new operations are added in future.
  (define_int_iterator SVE_FP_UNARY [UNSPEC_FRECPE UNSPEC_RSQRTE])
  
  (define_int_iterator SVE_FP_UNARY_INT [(UNSPEC_FEXPA "TARGET_NON_STREAMING")])
***************
*** 3378,3383 ****
--- 3383,3392 ----
  (define_int_iterator SVE_INT_BINARY_MULTI [UNSPEC_SQDMULH
  					   UNSPEC_SRSHL UNSPEC_URSHL])
  
+ ;; This iterator is currently only used for estimation instructions,
+ ;; which are never generated automatically when -ftrapping-math is true.
+ ;; The iterator is therefore applied unconditionally to partial FP modes.
+ ;; This might need to be revisited if new operations are added in future.
  (define_int_iterator SVE_FP_BINARY [UNSPEC_FRECPS UNSPEC_RSQRTS])
  
  (define_int_iterator SVE_FP_BINARY_INT [UNSPEC_FTSMUL UNSPEC_FTSSEL])
***************
*** 3429,3437 ****
  					   UNSPEC_FMINQV
  					   UNSPEC_FMINNMQV])
  
! (define_int_iterator SVE_COND_FP_UNARY [UNSPEC_COND_FABS
! 					UNSPEC_COND_FNEG
! 					UNSPEC_COND_FRECPX
  					UNSPEC_COND_FRINTA
  					UNSPEC_COND_FRINTI
  					UNSPEC_COND_FRINTM
--- 3438,3447 ----
  					   UNSPEC_FMINQV
  					   UNSPEC_FMINNMQV])
  
! (define_int_iterator SVE_COND_FP_UNARY_BITWISE [UNSPEC_COND_FABS
! 						UNSPEC_COND_FNEG])
! 
! (define_int_iterator SVE_COND_FP_UNARY [UNSPEC_COND_FRECPX
  					UNSPEC_COND_FRINTA
  					UNSPEC_COND_FRINTI
  					UNSPEC_COND_FRINTM
***************
*** 3439,3451 ****
  					UNSPEC_COND_FRINTP
  					UNSPEC_COND_FRINTX
  					UNSPEC_COND_FRINTZ
! 					UNSPEC_COND_FSQRT])
  
  ;; Same as SVE_COND_FP_UNARY, but without codes that have a dedicated
  ;; <optab><mode>2 expander.
! (define_int_iterator SVE_COND_FP_UNARY_OPTAB [UNSPEC_COND_FABS
! 					      UNSPEC_COND_FNEG
! 					      UNSPEC_COND_FRECPX
  					      UNSPEC_COND_FRINTA
  					      UNSPEC_COND_FRINTI
  					      UNSPEC_COND_FRINTM
--- 3449,3460 ----
  					UNSPEC_COND_FRINTP
  					UNSPEC_COND_FRINTX
  					UNSPEC_COND_FRINTZ
! 					UNSPEC_COND_FSQRT
! 					SVE_COND_FP_UNARY_BITWISE])
  
  ;; Same as SVE_COND_FP_UNARY, but without codes that have a dedicated
  ;; <optab><mode>2 expander.
! (define_int_iterator SVE_COND_FP_UNARY_OPTAB [UNSPEC_COND_FRECPX
  					      UNSPEC_COND_FRINTA
  					      UNSPEC_COND_FRINTI
  					      UNSPEC_COND_FRINTM
diff -Nrcpad gcc-16-20250720/gcc/config/arm/aarch-cost-tables.h gcc-16-20250727/gcc/config/arm/aarch-cost-tables.h
*** gcc-16-20250720/gcc/config/arm/aarch-cost-tables.h	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config/arm/aarch-cost-tables.h	Sun Jul 27 22:32:08 2025
*************** const struct cpu_cost_table generic_extr
*** 123,131 ****
    {
      COSTS_N_INSNS (1),	/* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 123,131 ----
    {
      COSTS_N_INSNS (1),	/* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table cortexa53_ex
*** 230,238 ****
    {
      COSTS_N_INSNS (1),	/* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 230,238 ----
    {
      COSTS_N_INSNS (1),	/* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table cortexa57_ex
*** 337,345 ****
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 337,345 ----
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table cortexa76_ex
*** 444,452 ****
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 444,452 ----
    {
      COSTS_N_INSNS (1),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table exynosm1_ext
*** 551,559 ****
    {
      COSTS_N_INSNS (0),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 551,559 ----
    {
      COSTS_N_INSNS (0),  /* alu.  */
      COSTS_N_INSNS (4),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
*************** const struct cpu_cost_table xgene1_extra
*** 658,666 ****
    {
      COSTS_N_INSNS (2),  /* alu.  */
      COSTS_N_INSNS (8),  /* mult.  */
!     COSTS_N_INSNS (1),  /* movi.  */
!     COSTS_N_INSNS (2),  /* dup.  */
!     COSTS_N_INSNS (2)   /* extract.  */
    }
  };
  
--- 658,666 ----
    {
      COSTS_N_INSNS (2),  /* alu.  */
      COSTS_N_INSNS (8),  /* mult.  */
!     COSTS_N_INSNS (0),  /* movi.  */
!     COSTS_N_INSNS (1),  /* dup.  */
!     COSTS_N_INSNS (1)   /* extract.  */
    }
  };
  
diff -Nrcpad gcc-16-20250720/gcc/config/arm/arm.cc gcc-16-20250727/gcc/config/arm/arm.cc
*** gcc-16-20250720/gcc/config/arm/arm.cc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config/arm/arm.cc	Sun Jul 27 22:32:08 2025
*************** static bool arm_vector_alignment_reachab
*** 289,295 ****
  static bool arm_builtin_support_vector_misalignment (machine_mode mode,
  						     const_tree type,
  						     int misalignment,
! 						     bool is_packed);
  static void arm_conditional_register_usage (void);
  static enum flt_eval_method arm_excess_precision (enum excess_precision_type);
  static reg_class_t arm_preferred_rename_class (reg_class_t rclass);
--- 289,296 ----
  static bool arm_builtin_support_vector_misalignment (machine_mode mode,
  						     const_tree type,
  						     int misalignment,
! 						     bool is_packed,
! 						     bool is_gather_scatter);
  static void arm_conditional_register_usage (void);
  static enum flt_eval_method arm_excess_precision (enum excess_precision_type);
  static reg_class_t arm_preferred_rename_class (reg_class_t rclass);
*************** arm_vector_alignment_reachable (const_tr
*** 30661,30672 ****
  static bool
  arm_builtin_support_vector_misalignment (machine_mode mode,
  					 const_tree type, int misalignment,
! 					 bool is_packed)
  {
    if (TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access)
      {
        HOST_WIDE_INT align = TYPE_ALIGN_UNIT (type);
  
        if (is_packed)
          return align == 1;
  
--- 30662,30677 ----
  static bool
  arm_builtin_support_vector_misalignment (machine_mode mode,
  					 const_tree type, int misalignment,
! 					 bool is_packed,
! 					 bool is_gather_scatter)
  {
    if (TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access)
      {
        HOST_WIDE_INT align = TYPE_ALIGN_UNIT (type);
  
+       if (is_gather_scatter)
+ 	return true;
+ 
        if (is_packed)
          return align == 1;
  
*************** arm_builtin_support_vector_misalignment
*** 30683,30689 ****
      }
  
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed);
  }
  
  static void
--- 30688,30695 ----
      }
  
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed,
! 						      is_gather_scatter);
  }
  
  static void
diff -Nrcpad gcc-16-20250720/gcc/config/cris/cris.cc gcc-16-20250727/gcc/config/cris/cris.cc
*** gcc-16-20250720/gcc/config/cris/cris.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/cris/cris.cc	Sun Jul 27 22:32:08 2025
*************** cris_md_asm_adjust (vec<rtx> &outputs, v
*** 3711,3719 ****
    /* Determine if the source using MOF.  If it is, automatically
       clobbering MOF would cause it to have impossible constraints.  */
  
!   /* Look for a use of the MOF constraint letter: h.  */
    for (unsigned i = 0, n = constraints.length(); i < n; ++i)
!     if (strchr (constraints[i], 'h') != NULL)
        return NULL;
  
    /* Look for an output or an input that touches MOF.  */
--- 3711,3721 ----
    /* Determine if the source using MOF.  If it is, automatically
       clobbering MOF would cause it to have impossible constraints.  */
  
!   /* Look for a use of the MOF constraint letter h or a hard register
!      constraint.  */
    for (unsigned i = 0, n = constraints.length(); i < n; ++i)
!     if (strchr (constraints[i], 'h') != NULL
! 	|| strstr (constraints[i], "{mof}") != NULL)
        return NULL;
  
    /* Look for an output or an input that touches MOF.  */
diff -Nrcpad gcc-16-20250720/gcc/config/epiphany/epiphany.cc gcc-16-20250727/gcc/config/epiphany/epiphany.cc
*** gcc-16-20250720/gcc/config/epiphany/epiphany.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/epiphany/epiphany.cc	Sun Jul 27 22:32:08 2025
*************** epiphany_vector_alignment_reachable (con
*** 2816,2827 ****
  
  static bool
  epiphany_support_vector_misalignment (machine_mode mode, const_tree type,
! 				      int misalignment, bool is_packed)
  {
    if (GET_MODE_SIZE (mode) == 8 && misalignment % 4 == 0)
      return true;
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed);
  }
  
  /* STRUCTURE_SIZE_BOUNDARY seems a bit crude in how it enlarges small
--- 2816,2831 ----
  
  static bool
  epiphany_support_vector_misalignment (machine_mode mode, const_tree type,
! 				      int misalignment, bool is_packed,
! 				      bool is_gather_scatter)
  {
+   if (is_gather_scatter)
+     return true;
    if (GET_MODE_SIZE (mode) == 8 && misalignment % 4 == 0)
      return true;
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed,
! 						      is_gather_scatter);
  }
  
  /* STRUCTURE_SIZE_BOUNDARY seems a bit crude in how it enlarges small
diff -Nrcpad gcc-16-20250720/gcc/config/gcn/gcn-opts.h gcc-16-20250727/gcc/config/gcn/gcn-opts.h
*** gcc-16-20250720/gcc/config/gcn/gcn-opts.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/gcn/gcn-opts.h	Sun Jul 27 22:32:08 2025
*************** enum hsaco_attr_type
*** 82,89 ****
--- 82,94 ----
  #define TARGET_DPP_FULL !TARGET_RDNA2_PLUS
  #define TARGET_DPP16 TARGET_RDNA2_PLUS
  #define TARGET_DPP8 TARGET_RDNA2_PLUS
+ /* Device requires no manually inserted wait states; that's the
+    case for RDNA 2, 3 and 3.5 (but not for RNDA 4).  */
+ #define TARGET_NO_MANUAL_NOPS TARGET_RDNA2_PLUS
  /* Device requires CDNA1-style manually inserted wait states for AVGPRs.  */
  #define TARGET_AVGPR_CDNA1_NOPS TARGET_CDNA1
+ /* Device requires CDNA3-style manually inserted wait states.  */
+ #define TARGET_CDNA3_NOPS TARGET_CDNA3
  /* Whether to use the 'globally coherent' (glc) or the 'scope' (sc0) flag
     for non-scalar memory operations. The string starts on purpose with a space.
     Note: for scalar memory operations (i.e. 's_...'), 'glc' is still used.
diff -Nrcpad gcc-16-20250720/gcc/config/gcn/gcn-valu.md gcc-16-20250727/gcc/config/gcn/gcn-valu.md
*** gcc-16-20250720/gcc/config/gcn/gcn-valu.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/gcn/gcn-valu.md	Sun Jul 27 22:32:08 2025
***************
*** 811,817 ****
    [(set_attr "type" "vop3a")
     (set_attr "length" "8")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "yes")])
  
  ; FIXME: 64bit operations really should be splitters, but I am not sure how
  ; to represent vertical subregs.
--- 811,817 ----
    [(set_attr "type" "vop3a")
     (set_attr "length" "8")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "write")])
  
  ; FIXME: 64bit operations really should be splitters, but I am not sure how
  ; to represent vertical subregs.
***************
*** 828,834 ****
    [(set_attr "type" "vmult")
     (set_attr "length" "16")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "yes")])
  
  (define_expand "vec_set<mode>"
    [(set (match_operand:V_MOV 0 "register_operand")
--- 828,834 ----
    [(set_attr "type" "vmult")
     (set_attr "length" "16")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "write")])
  
  (define_expand "vec_set<mode>"
    [(set (match_operand:V_MOV 0 "register_operand")
***************
*** 854,860 ****
    [(set_attr "type" "vop3a")
     (set_attr "length" "8")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "yes")])
  
  (define_insn "*vec_set<mode>_1"
    [(set (match_operand:V_2REG 0 "register_operand"		   "=v")
--- 854,860 ----
    [(set_attr "type" "vop3a")
     (set_attr "length" "8")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "write")])
  
  (define_insn "*vec_set<mode>_1"
    [(set (match_operand:V_2REG 0 "register_operand"		   "=v")
***************
*** 871,877 ****
    [(set_attr "type" "vmult")
     (set_attr "length" "16")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "yes")])
  
  (define_insn "vec_duplicate<mode><exec>"
    [(set (match_operand:V_1REG 0 "register_operand"	   "=v")
--- 871,877 ----
    [(set_attr "type" "vmult")
     (set_attr "length" "16")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "write")])
  
  (define_insn "vec_duplicate<mode><exec>"
    [(set (match_operand:V_1REG 0 "register_operand"	   "=v")
***************
*** 910,916 ****
    [(set_attr "type" "vop3a")
     (set_attr "length" "8")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "yes")])
  
  (define_insn "vec_extract<mode><scalar_mode>"
    [(set (match_operand:<SCALAR_MODE> 0 "register_operand"  "=&Sg")
--- 910,916 ----
    [(set_attr "type" "vop3a")
     (set_attr "length" "8")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "read")])
  
  (define_insn "vec_extract<mode><scalar_mode>"
    [(set (match_operand:<SCALAR_MODE> 0 "register_operand"  "=&Sg")
***************
*** 922,928 ****
    [(set_attr "type" "vmult")
     (set_attr "length" "16")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "yes")])
  
  (define_insn "vec_extract<mode><scalar_mode>"
    [(set (match_operand:<SCALAR_MODE> 0 "register_operand"  "=&Sg")
--- 922,928 ----
    [(set_attr "type" "vmult")
     (set_attr "length" "16")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "read")])
  
  (define_insn "vec_extract<mode><scalar_mode>"
    [(set (match_operand:<SCALAR_MODE> 0 "register_operand"  "=&Sg")
***************
*** 934,940 ****
    [(set_attr "type" "vmult")
     (set_attr "length" "32")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "yes")])
  
  (define_insn "vec_extract<V_1REG:mode><V_1REG_ALT:mode>_nop"
    [(set (match_operand:V_1REG_ALT 0 "register_operand" "=v,v")
--- 934,940 ----
    [(set_attr "type" "vmult")
     (set_attr "length" "32")
     (set_attr "exec" "none")
!    (set_attr "laneselect" "read")])
  
  (define_insn "vec_extract<V_1REG:mode><V_1REG_ALT:mode>_nop"
    [(set (match_operand:V_1REG_ALT 0 "register_operand" "=v,v")
***************
*** 1133,1138 ****
--- 1133,1155 ----
      DONE;
    })
  
+ (define_expand "gather_load<mode><vndi>"
+   [(match_operand:V_MOV 0 "register_operand")
+    (match_operand:DI 1 "register_operand")
+    (match_operand:<VnDI> 2 "register_operand")
+    (match_operand 3 "immediate_operand")
+    (match_operand:SI 4 "gcn_alu_operand")]
+   ""
+   {
+     rtx addr = gcn_expand_scaled_offsets (DEFAULT_ADDR_SPACE, operands[1],
+ 					  operands[2], operands[4],
+ 					  INTVAL (operands[3]), NULL);
+ 
+     emit_insn (gen_gather<mode>_insn_1offset (operands[0], addr, const0_rtx,
+ 					      const0_rtx, const0_rtx));
+     DONE;
+   })
+ 
  ; Allow any address expression
  (define_expand "gather<mode>_expr<exec>"
    [(set (match_operand:V_MOV 0 "register_operand")
***************
*** 1175,1180 ****
--- 1192,1198 ----
      return buf;
    }
    [(set_attr "type" "flat")
+    (set_attr "flatmemaccess" "load")
     (set_attr "length" "12")
     (set_attr "cdna" "*,cdna2,*,cdna2")
     (set_attr "xnack" "off,off,on,on")])
***************
*** 1233,1238 ****
--- 1251,1257 ----
      return buf;
    }
    [(set_attr "type" "flat")
+    (set_attr "flatmemaccess" "load")
     (set_attr "length" "12")
     (set_attr "cdna" "*,cdna2,*,cdna2")
     (set_attr "xnack" "off,off,on,on")])
***************
*** 1259,1264 ****
--- 1278,1300 ----
      DONE;
    })
  
+ (define_expand "scatter_store<mode><vndi>"
+   [(match_operand:DI 0 "register_operand")
+    (match_operand:<VnDI> 1 "register_operand")
+    (match_operand 2 "immediate_operand")
+    (match_operand:SI 3 "gcn_alu_operand")
+    (match_operand:V_MOV 4 "register_operand")]
+   ""
+   {
+     rtx addr = gcn_expand_scaled_offsets (DEFAULT_ADDR_SPACE, operands[0],
+ 					  operands[1], operands[3],
+ 					  INTVAL (operands[2]), NULL);
+ 
+     emit_insn (gen_scatter<mode>_insn_1offset (addr, const0_rtx, operands[4],
+ 					       const0_rtx, const0_rtx));
+     DONE;
+   })
+ 
  ; Allow any address expression
  (define_expand "scatter<mode>_expr<exec_scatter>"
    [(set (mem:BLK (scratch))
***************
*** 1301,1306 ****
--- 1337,1343 ----
      return buf;
    }
    [(set_attr "type" "flat")
+    (set_attr "flatmemaccess" "store")
     (set_attr "length" "12")
     (set_attr "cdna" "*,cdna2")])
  
***************
*** 1356,1361 ****
--- 1393,1399 ----
      return buf;
    }
    [(set_attr "type" "flat")
+    (set_attr "flatmemaccess" "store")
     (set_attr "length" "12")
     (set_attr "cdna" "*,cdna2")])
  
***************
*** 1645,1650 ****
--- 1683,1721 ----
    [(set_attr "type" "vmult")
     (set_attr "length" "8")])
  
+ (define_insn_and_split "add<mode>3_dup"
+   [(set (match_operand:V_DI 0 "register_operand" "= v")
+ 	(plus:V_DI
+ 	  (vec_duplicate:V_DI
+ 	    (match_operand:DI 1 "register_operand"   "SvB"))
+ 	  (match_operand:V_DI 2 "gcn_alu_operand"    "vDb")))
+    (clobber (reg:DI VCC_REG))
+    (clobber (match_scratch:<VnSI> 3 "=&v"))]
+   ""
+   "#"
+   "gcn_can_split_p  (<MODE>mode, operands[0])
+    && gcn_can_split_p (<MODE>mode, operands[1])
+    && gcn_can_split_p (<MODE>mode, operands[2])"
+   [(const_int 0)]
+   {
+     rtx vcc = gen_rtx_REG (DImode, VCC_REG);
+     emit_insn (gen_add<vnsi>3_vcc_dup
+ 		(gcn_operand_part (<MODE>mode, operands[0], 0),
+ 		 gcn_operand_part (DImode, operands[1], 0),
+ 		 gcn_operand_part (<MODE>mode, operands[2], 0),
+ 		 vcc));
+     emit_insn (gen_vec_duplicate<vnsi> (operands[3],
+ 				  gcn_operand_part (DImode, operands[1], 1)));
+     emit_insn (gen_addc<vnsi>3
+ 		(gcn_operand_part (<MODE>mode, operands[0], 1),
+ 		 operands[3],
+ 		 gcn_operand_part (<MODE>mode, operands[2], 1),
+ 		 vcc, vcc));
+     DONE;
+   }
+   [(set_attr "type" "vmult")
+    (set_attr "length" "8")])
+ 
  (define_insn_and_split "add<mode>3_exec"
    [(set (match_operand:V_DI 0 "register_operand"		 "=  v")
  	(vec_merge:V_DI
***************
*** 1682,1687 ****
--- 1753,1801 ----
    [(set_attr "type" "vmult")
     (set_attr "length" "8")])
  
+ (define_insn_and_split "add<mode>3_dup_exec"
+   [(set (match_operand:V_DI 0 "register_operand"		     "= v")
+ 	(vec_merge:V_DI
+ 	  (plus:V_DI
+ 	    (vec_duplicate:V_DI
+ 	      (match_operand:DI 1 "register_operand"		     "SvB"))
+ 	    (match_operand:V_DI 2 "gcn_alu_operand"		         "vDb"))
+ 	  (match_operand:V_DI 3 "gcn_register_or_unspec_operand" " U0")
+ 	  (match_operand:DI 4 "gcn_exec_reg_operand"		     "  e")))
+    (clobber (reg:DI VCC_REG))
+    (clobber (match_scratch:<VnSI> 5 "=&v"))]
+   ""
+   "#"
+   "gcn_can_split_p  (<MODE>mode, operands[0])
+    && gcn_can_split_p (<MODE>mode, operands[1])
+    && gcn_can_split_p (<MODE>mode, operands[2])
+    && gcn_can_split_p (<MODE>mode, operands[4])"
+   [(const_int 0)]
+   {
+     rtx vcc = gen_rtx_REG (DImode, VCC_REG);
+     emit_insn (gen_add<vnsi>3_vcc_dup_exec
+ 		(gcn_operand_part (<MODE>mode, operands[0], 0),
+ 		 gcn_operand_part (DImode, operands[1], 0),
+ 		 gcn_operand_part (<MODE>mode, operands[2], 0),
+ 		 vcc,
+ 		 gcn_operand_part (<MODE>mode, operands[3], 0),
+ 		 operands[4]));
+     emit_insn (gen_vec_duplicate<vnsi>_exec (operands[5],
+ 				gcn_operand_part (DImode, operands[1], 1),
+ 				gcn_gen_undef (<VnSI>mode),
+ 				operands[4]));
+     emit_insn (gen_addc<vnsi>3_exec
+ 		(gcn_operand_part (<MODE>mode, operands[0], 1),
+ 		 operands[5],
+ 		 gcn_operand_part (<MODE>mode, operands[2], 1),
+ 		 vcc, vcc,
+ 		 gcn_operand_part (<MODE>mode, operands[3], 1),
+ 		 operands[4]));
+     DONE;
+   }
+   [(set_attr "type" "vmult")
+    (set_attr "length" "8")])
+ 
  (define_insn_and_split "sub<mode>3"
    [(set (match_operand:V_DI 0 "register_operand"  "= v,  v")
  	(minus:V_DI                                        
***************
*** 2187,2192 ****
--- 2301,2322 ----
    [(set_attr "type" "vop3a")
     (set_attr "length" "8")])
  
+ (define_insn "<su>mul<mode>3_highpart_dup<exec>"
+   [(set (match_operand:V_SI 0 "register_operand" "= v")
+ 	(truncate:V_SI
+ 	  (lshiftrt:<VnDI>
+ 	    (mult:<VnDI>
+ 	      (any_extend:<VnDI>
+ 		(vec_duplicate:V_SI
+ 		  (match_operand:SI 1 "gcn_alu_operand"  "SvA")))
+ 	      (any_extend:<VnDI>
+ 		(match_operand:V_SI 2 "gcn_alu_operand"  " vA")))
+ 	    (const_int 32))))]
+   ""
+   "v_mul_hi<sgnsuffix>0\t%0, %2, %1"
+   [(set_attr "type" "vop3a")
+    (set_attr "length" "8")])
+ 
  (define_insn "mul<mode>3<exec>"
    [(set (match_operand:V_INT_1REG 0 "register_operand"  "=   v")
  	(mult:V_INT_1REG
***************
*** 2198,2208 ****
     (set_attr "length" "8")])
  
  (define_insn "mul<mode>3_dup<exec>"
!   [(set (match_operand:V_INT_1REG 0 "register_operand"	     "=   v")
  	(mult:V_INT_1REG
- 	  (match_operand:V_INT_1REG 1 "gcn_alu_operand"	     "%vSvA")
  	  (vec_duplicate:V_INT_1REG
! 	    (match_operand:<SCALAR_MODE> 2 "gcn_alu_operand" "  SvA"))))]
    ""
    "v_mul_lo_u32\t%0, %1, %2"
    [(set_attr "type" "vop3a")
--- 2328,2338 ----
     (set_attr "length" "8")])
  
  (define_insn "mul<mode>3_dup<exec>"
!   [(set (match_operand:V_INT_1REG 0 "register_operand"	 "= v")
  	(mult:V_INT_1REG
  	  (vec_duplicate:V_INT_1REG
! 	    (match_operand:<SCALAR_MODE> 1 "gcn_alu_operand" "SvA"))
! 	  (match_operand:V_INT_1REG 2 "gcn_alu_operand"	     " vA")))]
    ""
    "v_mul_lo_u32\t%0, %1, %2"
    [(set_attr "type" "vop3a")
***************
*** 2238,2243 ****
--- 2368,2404 ----
      DONE;
    })
  
+ (define_insn_and_split "mul<mode>3_dup"
+   [(set (match_operand:V_DI 0 "register_operand" "=&v")
+ 	(mult:V_DI
+ 	  (vec_duplicate:V_DI
+ 	    (match_operand:DI 1 "gcn_alu_operand"    " Sv"))
+ 	  (match_operand:V_DI 2 "gcn_alu_operand"    "vDA")))
+    (clobber (match_scratch:<VnSI> 3 "=&v"))]
+   ""
+   "#"
+   "reload_completed"
+   [(const_int 0)]
+   {
+     rtx out_lo = gcn_operand_part (<MODE>mode, operands[0], 0);
+     rtx out_hi = gcn_operand_part (<MODE>mode, operands[0], 1);
+     rtx left_lo = gcn_operand_part (DImode, operands[1], 0);
+     rtx left_hi = gcn_operand_part (DImode, operands[1], 1);
+     rtx right_lo = gcn_operand_part (<MODE>mode, operands[2], 0);
+     rtx right_hi = gcn_operand_part (<MODE>mode, operands[2], 1);
+     rtx tmp = operands[3];
+ 
+     emit_insn (gen_mul<vnsi>3_dup (out_lo, left_lo, right_lo));
+     emit_insn (gen_umul<vnsi>3_highpart_dup (out_hi, left_lo, right_lo));
+     emit_insn (gen_mul<vnsi>3_dup (tmp, left_hi, right_lo));
+     emit_insn (gen_add<vnsi>3 (out_hi, out_hi, tmp));
+     emit_insn (gen_mul<vnsi>3_dup (tmp, left_lo, right_hi));
+     emit_insn (gen_add<vnsi>3 (out_hi, out_hi, tmp));
+     emit_insn (gen_mul<vnsi>3_dup (tmp, left_hi, right_hi));
+     emit_insn (gen_add<vnsi>3 (out_hi, out_hi, tmp));
+     DONE;
+   })
+ 
  (define_insn_and_split "mul<mode>3_exec"
    [(set (match_operand:V_DI 0 "register_operand"		 "=&v")
  	(vec_merge:V_DI
***************
*** 2286,2291 ****
--- 2447,2502 ----
      DONE;
    })
  
+ (define_insn_and_split "mul<mode>3_dup_exec"
+   [(set (match_operand:V_DI 0 "register_operand"		 "=&v")
+ 	(vec_merge:V_DI
+ 	  (mult:V_DI
+ 	    (vec_duplicate:V_DI
+ 	      (match_operand:DI 1 "gcn_alu_operand"		 " Sv"))
+ 	    (match_operand:V_DI 2 "gcn_alu_operand"		 "vDA"))
+ 	  (match_operand:V_DI 3 "gcn_register_or_unspec_operand" " U0")
+ 	  (match_operand:DI 4 "gcn_exec_reg_operand"		 "  e")))
+    (clobber (match_scratch:<VnSI> 5 "=&v"))]
+   ""
+   "#"
+   "reload_completed"
+   [(const_int 0)]
+   {
+     rtx out_lo = gcn_operand_part (<MODE>mode, operands[0], 0);
+     rtx out_hi = gcn_operand_part (<MODE>mode, operands[0], 1);
+     rtx left_lo = gcn_operand_part (DImode, operands[1], 0);
+     rtx left_hi = gcn_operand_part (DImode, operands[1], 1);
+     rtx right_lo = gcn_operand_part (<MODE>mode, operands[2], 0);
+     rtx right_hi = gcn_operand_part (<MODE>mode, operands[2], 1);
+     rtx exec = operands[4];
+     rtx tmp = operands[5];
+ 
+     rtx old_lo, old_hi;
+     if (GET_CODE (operands[3]) == UNSPEC)
+       {
+ 	old_lo = old_hi = gcn_gen_undef (<VnSI>mode);
+       }
+     else
+       {
+ 	old_lo = gcn_operand_part (<MODE>mode, operands[3], 0);
+ 	old_hi = gcn_operand_part (<MODE>mode, operands[3], 1);
+       }
+ 
+     rtx undef = gcn_gen_undef (<VnSI>mode);
+ 
+     emit_insn (gen_mul<vnsi>3_dup_exec (out_lo, left_lo, right_lo, old_lo,
+ 					exec));
+     emit_insn (gen_umul<vnsi>3_highpart_dup_exec (out_hi, left_lo, right_lo,
+ 						  old_hi, exec));
+     emit_insn (gen_mul<vnsi>3_dup_exec (tmp, left_hi, right_lo, undef, exec));
+     emit_insn (gen_add<vnsi>3_exec (out_hi, out_hi, tmp, out_hi, exec));
+     emit_insn (gen_mul<vnsi>3_dup_exec (tmp, left_lo, right_hi, undef, exec));
+     emit_insn (gen_add<vnsi>3_exec (out_hi, out_hi, tmp, out_hi, exec));
+     emit_insn (gen_mul<vnsi>3_dup_exec (tmp, left_hi, right_hi, undef, exec));
+     emit_insn (gen_add<vnsi>3_exec (out_hi, out_hi, tmp, out_hi, exec));
+     DONE;
+   })
+ 
  (define_insn_and_split "mul<mode>3_zext"
    [(set (match_operand:V_DI 0 "register_operand"      "=&v")
  	(mult:V_DI
***************
*** 3053,3059 ****
    "flag_unsafe_math_optimizations"
    "v_sqrt%i0\t%0, %1"
    [(set_attr "type" "vop1")
!    (set_attr "length" "8")])
  
  (define_insn "sqrt<mode>2"
    [(set (match_operand:FP 0 "register_operand"  "=  v")
--- 3264,3271 ----
    "flag_unsafe_math_optimizations"
    "v_sqrt%i0\t%0, %1"
    [(set_attr "type" "vop1")
!    (set_attr "length" "8")
!    (set_attr "transop" "yes")])
  
  (define_insn "sqrt<mode>2"
    [(set (match_operand:FP 0 "register_operand"  "=  v")
***************
*** 3062,3068 ****
    "flag_unsafe_math_optimizations"
    "v_sqrt%i0\t%0, %1"
    [(set_attr "type" "vop1")
!    (set_attr "length" "8")])
  
  ; These FP unops have f64, f32 and f16 versions.
  (define_int_iterator MATH_UNOP_1OR2REG
--- 3274,3281 ----
    "flag_unsafe_math_optimizations"
    "v_sqrt%i0\t%0, %1"
    [(set_attr "type" "vop1")
!    (set_attr "length" "8")
!    (set_attr "transop" "yes")])
  
  ; These FP unops have f64, f32 and f16 versions.
  (define_int_iterator MATH_UNOP_1OR2REG
***************
*** 3352,3358 ****
    ""
    "v_rcp%i0\t%0, %1"
    [(set_attr "type" "vop1")
!    (set_attr "length" "8")])
  
  ;; v_div_scale takes a numerator (op2) and denominator (op1) and returns the
  ;; one that matches op3 adjusted for best results in reciprocal division.
--- 3565,3572 ----
    ""
    "v_rcp%i0\t%0, %1"
    [(set_attr "type" "vop1")
!    (set_attr "length" "8")
!    (set_attr "transop" "yes")])
  
  ;; v_div_scale takes a numerator (op2) and denominator (op1) and returns the
  ;; one that matches op3 adjusted for best results in reciprocal division.
***************
*** 4049,4054 ****
--- 4263,4294 ----
      DONE;
    })
  
+ (define_expand "mask_gather_load<mode><vndi>"
+   [(set:V_MOV (match_operand:V_MOV 0 "register_operand")
+ 	      (unspec:V_MOV
+ 		[(match_operand:DI 1 "register_operand")
+ 		 (match_operand:<VnDI> 2 "register_operand")
+ 		 (match_operand 3 "immediate_operand")
+ 		 (match_operand:SI 4 "gcn_alu_operand")
+ 		 (match_operand:DI 5 "")
+ 		 (match_operand:V_MOV 6 "maskload_else_operand")]
+ 		UNSPEC_GATHER))]
+   ""
+   {
+     rtx exec = force_reg (DImode, operands[5]);
+ 
+     rtx addr = gcn_expand_scaled_offsets (DEFAULT_ADDR_SPACE, operands[1],
+ 					  operands[2], operands[4],
+ 					  INTVAL (operands[3]), exec);
+ 
+     emit_insn (gen_gather<mode>_insn_1offset_exec (operands[0], addr,
+ 						   const0_rtx, const0_rtx,
+ 						   const0_rtx,
+ 						   gcn_gen_undef (<MODE>mode),
+ 						   exec));
+     DONE;
+   })
+ 
  (define_expand "mask_scatter_store<mode><vnsi>"
    [(match_operand:DI 0 "register_operand")
     (match_operand:<VnSI> 1 "register_operand")
***************
*** 4077,4082 ****
--- 4317,4343 ----
      DONE;
    })
  
+ (define_expand "mask_scatter_store<mode><vndi>"
+   [(match_operand:DI 0 "register_operand")
+    (match_operand:<VnDI> 1 "register_operand")
+    (match_operand 2 "immediate_operand")
+    (match_operand:SI 3 "gcn_alu_operand")
+    (match_operand:V_MOV 4 "register_operand")
+    (match_operand:DI 5 "")]
+   ""
+   {
+     rtx exec = force_reg (DImode, operands[5]);
+ 
+     rtx addr = gcn_expand_scaled_offsets (DEFAULT_ADDR_SPACE, operands[0],
+ 					  operands[1], operands[3],
+ 					  INTVAL (operands[2]), exec);
+ 
+     emit_insn (gen_scatter<mode>_insn_1offset_exec (addr, const0_rtx,
+ 						    operands[4], const0_rtx,
+ 						    const0_rtx, exec));
+     DONE;
+   })
+ 
  (define_code_iterator cond_op [plus minus mult])
  
  (define_expand "cond_<expander><mode>"
***************
*** 4397,4403 ****
      rtx tmp = gen_reg_rtx (<MODE>mode);
      rtx v1 = gen_rtx_REG (<MODE>mode, VGPR_REGNO (1));
  
!     emit_insn (gen_mul<mode>3_dup (tmp, v1, operands[2]));
      emit_insn (gen_add<mode>3_dup (operands[0], tmp, operands[1]));
      DONE;
    })
--- 4658,4664 ----
      rtx tmp = gen_reg_rtx (<MODE>mode);
      rtx v1 = gen_rtx_REG (<MODE>mode, VGPR_REGNO (1));
  
!     emit_insn (gen_mul<mode>3_dup (tmp, operands[2], v1));
      emit_insn (gen_add<mode>3_dup (operands[0], tmp, operands[1]));
      DONE;
    })
diff -Nrcpad gcc-16-20250720/gcc/config/gcn/gcn.cc gcc-16-20250727/gcc/config/gcn/gcn.cc
*** gcc-16-20250720/gcc/config/gcn/gcn.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/gcn/gcn.cc	Sun Jul 27 22:32:08 2025
*************** gen_##PREFIX##vN##SUFFIX (PARAMS) \
*** 1275,1287 ****
  }
  
  #define GEN_VNM_NOEXEC(PREFIX, SUFFIX, PARAMS, ARGS) \
! GEN_VN_NOEXEC (PREFIX, qi##SUFFIX, A(PARAMS), A(ARGS)) \
! GEN_VN_NOEXEC (PREFIX, hi##SUFFIX, A(PARAMS), A(ARGS)) \
! GEN_VN_NOEXEC (PREFIX, hf##SUFFIX, A(PARAMS), A(ARGS)) \
  GEN_VN_NOEXEC (PREFIX, si##SUFFIX, A(PARAMS), A(ARGS)) \
! GEN_VN_NOEXEC (PREFIX, sf##SUFFIX, A(PARAMS), A(ARGS)) \
  GEN_VN_NOEXEC (PREFIX, di##SUFFIX, A(PARAMS), A(ARGS)) \
! GEN_VN_NOEXEC (PREFIX, df##SUFFIX, A(PARAMS), A(ARGS)) \
  static rtx \
  gen_##PREFIX##vNm##SUFFIX (PARAMS) \
  { \
--- 1275,1287 ----
  }
  
  #define GEN_VNM_NOEXEC(PREFIX, SUFFIX, PARAMS, ARGS) \
! USE_QHF (GEN_VN_NOEXEC (PREFIX, qi##SUFFIX, A(PARAMS), A(ARGS))) \
! USE_QHF (GEN_VN_NOEXEC (PREFIX, hi##SUFFIX, A(PARAMS), A(ARGS))) \
! USE_QHF (GEN_VN_NOEXEC (PREFIX, hf##SUFFIX, A(PARAMS), A(ARGS))) \
  GEN_VN_NOEXEC (PREFIX, si##SUFFIX, A(PARAMS), A(ARGS)) \
! USE_QHF (GEN_VN_NOEXEC (PREFIX, sf##SUFFIX, A(PARAMS), A(ARGS))) \
  GEN_VN_NOEXEC (PREFIX, di##SUFFIX, A(PARAMS), A(ARGS)) \
! USE_QHF (GEN_VN_NOEXEC (PREFIX, df##SUFFIX, A(PARAMS), A(ARGS))) \
  static rtx \
  gen_##PREFIX##vNm##SUFFIX (PARAMS) \
  { \
*************** gen_##PREFIX##vNm##SUFFIX (PARAMS) \
*** 1289,1301 ****
    \
    switch (mode) \
      { \
!     case E_QImode: return gen_##PREFIX##vNqi##SUFFIX (ARGS); \
!     case E_HImode: return gen_##PREFIX##vNhi##SUFFIX (ARGS); \
!     case E_HFmode: return gen_##PREFIX##vNhf##SUFFIX (ARGS); \
      case E_SImode: return gen_##PREFIX##vNsi##SUFFIX (ARGS); \
!     case E_SFmode: return gen_##PREFIX##vNsf##SUFFIX (ARGS); \
      case E_DImode: return gen_##PREFIX##vNdi##SUFFIX (ARGS); \
!     case E_DFmode: return gen_##PREFIX##vNdf##SUFFIX (ARGS); \
      default: \
        break; \
      } \
--- 1289,1301 ----
    \
    switch (mode) \
      { \
!     USE_QHF (case E_QImode: return gen_##PREFIX##vNqi##SUFFIX (ARGS);) \
!     USE_QHF (case E_HImode: return gen_##PREFIX##vNhi##SUFFIX (ARGS);) \
!     USE_QHF (case E_HFmode: return gen_##PREFIX##vNhf##SUFFIX (ARGS);) \
      case E_SImode: return gen_##PREFIX##vNsi##SUFFIX (ARGS); \
!     USE_QHF (case E_SFmode: return gen_##PREFIX##vNsf##SUFFIX (ARGS);) \
      case E_DImode: return gen_##PREFIX##vNdi##SUFFIX (ARGS); \
!     USE_QHF (case E_DFmode: return gen_##PREFIX##vNdf##SUFFIX (ARGS);) \
      default: \
        break; \
      } \
*************** gen_##PREFIX##vN##SUFFIX (PARAMS, rtx me
*** 1340,1352 ****
  }
  
  #define GEN_VNM(PREFIX, SUFFIX, PARAMS, ARGS) \
! GEN_VN (PREFIX, qi##SUFFIX, A(PARAMS), A(ARGS)) \
! GEN_VN (PREFIX, hi##SUFFIX, A(PARAMS), A(ARGS)) \
! GEN_VN (PREFIX, hf##SUFFIX, A(PARAMS), A(ARGS)) \
  GEN_VN (PREFIX, si##SUFFIX, A(PARAMS), A(ARGS)) \
! GEN_VN (PREFIX, sf##SUFFIX, A(PARAMS), A(ARGS)) \
  GEN_VN (PREFIX, di##SUFFIX, A(PARAMS), A(ARGS)) \
! GEN_VN (PREFIX, df##SUFFIX, A(PARAMS), A(ARGS)) \
  USE_TI (GEN_VN (PREFIX, ti##SUFFIX, A(PARAMS), A(ARGS))) \
  static rtx \
  gen_##PREFIX##vNm##SUFFIX (PARAMS, rtx merge_src=NULL, rtx exec=NULL) \
--- 1340,1352 ----
  }
  
  #define GEN_VNM(PREFIX, SUFFIX, PARAMS, ARGS) \
! USE_QHF (GEN_VN (PREFIX, qi##SUFFIX, A(PARAMS), A(ARGS))) \
! USE_QHF (GEN_VN (PREFIX, hi##SUFFIX, A(PARAMS), A(ARGS))) \
! USE_QHF (GEN_VN (PREFIX, hf##SUFFIX, A(PARAMS), A(ARGS))) \
  GEN_VN (PREFIX, si##SUFFIX, A(PARAMS), A(ARGS)) \
! USE_QHF (GEN_VN (PREFIX, sf##SUFFIX, A(PARAMS), A(ARGS))) \
  GEN_VN (PREFIX, di##SUFFIX, A(PARAMS), A(ARGS)) \
! USE_QHF (GEN_VN (PREFIX, df##SUFFIX, A(PARAMS), A(ARGS))) \
  USE_TI (GEN_VN (PREFIX, ti##SUFFIX, A(PARAMS), A(ARGS))) \
  static rtx \
  gen_##PREFIX##vNm##SUFFIX (PARAMS, rtx merge_src=NULL, rtx exec=NULL) \
*************** gen_##PREFIX##vNm##SUFFIX (PARAMS, rtx m
*** 1355,1369 ****
    \
    switch (mode) \
      { \
!     case E_QImode: return gen_##PREFIX##vNqi##SUFFIX (ARGS, merge_src, exec); \
!     case E_HImode: return gen_##PREFIX##vNhi##SUFFIX (ARGS, merge_src, exec); \
!     case E_HFmode: return gen_##PREFIX##vNhf##SUFFIX (ARGS, merge_src, exec); \
!     case E_SImode: return gen_##PREFIX##vNsi##SUFFIX (ARGS, merge_src, exec); \
!     case E_SFmode: return gen_##PREFIX##vNsf##SUFFIX (ARGS, merge_src, exec); \
!     case E_DImode: return gen_##PREFIX##vNdi##SUFFIX (ARGS, merge_src, exec); \
!     case E_DFmode: return gen_##PREFIX##vNdf##SUFFIX (ARGS, merge_src, exec); \
!     case E_TImode: \
! 	USE_TI (return gen_##PREFIX##vNti##SUFFIX (ARGS, merge_src, exec);) \
      default: \
        break; \
      } \
--- 1355,1376 ----
    \
    switch (mode) \
      { \
!     USE_QHF (case E_QImode: \
! 	return gen_##PREFIX##vNqi##SUFFIX (ARGS, merge_src, exec);) \
!     USE_QHF (case E_HImode: \
! 	return gen_##PREFIX##vNhi##SUFFIX (ARGS, merge_src, exec);) \
!     USE_QHF (case E_HFmode: \
! 	return gen_##PREFIX##vNhf##SUFFIX (ARGS, merge_src, exec);) \
!     case E_SImode: \
! 	return gen_##PREFIX##vNsi##SUFFIX (ARGS, merge_src, exec); \
!     USE_QHF (case E_SFmode: \
! 	return gen_##PREFIX##vNsf##SUFFIX (ARGS, merge_src, exec);) \
!     case E_DImode: \
! 	return gen_##PREFIX##vNdi##SUFFIX (ARGS, merge_src, exec); \
!     USE_QHF (case E_DFmode: \
! 	return gen_##PREFIX##vNdf##SUFFIX (ARGS, merge_src, exec);) \
!     USE_TI (case E_TImode: \
! 	return gen_##PREFIX##vNti##SUFFIX (ARGS, merge_src, exec);) \
      default: \
        break; \
      } \
*************** gen_##PREFIX##vNm##SUFFIX (PARAMS, rtx m
*** 1372,1378 ****
    return NULL_RTX; \
  }
  
! /* These have TImode support.  */
  #define USE_TI(ARGS) ARGS
  GEN_VNM (mov,, A(rtx dest, rtx src), A(dest, src))
  GEN_VNM (vec_duplicate,, A(rtx dest, rtx src), A(dest, src))
--- 1379,1386 ----
    return NULL_RTX; \
  }
  
! /* These support everything.  */
! #define USE_QHF(ARGS) ARGS
  #define USE_TI(ARGS) ARGS
  GEN_VNM (mov,, A(rtx dest, rtx src), A(dest, src))
  GEN_VNM (vec_duplicate,, A(rtx dest, rtx src), A(dest, src))
*************** GEN_VNM (vec_duplicate,, A(rtx dest, rtx
*** 1382,1387 ****
--- 1390,1396 ----
  #define USE_TI(ARGS)
  GEN_VNM (add,3, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
  GEN_VN (add,si3_dup, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
+ GEN_VN (add,di3_dup, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
  GEN_VN (add,si3_vcc_dup, A(rtx dest, rtx src1, rtx src2, rtx vcc),
  	A(dest, src1, src2, vcc))
  GEN_VN (add,di3_sext_dup2, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
*************** GEN_VN (add,di3_vcc_zext_dup2, A(rtx des
*** 1393,1407 ****
  GEN_VN (addc,si3, A(rtx dest, rtx src1, rtx src2, rtx vccout, rtx vccin),
  	A(dest, src1, src2, vccout, vccin))
  GEN_VN (and,si3, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
- GEN_VN (ashl,si3, A(rtx dest, rtx src, rtx shift), A(dest, src, shift))
  GEN_VNM_NOEXEC (ds_bpermute,, A(rtx dest, rtx addr, rtx src, rtx exec),
  		A(dest, addr, src, exec))
  GEN_VNM (gather,_expr, A(rtx dest, rtx addr, rtx as, rtx vol),
  	 A(dest, addr, as, vol))
- GEN_VN (mul,si3_dup, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
  GEN_VN (sub,si3, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
  GEN_VN_NOEXEC (vec_series,si, A(rtx dest, rtx x, rtx c), A(dest, x, c))
  
  #undef USE_TI
  #undef GEN_VNM
  #undef GEN_VN
--- 1402,1421 ----
  GEN_VN (addc,si3, A(rtx dest, rtx src1, rtx src2, rtx vccout, rtx vccin),
  	A(dest, src1, src2, vccout, vccin))
  GEN_VN (and,si3, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
  GEN_VNM_NOEXEC (ds_bpermute,, A(rtx dest, rtx addr, rtx src, rtx exec),
  		A(dest, addr, src, exec))
  GEN_VNM (gather,_expr, A(rtx dest, rtx addr, rtx as, rtx vol),
  	 A(dest, addr, as, vol))
  GEN_VN (sub,si3, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
  GEN_VN_NOEXEC (vec_series,si, A(rtx dest, rtx x, rtx c), A(dest, x, c))
  
+ /* These do not have QI, HI, or any FP support.  */
+ #undef USE_QHF
+ #define USE_QHF(ARGS)
+ GEN_VNM (ashl,3, A(rtx dest, rtx src, rtx shift), A(dest, src, shift))
+ GEN_VNM (mul,3_dup, A(rtx dest, rtx src1, rtx src2), A(dest, src1, src2))
+ 
+ #undef USE_QHF
  #undef USE_TI
  #undef GEN_VNM
  #undef GEN_VN
*************** gcn_expand_vector_init (rtx op0, rtx vec
*** 1995,2002 ****
    rtx addr = gen_reg_rtx (addrmode);
  
    int unit_size = GET_MODE_SIZE (GET_MODE_INNER (GET_MODE (op0)));
!   emit_insn (gen_mulvNsi3_dup (ramp, gen_rtx_REG (offsetmode, VGPR_REGNO (1)),
! 			       GEN_INT (unit_size)));
  
    bool simple_repeat = true;
  
--- 2009,2016 ----
    rtx addr = gen_reg_rtx (addrmode);
  
    int unit_size = GET_MODE_SIZE (GET_MODE_INNER (GET_MODE (op0)));
!   emit_insn (gen_mulvNsi3_dup (ramp, GEN_INT (unit_size),
! 			       gen_rtx_REG (offsetmode, VGPR_REGNO (1))));
  
    bool simple_repeat = true;
  
*************** gcn_expand_scalar_to_vector_address (mac
*** 2293,2328 ****
  
     Return values.
       ADDR_SPACE_FLAT   - return VnDImode vector of absolute addresses.
!      ADDR_SPACE_GLOBAL - return VnSImode vector of offsets.  */
  
  rtx
  gcn_expand_scaled_offsets (addr_space_t as, rtx base, rtx offsets, rtx scale,
  			   bool unsigned_p, rtx exec)
  {
    int vf = GET_MODE_NUNITS (GET_MODE (offsets));
!   rtx tmpsi = gen_reg_rtx (VnMODE (vf, SImode));
!   rtx tmpdi = gen_reg_rtx (VnMODE (vf, DImode));
  
    if (CONST_INT_P (scale)
        && INTVAL (scale) > 0
        && exact_log2 (INTVAL (scale)) >= 0)
!     emit_insn (gen_ashlvNsi3 (tmpsi, offsets,
! 			      GEN_INT (exact_log2 (INTVAL (scale))),
! 			      NULL, exec));
    else
!      emit_insn (gen_mulvNsi3_dup (tmpsi, offsets, scale, NULL, exec));
  
    /* "Global" instructions do not support negative register offsets.  */
!   if (as == ADDR_SPACE_FLAT || !unsigned_p)
      {
        if (unsigned_p)
! 	 emit_insn (gen_addvNdi3_zext_dup2 (tmpdi, tmpsi, base, NULL, exec));
        else
! 	 emit_insn (gen_addvNdi3_sext_dup2 (tmpdi, tmpsi, base, NULL, exec));
!       return tmpdi;
      }
    else if (as == ADDR_SPACE_GLOBAL)
!     return tmpsi;
  
    gcc_unreachable ();
  }
--- 2307,2352 ----
  
     Return values.
       ADDR_SPACE_FLAT   - return VnDImode vector of absolute addresses.
!      ADDR_SPACE_GLOBAL - return VnSImode vector of offsets.
!      64-bit offsets    - return VnDImode vector of absolute addresses. */
  
  rtx
  gcn_expand_scaled_offsets (addr_space_t as, rtx base, rtx offsets, rtx scale,
  			   bool unsigned_p, rtx exec)
  {
    int vf = GET_MODE_NUNITS (GET_MODE (offsets));
!   rtx scaled_offsets = gen_reg_rtx (GET_MODE (offsets));
!   rtx abs_addr = gen_reg_rtx (VnMODE (vf, DImode));
!   bool use_di = GET_MODE_INNER (GET_MODE (scaled_offsets)) == DImode;
  
    if (CONST_INT_P (scale)
        && INTVAL (scale) > 0
        && exact_log2 (INTVAL (scale)) >= 0)
!     emit_insn (gen_ashlvNm3 (scaled_offsets, offsets,
! 			     GEN_INT (exact_log2 (INTVAL (scale))),
! 			     NULL, exec));
    else
!      emit_insn (gen_mulvNm3_dup (scaled_offsets, scale, offsets, NULL, exec));
  
+   /* No instructions support DImode offsets.  */
+   if (use_di)
+     {
+       emit_insn (gen_addvNdi3_dup (abs_addr, base, scaled_offsets, NULL, exec));
+       return abs_addr;
+     }
    /* "Global" instructions do not support negative register offsets.  */
!   else if (as == ADDR_SPACE_FLAT || !unsigned_p)
      {
        if (unsigned_p)
! 	emit_insn (gen_addvNdi3_zext_dup2 (abs_addr, scaled_offsets, base,
! 					   NULL, exec));
        else
! 	emit_insn (gen_addvNdi3_sext_dup2 (abs_addr, scaled_offsets, base,
! 					   NULL, exec));
!       return abs_addr;
      }
    else if (as == ADDR_SPACE_GLOBAL)
!     return scaled_offsets;
  
    gcc_unreachable ();
  }
*************** gcn_preferred_vector_alignment (const_tr
*** 5315,5322 ****
  static bool
  gcn_vectorize_support_vector_misalignment (machine_mode ARG_UNUSED (mode),
  					   const_tree type, int misalignment,
! 					   bool is_packed)
  {
    if (is_packed)
      return false;
  
--- 5339,5350 ----
  static bool
  gcn_vectorize_support_vector_misalignment (machine_mode ARG_UNUSED (mode),
  					   const_tree type, int misalignment,
! 					   bool is_packed,
! 					   bool is_gather_scatter)
  {
+   if (is_gather_scatter)
+     return true;
+ 
    if (is_packed)
      return false;
  
*************** gcn_libc_has_function (enum function_cla
*** 5764,5769 ****
--- 5792,5833 ----
  /* }}}  */
  /* {{{ md_reorg pass.  */
  
+ /* Identify V_CMPX from the "type" attribute;
+    note: this will also match 'v_cmp %E1 vcc'.  */
+ 
+ static bool
+ gcn_cmpx_insn_p (attr_type type)
+ {
+   switch (type)
+     {
+     case TYPE_VOPC:
+       return true;
+     case TYPE_MUBUF:
+     case TYPE_MTBUF:
+     case TYPE_FLAT:
+     case TYPE_VOP3P_MAI:
+     case TYPE_UNKNOWN:
+     case TYPE_SOP1:
+     case TYPE_SOP2:
+     case TYPE_SOPK:
+     case TYPE_SOPC:
+     case TYPE_SOPP:
+     case TYPE_SMEM:
+     case TYPE_DS:
+     case TYPE_VOP2:
+     case TYPE_VOP1:
+     case TYPE_VOP3A:
+     case TYPE_VOP3B:
+     case TYPE_VOP_SDWA:
+     case TYPE_VOP_DPP:
+     case TYPE_MULT:
+     case TYPE_VMULT:
+       return false;
+     }
+   gcc_unreachable ();
+   return false;
+ }
+ 
  /* Identify VMEM instructions from their "type" attribute.  */
  
  static bool
*************** gcn_md_reorg (void)
*** 6124,6135 ****
       detects the missed cases, and inserts the documented number of NOPs
       required for correct execution.  */
  
    const int max_waits = 5;
    struct ilist
    {
      rtx_insn *insn;
      attr_unit unit;
!     attr_delayeduse delayeduse;
      HARD_REG_SET writes;
      HARD_REG_SET reads;
      int age;
--- 6188,6209 ----
       detects the missed cases, and inserts the documented number of NOPs
       required for correct execution.  */
  
+   /* RDNA4 (not yet implemented) differs from RNDA 2/3/3.5 and requires some
+      s_nop, see 5.7 and esp. 5.7.2. in its ISA manual.
+      The assert here is a reminder to add those.  */
+   STATIC_ASSERT (ISA_CDNA1 - ISA_RDNA3 == 1);
+ 
+   if (TARGET_NO_MANUAL_NOPS)
+     return;
+ 
    const int max_waits = 5;
    struct ilist
    {
      rtx_insn *insn;
      attr_unit unit;
!     attr_type type;
!     attr_flatmemaccess flatmemaccess;
!     bool delayeduse;
      HARD_REG_SET writes;
      HARD_REG_SET reads;
      int age;
*************** gcn_md_reorg (void)
*** 6150,6156 ****
  
        attr_type itype = get_attr_type (insn);
        attr_unit iunit = get_attr_unit (insn);
!       attr_delayeduse idelayeduse = get_attr_delayeduse (insn);
        int ivccwait = get_attr_vccwait (insn);
        HARD_REG_SET ireads, iwrites;
        CLEAR_HARD_REG_SET (ireads);
--- 6224,6252 ----
  
        attr_type itype = get_attr_type (insn);
        attr_unit iunit = get_attr_unit (insn);
!       attr_flatmemaccess iflatmemaccess = get_attr_flatmemaccess (insn);
!       bool delayeduse;
!       if (TARGET_CDNA3_NOPS)
! 	switch (iflatmemaccess)
! 	  {
! 	  case FLATMEMACCESS_STORE:
! 	  case FLATMEMACCESS_STOREX34:
! 	  case FLATMEMACCESS_ATOMIC:
! 	  case FLATMEMACCESS_CMPSWAPX2:
! 	    delayeduse = true;
! 	    break;
! 	  case FLATMEMACCESS_LOAD:
! 	  case FLATMEMACCESS_ATOMICWAIT:
! 	  case FLATMEMACCESS_NO:
! 	    delayeduse = false;
! 	    break;
! 	  default:
! 	    gcc_unreachable ();
! 	  }
!       else
! 	delayeduse = (iflatmemaccess == FLATMEMACCESS_CMPSWAPX2
! 		      || iflatmemaccess == FLATMEMACCESS_STOREX34);
! 
        int ivccwait = get_attr_vccwait (insn);
        HARD_REG_SET ireads, iwrites;
        CLEAR_HARD_REG_SET (ireads);
*************** gcn_md_reorg (void)
*** 6195,6210 ****
  		   && TEST_HARD_REG_BIT (ireads, VCCZ_REG))))
  	    nops_rqd = 5 - prev_insn->age;
  
! 	  /* VALU writes SGPR/VCC followed by v_{read,write}lane using
! 	     SGPR/VCC as lane select requires 4 wait states.  */
  	  if ((prev_insn->age + nops_rqd) < 4
  	      && prev_insn->unit == UNIT_VECTOR
! 	      && get_attr_laneselect (insn) == LANESELECT_YES
  	      && (hard_reg_set_intersect_p
  		    (depregs, reg_class_contents[(int) SGPR_REGS])
  		  || hard_reg_set_intersect_p
  		       (depregs, reg_class_contents[(int) VCC_CONDITIONAL_REG])))
  	    nops_rqd = 4 - prev_insn->age;
  
  	  /* VALU writes VGPR followed by VALU_DPP reading that VGPR
  	     requires 2 wait states.  */
--- 6291,6316 ----
  		   && TEST_HARD_REG_BIT (ireads, VCCZ_REG))))
  	    nops_rqd = 5 - prev_insn->age;
  
! 	  /* VALU writes SGPR/VCC followed by
! 	     - v_{read,write}lane using SGPR/VCC as lane select requires
! 	       4 wait states
! 	     - [CDNA3] VALU reads SGPR as constant requires 1 wait state
! 	     - [CDNA3] VALU reads SGPR as carry-in requires no wait states  */
  	  if ((prev_insn->age + nops_rqd) < 4
  	      && prev_insn->unit == UNIT_VECTOR
! 	      && get_attr_laneselect (insn) != LANESELECT_NO
  	      && (hard_reg_set_intersect_p
  		    (depregs, reg_class_contents[(int) SGPR_REGS])
  		  || hard_reg_set_intersect_p
  		       (depregs, reg_class_contents[(int) VCC_CONDITIONAL_REG])))
  	    nops_rqd = 4 - prev_insn->age;
+ 	  else if (TARGET_CDNA3_NOPS
+ 		   && (prev_insn->age + nops_rqd) < 1
+ 		   && prev_insn->unit == UNIT_VECTOR
+ 		   && iunit == UNIT_VECTOR
+ 		   && hard_reg_set_intersect_p
+ 			(depregs, reg_class_contents[(int) SGPR_REGS]))
+ 	    nops_rqd = 1 - prev_insn->age;
  
  	  /* VALU writes VGPR followed by VALU_DPP reading that VGPR
  	     requires 2 wait states.  */
*************** gcn_md_reorg (void)
*** 6217,6238 ****
  		nops_rqd = 2 - prev_insn->age;
  	    }
  
  	  /* Store that requires input registers are not overwritten by
! 	     following instruction.  */
! 	  if ((prev_insn->age + nops_rqd) < 1
! 	      && prev_insn->delayeduse == DELAYEDUSE_YES
  	      && ((hard_reg_set_intersect_p
  		   (prev_insn->reads, iwrites))))
  	    nops_rqd = 1 - prev_insn->age;
  
! 	  /* Instruction that requires VCC is not written too close before
! 	     using it.  */
  	  if (prev_insn->age < ivccwait
  	      && (hard_reg_set_intersect_p
  		  (prev_insn->writes,
  		   reg_class_contents[(int)VCC_CONDITIONAL_REG])))
  	    nops_rqd = ivccwait - prev_insn->age;
  
  	  /* CDNA1: write VGPR before v_accvgpr_write reads it.  */
  	  if (TARGET_AVGPR_CDNA1_NOPS
  	      && (prev_insn->age + nops_rqd) < 2
--- 6323,6410 ----
  		nops_rqd = 2 - prev_insn->age;
  	    }
  
+ 	  /* VALU writes EXEC followed by VALU DPP op requires 5 nop.  */
+ 	  if ((prev_insn->age + nops_rqd) < 5
+ 	      && itype == TYPE_VOP_DPP
+ 	      && prev_insn->unit == UNIT_VECTOR
+ 	      && TEST_HARD_REG_BIT (prev_insn->writes, EXECZ_REG))
+ 	    nops_rqd = 5 - prev_insn->age;
+ 
  	  /* Store that requires input registers are not overwritten by
! 	     following instruction.
! 	     For CDNA3, only, VALU writes require 2 not 1 nop.
! 	     CDNA3 additionally requires that 1 or 2 nop for global & scatch
! 	     store/atomic.  */
! 	  if (TARGET_CDNA3_NOPS
! 	      && (prev_insn->age + nops_rqd) < 2
! 	      && prev_insn->delayeduse
! 	      && iunit == UNIT_VECTOR
! 	      && ((hard_reg_set_intersect_p
! 		   (prev_insn->reads, iwrites))))
! 	    nops_rqd = 2 - prev_insn->age;
! 	  else if ((prev_insn->age + nops_rqd) < 1
! 	      && prev_insn->delayeduse
  	      && ((hard_reg_set_intersect_p
  		   (prev_insn->reads, iwrites))))
  	    nops_rqd = 1 - prev_insn->age;
  
! 	  /* Instruction (such as v_div_fmas) that requires VCC is not written
! 	     too close before using it  */
  	  if (prev_insn->age < ivccwait
  	      && (hard_reg_set_intersect_p
  		  (prev_insn->writes,
  		   reg_class_contents[(int)VCC_CONDITIONAL_REG])))
  	    nops_rqd = ivccwait - prev_insn->age;
  
+ 	  /* CDNA3: v_cmpx followed by
+ 	     - V_readlane, v_readfirstlane, v_writelane requires 4 wait states
+ 	     - VALU reads EXEC as constant requires 2 wait states
+ 	     - other VALU requires no wait state  */
+ 	  if (TARGET_CDNA3_NOPS
+ 	      && (prev_insn->age + nops_rqd) < 4
+ 	      && gcn_cmpx_insn_p (prev_insn->type)
+ 	      && get_attr_laneselect (insn) != LANESELECT_NO)
+ 	    nops_rqd = 4 - prev_insn->age;
+ 	  else if (TARGET_CDNA3_NOPS
+ 		   && (prev_insn->age + nops_rqd) < 2
+ 		   && iunit == UNIT_VECTOR
+ 		   && gcn_cmpx_insn_p (prev_insn->type)
+ 		   && TEST_HARD_REG_BIT (ireads, EXECZ_REG))
+ 	    nops_rqd = 2 - prev_insn->age;
+ 
+ 	  /* CDNA3: VALU writes VGPR followed by v_readlane vsrc0 reads VGPRn
+ 	     requires 1 wait state. */
+ 	  if (TARGET_CDNA3_NOPS
+ 	      && (prev_insn->age + nops_rqd) < 1
+ 	      && prev_insn->unit == UNIT_VECTOR
+ 	      && prev_insn->flatmemaccess != FLATMEMACCESS_LOAD
+ 	      && get_attr_laneselect (insn) == LANESELECT_READ
+ 	      && hard_reg_set_intersect_p
+ 		    (depregs, reg_class_contents[(int) VGPR_REGS]))
+ 	    nops_rqd = 1 - prev_insn->age;
+ 
+ 	  /* CDNA3: VALU op which uses OPSEL or SDWA with changes the result's
+ 	     bit position followed by VALU op consumes result of that op
+ 	     requires 1 wait state.
+ 	     FIXME: Handle OPSEL, once used.  */
+ 	  if (TARGET_CDNA3_NOPS
+ 	      && (prev_insn->age + nops_rqd) < 1
+ 	      && prev_insn->unit == UNIT_VECTOR
+ 	      && prev_insn->type == TYPE_VOP_SDWA
+ 	      && !hard_reg_set_empty_p (depregs))
+ 	    nops_rqd = 1 - prev_insn->age;
+ 
+ 	  /* CNDA3: VALU Trans Op (such as v_rcp_f64) followed by non-trans VALU
+ 	     op consumes result of that op requires 1 wait state.  */
+ 	  if (TARGET_CDNA3_NOPS
+ 	      && (prev_insn->age + nops_rqd) < 1
+ 	      && prev_insn->unit == UNIT_VECTOR
+ 	      && iunit == UNIT_VECTOR
+ 	      && get_attr_transop (prev_insn->insn) == TRANSOP_YES
+ 	      && get_attr_transop (insn) == TRANSOP_NO
+ 	      && !hard_reg_set_empty_p (depregs))
+ 	    nops_rqd = 1 - prev_insn->age;
+ 
  	  /* CDNA1: write VGPR before v_accvgpr_write reads it.  */
  	  if (TARGET_AVGPR_CDNA1_NOPS
  	      && (prev_insn->age + nops_rqd) < 2
*************** gcn_md_reorg (void)
*** 6288,6294 ****
        /* Track the current instruction as a previous instruction.  */
        back[oldest].insn = insn;
        back[oldest].unit = iunit;
!       back[oldest].delayeduse = idelayeduse;
        back[oldest].writes = iwrites;
        back[oldest].reads = ireads;
        back[oldest].age = 0;
--- 6460,6468 ----
        /* Track the current instruction as a previous instruction.  */
        back[oldest].insn = insn;
        back[oldest].unit = iunit;
!       back[oldest].type = itype;
!       back[oldest].flatmemaccess = iflatmemaccess;
!       back[oldest].delayeduse = delayeduse;
        back[oldest].writes = iwrites;
        back[oldest].reads = ireads;
        back[oldest].age = 0;
diff -Nrcpad gcc-16-20250720/gcc/config/gcn/gcn.md gcc-16-20250727/gcc/config/gcn/gcn.md
*** gcc-16-20250720/gcc/config/gcn/gcn.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/gcn/gcn.md	Sun Jul 27 22:32:08 2025
***************
*** 312,329 ****
  ; We need to be able to identify v_readlane and v_writelane with
  ; SGPR lane selection in order to handle "Manually Inserted Wait States".
  
! (define_attr "laneselect" "yes,no" (const_string "no"))
  
! ; Identify instructions that require a "Manually Inserted Wait State" if
! ; their inputs are overwritten by subsequent instructions.
  
! (define_attr "delayeduse" "yes,no" (const_string "no"))
  
  ; Identify instructions that require "Manually Inserted Wait State" if
  ; a previous instruction writes to VCC.  The number gives the number of NOPs.
  
  (define_attr "vccwait" "" (const_int 0))
  
  ;; }}}
  ;; {{{ Iterators useful across the wole machine description
  
--- 312,339 ----
  ; We need to be able to identify v_readlane and v_writelane with
  ; SGPR lane selection in order to handle "Manually Inserted Wait States".
  
! (define_attr "laneselect" "write,read,no" (const_string "no"))
  
! ; Global or flat memory access using store or load followed by waitcnt
! ; and using flat/global atomic access, possibly followed by a waitcnt.
! ; 'storex34' denotes FLAT_STORE_X{3,4}.
! ; 'cmpswapx2' denotes FLAT_ATOMIC_{F}CMPSWAP_X2
! ; Used to handle "Manually Inserted Wait State".
  
! (define_attr "flatmemaccess"
!              "store,storex34,load,atomic,atomicwait,cmpswapx2,no"
!              (const_string "no"))
  
  ; Identify instructions that require "Manually Inserted Wait State" if
  ; a previous instruction writes to VCC.  The number gives the number of NOPs.
  
  (define_attr "vccwait" "" (const_int 0))
  
+ ; Mark trans ops such as v_{exp,rsq,sqrt,sin,cos,log,...}_F{16,32,64}
+ ; for later conditional s_nop insertion.
+ 
+ (define_attr "transop" "yes,no" (const_string "no"))
+ 
  ;; }}}
  ;; {{{ Iterators useful across the wole machine description
  
***************
*** 555,563 ****
    }
    [(set_attr "type" "sop1,vop1,vop3a,sopk,vopc,mult,smem,smem,smem,flat,flat,
  		     flat,flat,flat,flat")
     (set_attr "exec" "*,*,none,*,*,*,*,*,*,*,*,*,*,*,*")
     (set_attr "length" "4,4,4,4,4,8,12,12,12,12,12,12,12,12,12")
!    (set_attr "xnack" "*,*,*,*,*,*,off,on,*,off,on,*,off,on,*")])
  
  ; 32bit move pattern
  
--- 565,575 ----
    }
    [(set_attr "type" "sop1,vop1,vop3a,sopk,vopc,mult,smem,smem,smem,flat,flat,
  		     flat,flat,flat,flat")
+    (set_attr "flatmemaccess" "*,*,*,*,*,*,*,*,*,load,load,store,load,load,store")
     (set_attr "exec" "*,*,none,*,*,*,*,*,*,*,*,*,*,*,*")
     (set_attr "length" "4,4,4,4,4,8,12,12,12,12,12,12,12,12,12")
!    (set_attr "xnack" "*,*,*,*,*,*,off,on,*,off,on,*,off,on,*")
!    (set_attr "laneselect" "*,*,read,*,*,*,*,*,*,*,*,*,*,*,*")])
  
  ; 32bit move pattern
  
***************
*** 565,602 ****
    [(set (match_operand:SISF 0 "nonimmediate_operand")
  	(match_operand:SISF 1 "gcn_load_operand"))]
    ""
!   {@ [cons: =0, 1; attrs: type, exec, length, cdna, xnack]
!    [SD  ,SSA ;sop1 ,*   ,4 ,*    ,*  ] s_mov_b32\t%0, %1
!    [SD  ,J   ;sopk ,*   ,4 ,*    ,*  ] s_movk_i32\t%0, %1
!    [SD  ,B   ;sop1 ,*   ,8 ,*    ,*  ] s_mov_b32\t%0, %1
!    [SD  ,RB  ;smem ,*   ,12,*    ,off] s_buffer_load%s0\t%0, s[0:3], %1\;s_waitcnt\tlgkmcnt(0)
!    [&SD ,RB  ;smem ,*   ,12,*    ,on ] ^
!    [RB  ,Sm  ;smem ,*   ,12,*    ,*  ] s_buffer_store%s1\t%1, s[0:3], %0
!    [Sm  ,RS  ;smem ,*   ,12,*    ,off] s_load_dword\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
!    [&Sm ,RS  ;smem ,*   ,12,*    ,on ] ^
!    [RS  ,Sm  ;smem ,*   ,12,*    ,*  ] s_store_dword\t%1, %A0
!    [v   ,v   ;vop1 ,*   ,4 ,*    ,*  ] v_mov_b32\t%0, %1
!    [Sg  ,v   ;vop3a,none,8 ,*    ,*  ] v_readlane_b32\t%0, %1, 0
!    [v   ,Sv  ;vop3a,none,8 ,*    ,*  ] v_writelane_b32\t%0, %1, 0
!    [v   ,^a  ;vop3p_mai,*,8,*    ,*  ] v_accvgpr_read_b32\t%0, %1
!    [a   ,v   ;vop3p_mai,*,8,*    ,*  ] v_accvgpr_write_b32\t%0, %1
!    [a   ,a   ;vop1 ,*    ,4,cdna2,*  ] v_accvgpr_mov_b32\t%0, %1
!    [v   ,RF  ;flat ,*   ,12,*    ,off] flat_load_dword\t%0, %A1%O1%g1\;s_waitcnt\t0
!    [&v  ,RF  ;flat ,*   ,12,*    ,on ] ^
!    [^a  ,RF  ;flat ,*   ,12,cdna2,off] ^
!    [&^a ,RF  ;flat ,*   ,12,cdna2,on ] ^
!    [RF  ,v   ;flat ,*   ,12,*    ,*  ] flat_store_dword\t%A0, %1%O0%g0
!    [RF  ,a   ;flat ,*   ,12,cdna2,*  ] ^
!    [v   ,B   ;vop1 ,*   ,8 ,*    ,*  ] v_mov_b32\t%0, %1
!    [RLRG,v   ;ds   ,*   ,12,*    ,*  ] ds_write_b32\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
!    [v   ,RLRG;ds   ,*   ,12,*    ,*  ] ds_read_b32\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
!    [SD  ,Y   ;sop1 ,*   ,8 ,*    ,*  ] s_mov_b32\t%0, %1
!    [v   ,RM  ;flat ,*   ,12,*    ,off] global_load_dword\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
!    [&v  ,RM  ;flat ,*   ,12,*    ,on ] ^
!    [^a  ,RM  ;flat ,*   ,12,cdna2,off] ^
!    [&^a ,RM  ;flat ,*   ,12,cdna2,on ] ^
!    [RM  ,v   ;flat ,*   ,12,*    ,*  ] global_store_dword\t%A0, %1%O0%g0
!    [RM  ,a   ;flat ,*   ,12,cdna2,*  ] ^
    })
  
  ; 8/16bit move pattern
--- 577,614 ----
    [(set (match_operand:SISF 0 "nonimmediate_operand")
  	(match_operand:SISF 1 "gcn_load_operand"))]
    ""
!   {@ [cons: =0, 1; attrs: type, exec, length, cdna, xnack, laneselect, flatmemaccess]
!    [SD  ,SSA ;sop1 ,*   ,4 ,*    ,*  ,*    ,*    ] s_mov_b32\t%0, %1
!    [SD  ,J   ;sopk ,*   ,4 ,*    ,*  ,*    ,*    ] s_movk_i32\t%0, %1
!    [SD  ,B   ;sop1 ,*   ,8 ,*    ,*  ,*    ,*    ] s_mov_b32\t%0, %1
!    [SD  ,RB  ;smem ,*   ,12,*    ,off,*    ,*    ] s_buffer_load%s0\t%0, s[0:3], %1\;s_waitcnt\tlgkmcnt(0)
!    [&SD ,RB  ;smem ,*   ,12,*    ,on ,*    ,*    ] ^
!    [RB  ,Sm  ;smem ,*   ,12,*    ,*  ,*    ,*    ] s_buffer_store%s1\t%1, s[0:3], %0
!    [Sm  ,RS  ;smem ,*   ,12,*    ,off,*    ,*    ] s_load_dword\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
!    [&Sm ,RS  ;smem ,*   ,12,*    ,on ,*    ,*    ] ^
!    [RS  ,Sm  ;smem ,*   ,12,*    ,*  ,*    ,*    ] s_store_dword\t%1, %A0
!    [v   ,v   ;vop1 ,*   ,4 ,*    ,*  ,*    ,*    ] v_mov_b32\t%0, %1
!    [Sg  ,v   ;vop3a,none,8 ,*    ,*  ,read ,*    ] v_readlane_b32\t%0, %1, 0
!    [v   ,Sv  ;vop3a,none,8 ,*    ,*  ,write,*    ] v_writelane_b32\t%0, %1, 0
!    [v   ,^a  ;vop3p_mai,*,8,*    ,*  ,*    ,*    ] v_accvgpr_read_b32\t%0, %1
!    [a   ,v   ;vop3p_mai,*,8,*    ,*  ,*    ,*    ] v_accvgpr_write_b32\t%0, %1
!    [a   ,a   ;vop1 ,*    ,4,cdna2,*  ,*    ,*    ] v_accvgpr_mov_b32\t%0, %1
!    [v   ,RF  ;flat ,*   ,12,*    ,off,*    ,load ] flat_load_dword\t%0, %A1%O1%g1\;s_waitcnt\t0
!    [&v  ,RF  ;flat ,*   ,12,*    ,on ,*    ,load ] ^
!    [^a  ,RF  ;flat ,*   ,12,cdna2,off,*    ,load ] ^
!    [&^a ,RF  ;flat ,*   ,12,cdna2,on ,*    ,load ] ^
!    [RF  ,v   ;flat ,*   ,12,*    ,*  ,*    ,store] flat_store_dword\t%A0, %1%O0%g0
!    [RF  ,a   ;flat ,*   ,12,cdna2,*  ,*    ,store] ^
!    [v   ,B   ;vop1 ,*   ,8 ,*    ,*  ,*    ,*    ] v_mov_b32\t%0, %1
!    [RLRG,v   ;ds   ,*   ,12,*    ,*  ,*    ,*    ] ds_write_b32\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
!    [v   ,RLRG;ds   ,*   ,12,*    ,*  ,*    ,*    ] ds_read_b32\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
!    [SD  ,Y   ;sop1 ,*   ,8 ,*    ,*  ,*    ,*    ] s_mov_b32\t%0, %1
!    [v   ,RM  ;flat ,*   ,12,*    ,off,*    ,load ] global_load_dword\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
!    [&v  ,RM  ;flat ,*   ,12,*    ,on ,*    ,load ] ^
!    [^a  ,RM  ;flat ,*   ,12,cdna2,off,*    ,load ] ^
!    [&^a ,RM  ;flat ,*   ,12,cdna2,on ,*    ,load ] ^
!    [RM  ,v   ;flat ,*   ,12,*    ,*  ,*    ,store] global_store_dword\t%A0, %1%O0%g0
!    [RM  ,a   ;flat ,*   ,12,cdna2,*  ,*    ,store] ^
    })
  
  ; 8/16bit move pattern
***************
*** 606,636 ****
    [(set (match_operand:QIHI 0 "nonimmediate_operand")
  	(match_operand:QIHI 1 "gcn_load_operand"))]
    "gcn_valid_move_p (<MODE>mode, operands[0], operands[1])"
!   {@ [cons: =0, 1; attrs: type, exec, length, cdna, xnack]
!   [SD  ,SSA ;sop1 ,*   ,4 ,*    ,*  ] s_mov_b32\t%0, %1
!   [SD  ,J   ;sopk ,*   ,4 ,*    ,*  ] s_movk_i32\t%0, %1
!   [SD  ,B   ;sop1 ,*   ,8 ,*    ,*  ] s_mov_b32\t%0, %1
!   [v   ,v   ;vop1 ,*   ,4 ,*    ,*  ] v_mov_b32\t%0, %1
!   [Sg  ,v   ;vop3a,none,4 ,*    ,*  ] v_readlane_b32\t%0, %1, 0
!   [v   ,Sv  ;vop3a,none,4 ,*    ,*  ] v_writelane_b32\t%0, %1, 0
!   [v   ,^a  ;vop3p_mai,*,8,*    ,*  ] v_accvgpr_read_b32\t%0, %1
!   [a   ,v   ;vop3p_mai,*,8,*    ,*  ] v_accvgpr_write_b32\t%0, %1
!   [a   ,a   ;vop1 ,*    ,8,cdna2,*  ] v_accvgpr_mov_b32\t%0, %1
!   [v   ,RF  ;flat ,*   ,12,*    ,off] flat_load%o1\t%0, %A1%O1%g1\;s_waitcnt\t0
!   [&v  ,RF  ;flat ,*   ,12,*    ,on ] ^
!   [^a  ,RF  ;flat ,*   ,12,cdna2,off] ^
!   [&^a ,RF  ;flat ,*   ,12,cdna2,on ] ^
!   [RF  ,v   ;flat ,*   ,12,*    ,*  ] flat_store%s0\t%A0, %1%O0%g0
!   [RF  ,a   ;flat ,*   ,12,cdna2,*  ] ^
!   [v   ,B   ;vop1 ,*   ,8 ,*    ,*  ] v_mov_b32\t%0, %1
!   [RLRG,v   ;ds   ,*   ,12,*    ,*  ] ds_write%b0\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
!   [v   ,RLRG;ds   ,*   ,12,*    ,*  ] ds_read%u1\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
!   [v   ,RM  ;flat ,*   ,12,*    ,off] global_load%o1\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
!   [&v  ,RM  ;flat ,*   ,12,*    ,on ] ^
!   [^a  ,RM  ;flat ,*   ,12,cdna2,off] ^
!   [&^a ,RM  ;flat ,*   ,12,cdna2,on ] ^
!   [RM  ,v   ;flat ,*   ,12,*    ,*  ] global_store%s0\t%A0, %1%O0%g0
!   [RM  ,a   ;flat ,*   ,12,cdna2,*  ] ^
    })
  
  ; 64bit move pattern
--- 618,648 ----
    [(set (match_operand:QIHI 0 "nonimmediate_operand")
  	(match_operand:QIHI 1 "gcn_load_operand"))]
    "gcn_valid_move_p (<MODE>mode, operands[0], operands[1])"
!   {@ [cons: =0, 1; attrs: type, exec, length, cdna, xnack, laneselect, flatmemaccess]
!   [SD  ,SSA ;sop1 ,*   ,4 ,*    ,*  ,*    ,*    ] s_mov_b32\t%0, %1
!   [SD  ,J   ;sopk ,*   ,4 ,*    ,*  ,*    ,*    ] s_movk_i32\t%0, %1
!   [SD  ,B   ;sop1 ,*   ,8 ,*    ,*  ,*    ,*    ] s_mov_b32\t%0, %1
!   [v   ,v   ;vop1 ,*   ,4 ,*    ,*  ,*    ,*    ] v_mov_b32\t%0, %1
!   [Sg  ,v   ;vop3a,none,4 ,*    ,*  ,read ,*    ] v_readlane_b32\t%0, %1, 0
!   [v   ,Sv  ;vop3a,none,4 ,*    ,*  ,write,*    ] v_writelane_b32\t%0, %1, 0
!   [v   ,^a  ;vop3p_mai,*,8,*    ,*  ,*    ,*    ] v_accvgpr_read_b32\t%0, %1
!   [a   ,v   ;vop3p_mai,*,8,*    ,*  ,*    ,*    ] v_accvgpr_write_b32\t%0, %1
!   [a   ,a   ;vop1 ,*    ,8,cdna2,*  ,*    ,*    ] v_accvgpr_mov_b32\t%0, %1
!   [v   ,RF  ;flat ,*   ,12,*    ,off,*    ,load ] flat_load%o1\t%0, %A1%O1%g1\;s_waitcnt\t0
!   [&v  ,RF  ;flat ,*   ,12,*    ,on ,*    ,load ] ^
!   [^a  ,RF  ;flat ,*   ,12,cdna2,off,*    ,load ] ^
!   [&^a ,RF  ;flat ,*   ,12,cdna2,on ,*    ,load ] ^
!   [RF  ,v   ;flat ,*   ,12,*    ,*  ,*    ,store] flat_store%s0\t%A0, %1%O0%g0
!   [RF  ,a   ;flat ,*   ,12,cdna2,*  ,*    ,store] ^
!   [v   ,B   ;vop1 ,*   ,8 ,*    ,*  ,*    ,*    ] v_mov_b32\t%0, %1
!   [RLRG,v   ;ds   ,*   ,12,*    ,*  ,*    ,*    ] ds_write%b0\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
!   [v   ,RLRG;ds   ,*   ,12,*    ,*  ,*    ,*    ] ds_read%u1\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
!   [v   ,RM  ;flat ,*   ,12,*    ,off,*    ,load ] global_load%o1\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
!   [&v  ,RM  ;flat ,*   ,12,*    ,on ,*    ,load ] ^
!   [^a  ,RM  ;flat ,*   ,12,cdna2,off,*    ,load ] ^
!   [&^a ,RM  ;flat ,*   ,12,cdna2,on ,*    ,load ] ^
!   [RM  ,v   ;flat ,*   ,12,*    ,*  ,*    ,store] global_store%s0\t%A0, %1%O0%g0
!   [RM  ,a   ;flat ,*   ,12,cdna2,*  ,*    ,store] ^
    })
  
  ; 64bit move pattern
***************
*** 639,672 ****
    [(set (match_operand:DIDF 0 "nonimmediate_operand")
  	(match_operand:DIDF 1 "general_operand"))]
    "GET_CODE(operands[1]) != SYMBOL_REF"
!   {@ [cons: =0, 1; attrs: type, length, cdna, xnack]
!   [SD  ,SSA ;sop1 ,4 ,*    ,*  ] s_mov_b64\t%0, %1
!   [SD  ,C   ;sop1 ,8 ,*    ,*  ] ^
!   [SD  ,DB  ;mult ,* ,*    ,*  ] #
!   [RS  ,Sm  ;smem ,12,*    ,*  ] s_store_dwordx2\t%1, %A0
!   [Sm  ,RS  ;smem ,12,*    ,off] s_load_dwordx2\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
!   [&Sm ,RS  ;smem ,12,*    ,on ] ^
!   [v   ,v   ;vmult,* ,*    ,*  ] #
!   [v   ,DB  ;vmult,* ,*    ,*  ] #
!   [Sg  ,v   ;vmult,* ,*    ,*  ] #
!   [v   ,Sv  ;vmult,* ,*    ,*  ] #
!   [v   ,^a  ;vmult,* ,*    ,*  ] #
!   [a   ,v   ;vmult,* ,*    ,*  ] #
!   [a   ,a   ;vmult,* ,cdna2,*  ] #
!   [v   ,RF  ;flat ,12,*    ,off] flat_load_dwordx2\t%0, %A1%O1%g1\;s_waitcnt\t0
!   [&v  ,RF  ;flat ,12,*    ,on ] ^
!   [^a  ,RF  ;flat ,12,cdna2,off] ^
!   [&^a ,RF  ;flat ,12,cdna2,on ] ^
!   [RF  ,v   ;flat ,12,*    ,*  ] flat_store_dwordx2\t%A0, %1%O0%g0
!   [RF  ,a   ;flat ,12,cdna2,*  ] ^
!   [RLRG,v   ;ds   ,12,*    ,*  ] ds_write_b64\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
!   [v   ,RLRG;ds   ,12,*    ,*  ] ds_read_b64\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
!   [v   ,RM  ;flat ,12,*    ,off] global_load_dwordx2\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
!   [&v  ,RM  ;flat ,12,*    ,on ] ^
!   [^a  ,RM  ;flat ,12,cdna2,off] ^
!   [&^a ,RM  ;flat ,12,cdna2,on ] ^
!   [RM  ,v   ;flat ,12,*    ,*  ] global_store_dwordx2\t%A0, %1%O0%g0
!   [RM  ,a   ;flat ,12,cdna2,*  ] ^
    }
    "reload_completed
     && ((!MEM_P (operands[0]) && !MEM_P (operands[1])
--- 651,684 ----
    [(set (match_operand:DIDF 0 "nonimmediate_operand")
  	(match_operand:DIDF 1 "general_operand"))]
    "GET_CODE(operands[1]) != SYMBOL_REF"
!   {@ [cons: =0, 1; attrs: type, length, cdna, xnack, flatmemaccess]
!   [SD  ,SSA ;sop1 ,4 ,*    ,*  ,*    ] s_mov_b64\t%0, %1
!   [SD  ,C   ;sop1 ,8 ,*    ,*  ,*    ] ^
!   [SD  ,DB  ;mult ,* ,*    ,*  ,*    ] #
!   [RS  ,Sm  ;smem ,12,*    ,*  ,*    ] s_store_dwordx2\t%1, %A0
!   [Sm  ,RS  ;smem ,12,*    ,off,*    ] s_load_dwordx2\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
!   [&Sm ,RS  ;smem ,12,*    ,on ,*    ] ^
!   [v   ,v   ;vmult,* ,*    ,*  ,*    ] #
!   [v   ,DB  ;vmult,* ,*    ,*  ,*    ] #
!   [Sg  ,v   ;vmult,* ,*    ,*  ,*    ] #
!   [v   ,Sv  ;vmult,* ,*    ,*  ,*    ] #
!   [v   ,^a  ;vmult,* ,*    ,*  ,*    ] #
!   [a   ,v   ;vmult,* ,*    ,*  ,*    ] #
!   [a   ,a   ;vmult,* ,cdna2,*  ,*    ] #
!   [v   ,RF  ;flat ,12,*    ,off,load ] flat_load_dwordx2\t%0, %A1%O1%g1\;s_waitcnt\t0
!   [&v  ,RF  ;flat ,12,*    ,on ,load ] ^
!   [^a  ,RF  ;flat ,12,cdna2,off,load ] ^
!   [&^a ,RF  ;flat ,12,cdna2,on ,load ] ^
!   [RF  ,v   ;flat ,12,*    ,*  ,store] flat_store_dwordx2\t%A0, %1%O0%g0
!   [RF  ,a   ;flat ,12,cdna2,*  ,store] ^
!   [RLRG,v   ;ds   ,12,*    ,*  ,*    ] ds_write_b64\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
!   [v   ,RLRG;ds   ,12,*    ,*  ,*    ] ds_read_b64\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
!   [v   ,RM  ;flat ,12,*    ,off,load ] global_load_dwordx2\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
!   [&v  ,RM  ;flat ,12,*    ,on ,load ] ^
!   [^a  ,RM  ;flat ,12,cdna2,off,load ] ^
!   [&^a ,RM  ;flat ,12,cdna2,on ,load ] ^
!   [RM  ,v   ;flat ,12,*    ,*  ,store] global_store_dwordx2\t%A0, %1%O0%g0
!   [RM  ,a   ;flat ,12,cdna2,*  ,store] ^
    }
    "reload_completed
     && ((!MEM_P (operands[0]) && !MEM_P (operands[1])
***************
*** 704,734 ****
    [(set (match_operand:TI 0 "nonimmediate_operand")
  	(match_operand:TI 1 "general_operand"  ))]
    ""
!   {@ [cons: =0, 1; attrs: type, delayeduse, length, cdna, xnack]
!   [SD ,SSB;mult ,*  ,* ,*    ,*  ] #
!   [RS ,Sm ;smem ,*  ,12,*    ,*  ] s_store_dwordx4\t%1, %A0
!   [Sm ,RS ;smem ,yes,12,*    ,off] s_load_dwordx4\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
!   [&Sm,RS ;smem ,yes,12,*    ,on ] ^
!   [RF ,v  ;flat ,*  ,12,*    ,*  ] flat_store_dwordx4\t%A0, %1%O0%g0
!   [RF ,a  ;flat ,*  ,12,cdna2,*  ] ^
!   [v  ,RF ;flat ,*  ,12,*    ,off] flat_load_dwordx4\t%0, %A1%O1%g1\;s_waitcnt\t0
!   [&v ,RF ;flat ,*  ,12,*    ,on ] ^
!   [^a ,RF ;flat ,*  ,12,cdna2,off] ^
!   [&^a,RF ;flat ,*  ,12,cdna2,on ] ^
!   [v  ,v  ;vmult,*  ,* ,*    ,*  ] #
!   [v  ,Sv ;vmult,*  ,* ,*    ,*  ] #
!   [SD ,v  ;vmult,*  ,* ,*    ,*  ] #
!   [RM ,v  ;flat ,yes,12,*    ,*  ] global_store_dwordx4\t%A0, %1%O0%g0
!   [RM ,a  ;flat ,yes,12,cdna2,*  ] ^
!   [v  ,RM ;flat ,*  ,12,*    ,off] global_load_dwordx4\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
!   [&v ,RM ;flat ,*  ,12,*    ,on ] ^
!   [^a ,RM ;flat ,*  ,12,cdna2,off] ^
!   [&^a,RM ;flat ,*  ,12,cdna2,on ] ^
!   [RL ,v  ;ds   ,*  ,12,*    ,*  ] ds_write_b128\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
!   [v  ,RL ;ds   ,*  ,12,*    ,*  ] ds_read_b128\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
!   [v  ,^a ;vmult,*  ,* ,*    ,*  ] #
!   [a  ,v  ;vmult,*  ,* ,*    ,*  ] #
!   [a  ,a  ;vmult,*  ,* ,cdna2,*  ] #
    }
    "reload_completed
     && REG_P (operands[0])
--- 716,746 ----
    [(set (match_operand:TI 0 "nonimmediate_operand")
  	(match_operand:TI 1 "general_operand"  ))]
    ""
!   {@ [cons: =0, 1; attrs: type, length, cdna, xnack, flatmemaccess]
!   [SD ,SSB;mult ,* ,*    ,*  ,*       ] #
!   [RS ,Sm ;smem ,12,*    ,*  ,*       ] s_store_dwordx4\t%1, %A0
!   [Sm ,RS ;smem ,12,*    ,off,*       ] s_load_dwordx4\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
!   [&Sm,RS ;smem ,12,*    ,on ,*       ] ^
!   [RF ,v  ;flat ,12,*    ,*  ,storex34] flat_store_dwordx4\t%A0, %1%O0%g0
!   [RF ,a  ;flat ,12,cdna2,*  ,storex34] ^
!   [v  ,RF ;flat ,12,*    ,off,load    ] flat_load_dwordx4\t%0, %A1%O1%g1\;s_waitcnt\t0
!   [&v ,RF ;flat ,12,*    ,on ,load    ] ^
!   [^a ,RF ;flat ,12,cdna2,off,load    ] ^
!   [&^a,RF ;flat ,12,cdna2,on ,load    ] ^
!   [v  ,v  ;vmult,* ,*    ,*  ,*       ] #
!   [v  ,Sv ;vmult,* ,*    ,*  ,*       ] #
!   [SD ,v  ;vmult,* ,*    ,*  ,*       ] #
!   [RM ,v  ;flat ,12,*    ,*  ,storex34] global_store_dwordx4\t%A0, %1%O0%g0
!   [RM ,a  ;flat ,12,cdna2,*  ,storex34] ^
!   [v  ,RM ;flat ,12,*    ,off,load    ] global_load_dwordx4\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
!   [&v ,RM ;flat ,12,*    ,on ,load    ] ^
!   [^a ,RM ;flat ,12,cdna2,off,load    ] ^
!   [&^a,RM ;flat ,12,cdna2,on ,load    ] ^
!   [RL ,v  ;ds   ,12,*    ,*  ,*       ] ds_write_b128\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
!   [v  ,RL ;ds   ,12,*    ,*  ,*       ] ds_read_b128\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
!   [v  ,^a ;vmult,* ,*    ,*  ,*       ] #
!   [a  ,v  ;vmult,* ,*    ,*  ,*       ] #
!   [a  ,a  ;vmult,* ,cdna2,*  ,*       ] #
    }
    "reload_completed
     && REG_P (operands[0])
***************
*** 1985,1990 ****
--- 1997,2003 ----
     flat_atomic_<bare_mnemonic><X>\t%0, %1, %2 %G2\;s_waitcnt\t0
     global_atomic_<bare_mnemonic><X>\t%0, %A1, %2%O1 %G2\;s_waitcnt\tvmcnt(0)"
    [(set_attr "type" "smem,flat,flat")
+    (set_attr "flatmemaccess" "*,atomicwait,atomicwait")
     (set_attr "length" "12")])
  
  ; FIXME: These patterns are disabled because the instructions don't
***************
*** 2006,2011 ****
--- 2019,2025 ----
     flat_atomic_<bare_mnemonic><X>\t%0, %1\;s_waitcnt\t0
     global_atomic_<bare_mnemonic><X>\t%A0, %1%O0\;s_waitcnt\tvmcnt(0)"
    [(set_attr "type" "smem,flat,flat")
+    (set_attr "flatmemaccess" "*,atomicwait,atomicwait")
     (set_attr "length" "12")])
  
  (define_mode_attr x2 [(SI "DI") (DI "TI")])
***************
*** 2053,2059 ****
     global_atomic_cmpswap<X>\t%0, %A1, %2%O1 %G2\;s_waitcnt\tvmcnt(0)"
    [(set_attr "type" "smem,flat,flat")
     (set_attr "length" "12")
!    (set_attr "delayeduse" "*,yes,yes")])
  
  (define_insn "sync_compare_and_swap<mode>_lds_insn"
    [(set (match_operand:SIDI 0 "register_operand"    "= v")
--- 2067,2073 ----
     global_atomic_cmpswap<X>\t%0, %A1, %2%O1 %G2\;s_waitcnt\tvmcnt(0)"
    [(set_attr "type" "smem,flat,flat")
     (set_attr "length" "12")
!    (set_attr "flatmemaccess" "*,cmpswapx2,cmpswapx2")])
  
  (define_insn "sync_compare_and_swap<mode>_lds_insn"
    [(set (match_operand:SIDI 0 "register_operand"    "= v")
***************
*** 2173,2178 ****
--- 2187,2193 ----
      gcc_unreachable ();
    }
    [(set_attr "type" "smem,flat,flat")
+    (set_attr "flatmemaccess" "*,load,load")
     (set_attr "length" "28")
     (set_attr "rdna" "no,*,*")])
  
***************
*** 2257,2262 ****
--- 2272,2278 ----
      gcc_unreachable ();
    }
    [(set_attr "type" "smem,flat,flat")
+    (set_attr "flatmemaccess" "*,store,store")
     (set_attr "length" "28")
     (set_attr "rdna" "no,*,*")])
  
***************
*** 2389,2394 ****
--- 2405,2411 ----
      gcc_unreachable ();
    }
    [(set_attr "type" "smem,flat,flat")
+    (set_attr "flatmemaccess" "*,atomicwait,atomicwait")
     (set_attr "length" "28")
     (set_attr "rdna" "no,*,*")])
  
diff -Nrcpad gcc-16-20250720/gcc/config/i386/i386-options.cc gcc-16-20250727/gcc/config/i386/i386-options.cc
*** gcc-16-20250720/gcc/config/i386/i386-options.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/i386/i386-options.cc	Sun Jul 27 22:32:08 2025
*************** ix86_valid_target_attribute_inner_p (tre
*** 1362,1368 ****
  	  arg_ok = opt_enum_arg_to_value (opt, p + opt_len, &value, CL_TARGET);
  	  if (arg_ok)
  	    set_option (opts, enum_opts_set, opt, value,
! 			p + opt_len, DK_UNSPECIFIED, input_location,
  			global_dc);
  	  else
  	    {
--- 1362,1370 ----
  	  arg_ok = opt_enum_arg_to_value (opt, p + opt_len, &value, CL_TARGET);
  	  if (arg_ok)
  	    set_option (opts, enum_opts_set, opt, value,
! 			p + opt_len,
! 			static_cast<int> (diagnostics::kind::unspecified),
! 			input_location,
  			global_dc);
  	  else
  	    {
diff -Nrcpad gcc-16-20250720/gcc/config/i386/i386.cc gcc-16-20250727/gcc/config/i386/i386.cc
*** gcc-16-20250720/gcc/config/i386/i386.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/i386/i386.cc	Sun Jul 27 22:32:08 2025
*************** static void map_egpr_constraints (vec<co
*** 24788,24793 ****
--- 24788,24799 ----
  	      buf.safe_push (cur[j + 1]);
  	      j++;
  	      break;
+ 	    case '{':
+ 	      do
+ 		{
+ 		  buf.safe_push (cur[j]);
+ 		} while (cur[j++] != '}');
+ 	      break;
  	    default:
  	      buf.safe_push (cur[j]);
  	      break;
diff -Nrcpad gcc-16-20250720/gcc/config/loongarch/loongarch.cc gcc-16-20250727/gcc/config/loongarch/loongarch.cc
*** gcc-16-20250720/gcc/config/loongarch/loongarch.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/loongarch/loongarch.cc	Sun Jul 27 22:32:08 2025
*************** static bool
*** 11052,11068 ****
  loongarch_builtin_support_vector_misalignment (machine_mode mode,
  					       const_tree type,
  					       int misalignment,
! 					       bool is_packed)
  {
    if ((ISA_HAS_LSX || ISA_HAS_LASX) && STRICT_ALIGNMENT)
      {
        if (optab_handler (movmisalign_optab, mode) == CODE_FOR_nothing)
  	return false;
        if (misalignment == -1)
  	return false;
      }
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed);
  }
  
  /* Return a PARALLEL containing NELTS elements, with element I equal
--- 11052,11072 ----
  loongarch_builtin_support_vector_misalignment (machine_mode mode,
  					       const_tree type,
  					       int misalignment,
! 					       bool is_packed,
! 					       bool is_gather_scatter)
  {
    if ((ISA_HAS_LSX || ISA_HAS_LASX) && STRICT_ALIGNMENT)
      {
+       if (is_gather_scatter)
+ 	return true;
        if (optab_handler (movmisalign_optab, mode) == CODE_FOR_nothing)
  	return false;
        if (misalignment == -1)
  	return false;
      }
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed,
! 						      is_gather_scatter);
  }
  
  /* Return a PARALLEL containing NELTS elements, with element I equal
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/autovec-opt.md gcc-16-20250727/gcc/config/riscv/autovec-opt.md
*** gcc-16-20250720/gcc/config/riscv/autovec-opt.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/autovec-opt.md	Sun Jul 27 22:32:08 2025
***************
*** 1714,1719 ****
--- 1714,1787 ----
    }
    [(set_attr "type" "vialu")])
  
+ (define_insn_and_split "*<sat_op_v_vdup>_vx_<mode>"
+  [(set (match_operand:V_VLSI   0 "register_operand")
+    (if_then_else:V_VLSI
+     (unspec:<VM>
+      [(match_operand:<VM>      1 "vector_mask_operand")
+       (match_operand           5 "vector_length_operand")
+       (match_operand           6 "const_int_operand")
+       (match_operand           7 "const_int_operand")
+       (match_operand           8 "const_int_operand")
+       (match_operand           9 "const_int_operand")
+       (reg:SI VL_REGNUM)
+       (reg:SI VTYPE_REGNUM)
+       (reg:SI VXRM_REGNUM)] UNSPEC_VPREDICATE)
+     (unspec:V_VLSI
+      [(match_operand:V_VLSI    3 "register_operand")
+       (vec_duplicate:V_VLSI
+        (match_operand:<VEL>    4 "reg_or_int_operand"))] VSAT_VX_OP_V_VDUP)
+     (unspec:V_VLSI
+      [(match_operand:DI        2 "register_operand")] UNSPEC_VUNDEF)))]
+   "TARGET_VECTOR && can_create_pseudo_p ()"
+   "#"
+   "&& 1"
+   [(const_int 0)]
+   {
+     int vxrm_val = INTVAL (operands[9]);
+     riscv_vector::expand_vx_binary_vxrm_vec_vec_dup (operands[0], operands[3],
+ 						     operands[4],
+ 						     <VSAT_VX_OP_V_VDUP>,
+ 						     vxrm_val, <MODE>mode);
+ 
+     DONE;
+   }
+   [(set_attr "type" "vaalu")])
+ 
+ (define_insn_and_split "*<sat_op_vdup_v>_vx_<mode>"
+  [(set (match_operand:V_VLSI   0 "register_operand")
+    (if_then_else:V_VLSI
+     (unspec:<VM>
+      [(match_operand:<VM>      1 "vector_mask_operand")
+       (match_operand           5 "vector_length_operand")
+       (match_operand           6 "const_int_operand")
+       (match_operand           7 "const_int_operand")
+       (match_operand           8 "const_int_operand")
+       (match_operand           9 "const_int_operand")
+       (reg:SI VL_REGNUM)
+       (reg:SI VTYPE_REGNUM)
+       (reg:SI VXRM_REGNUM)] UNSPEC_VPREDICATE)
+     (unspec:V_VLSI
+      [(vec_duplicate:V_VLSI
+        (match_operand:<VEL>    4 "reg_or_int_operand"))
+       (match_operand:V_VLSI    3 "register_operand")] VSAT_VX_OP_VDUP_V)
+     (unspec:V_VLSI
+      [(match_operand:DI        2 "register_operand")] UNSPEC_VUNDEF)))]
+   "TARGET_VECTOR && can_create_pseudo_p ()"
+   "#"
+   "&& 1"
+   [(const_int 0)]
+   {
+     int vxrm_val = INTVAL (operands[9]);
+     riscv_vector::expand_vx_binary_vxrm_vec_dup_vec (operands[0], operands[3],
+ 						     operands[4],
+ 						     <VSAT_VX_OP_VDUP_V>,
+ 						     vxrm_val, <MODE>mode);
+ 
+     DONE;
+   }
+   [(set_attr "type" "vaalu")])
+ 
  ;; =============================================================================
  ;; Combine vec_duplicate + op.vv to op.vf
  ;; Include
***************
*** 1838,1845 ****
      emit_insn (gen_extend<vsubel><vel>2(tmp, operands[1]));
  
      rtx ops[] = {operands[0], tmp};
!     riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (<MODE>mode),
!                                    riscv_vector::UNARY_OP, ops);
      DONE;
    }
    [(set_attr "type" "vfwmuladd")]
--- 1906,1912 ----
      emit_insn (gen_extend<vsubel><vel>2(tmp, operands[1]));
  
      rtx ops[] = {operands[0], tmp};
!     riscv_vector::expand_broadcast (<MODE>mode, ops);
      DONE;
    }
    [(set_attr "type" "vfwmuladd")]
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/autovec.md gcc-16-20250727/gcc/config/riscv/autovec.md
*** gcc-16-20250720/gcc/config/riscv/autovec.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/autovec.md	Sun Jul 27 22:32:08 2025
***************
*** 1359,1367 ****
    if (operands[2] == const0_rtx)
      {
        rtx ops[] = {operands[0], operands[0], operands[1]};
!       riscv_vector::emit_nonvlmax_insn (code_for_pred_broadcast (<MODE>mode),
! 					riscv_vector::SCALAR_MOVE_MERGED_OP_TU,
! 					ops, CONST1_RTX (Pmode));
      }
    else
      {
--- 1359,1365 ----
    if (operands[2] == const0_rtx)
      {
        rtx ops[] = {operands[0], operands[0], operands[1]};
!       riscv_vector::expand_set_first_tu (<MODE>mode, ops);
      }
    else
      {
***************
*** 1385,1392 ****
  	 VL we need for the slide.  */
        rtx tmp = gen_reg_rtx (<MODE>mode);
        rtx ops1[] = {tmp, operands[1]};
!       emit_nonvlmax_insn (code_for_pred_broadcast (<MODE>mode),
!                            riscv_vector::UNARY_OP, ops1, length);
  
        /* Slide exactly one element up leaving the tail elements
  	 unchanged.  */
--- 1383,1389 ----
  	 VL we need for the slide.  */
        rtx tmp = gen_reg_rtx (<MODE>mode);
        rtx ops1[] = {tmp, operands[1]};
!       riscv_vector::expand_broadcast (<MODE>mode, ops1, length);
  
        /* Slide exactly one element up leaving the tail elements
  	 unchanged.  */
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/generic-vector-ooo.md gcc-16-20250727/gcc/config/riscv/generic-vector-ooo.md
*** gcc-16-20250720/gcc/config/riscv/generic-vector-ooo.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/generic-vector-ooo.md	Sun Jul 27 22:32:08 2025
***************
*** 17,22 ****
--- 17,25 ----
  ;; <http://www.gnu.org/licenses/>.
  ;; Vector load/store
  
+ ;; The insn reservations include "generic" as we won't have a in-order
+ ;; generic definition for vector instructions.
+ 
  (define_automaton "vector_ooo")
  
  ;; Separate issue queue for vector instructions.
***************
*** 29,147 ****
  (define_cpu_unit "vxu_ooo_multicycle" "vector_ooo")
  
  (define_insn_reservation "vec_load" 6
!   (eq_attr "type" "vlde,vldm,vlds,vldux,vldox,vldff,vldr")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  (define_insn_reservation "vec_store" 6
!   (eq_attr "type" "vste,vstm,vsts,vstux,vstox,vstr")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector segment loads/stores.
  (define_insn_reservation "vec_loadstore_seg" 10
!   (eq_attr "type" "vlsegde,vlsegds,vlsegdux,vlsegdox,vlsegdff,\
! 		   vssegte,vssegts,vssegtux,vssegtox")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Regular vector operations and integer comparisons.
  (define_insn_reservation "vec_alu" 3
!   (eq_attr "type" "vialu,viwalu,vext,vicalu,vshift,vnshift,viminmax,vicmp,\
! 		   vimov,vsalu,vaalu,vsshift,vnclip,vmov,vfmov,vector,\
! 		   vandn,vbrev,vbrev8,vrev8,vclz,vctz,vrol,vror,vwsll")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector float comparison, conversion etc.
  (define_insn_reservation "vec_fcmp" 3
!   (eq_attr "type" "vfrecp,vfminmax,vfcmp,vfsgnj,vfclass,vfcvtitof,\
!                    vfcvtftoi,vfwcvtitof,vfwcvtftoi,vfwcvtftof,vfncvtitof,\
!                    vfncvtftoi,vfncvtftof,vfncvtbf16,vfwcvtbf16")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector integer multiplication.
  (define_insn_reservation "vec_imul" 4
!   (eq_attr "type" "vimul,viwmul,vimuladd,viwmuladd,vsmul,vclmul,vclmulh,\
!                    vghsh,vgmul")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector float addition.
  (define_insn_reservation "vec_fadd" 4
!   (eq_attr "type" "vfalu,vfwalu")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector float multiplication and FMA.
  (define_insn_reservation "vec_fmul" 6
!   (eq_attr "type" "vfmul,vfwmul,vfmuladd,vfwmuladd,vfwmaccbf16,sf_vqmacc,sf_vfnrclip")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector crypto, assumed to be a generic operation for now.
  (define_insn_reservation "vec_crypto" 4
!   (eq_attr "type" "crypto,vclz,vctz,vcpop")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector crypto, AES
  (define_insn_reservation "vec_crypto_aes" 4
!   (eq_attr "type" "vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector crypto, sha
  (define_insn_reservation "vec_crypto_sha" 4
!   (eq_attr "type" "vsha2ms,vsha2ch,vsha2cl")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector crypto, SM3/4
  (define_insn_reservation "vec_crypto_sm" 4
!   (eq_attr "type" "vsm4k,vsm4r,vsm3me,vsm3c")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector permute.
  (define_insn_reservation "vec_perm" 3
!   (eq_attr "type" "vimerge,vfmerge,vslideup,vslidedown,vislide1up,\
!                    vislide1down,vfslide1up,vfslide1down,vgather,vcompress")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector reduction.
  (define_insn_reservation "vec_reduction" 8
!   (eq_attr "type" "vired,viwred,vfredu,vfwredu")
    "vxu_ooo_issue,vxu_ooo_multicycle")
  
  ;; Vector ordered reduction, assume the latency number is for
  ;; a 128-bit vector.  It is scaled in riscv_sched_adjust_cost
  ;; for larger vectors.
  (define_insn_reservation "vec_ordered_reduction" 10
!   (eq_attr "type" "vfredo,vfwredo")
    "vxu_ooo_issue,vxu_ooo_multicycle*3")
  
  ;; Vector integer division, assume not pipelined.
  (define_insn_reservation "vec_idiv" 16
!   (eq_attr "type" "vidiv")
    "vxu_ooo_issue,vxu_ooo_multicycle*3")
  
  ;; Vector float divisions and sqrt, assume not pipelined.
  (define_insn_reservation "vec_float_divsqrt" 16
!   (eq_attr "type" "vfdiv,vfsqrt")
    "vxu_ooo_issue,vxu_ooo_multicycle*3")
  
  ;; Vector mask operations.
  (define_insn_reservation "vec_mask" 2
!   (eq_attr "type" "vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,\
!                    vfmovvf,vfmovfv")
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector vsetvl.
  (define_insn_reservation "vec_vesetvl" 1
!   (eq_attr "type" "vsetvl,vsetvl_pre")
    "vxu_ooo_issue")
  
  ;; Vector rounding mode setters, assume pipeline barrier.
  (define_insn_reservation "vec_setrm" 20
!   (eq_attr "type" "wrvxrm,wrfrm")
    "vxu_ooo_issue,vxu_ooo_issue*3")
  
  ;; Vector read vlen/vlenb.
  (define_insn_reservation "vec_readlen" 4
!   (eq_attr "type" "rdvlenb,rdvl")
    "vxu_ooo_issue,vxu_ooo_issue")
  
  ;; Vector sf_vcp.
  (define_insn_reservation "vec_sf_vcp" 2
!   (eq_attr "type" "sf_vc,sf_vc_se")
    "vxu_ooo_issue")
--- 32,172 ----
  (define_cpu_unit "vxu_ooo_multicycle" "vector_ooo")
  
  (define_insn_reservation "vec_load" 6
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vlde,vldm,vlds,vldux,vldox,vldff,vldr"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  (define_insn_reservation "vec_store" 6
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vste,vstm,vsts,vstux,vstox,vstr"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector segment loads/stores.
  (define_insn_reservation "vec_loadstore_seg" 10
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vlsegde,vlsegds,vlsegdux,vlsegdox,vlsegdff,\
! 		        vssegte,vssegts,vssegtux,vssegtox"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Regular vector operations and integer comparisons.
  (define_insn_reservation "vec_alu" 3
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vialu,viwalu,vext,vicalu,vshift,vnshift,viminmax,vicmp,\
! 		        vimov,vsalu,vaalu,vsshift,vnclip,vmov,vfmov,vector,\
! 		        vandn,vbrev,vbrev8,vrev8,vclz,vctz,vrol,vror,vwsll"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector float comparison, conversion etc.
  (define_insn_reservation "vec_fcmp" 3
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vfrecp,vfminmax,vfcmp,vfsgnj,vfclass,vfcvtitof,\
!                         vfcvtftoi,vfwcvtitof,vfwcvtftoi,vfwcvtftof,vfncvtitof,\
!                         vfncvtftoi,vfncvtftof,vfncvtbf16,vfwcvtbf16"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector integer multiplication.
  (define_insn_reservation "vec_imul" 4
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vimul,viwmul,vimuladd,viwmuladd,vsmul,vclmul,vclmulh,\
!                         vghsh,vgmul"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector float addition.
  (define_insn_reservation "vec_fadd" 4
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vfalu,vfwalu"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector float multiplication and FMA.
  (define_insn_reservation "vec_fmul" 6
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vfmul,vfwmul,vfmuladd,vfwmuladd,vfwmaccbf16,sf_vqmacc,sf_vfnrclip"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector crypto, assumed to be a generic operation for now.
  (define_insn_reservation "vec_crypto" 4
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "crypto,vclz,vctz,vcpop"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector crypto, AES
  (define_insn_reservation "vec_crypto_aes" 4
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector crypto, sha
  (define_insn_reservation "vec_crypto_sha" 4
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vsha2ms,vsha2ch,vsha2cl"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector crypto, SM3/4
  (define_insn_reservation "vec_crypto_sm" 4
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vsm4k,vsm4r,vsm3me,vsm3c"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector permute.
  (define_insn_reservation "vec_perm" 3
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vimerge,vfmerge,vslideup,vslidedown,vislide1up,\
!                         vislide1down,vfslide1up,vfslide1down,vgather,vcompress"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector reduction.
  (define_insn_reservation "vec_reduction" 8
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vired,viwred,vfredu,vfwredu"))
    "vxu_ooo_issue,vxu_ooo_multicycle")
  
  ;; Vector ordered reduction, assume the latency number is for
  ;; a 128-bit vector.  It is scaled in riscv_sched_adjust_cost
  ;; for larger vectors.
  (define_insn_reservation "vec_ordered_reduction" 10
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vfredo,vfwredo"))
    "vxu_ooo_issue,vxu_ooo_multicycle*3")
  
  ;; Vector integer division, assume not pipelined.
  (define_insn_reservation "vec_idiv" 16
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vidiv"))
    "vxu_ooo_issue,vxu_ooo_multicycle*3")
  
  ;; Vector float divisions and sqrt, assume not pipelined.
  (define_insn_reservation "vec_float_divsqrt" 16
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vfdiv,vfsqrt"))
    "vxu_ooo_issue,vxu_ooo_multicycle*3")
  
  ;; Vector mask operations.
  (define_insn_reservation "vec_mask" 2
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,\
!                         vfmovvf,vfmovfv"))
    "vxu_ooo_issue,vxu_ooo_alu")
  
  ;; Vector vsetvl.
  (define_insn_reservation "vec_vesetvl" 1
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "vsetvl,vsetvl_pre"))
    "vxu_ooo_issue")
  
  ;; Vector rounding mode setters, assume pipeline barrier.
  (define_insn_reservation "vec_setrm" 20
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "wrvxrm,wrfrm"))
    "vxu_ooo_issue,vxu_ooo_issue*3")
  
  ;; Vector read vlen/vlenb.
  (define_insn_reservation "vec_readlen" 4
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "rdvlenb,rdvl"))
    "vxu_ooo_issue,vxu_ooo_issue")
  
  ;; Vector sf_vcp.
  (define_insn_reservation "vec_sf_vcp" 2
!   (and (eq_attr "tune" "generic_ooo,generic")
!        (eq_attr "type" "sf_vc,sf_vc_se"))
    "vxu_ooo_issue")
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/mips-p8700.md gcc-16-20250727/gcc/config/riscv/mips-p8700.md
*** gcc-16-20250720/gcc/config/riscv/mips-p8700.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/mips-p8700.md	Sun Jul 27 22:32:08 2025
***************
*** 163,167 ****
     vgather,vcompress,vmov,vector,vandn,vbrev,vbrev8,vrev8,vclz,vctz,vcpop,vrol,vror,vwsll,
     vclmul,vclmulh,vghsh,vgmul,vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz,
     vsha2ms,vsha2ch,vsha2cl,vsm4k,vsm4r,vsm3me,vsm3c,vfncvtbf16,vfwcvtbf16,vfwmaccbf16,
!    sf_vc,sf_vc_se"))
    "mips_p8700_dummies")
--- 163,167 ----
     vgather,vcompress,vmov,vector,vandn,vbrev,vbrev8,vrev8,vclz,vctz,vcpop,vrol,vror,vwsll,
     vclmul,vclmulh,vghsh,vgmul,vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz,
     vsha2ms,vsha2ch,vsha2cl,vsm4k,vsm4r,vsm3me,vsm3c,vfncvtbf16,vfwcvtbf16,vfwmaccbf16,
!    sf_vc,sf_vc_se,ghost"))
    "mips_p8700_dummies")
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/predicates.md gcc-16-20250727/gcc/config/riscv/predicates.md
*** gcc-16-20250720/gcc/config/riscv/predicates.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/predicates.md	Sun Jul 27 22:32:08 2025
***************
*** 518,523 ****
--- 518,527 ----
  
  (define_predicate "vector_broadcast_mask_operand"
    (ior (match_operand 0 "vector_least_significant_set_mask_operand")
+        (match_operand 0 "vector_all_trues_mask_operand")))
+ 
+ (define_predicate "strided_broadcast_mask_operand"
+   (ior (match_operand 0 "vector_least_significant_set_mask_operand")
      (ior (match_operand 0 "register_operand")
           (match_operand 0 "vector_all_trues_mask_operand"))))
  
***************
*** 619,624 ****
--- 623,637 ----
  (define_predicate "direct_broadcast_operand"
    (match_test "riscv_vector::can_be_broadcast_p (op)"))
  
+ ;; A strided broadcast is just a fallback pattern that loads from
+ ;; memory.
+ (define_predicate "strided_broadcast_operand"
+   (match_test "riscv_vector::strided_broadcast_p (op)"))
+ 
+ (define_predicate "any_broadcast_operand"
+   (ior (match_operand 0 "direct_broadcast_operand")
+        (match_operand 0 "strided_broadcast_operand")))
+ 
  ;; A CONST_INT operand that has exactly two bits cleared.
  (define_predicate "const_nottwobits_operand"
    (and (match_code "const_int")
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv-ext.def gcc-16-20250727/gcc/config/riscv/riscv-ext.def
*** gcc-16-20250720/gcc/config/riscv/riscv-ext.def	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv-ext.def	Sun Jul 27 22:32:08 2025
*************** DEFINE_RISCV_EXT(
*** 80,87 ****
    /* DEP_EXTS */ ({}),
    /* SUPPORTED_VERSIONS */ ({{2, 0}}),
    /* FLAG_GROUP */ base,
!   /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
!   /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
--- 80,87 ----
    /* DEP_EXTS */ ({}),
    /* SUPPORTED_VERSIONS */ ({{2, 0}}),
    /* FLAG_GROUP */ base,
!   /* BITMASK_GROUP_ID */ 0,
!   /* BITMASK_BIT_POSITION*/ 4,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
*************** DEFINE_RISCV_EXT(
*** 190,197 ****
    /* DEP_EXTS */ ({"zba", "zbb", "zbs"}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ base,
!   /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
!   /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
    /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
  
  DEFINE_RISCV_EXT(
--- 190,197 ----
    /* DEP_EXTS */ ({"zba", "zbb", "zbs"}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ base,
!   /* BITMASK_GROUP_ID */ 0,
!   /* BITMASK_BIT_POSITION*/ 1,
    /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
  
  DEFINE_RISCV_EXT(
*************** DEFINE_RISCV_EXT(
*** 216,223 ****
    /* DEP_EXTS */ ({}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ base,
!   /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
!   /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
--- 216,223 ----
    /* DEP_EXTS */ ({}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ base,
!   /* BITMASK_GROUP_ID */ 0,
!   /* BITMASK_BIT_POSITION*/ 7,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
*************** DEFINE_RISCV_EXT(
*** 398,405 ****
    /* DEP_EXTS */ ({}),
    /* SUPPORTED_VERSIONS */ ({{2, 0}}),
    /* FLAG_GROUP */ zi,
!   /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
!   /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
--- 398,405 ----
    /* DEP_EXTS */ ({}),
    /* SUPPORTED_VERSIONS */ ({{2, 0}}),
    /* FLAG_GROUP */ zi,
!   /* BITMASK_GROUP_ID */ 1,
!   /* BITMASK_BIT_POSITION*/ 11,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
*************** DEFINE_RISCV_EXT(
*** 464,470 ****
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ zi,
    /* BITMASK_GROUP_ID */ 1,
!   /* BITMASK_BIT_POSITION*/ 1,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
--- 464,470 ----
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ zi,
    /* BITMASK_GROUP_ID */ 1,
!   /* BITMASK_BIT_POSITION*/ 8,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
*************** DEFINE_RISCV_EXT(
*** 476,483 ****
    /* DEP_EXTS */ ({}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ zm,
!   /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
!   /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
--- 476,483 ----
    /* DEP_EXTS */ ({}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ zm,
!   /* BITMASK_GROUP_ID */ 1,
!   /* BITMASK_BIT_POSITION*/ 12,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
*************** DEFINE_RISCV_EXT(
*** 787,794 ****
    /* DEP_EXTS */ ({"zca"}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ zc,
!   /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
!   /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
--- 787,794 ----
    /* DEP_EXTS */ ({"zca"}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ zc,
!   /* BITMASK_GROUP_ID */ 1,
!   /* BITMASK_BIT_POSITION*/ 10,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
*************** DEFINE_RISCV_EXT(
*** 813,820 ****
    /* DEP_EXTS */ ({"zca", "zilsd"}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ zc,
!   /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
!   /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
--- 813,820 ----
    /* DEP_EXTS */ ({"zca", "zilsd"}),
    /* SUPPORTED_VERSIONS */ ({{1, 0}}),
    /* FLAG_GROUP */ zc,
!   /* BITMASK_GROUP_ID */ 1,
!   /* BITMASK_BIT_POSITION*/ 9,
    /* EXTRA_EXTENSION_FLAGS */ 0)
  
  DEFINE_RISCV_EXT(
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv-protos.h gcc-16-20250727/gcc/config/riscv/riscv-protos.h
*** gcc-16-20250720/gcc/config/riscv/riscv-protos.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv-protos.h	Sun Jul 27 22:32:08 2025
*************** enum insn_flags : unsigned int
*** 414,421 ****
    /* Means INSN has VXRM operand and the value is VXRM_RNU.  */
    VXRM_RNU_P = 1 << 20,
  
    /* Means INSN has VXRM operand and the value is VXRM_RDN.  */
!   VXRM_RDN_P = 1 << 21,
  };
  
  enum insn_type : unsigned int
--- 414,427 ----
    /* Means INSN has VXRM operand and the value is VXRM_RNU.  */
    VXRM_RNU_P = 1 << 20,
  
+   /* Means INSN has VXRM operand and the value is VXRM_RNE.  */
+   VXRM_RNE_P = 1 << 21,
+ 
    /* Means INSN has VXRM operand and the value is VXRM_RDN.  */
!   VXRM_RDN_P = 1 << 22,
! 
!   /* Means INSN has VXRM operand and the value is VXRM_ROD.  */
!   VXRM_ROD_P = 1 << 23,
  };
  
  enum insn_type : unsigned int
*************** enum insn_type : unsigned int
*** 477,483 ****
--- 483,491 ----
    BINARY_OP_TUMA = __MASK_OP_TUMA | BINARY_OP_P,
    BINARY_OP_FRM_DYN = BINARY_OP | FRM_DYN_P,
    BINARY_OP_VXRM_RNU = BINARY_OP | VXRM_RNU_P,
+   BINARY_OP_VXRM_RNE = BINARY_OP | VXRM_RNE_P,
    BINARY_OP_VXRM_RDN = BINARY_OP | VXRM_RDN_P,
+   BINARY_OP_VXRM_ROD = BINARY_OP | VXRM_ROD_P,
  
    /* Ternary operator. Always have real merge operand.  */
    TERNARY_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
*************** void expand_vec_oct_sstrunc (rtx, rtx, m
*** 672,677 ****
--- 680,687 ----
  			     machine_mode);
  void expand_vx_binary_vec_dup_vec (rtx, rtx, rtx, rtx_code, machine_mode);
  void expand_vx_binary_vec_vec_dup (rtx, rtx, rtx, rtx_code, machine_mode);
+ void expand_vx_binary_vxrm_vec_vec_dup (rtx, rtx, rtx, int, int, machine_mode);
+ void expand_vx_binary_vxrm_vec_dup_vec (rtx, rtx, rtx, int, int, machine_mode);
  #endif
  bool sew64_scalar_helper (rtx *, rtx *, rtx, machine_mode,
  			  bool, void (*)(rtx *, rtx), enum avl_type);
*************** bool expand_block_move (rtx, rtx, rtx, b
*** 695,700 ****
--- 705,713 ----
  machine_mode preferred_simd_mode (scalar_mode);
  machine_mode get_mask_mode (machine_mode);
  void expand_vec_series (rtx, rtx, rtx, rtx = 0);
+ void expand_broadcast (machine_mode, rtx *, rtx = 0);
+ void expand_set_first (machine_mode, rtx *, rtx = 0);
+ void expand_set_first_tu (machine_mode, rtx *, rtx = 0);
  void expand_vec_init (rtx, rtx);
  void expand_vec_perm (rtx, rtx, rtx, rtx);
  void expand_select_vl (rtx *);
*************** enum vlmul_type get_vlmul (rtx_insn *);
*** 762,767 ****
--- 775,781 ----
  int count_regno_occurrences (rtx_insn *, unsigned int);
  bool imm_avl_p (machine_mode);
  bool can_be_broadcast_p (rtx);
+ bool strided_broadcast_p (rtx);
  bool gather_scatter_valid_offset_p (machine_mode);
  HOST_WIDE_INT estimated_poly_value (poly_int64, unsigned int);
  bool whole_reg_to_reg_move_p (rtx *, machine_mode, int);
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv-string.cc gcc-16-20250727/gcc/config/riscv/riscv-string.cc
*** gcc-16-20250720/gcc/config/riscv/riscv-string.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv-string.cc	Sun Jul 27 22:32:08 2025
*************** expand_vec_setmem (rtx dst_in, rtx lengt
*** 1625,1640 ****
       Otherwise, use a predicated store.  */
    if (known_eq (GET_MODE_SIZE (info.vmode), INTVAL (info.avl)))
      {
!       emit_vlmax_insn (code_for_pred_broadcast (info.vmode), UNARY_OP,
! 		       broadcast_ops);
        emit_move_insn (dst, fill_value);
      }
    else
      {
        if (!satisfies_constraint_vl (info.avl))
  	info.avl = force_reg (Pmode, info.avl);
!       emit_nonvlmax_insn (code_for_pred_broadcast (info.vmode),
! 			  riscv_vector::UNARY_OP, broadcast_ops, info.avl);
        machine_mode mask_mode
  	= riscv_vector::get_vector_mode (BImode, GET_MODE_NUNITS (info.vmode))
  	  .require ();
--- 1625,1638 ----
       Otherwise, use a predicated store.  */
    if (known_eq (GET_MODE_SIZE (info.vmode), INTVAL (info.avl)))
      {
!       riscv_vector::expand_broadcast (info.vmode, broadcast_ops);
        emit_move_insn (dst, fill_value);
      }
    else
      {
        if (!satisfies_constraint_vl (info.avl))
  	info.avl = force_reg (Pmode, info.avl);
!       riscv_vector::expand_broadcast (info.vmode, broadcast_ops, info.avl);
        machine_mode mask_mode
  	= riscv_vector::get_vector_mode (BImode, GET_MODE_NUNITS (info.vmode))
  	  .require ();
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv-v.cc gcc-16-20250727/gcc/config/riscv/riscv-v.cc
*** gcc-16-20250720/gcc/config/riscv/riscv-v.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv-v.cc	Sun Jul 27 22:32:08 2025
*************** public:
*** 351,359 ****
        add_rounding_mode_operand (FRM_RNE);
      else if (m_insn_flags & VXRM_RNU_P)
        add_rounding_mode_operand (VXRM_RNU);
      else if (m_insn_flags & VXRM_RDN_P)
        add_rounding_mode_operand (VXRM_RDN);
! 
  
      if (insn_data[(int) icode].n_operands != m_opno)
        internal_error ("invalid number of operands for insn %s, "
--- 351,362 ----
        add_rounding_mode_operand (FRM_RNE);
      else if (m_insn_flags & VXRM_RNU_P)
        add_rounding_mode_operand (VXRM_RNU);
+     else if (m_insn_flags & VXRM_RNE_P)
+       add_rounding_mode_operand (VXRM_RNE);
      else if (m_insn_flags & VXRM_RDN_P)
        add_rounding_mode_operand (VXRM_RDN);
!     else if (m_insn_flags & VXRM_ROD_P)
!       add_rounding_mode_operand (VXRM_ROD);
  
      if (insn_data[(int) icode].n_operands != m_opno)
        internal_error ("invalid number of operands for insn %s, "
*************** expand_vector_init_trailing_same_elem (r
*** 1190,1195 ****
--- 1193,1251 ----
    return false;
  }
  
+ /* Helper function to emit a vmv.vx/vi and float variants.
+    If VL is not given a VLMAX insn will be emitted, otherwise
+    a non-VLMAX insn with length VL.
+    If the value to be broadcast is not suitable for vmv.vx
+    fall back to a vlse with zero stride.  This itself has a
+    fallback if the uarch prefers not to use a strided load
+    for broadcast.  */
+ 
+ void
+ expand_broadcast (machine_mode mode, rtx *ops, rtx vl)
+ {
+   rtx elt = ops[1];
+   avl_type type = vl ? NONVLMAX : VLMAX;
+   if (can_be_broadcast_p (elt))
+     emit_avltype_insn (code_for_pred_broadcast (mode), UNARY_OP, ops,
+ 		       type, vl);
+   else
+     emit_avltype_insn (code_for_pred_strided_broadcast (mode),
+ 		       UNARY_OP, ops, type, vl);
+ }
+ 
+ /* Similar to expand_broadcast but emits a vmv.s.x/vfmv.s.f instead.  */
+ 
+ void
+ expand_set_first (machine_mode mode, rtx *ops, rtx vl)
+ {
+   rtx elt = ops[1];
+   avl_type type = vl ? NONVLMAX : VLMAX;
+   if (can_be_broadcast_p (elt))
+     emit_avltype_insn (code_for_pred_broadcast (mode),
+ 			SCALAR_MOVE_OP, ops, type, vl);
+   else
+     emit_avltype_insn (code_for_pred_strided_broadcast (mode),
+ 			SCALAR_MOVE_OP, ops, type, vl);
+ }
+ 
+ /* Similar to expand_set_first but keeping the tail elements
+    unchanged (TU) */
+ 
+ void
+ expand_set_first_tu (machine_mode mode, rtx *ops, rtx vl)
+ {
+   rtx elt = ops[2];
+   if (!vl)
+     vl = const1_rtx;
+   if (can_be_broadcast_p (elt))
+     emit_nonvlmax_insn (code_for_pred_broadcast (mode),
+ 			SCALAR_MOVE_MERGED_OP_TU, ops, vl);
+   else
+     emit_nonvlmax_insn (code_for_pred_strided_broadcast (mode),
+ 			SCALAR_MOVE_MERGED_OP_TU, ops, vl);
+ }
+ 
  static void
  expand_const_vec_duplicate (rtx target, rtx src, rtx elt)
  {
*************** expand_const_vec_duplicate (rtx target,
*** 1226,1232 ****
        if (lra_in_progress)
  	{
  	  rtx ops[] = {result, elt};
! 	  emit_vlmax_insn (code_for_pred_broadcast (mode), UNARY_OP, ops);
  	}
        else
  	{
--- 1282,1288 ----
        if (lra_in_progress)
  	{
  	  rtx ops[] = {result, elt};
! 	  expand_broadcast (mode, ops);
  	}
        else
  	{
*************** expand_const_vector_duplicate_repeating
*** 1278,1285 ****
      {
        dup = gen_reg_rtx (builder->new_mode ());
        rtx ops[] = {dup, ele};
!       emit_vlmax_insn (code_for_pred_broadcast (builder->new_mode ()),
! 		       UNARY_OP, ops);
      }
    else
      dup = expand_vector_broadcast (builder->new_mode (), ele);
--- 1334,1340 ----
      {
        dup = gen_reg_rtx (builder->new_mode ());
        rtx ops[] = {dup, ele};
!       expand_broadcast (builder->new_mode (), ops);
      }
    else
      dup = expand_vector_broadcast (builder->new_mode (), ele);
*************** expand_const_vector_duplicate_default (r
*** 1322,1329 ****
  
    rtx tmp1 = gen_reg_rtx (builder->mode ());
    rtx dup_ops[] = {tmp1, builder->elt (0)};
!   emit_vlmax_insn (code_for_pred_broadcast (builder->mode ()), UNARY_OP,
! 		   dup_ops);
  
    for (unsigned int i = 1; i < builder->npatterns (); i++)
      {
--- 1377,1383 ----
  
    rtx tmp1 = gen_reg_rtx (builder->mode ());
    rtx dup_ops[] = {tmp1, builder->elt (0)};
!   expand_broadcast (builder->mode (), dup_ops);
  
    for (unsigned int i = 1; i < builder->npatterns (); i++)
      {
*************** has_vi_variant_p (rtx_code code, rtx x)
*** 2136,2153 ****
--- 2190,2221 ----
      }
  }
  
+ /* This is a helper for binary ops with DImode scalar operands that are
+    broadcast (like vadd.vx v1, a1).
+    Instead of having similar code for all the expanders this function
+    unifies the handling.  For 64-bit targets all we do is choose
+    between the vi variant (if available) and the register variant.
+    For 32-bit targets we either create the sign-extending variant
+    of vop.vx (when the immediate fits 32 bits) or emit a vector
+    broadcast of the 64-bit register/immediate and switch to a
+    vop.vv (replacing the scalar op with the broadcast vector.  */
+ 
  bool
  sew64_scalar_helper (rtx *operands, rtx *scalar_op, rtx vl,
  		     machine_mode vector_mode, bool has_vi_variant_p,
  		     void (*emit_vector_func) (rtx *, rtx), enum avl_type type)
  {
    machine_mode scalar_mode = GET_MODE_INNER (vector_mode);
+ 
+   /* If the scalar broadcast op fits an immediate, use the
+      vop.vi variant if there is one.  */
    if (has_vi_variant_p)
      {
        *scalar_op = force_reg (scalar_mode, *scalar_op);
        return false;
      }
  
+   /* On a 64-bit target we can always use the vop.vx variant.  */
    if (TARGET_64BIT)
      {
        if (!rtx_equal_p (*scalar_op, const0_rtx))
*************** sew64_scalar_helper (rtx *operands, rtx
*** 2155,2160 ****
--- 2223,2230 ----
        return false;
      }
  
+   /* For 32 bit and if there is no vop.vi variant for a 32-bit immediate
+      we need to use the sign-extending (SI -> DI) vop.vx variants.  */
    if (immediate_operand (*scalar_op, Pmode))
      {
        if (!rtx_equal_p (*scalar_op, const0_rtx))
*************** sew64_scalar_helper (rtx *operands, rtx
*** 2164,2203 ****
        return false;
      }
  
!   bool avoid_strided_broadcast = false;
    if (CONST_INT_P (*scalar_op))
      {
        if (maybe_gt (GET_MODE_SIZE (scalar_mode), GET_MODE_SIZE (Pmode)))
! 	{
! 	  if (strided_load_broadcast_p ())
! 	    *scalar_op = force_const_mem (scalar_mode, *scalar_op);
! 	  else
! 	    avoid_strided_broadcast = true;
! 	}
        else
  	*scalar_op = force_reg (scalar_mode, *scalar_op);
      }
  
    rtx tmp = gen_reg_rtx (vector_mode);
!   if (!avoid_strided_broadcast)
!     {
!       rtx ops[] = {tmp, *scalar_op};
!       emit_avltype_insn (code_for_pred_broadcast (vector_mode), UNARY_OP, ops,
! 			 type, vl);
!     }
!   else
!     {
!       /* Load scalar as V1DI and broadcast via vrgather.vi.  */
!       rtx tmp1 = gen_reg_rtx (V1DImode);
!       emit_move_insn (tmp1, lowpart_subreg (V1DImode, *scalar_op,
! 					    scalar_mode));
!       tmp1 = lowpart_subreg (vector_mode, tmp1, V1DImode);
! 
!       rtx ops[] = {tmp, tmp1, CONST0_RTX (Pmode)};
!       emit_vlmax_insn (code_for_pred_gather_scalar (vector_mode),
! 		       BINARY_OP, ops);
!     }
! 
    emit_vector_func (operands, tmp);
  
    return true;
--- 2234,2262 ----
        return false;
      }
  
!   /* Now we're left with a 64-bit immediate or a register.
!      We cannot use a vop.vx variant but must broadcast the value first
!      and switch to a vop.vv variant.
!      Broadcast can either be done via vlse64.v v1, reg, zero
!      or by loading one 64-bit element (vle64.v) and using a
!      broadcast vrgather.vi.  This is decided when splitting
!      the strided broadcast insn.  */
!   gcc_assert (!TARGET_64BIT
! 	      && (CONST_INT_P (*scalar_op)
! 		  || register_operand (*scalar_op, scalar_mode)));
! 
    if (CONST_INT_P (*scalar_op))
      {
        if (maybe_gt (GET_MODE_SIZE (scalar_mode), GET_MODE_SIZE (Pmode)))
! 	*scalar_op = force_const_mem (scalar_mode, *scalar_op);
        else
  	*scalar_op = force_reg (scalar_mode, *scalar_op);
      }
  
    rtx tmp = gen_reg_rtx (vector_mode);
!   rtx ops[] = {tmp, *scalar_op};
!   emit_avltype_insn (code_for_pred_strided_broadcast (vector_mode),
! 		     UNARY_OP, ops, type, vl);
    emit_vector_func (operands, tmp);
  
    return true;
*************** expand_vector_init_merge_repeating_seque
*** 2591,2598 ****
  
    /* Step 1: Broadcast the first pattern.  */
    rtx ops[] = {target, force_reg (builder.inner_mode (), builder.elt (0))};
!   emit_vlmax_insn (code_for_pred_broadcast (builder.mode ()),
! 		    UNARY_OP, ops);
    /* Step 2: Merge the rest iteration of pattern.  */
    for (unsigned int i = 1; i < builder.npatterns (); i++)
      {
--- 2650,2656 ----
  
    /* Step 1: Broadcast the first pattern.  */
    rtx ops[] = {target, force_reg (builder.inner_mode (), builder.elt (0))};
!   expand_broadcast (builder.mode (), ops);
    /* Step 2: Merge the rest iteration of pattern.  */
    for (unsigned int i = 1; i < builder.npatterns (); i++)
      {
*************** expand_vector_init_merge_repeating_seque
*** 2605,2612 ****
        if (full_nelts <= builder.inner_bits_size ()) /* vmv.s.x.  */
  	{
  	  rtx ops[] = {dup, merge_mask};
! 	  emit_nonvlmax_insn (code_for_pred_broadcast (GET_MODE (dup)),
! 			       SCALAR_MOVE_OP, ops, CONST1_RTX (Pmode));
  	}
        else /* vmv.v.x.  */
  	{
--- 2663,2669 ----
        if (full_nelts <= builder.inner_bits_size ()) /* vmv.s.x.  */
  	{
  	  rtx ops[] = {dup, merge_mask};
! 	  expand_set_first (GET_MODE (dup), ops);
  	}
        else /* vmv.v.x.  */
  	{
*************** expand_vector_init_merge_repeating_seque
*** 2614,2621 ****
  		       force_reg (GET_MODE_INNER (mask_int_mode), merge_mask)};
  	  rtx vl = gen_int_mode (CEIL (full_nelts, builder.inner_bits_size ()),
  				 Pmode);
! 	  emit_nonvlmax_insn (code_for_pred_broadcast (mask_int_mode), UNARY_OP,
! 			       ops, vl);
  	}
  
        emit_move_insn (mask, gen_lowpart (mask_bit_mode, dup));
--- 2671,2677 ----
  		       force_reg (GET_MODE_INNER (mask_int_mode), merge_mask)};
  	  rtx vl = gen_int_mode (CEIL (full_nelts, builder.inner_bits_size ()),
  				 Pmode);
! 	  expand_broadcast (mask_int_mode, ops, vl);
  	}
  
        emit_move_insn (mask, gen_lowpart (mask_bit_mode, dup));
*************** expand_reduction (unsigned unspec, unsig
*** 4706,4725 ****
  
    rtx m1_tmp = gen_reg_rtx (m1_mode);
    rtx scalar_move_ops[] = {m1_tmp, init};
-   insn_code icode = code_for_pred_broadcast (m1_mode);
    if (need_mask_operand_p (insn_flags))
      {
        if (need_vl0_safe)
! 	emit_nonvlmax_insn (icode, SCALAR_MOVE_OP, scalar_move_ops, const1_rtx);
        else
! 	emit_nonvlmax_insn (icode, SCALAR_MOVE_OP, scalar_move_ops, vl_op);
      }
    else
!     emit_vlmax_insn (icode, SCALAR_MOVE_OP, scalar_move_ops);
  
    rtx m1_tmp2 = gen_reg_rtx (m1_mode);
    rtx reduc_ops[] = {m1_tmp2, vector_src, m1_tmp};
  
    if (need_vl0_safe)
      icode = code_for_pred (unspec_for_vl0_safe, vmode);
    else
--- 4762,4781 ----
  
    rtx m1_tmp = gen_reg_rtx (m1_mode);
    rtx scalar_move_ops[] = {m1_tmp, init};
    if (need_mask_operand_p (insn_flags))
      {
        if (need_vl0_safe)
! 	expand_set_first (m1_mode, scalar_move_ops, const1_rtx);
        else
! 	expand_set_first (m1_mode, scalar_move_ops, vl_op);
      }
    else
!     expand_set_first (m1_mode, scalar_move_ops);
  
    rtx m1_tmp2 = gen_reg_rtx (m1_mode);
    rtx reduc_ops[] = {m1_tmp2, vector_src, m1_tmp};
  
+   insn_code icode;
    if (need_vl0_safe)
      icode = code_for_pred (unspec_for_vl0_safe, vmode);
    else
*************** expand_vx_binary_vec_dup_vec (rtx op_0,
*** 5597,5602 ****
--- 5653,5734 ----
    emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
  }
  
+ static enum insn_type
+ get_insn_type_by_vxrm_val (int vxrm_val)
+ {
+   enum insn_type itype;
+ 
+   switch (vxrm_val)
+     {
+     case VXRM_RNU:
+       itype = BINARY_OP_VXRM_RNU;
+       break;
+     case VXRM_RNE:
+       itype = BINARY_OP_VXRM_RNE;
+       break;
+     case VXRM_RDN:
+       itype = BINARY_OP_VXRM_RDN;
+       break;
+     case VXRM_ROD:
+       itype = BINARY_OP_VXRM_ROD;
+       break;
+     default:
+       gcc_unreachable ();
+     }
+ 
+   return itype;
+ }
+ 
+ /* Expand the binary vx combine with the format like v2 = vop(v1, vec_dup(x))
+    and its' vxrm value.  Aka the second op comes from the vec_duplicate,
+    and the first op is the vector reg.  */
+ 
+ void
+ expand_vx_binary_vxrm_vec_vec_dup (rtx op_0, rtx op_1, rtx op_2, int unspec,
+ 				   int vxrm_val, machine_mode mode)
+ {
+   enum insn_code icode;
+   enum insn_type itype = get_insn_type_by_vxrm_val (vxrm_val);
+   rtx ops[] = {op_0, op_1, op_2};
+ 
+   switch (unspec)
+     {
+     case UNSPEC_VAADD:
+     case UNSPEC_VAADDU:
+       icode = code_for_pred_scalar (unspec, mode);
+       break;
+     default:
+       gcc_unreachable ();
+     }
+ 
+   emit_vlmax_insn (icode, itype, ops);
+ }
+ 
+ /* Expand the binary vx combine with the format like v2 = vop(vec_dup(x), v1)
+    and its' vxrm value.  Aka the second op comes from the vec_duplicate,
+    and the first op is the vector reg.  */
+ 
+ void
+ expand_vx_binary_vxrm_vec_dup_vec (rtx op_0, rtx op_1, rtx op_2, int unspec,
+ 				   int vxrm_val, machine_mode mode)
+ {
+   enum insn_code icode;
+   enum insn_type itype = get_insn_type_by_vxrm_val (vxrm_val);
+   rtx ops[] = {op_0, op_1, op_2};
+ 
+   switch (unspec)
+     {
+     case UNSPEC_VAADD:
+     case UNSPEC_VAADDU:
+       icode = code_for_pred_scalar (unspec, mode);
+       break;
+     default:
+       gcc_unreachable ();
+     }
+ 
+   emit_vlmax_insn (icode, itype, ops);
+ }
+ 
  /* Expand the binary vx combine with the format like v2 = vop(v1, vec_dup(x)).
     Aka the second op comes from the vec_duplicate, and the first op is
     the vector reg.  */
*************** count_regno_occurrences (rtx_insn *rinsn
*** 5808,5832 ****
    return count;
  }
  
! /* Return true if the OP can be directly broadcast.  */
  bool
  can_be_broadcast_p (rtx op)
  {
    machine_mode mode = GET_MODE (op);
!   /* We don't allow RA (register allocation) reload generate
!     (vec_duplicate:DI reg) in RV32 system wheras we allow
!     (vec_duplicate:DI mem) in RV32 system.  */
!   if (!can_create_pseudo_p () && !FLOAT_MODE_P (mode)
!       && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (Pmode))
!       && !satisfies_constraint_Wdm (op))
      return false;
  
!   if (satisfies_constraint_K (op) || register_operand (op, mode)
!       || (strided_load_broadcast_p () && satisfies_constraint_Wdm (op))
!       || rtx_equal_p (op, CONST0_RTX (mode)))
      return true;
  
!   return can_create_pseudo_p () && nonmemory_operand (op, mode);
  }
  
  void
--- 5940,6023 ----
    return count;
  }
  
! /* Return true if the OP can be broadcast with a
!    v[f]mv.v.[xif] instruction.  */
! 
  bool
  can_be_broadcast_p (rtx op)
  {
    machine_mode mode = GET_MODE (op);
! 
!   /* Zero always works and we can always put an immediate into a
!      register.
!      What's tricky is that for an immediate we don't know the
!      register's mode it will end up in, i.e. what element size
!      we want to broadcast.  So even if the immediate is small it might
!      still end up in a DImode register that we cannot broadcast.
!      vmv.s.x, i.e. a single-element set can handle this, though,
!      because it implicitly sign-extends to SEW.  */
!   if (rtx_equal_p (op, CONST0_RTX (mode))
!       || const_int_operand (op, Xmode))
!     return true;
! 
!   /* Do not accept DImode broadcasts on !TARGET_64BIT.  Those
!      are handled by strided broadcast.  */
!   if (INTEGRAL_MODE_P (mode)
!       && maybe_gt (GET_MODE_SIZE (mode), UNITS_PER_WORD))
      return false;
  
!   /* Non-register operands that can be forced into a register we can
!      handle.  These don't need to use strided broadcast. */
!   if (INTEGRAL_MODE_P (mode)
!       && (memory_operand (op, mode) || CONST_POLY_INT_P (op))
!       && can_create_pseudo_p ())
      return true;
  
!   /* Likewise, do not accept HFmode broadcast if we don't have
!      vfmv.v.f for 16-bit registers available.  */
!   if (mode == HFmode && !TARGET_ZVFH)
!     return false;
! 
!   /* Same for float, just that we can always handle 64-bit doubles
!      even on !TARGET_64BIT.  We have ruled out 16-bit HF already
!      above.  */
!   if (FLOAT_MODE_P (mode)
!       && (memory_operand (op, mode) || CONSTANT_P (op))
!       && can_create_pseudo_p ())
!     return true;
! 
!   /* After excluding all the cases we cannot handle the register types
!      that remain can always be broadcast.  */
!   if (register_operand (op, mode))
!     return true;
! 
!   return false;
! }
! 
! /* Returns true for all operands that cannot use vmv.vx, vfmv.vf,
!    vmv.s.x, or vfmv.s.f but rather need to go via memory.  */
! 
! bool
! strided_broadcast_p (rtx op)
! {
!   machine_mode mode = GET_MODE (op);
!   if (!memory_operand (op, mode)
!       && !register_operand (op, mode)
!       && !rtx_equal_p (op, CONST0_RTX (mode))
!       && !const_int_operand (op, mode))
!     return false;
! 
!   /* !TARGET64_BIT does not have a vmv.v.x/vmv.s.x for 64-bit
!      DImode elements.  */
!   if (INTEGRAL_MODE_P (mode)
!       && maybe_gt (GET_MODE_SIZE (mode), UNITS_PER_WORD))
!     return true;
! 
!   /* Zvfhmin does not have a vfmv.v.f/vfmv.s.f.  for 16-bit elements.  */
!   if (!TARGET_ZVFH && mode == HFmode)
!     return true;
! 
!   return false;
  }
  
  void
*************** whole_reg_to_reg_move_p (rtx *ops, machi
*** 5941,5947 ****
    return false;
  }
  
! /* Return true if we can transform vmv.v.x/vfmv.v.f to vmv.s.x/vfmv.s.f.  */
  bool
  splat_to_scalar_move_p (rtx *ops)
  {
--- 6132,6141 ----
    return false;
  }
  
! /* Return true if we can transform vmv.v.x/vfmv.v.f to vmv.s.x/vfmv.s.f.
!    That's the case if we're dealing with a scalar broadcast that
!    has VL = 1.  */
! 
  bool
  splat_to_scalar_move_p (rtx *ops)
  {
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv-vector-builtins-bases.cc gcc-16-20250727/gcc/config/riscv/riscv-vector-builtins-bases.cc
*** gcc-16-20250720/gcc/config/riscv/riscv-vector-builtins-bases.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv-vector-builtins-bases.cc	Sun Jul 27 22:32:08 2025
*************** public:
*** 643,649 ****
  	return e.use_exact_insn (code_for_pred_mov (e.vector_mode ()));
        case OP_TYPE_x:
        case OP_TYPE_f:
! 	return e.use_exact_insn (code_for_pred_broadcast (e.vector_mode ()));
        default:
  	gcc_unreachable ();
        }
--- 643,650 ----
  	return e.use_exact_insn (code_for_pred_mov (e.vector_mode ()));
        case OP_TYPE_x:
        case OP_TYPE_f:
! 	return e.use_scalar_broadcast_insn
! 	  (code_for_pred_broadcast (e.vector_mode ()));
        default:
  	gcc_unreachable ();
        }
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv-vector-builtins.cc gcc-16-20250727/gcc/config/riscv/riscv-vector-builtins.cc
*** gcc-16-20250720/gcc/config/riscv/riscv-vector-builtins.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv-vector-builtins.cc	Sun Jul 27 22:32:08 2025
*************** function_expander::use_ternop_insn (bool
*** 4753,4759 ****
  }
  
  /* Implement the call using instruction ICODE, with a 1:1 mapping between
!    arguments and input operands.  */
  rtx
  function_expander::use_widen_ternop_insn (insn_code icode)
  {
--- 4753,4762 ----
  }
  
  /* Implement the call using instruction ICODE, with a 1:1 mapping between
!    arguments and input operands.
!    There are operands that cannot be broadcast using v[f]mv.  In that case
!    we switch to a strided broadcast.  */
! 
  rtx
  function_expander::use_widen_ternop_insn (insn_code icode)
  {
*************** function_expander::use_widen_ternop_insn
*** 4794,4800 ****
  }
  
  /* Implement the call using instruction ICODE, with a 1:1 mapping between
!    arguments and input operands.  */
  rtx
  function_expander::use_scalar_move_insn (insn_code icode)
  {
--- 4797,4806 ----
  }
  
  /* Implement the call using instruction ICODE, with a 1:1 mapping between
!    arguments and input operands.
!    There are operands that cannot be broadcast using v[f]mv.  In that case
!    we switch to a strided broadcast.  */
! 
  rtx
  function_expander::use_scalar_move_insn (insn_code icode)
  {
*************** function_expander::use_scalar_move_insn
*** 4812,4817 ****
--- 4818,4854 ----
    for (int argno = arg_offset; argno < call_expr_nargs (exp); argno++)
      add_input_operand (argno);
  
+   if (!can_be_broadcast_p (m_ops[3].value))
+     icode = code_for_pred_strided_broadcast (vector_mode ());
+ 
+   add_input_operand (Pmode, get_tail_policy_for_pred (pred));
+   add_input_operand (Pmode, get_mask_policy_for_pred (pred));
+   add_input_operand (Pmode, get_avl_type_rtx (avl_type::NONVLMAX));
+   return generate_insn (icode);
+ }
+ 
+ /* Implement the call using instruction ICODE, with a 1:1 mapping between
+    arguments and input operands.  */
+ rtx
+ function_expander::use_scalar_broadcast_insn (insn_code icode)
+ {
+   machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
+ 
+   /* Record the offset to get the argument.  */
+   int arg_offset = 0;
+   add_all_one_mask_operand (mask_mode ());
+ 
+   if (use_real_merge_p (pred))
+     add_input_operand (arg_offset++);
+   else
+     add_vundef_operand (mode);
+ 
+   for (int argno = arg_offset; argno < call_expr_nargs (exp); argno++)
+     add_input_operand (argno);
+ 
+   if (!can_be_broadcast_p (m_ops[3].value))
+     icode = code_for_pred_strided_broadcast (vector_mode ());
+ 
    add_input_operand (Pmode, get_tail_policy_for_pred (pred));
    add_input_operand (Pmode, get_mask_policy_for_pred (pred));
    add_input_operand (Pmode, get_avl_type_rtx (avl_type::NONVLMAX));
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv-vector-builtins.h gcc-16-20250727/gcc/config/riscv/riscv-vector-builtins.h
*** gcc-16-20250720/gcc/config/riscv/riscv-vector-builtins.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv-vector-builtins.h	Sun Jul 27 22:32:08 2025
*************** public:
*** 497,502 ****
--- 497,503 ----
    rtx use_ternop_insn (bool, insn_code);
    rtx use_widen_ternop_insn (insn_code);
    rtx use_scalar_move_insn (insn_code);
+   rtx use_scalar_broadcast_insn (insn_code);
    rtx generate_insn (insn_code);
  
    /* The function call expression.  */
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv-vector-costs.cc gcc-16-20250727/gcc/config/riscv/riscv-vector-costs.cc
*** gcc-16-20250720/gcc/config/riscv/riscv-vector-costs.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv-vector-costs.cc	Sun Jul 27 22:32:08 2025
*************** get_live_range (hash_map<tree, pair> *li
*** 178,185 ****
         STMT 5 (be vectorized)      -- point 2
         ...
  */
! static void
! compute_local_program_points (
    vec_info *vinfo,
    hash_map<basic_block, vec<stmt_point>> &program_points_per_bb)
  {
--- 178,185 ----
         STMT 5 (be vectorized)      -- point 2
         ...
  */
! void
! costs::compute_local_program_points (
    vec_info *vinfo,
    hash_map<basic_block, vec<stmt_point>> &program_points_per_bb)
  {
*************** loop_invariant_op_p (class loop *loop,
*** 274,287 ****
  
  /* Return true if the variable should be counted into liveness.  */
  static bool
! variable_vectorized_p (class loop *loop, stmt_vec_info stmt_info, tree var,
! 		       bool lhs_p)
  {
    if (!var)
      return false;
    gimple *stmt = STMT_VINFO_STMT (stmt_info);
!   enum stmt_vec_info_type type
!     = STMT_VINFO_TYPE (vect_stmt_to_vectorize (stmt_info));
    if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
      {
        if (gimple_call_internal_fn (stmt) == IFN_MASK_STORE
--- 274,287 ----
  
  /* Return true if the variable should be counted into liveness.  */
  static bool
! variable_vectorized_p (class loop *loop, stmt_vec_info stmt_info,
! 		       slp_tree node ATTRIBUTE_UNUSED, tree var, bool lhs_p)
  {
    if (!var)
      return false;
    gimple *stmt = STMT_VINFO_STMT (stmt_info);
!   stmt_info = vect_stmt_to_vectorize (stmt_info);
!   enum stmt_vec_info_type type = STMT_VINFO_TYPE (stmt_info);
    if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
      {
        if (gimple_call_internal_fn (stmt) == IFN_MASK_STORE
*************** variable_vectorized_p (class loop *loop,
*** 357,364 ****
  
     The live range of SSA 1 is [1, 3] in bb 2.
     The live range of SSA 2 is [0, 4] in bb 3.  */
! static machine_mode
! compute_local_live_ranges (
    loop_vec_info loop_vinfo,
    const hash_map<basic_block, vec<stmt_point>> &program_points_per_bb,
    hash_map<basic_block, hash_map<tree, pair>> &live_ranges_per_bb)
--- 357,364 ----
  
     The live range of SSA 1 is [1, 3] in bb 2.
     The live range of SSA 2 is [0, 4] in bb 3.  */
! machine_mode
! costs::compute_local_live_ranges (
    loop_vec_info loop_vinfo,
    const hash_map<basic_block, vec<stmt_point>> &program_points_per_bb,
    hash_map<basic_block, hash_map<tree, pair>> &live_ranges_per_bb)
*************** compute_local_live_ranges (
*** 388,395 ****
  	      unsigned int point = program_point.point;
  	      gimple *stmt = program_point.stmt;
  	      tree lhs = gimple_get_lhs (stmt);
! 	      if (variable_vectorized_p (loop, program_point.stmt_info, lhs,
! 					 true))
  		{
  		  biggest_mode = get_biggest_mode (biggest_mode,
  						   TYPE_MODE (TREE_TYPE (lhs)));
--- 388,398 ----
  	      unsigned int point = program_point.point;
  	      gimple *stmt = program_point.stmt;
  	      tree lhs = gimple_get_lhs (stmt);
! 	      slp_tree *node = vinfo_slp_map.get (program_point.stmt_info);
! 	      if (!node)
! 		continue;
! 	      if (variable_vectorized_p (loop, program_point.stmt_info,
! 					 *node, lhs, true))
  		{
  		  biggest_mode = get_biggest_mode (biggest_mode,
  						   TYPE_MODE (TREE_TYPE (lhs)));
*************** compute_local_live_ranges (
*** 406,413 ****
  	      for (i = 0; i < gimple_num_args (stmt); i++)
  		{
  		  tree var = gimple_arg (stmt, i);
! 		  if (variable_vectorized_p (loop, program_point.stmt_info, var,
! 					     false))
  		    {
  		      biggest_mode
  			= get_biggest_mode (biggest_mode,
--- 409,416 ----
  	      for (i = 0; i < gimple_num_args (stmt); i++)
  		{
  		  tree var = gimple_arg (stmt, i);
! 		  if (variable_vectorized_p (loop, program_point.stmt_info,
! 					     *node, var, false))
  		    {
  		      biggest_mode
  			= get_biggest_mode (biggest_mode,
*************** get_store_value (gimple *stmt)
*** 597,607 ****
  }
  
  /* Return true if additional vector vars needed.  */
! static bool
! need_additional_vector_vars_p (stmt_vec_info stmt_info)
  {
!   enum stmt_vec_info_type type
!     = STMT_VINFO_TYPE (vect_stmt_to_vectorize (stmt_info));
    if (type == load_vec_info_type || type == store_vec_info_type)
      {
        if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)
--- 600,610 ----
  }
  
  /* Return true if additional vector vars needed.  */
! bool
! costs::need_additional_vector_vars_p (stmt_vec_info stmt_info,
! 				      slp_tree node ATTRIBUTE_UNUSED)
  {
!   enum stmt_vec_info_type type = STMT_VINFO_TYPE (stmt_info);
    if (type == load_vec_info_type || type == store_vec_info_type)
      {
        if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)
*************** compute_estimated_lmul (loop_vec_info lo
*** 657,664 ****
  
     Then, after this function, we update SSA 1 live range in bb 2
     into [2, 4] since SSA 1 is live out into bb 3.  */
! static void
! update_local_live_ranges (
    vec_info *vinfo,
    hash_map<basic_block, vec<stmt_point>> &program_points_per_bb,
    hash_map<basic_block, hash_map<tree, pair>> &live_ranges_per_bb,
--- 660,667 ----
  
     Then, after this function, we update SSA 1 live range in bb 2
     into [2, 4] since SSA 1 is live out into bb 3.  */
! void
! costs::update_local_live_ranges (
    vec_info *vinfo,
    hash_map<basic_block, vec<stmt_point>> &program_points_per_bb,
    hash_map<basic_block, hash_map<tree, pair>> &live_ranges_per_bb,
*************** update_local_live_ranges (
*** 685,692 ****
  	{
  	  gphi *phi = psi.phi ();
  	  stmt_vec_info stmt_info = vinfo->lookup_stmt (phi);
! 	  if (STMT_VINFO_TYPE (vect_stmt_to_vectorize (stmt_info))
! 	      == undef_vec_info_type)
  	    continue;
  
  	  for (j = 0; j < gimple_phi_num_args (phi); j++)
--- 688,700 ----
  	{
  	  gphi *phi = psi.phi ();
  	  stmt_vec_info stmt_info = vinfo->lookup_stmt (phi);
! 	  stmt_info = vect_stmt_to_vectorize (stmt_info);
! 	  slp_tree *node = vinfo_slp_map.get (stmt_info);
! 
! 	  if (!node)
! 	    continue;
! 
! 	  if (STMT_VINFO_TYPE (stmt_info) == undef_vec_info_type)
  	    continue;
  
  	  for (j = 0; j < gimple_phi_num_args (phi); j++)
*************** update_local_live_ranges (
*** 761,769 ****
  	  if (!is_gimple_assign_or_call (gsi_stmt (si)))
  	    continue;
  	  stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (si));
! 	  enum stmt_vec_info_type type
! 	    = STMT_VINFO_TYPE (vect_stmt_to_vectorize (stmt_info));
! 	  if (need_additional_vector_vars_p (stmt_info))
  	    {
  	      /* For non-adjacent load/store STMT, we will potentially
  		 convert it into:
--- 769,780 ----
  	  if (!is_gimple_assign_or_call (gsi_stmt (si)))
  	    continue;
  	  stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (si));
! 	  stmt_info = vect_stmt_to_vectorize (stmt_info);
! 	  slp_tree *node = vinfo_slp_map.get (stmt_info);
! 	  if (!node)
! 	    continue;
! 	  enum stmt_vec_info_type type = STMT_VINFO_TYPE (stmt_info);
! 	  if (need_additional_vector_vars_p (stmt_info, *node))
  	    {
  	      /* For non-adjacent load/store STMT, we will potentially
  		 convert it into:
*************** update_local_live_ranges (
*** 816,823 ****
  }
  
  /* Compute the maximum live V_REGS.  */
! static bool
! has_unexpected_spills_p (loop_vec_info loop_vinfo)
  {
    /* Compute local program points.
       It's a fast and effective computation.  */
--- 827,834 ----
  }
  
  /* Compute the maximum live V_REGS.  */
! bool
! costs::has_unexpected_spills_p (loop_vec_info loop_vinfo)
  {
    /* Compute local program points.
       It's a fast and effective computation.  */
*************** costs::analyze_loop_vinfo (loop_vec_info
*** 899,905 ****
--- 910,920 ----
    /* Detect whether we're vectorizing for VLA and should apply the unrolling
       heuristic described above m_unrolled_vls_niters.  */
    record_potential_vls_unrolling (loop_vinfo);
+ }
  
+ void
+ costs::record_lmul_spills (loop_vec_info loop_vinfo)
+ {
    /* Detect whether the LOOP has unexpected spills.  */
    record_potential_unexpected_spills (loop_vinfo);
  }
*************** costs::add_stmt_cost (int count, vect_co
*** 1239,1246 ****
--- 1254,1265 ----
    int stmt_cost
      = targetm.vectorize.builtin_vectorization_cost (kind, vectype, misalign);
  
+   if (stmt_info && node)
+     vinfo_slp_map.put (stmt_info, node);
+ 
    /* Do one-time initialization based on the vinfo.  */
    loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo);
+ 
    if (!m_analyzed_vinfo)
      {
        if (loop_vinfo)
*************** costs::finish_cost (const vector_costs *
*** 1326,1331 ****
--- 1345,1352 ----
  {
    if (loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo))
      {
+       record_lmul_spills (loop_vinfo);
+ 
        adjust_vect_cost_per_loop (loop_vinfo);
      }
    vector_costs::finish_cost (scalar_costs);
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv-vector-costs.h gcc-16-20250727/gcc/config/riscv/riscv-vector-costs.h
*** gcc-16-20250720/gcc/config/riscv/riscv-vector-costs.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv-vector-costs.h	Sun Jul 27 22:32:08 2025
*************** private:
*** 91,97 ****
--- 91,100 ----
    typedef pair_hash <tree_operand_hash, tree_operand_hash> tree_pair_hash;
    hash_set <tree_pair_hash> memrefs;
  
+   hash_map <stmt_vec_info, slp_tree> vinfo_slp_map;
+ 
    void analyze_loop_vinfo (loop_vec_info);
+   void record_lmul_spills (loop_vec_info loop_vinfo);
    void record_potential_vls_unrolling (loop_vec_info);
    bool prefer_unrolled_loop () const;
  
*************** private:
*** 103,108 ****
--- 106,124 ----
    bool m_has_unexpected_spills_p = false;
    void record_potential_unexpected_spills (loop_vec_info);
  
+   void compute_local_program_points (vec_info *,
+ 				     hash_map<basic_block, vec<stmt_point>> &);
+   void update_local_live_ranges (vec_info *,
+ 				 hash_map<basic_block, vec<stmt_point>> &,
+ 				 hash_map<basic_block, hash_map<tree, pair>> &,
+ 				 machine_mode *);
+   machine_mode compute_local_live_ranges
+     (loop_vec_info, const hash_map<basic_block, vec<stmt_point>> &,
+      hash_map<basic_block, hash_map<tree, pair>> &);
+ 
+   bool has_unexpected_spills_p (loop_vec_info);
+   bool need_additional_vector_vars_p (stmt_vec_info, slp_tree);
+ 
    void adjust_vect_cost_per_loop (loop_vec_info);
    unsigned adjust_stmt_cost (enum vect_cost_for_stmt kind,
  			     loop_vec_info,
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv.cc gcc-16-20250727/gcc/config/riscv/riscv.cc
*** gcc-16-20250720/gcc/config/riscv/riscv.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv.cc	Sun Jul 27 22:32:08 2025
*************** struct GTY(())  riscv_frame_info {
*** 170,176 ****
  };
  
  enum riscv_privilege_levels {
!   UNKNOWN_MODE, USER_MODE, SUPERVISOR_MODE, MACHINE_MODE
  };
  
  struct GTY(()) mode_switching_info {
--- 170,176 ----
  };
  
  enum riscv_privilege_levels {
!   UNKNOWN_MODE, SUPERVISOR_MODE, MACHINE_MODE, RNMI_MODE
  };
  
  struct GTY(()) mode_switching_info {
*************** get_vector_binary_rtx_cost (rtx x, int s
*** 3967,3975 ****
  {
    gcc_assert (riscv_v_ext_mode_p (GET_MODE (x)));
  
-   rtx op_0 = XEXP (x, 0);
-   rtx op_1 = XEXP (x, 1);
    rtx neg;
  
    if (GET_CODE (op_0) == VEC_DUPLICATE
        || GET_CODE (op_1) == VEC_DUPLICATE)
--- 3967,3986 ----
  {
    gcc_assert (riscv_v_ext_mode_p (GET_MODE (x)));
  
    rtx neg;
+   rtx op_0;
+   rtx op_1;
+ 
+   if (GET_CODE (x) == UNSPEC)
+     {
+       op_0 = XVECEXP (x, 0, 0);
+       op_1 = XVECEXP (x, 0, 1);
+     }
+   else
+     {
+       op_0 = XEXP (x, 0);
+       op_1 = XEXP (x, 1);
+     }
  
    if (GET_CODE (op_0) == VEC_DUPLICATE
        || GET_CODE (op_1) == VEC_DUPLICATE)
*************** riscv_rtx_costs (rtx x, machine_mode mod
*** 4024,4029 ****
--- 4035,4055 ----
  		    case SS_MINUS:
  		      *total = get_vector_binary_rtx_cost (op, scalar2vr_cost);
  		      break;
+ 		    case UNSPEC:
+ 		      {
+ 			switch (XINT (op, 1))
+ 			  {
+ 			  case UNSPEC_VAADDU:
+ 			  case UNSPEC_VAADD:
+ 			    *total
+ 			      = get_vector_binary_rtx_cost (op, scalar2vr_cost);
+ 			    break;
+ 			  default:
+ 			    *total = COSTS_N_INSNS (1);
+ 			    break;
+ 			  }
+ 		      }
+ 		      break;
  		    default:
  		      *total = COSTS_N_INSNS (1);
  		      break;
*************** riscv_handle_type_attribute (tree *node
*** 6899,6910 ****
  	    }
  
  	  string = TREE_STRING_POINTER (cst);
! 	  if (strcmp (string, "user") && strcmp (string, "supervisor")
! 	      && strcmp (string, "machine"))
  	    {
  	      warning (OPT_Wattributes,
! 		       "argument to %qE attribute is not %<\"user\"%>, %<\"supervisor\"%>, "
! 		       "or %<\"machine\"%>", name);
  	      *no_add_attrs = true;
  	    }
  	}
--- 6925,6942 ----
  	    }
  
  	  string = TREE_STRING_POINTER (cst);
! 	  if (!strcmp (string, "rnmi") && !TARGET_SMRNMI)
! 	    {
! 	      error ("attribute 'rnmi' requires the Smrnmi ISA extension");
! 	      *no_add_attrs = true;
! 	    }
! 	  else if (strcmp (string, "supervisor")
! 		   && strcmp (string, "machine")
! 		   && strcmp (string, "rnmi"))
  	    {
  	      warning (OPT_Wattributes,
! 		       "argument to %qE attribute is not %<\"supervisor\"%>, "
! 		       "%<\"machine\"%>, or %<\"rnmi\"%>", name);
  	      *no_add_attrs = true;
  	    }
  	}
*************** riscv_allocate_and_probe_stack_space (rt
*** 9052,9058 ****
  	  /* We want the CFA independent of the stack pointer for the
  	     duration of the loop.  */
  	  add_reg_note (insn, REG_CFA_DEF_CFA,
! 			plus_constant (Pmode, temp1,
  				       initial_cfa_offset + rounded_size));
  	  RTX_FRAME_RELATED_P (insn) = 1;
  	}
--- 9084,9090 ----
  	  /* We want the CFA independent of the stack pointer for the
  	     duration of the loop.  */
  	  add_reg_note (insn, REG_CFA_DEF_CFA,
! 			plus_constant (Pmode, temp2,
  				       initial_cfa_offset + rounded_size));
  	  RTX_FRAME_RELATED_P (insn) = 1;
  	}
*************** riscv_expand_epilogue (int style)
*** 9685,9696 ****
  
        if (th_int_mask && TH_INT_INTERRUPT (cfun))
  	emit_jump_insn (gen_th_int_pop ());
-       else if (mode == MACHINE_MODE)
- 	emit_jump_insn (gen_riscv_mret ());
        else if (mode == SUPERVISOR_MODE)
  	emit_jump_insn (gen_riscv_sret ());
!       else
! 	emit_jump_insn (gen_riscv_uret ());
      }
    else if (style != SIBCALL_RETURN)
      {
--- 9717,9728 ----
  
        if (th_int_mask && TH_INT_INTERRUPT (cfun))
  	emit_jump_insn (gen_th_int_pop ());
        else if (mode == SUPERVISOR_MODE)
  	emit_jump_insn (gen_riscv_sret ());
!       else if (mode == RNMI_MODE)
! 	emit_jump_insn (gen_riscv_mnret ());
!       else /* Must be MACHINE_MODE.  */
! 	emit_jump_insn (gen_riscv_mret ());
      }
    else if (style != SIBCALL_RETURN)
      {
*************** riscv_get_interrupt_type (tree decl)
*** 12032,12041 ****
      {
        const char *string = TREE_STRING_POINTER (TREE_VALUE (attr_args));
  
!       if (!strcmp (string, "user"))
! 	return USER_MODE;
!       else if (!strcmp (string, "supervisor"))
  	return SUPERVISOR_MODE;
        else /* Must be "machine".  */
  	return MACHINE_MODE;
      }
--- 12064,12073 ----
      {
        const char *string = TREE_STRING_POINTER (TREE_VALUE (attr_args));
  
!       if (!strcmp (string, "supervisor"))
  	return SUPERVISOR_MODE;
+       else if (!strcmp (string, "rnmi"))
+ 	return RNMI_MODE;
        else /* Must be "machine".  */
  	return MACHINE_MODE;
      }
*************** riscv_estimated_poly_value (poly_int64 v
*** 12652,12665 ****
  /* Return true if the vector misalignment factor is supported by the
     target.  */
  bool
! riscv_support_vector_misalignment (machine_mode mode,
! 				   const_tree type ATTRIBUTE_UNUSED,
! 				   int misalignment,
! 				   bool is_packed ATTRIBUTE_UNUSED)
  {
!   /* Depend on movmisalign pattern.  */
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed);
  }
  
  /* Implement TARGET_VECTORIZE_GET_MASK_MODE.  */
--- 12684,12714 ----
  /* Return true if the vector misalignment factor is supported by the
     target.  */
  bool
! riscv_support_vector_misalignment (machine_mode mode, const_tree type,
! 				   int misalignment, bool is_packed,
! 				   bool is_gather_scatter)
  {
!   /* IS_PACKED is true if the corresponding scalar element is not naturally
!      aligned.  If the misalignment is unknown and the the access is packed
!      we defer to the default hook which will check if movmisalign is present.
!      Movmisalign, in turn, depends on TARGET_VECTOR_MISALIGN_SUPPORTED.  */
!   if (misalignment == DR_MISALIGNMENT_UNKNOWN)
!     {
!       if (!is_packed)
! 	return true;
!     }
!   else
!     {
!       /* If we know that misalignment is a multiple of the element size, we're
! 	 good.  */
!       if (misalignment % TYPE_ALIGN_UNIT (type) == 0)
! 	return true;
!     }
! 
!   /* Otherwise fall back to movmisalign again.  */
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed,
! 						      is_gather_scatter);
  }
  
  /* Implement TARGET_VECTORIZE_GET_MASK_MODE.  */
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/riscv.md gcc-16-20250727/gcc/config/riscv/riscv.md
*** gcc-16-20250720/gcc/config/riscv/riscv.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/riscv.md	Sun Jul 27 22:32:08 2025
***************
*** 120,126 ****
    ;; Interrupt handler instructions.
    UNSPECV_MRET
    UNSPECV_SRET
!   UNSPECV_URET
  
    ;; Blockage and synchronization.
    UNSPECV_BLOCKAGE
--- 120,126 ----
    ;; Interrupt handler instructions.
    UNSPECV_MRET
    UNSPECV_SRET
!   UNSPECV_MNRET
  
    ;; Blockage and synchronization.
    UNSPECV_BLOCKAGE
***************
*** 4166,4176 ****
    "sret"
    [(set_attr "type" "ret")])
  
! (define_insn "riscv_uret"
    [(return)
!    (unspec_volatile [(const_int 0)] UNSPECV_URET)]
!   ""
!   "uret"
    [(set_attr "type" "ret")])
  
  (define_insn "stack_tie<mode>"
--- 4166,4176 ----
    "sret"
    [(set_attr "type" "ret")])
  
! (define_insn "riscv_mnret"
    [(return)
!    (unspec_volatile [(const_int 0)] UNSPECV_MNRET)]
!   "TARGET_SMRNMI"
!   "mnret"
    [(set_attr "type" "ret")])
  
  (define_insn "stack_tie<mode>"
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/vector-iterators.md gcc-16-20250727/gcc/config/riscv/vector-iterators.md
*** gcc-16-20250720/gcc/config/riscv/vector-iterators.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/vector-iterators.md	Sun Jul 27 22:32:08 2025
***************
*** 4013,4018 ****
--- 4013,4026 ----
  			      UNSPEC_VASUBU UNSPEC_VASUB UNSPEC_VSMUL
  			      UNSPEC_VSSRL UNSPEC_VSSRA])
  
+ (define_int_iterator VSAT_VX_OP_V_VDUP [
+   UNSPEC_VAADDU UNSPEC_VAADD
+ ])
+ 
+ (define_int_iterator VSAT_VX_OP_VDUP_V [
+   UNSPEC_VAADDU UNSPEC_VAADD
+ ])
+ 
  (define_int_iterator VSAT_ARITH_OP [UNSPEC_VAADDU UNSPEC_VAADD
  			      	    UNSPEC_VASUBU UNSPEC_VASUB UNSPEC_VSMUL])
  (define_int_iterator VSAT_SHIFT_OP [UNSPEC_VSSRL UNSPEC_VSSRA])
***************
*** 4047,4052 ****
--- 4055,4068 ----
  			 	(UNSPEC_VSSRA "vsshift") (UNSPEC_VNCLIP "vnclip")
  				(UNSPEC_VNCLIPU "vnclip")])
  
+ (define_int_attr sat_op_v_vdup [
+   (UNSPEC_VAADDU "aaddu") (UNSPEC_VAADD "aadd")
+ ])
+ 
+ (define_int_attr sat_op_vdup_v [
+   (UNSPEC_VAADDU "aaddu") (UNSPEC_VAADD "aadd")
+ ])
+ 
  (define_int_attr misc_op [(UNSPEC_VMSBF "sbf") (UNSPEC_VMSIF "sif") (UNSPEC_VMSOF "sof")
  			  (UNSPEC_VFRSQRT7 "rsqrt7")])
  
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/vector.md gcc-16-20250727/gcc/config/riscv/vector.md
*** gcc-16-20250720/gcc/config/riscv/vector.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/vector.md	Sun Jul 27 22:32:08 2025
***************
*** 1551,1570 ****
  (define_expand "vec_duplicate<mode>"
    [(set (match_operand:V_VLS 0 "register_operand")
          (vec_duplicate:V_VLS
!           (match_operand:<VEL> 1 "direct_broadcast_operand")))]
    "TARGET_VECTOR"
    {
!     /* Early expand DImode broadcast in RV32 system to avoid RA reload
!        generate (set (reg) (vec_duplicate:DI)).  */
      bool gt_p = maybe_gt (GET_MODE_SIZE (<VEL>mode), GET_MODE_SIZE (Pmode));
      if (!FLOAT_MODE_P (<VEL>mode) && gt_p)
        {
!         riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (<MODE>mode),
! 				       riscv_vector::UNARY_OP, operands);
! 	DONE;
        }
!     /* Otherwise, allow it fall into general vec_duplicate pattern
!        which allow us to have vv->vx combine optimization in later pass.  */
    })
  
  ;; According to GCC internal:
--- 1551,1594 ----
  (define_expand "vec_duplicate<mode>"
    [(set (match_operand:V_VLS 0 "register_operand")
          (vec_duplicate:V_VLS
!           (match_operand:<VEL> 1 "any_broadcast_operand")))]
    "TARGET_VECTOR"
    {
!     /* Don't keep a DImode broadcast for RV32 in the vec_duplicate form.
!        Otherwise combine or late combine could end up doing
! 	      "64-bit broadcast" (!= vmv.v.x)
!             + vadd.vv
! 	    = vadd.vx
!        which would be invalid.  */
      bool gt_p = maybe_gt (GET_MODE_SIZE (<VEL>mode), GET_MODE_SIZE (Pmode));
      if (!FLOAT_MODE_P (<VEL>mode) && gt_p)
        {
!         riscv_vector::emit_vlmax_insn
! 	  (code_for_pred_strided_broadcast
! 	    (<MODE>mode), riscv_vector::UNARY_OP, operands);
!        DONE;
        }
! 
!     /* Even though we can eventually broadcast any permissible
!        constant by moving it into a register we need to force
!        any non-immediate one into a register here.
!        If we didn't do that we couldn't fwprop/late-combine
! 	      vec_duplicate 123.45f
! 	    + vfadd.vv
! 	    = vfadd.vf
!        because the constant is valid for vec_duplicate but not
!        for vfadd.vf.  Therefore we need to do
! 	      fa0 = 123.45f
! 	      vec_duplicate fa0
! 	    + vfadd.vv
! 	    = vfadd.vf  */
!     if (!satisfies_constraint_P (operands[1])
! 	&& !satisfies_constraint_J (operands[1])
! 	&& !rtx_equal_p (operands[1], CONST0_RTX (<VEL>mode))
! 	&& !memory_operand (operands[1], <VEL>mode))
!       operands[1] = force_reg (<VEL>mode, operands[1]);
! 
!     /* Otherwise keep the vec_duplicate pattern until split.  */
    })
  
  ;; According to GCC internal:
***************
*** 1574,1601 ****
  (define_insn_and_split "*vec_duplicate<mode>"
    [(set (match_operand:V_VLS 0 "register_operand")
          (vec_duplicate:V_VLS
!           (match_operand:<VEL> 1 "direct_broadcast_operand")))]
    "TARGET_VECTOR && can_create_pseudo_p ()"
    "#"
    "&& 1"
    [(const_int 0)]
    {
!     if (!strided_load_broadcast_p ()
! 	&& TARGET_ZVFHMIN && !TARGET_ZVFH && <VEL>mode == HFmode)
!       {
! 	/* For Float16, reinterpret as HImode, broadcast and reinterpret
! 	   back.  */
! 	poly_uint64 nunits = GET_MODE_NUNITS (<MODE>mode);
! 	machine_mode vmodehi
! 	  = riscv_vector::get_vector_mode (HImode, nunits).require ();
! 	rtx ops[] = {lowpart_subreg (vmodehi, operands[0], <MODE>mode),
! 		     lowpart_subreg (HImode, operands[1], HFmode)};
! 	riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (vmodehi),
! 				       riscv_vector::UNARY_OP, ops);
!       }
!     else
        riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (<MODE>mode),
  				     riscv_vector::UNARY_OP, operands);
      DONE;
    }
    [(set_attr "type" "vector")]
--- 1598,1617 ----
  (define_insn_and_split "*vec_duplicate<mode>"
    [(set (match_operand:V_VLS 0 "register_operand")
          (vec_duplicate:V_VLS
!           (match_operand:<VEL> 1 "any_broadcast_operand")))]
    "TARGET_VECTOR && can_create_pseudo_p ()"
    "#"
    "&& 1"
    [(const_int 0)]
    {
!     if (riscv_vector::can_be_broadcast_p (operands[1]))
        riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (<MODE>mode),
  				     riscv_vector::UNARY_OP, operands);
+     else
+       riscv_vector::emit_vlmax_insn (code_for_pred_strided_broadcast
+ 				     (<MODE>mode), riscv_vector::UNARY_OP,
+ 				     operands);
+ 
      DONE;
    }
    [(set_attr "type" "vector")]
***************
*** 2141,2209 ****
  	  (match_operand:V_VLS 2 "vector_merge_operand")))]
    "TARGET_VECTOR"
  {
-   /* Transform vmv.v.x/vfmv.v.f (avl = 1) into vmv.s.x since vmv.s.x/vfmv.s.f
-      has better chances to do vsetvl fusion in vsetvl pass.  */
    bool wrap_vec_dup = true;
    rtx vec_cst = NULL_RTX;
!   if (riscv_vector::splat_to_scalar_move_p (operands))
!     {
!       operands[1] = riscv_vector::gen_scalar_move_mask (<VM>mode);
!       operands[3] = force_reg (<VEL>mode, operands[3]);
!     }
!   else if (immediate_operand (operands[3], <VEL>mode)
! 	   && (vec_cst = gen_const_vec_duplicate (<MODE>mode, operands[3]))
! 	   && (/* -> pred_broadcast<mode>_zero */
! 	       (vector_least_significant_set_mask_operand (operands[1],
! 							   <VM>mode)
! 		&& vector_const_0_operand (vec_cst, <MODE>mode))
! 	       || (/* pred_broadcast<mode>_imm */
! 		   vector_all_trues_mask_operand (operands[1], <VM>mode)
! 		   && vector_const_int_or_double_0_operand (vec_cst,
! 							    <MODE>mode))))
      {
        operands[3] = vec_cst;
        wrap_vec_dup = false;
      }
!   /* Handle vmv.s.x instruction (Wb1 mask) which has memory scalar.  */
!   else if (satisfies_constraint_Wdm (operands[3]))
!     {
!       if (satisfies_constraint_Wb1 (operands[1]))
! 	{
! 	  /* Case 1: vmv.s.x (TA, x == memory) ==> vlse.v (TA)  */
! 	  if (satisfies_constraint_vu (operands[2]))
! 	    operands[1] = CONSTM1_RTX (<VM>mode);
! 	  else if (GET_MODE_BITSIZE (<VEL>mode) > GET_MODE_BITSIZE (Pmode))
! 	    {
! 	      /* Case 2: vmv.s.x (TU, x == memory) ==>
! 			   vl = 0 or 1; + vlse.v (TU) in RV32 system  */
! 	      operands[4] = riscv_vector::gen_avl_for_scalar_move (operands[4]);
! 	      operands[1] = CONSTM1_RTX (<VM>mode);
! 	    }
! 	  else
! 	    /* Case 3: load x (memory) to register.  */
! 	    operands[3] = force_reg (<VEL>mode, operands[3]);
! 	}
!     }
!   else if (GET_MODE_BITSIZE (<VEL>mode) > GET_MODE_BITSIZE (Pmode)
! 	   && (immediate_operand (operands[3], Pmode)
  	       || (CONST_POLY_INT_P (operands[3])
  	           && known_ge (rtx_to_poly_int64 (operands[3]), 0U)
! 		   && known_le (rtx_to_poly_int64 (operands[3]), GET_MODE_SIZE (<MODE>mode)))))
      {
        rtx tmp = gen_reg_rtx (Pmode);
        poly_int64 value = rtx_to_poly_int64 (operands[3]);
!       emit_move_insn (tmp, gen_int_mode (value, Pmode));
        operands[3] = gen_rtx_SIGN_EXTEND (<VEL>mode, tmp);
      }
!   /* Never load (const_int 0) into a register, that's silly.  */
!   else if (operands[3] == CONST0_RTX (<VEL>mode))
      ;
!   /* If we're broadcasting [-16..15] across more than just
!      element 0, then we can use vmv.v.i directly, thus avoiding
!      the load of the constant into a GPR.  */
!   else if (CONST_INT_P (operands[3])
! 	   && IN_RANGE (INTVAL (operands[3]), -16, 15)
! 	   && !satisfies_constraint_Wb1 (operands[1]))
      ;
    else
      operands[3] = force_reg (<VEL>mode, operands[3]);
--- 2157,2201 ----
  	  (match_operand:V_VLS 2 "vector_merge_operand")))]
    "TARGET_VECTOR"
  {
    bool wrap_vec_dup = true;
    rtx vec_cst = NULL_RTX;
!   if (immediate_operand (operands[3], <VEL>mode)
!       && (vec_cst = gen_const_vec_duplicate (<MODE>mode, operands[3]))
!       && (/* -> pred_broadcast<mode>_zero */
! 	  (vector_least_significant_set_mask_operand (operands[1],
! 						      <VM>mode)
! 	   && vector_const_0_operand (vec_cst, <MODE>mode))
! 	  || (/* pred_broadcast<mode>_imm */
! 	      vector_all_trues_mask_operand (operands[1], <VM>mode)
! 	      && vector_const_int_or_double_0_operand (vec_cst,
! 						       <MODE>mode))))
      {
        operands[3] = vec_cst;
        wrap_vec_dup = false;
      }
!   else if (GET_MODE_SIZE (<VEL>mode) > UNITS_PER_WORD
! 	   && satisfies_constraint_Wb1 (operands[1])
! 	   && (immediate_operand (operands[3], Xmode)
  	       || (CONST_POLY_INT_P (operands[3])
  	           && known_ge (rtx_to_poly_int64 (operands[3]), 0U)
! 		   && known_le (rtx_to_poly_int64 (operands[3]),
! 				GET_MODE_SIZE (<MODE>mode)))))
      {
        rtx tmp = gen_reg_rtx (Pmode);
        poly_int64 value = rtx_to_poly_int64 (operands[3]);
!       emit_move_insn (tmp, gen_int_mode (value, Xmode));
        operands[3] = gen_rtx_SIGN_EXTEND (<VEL>mode, tmp);
      }
! 
!   /* For a vmv.v.x never load (const_int 0) or valid immediate operands
!      into a register, because we can use vmv.v.i.  */
!   else if (satisfies_constraint_Wc1 (operands[1])
!       && (satisfies_constraint_P (operands[3])
! 	  || operands[3] == CONST0_RTX (<VEL>mode)))
      ;
!   /* For vmv.s.x we have vmv.s.x v1, zero.  */
!   else if (satisfies_constraint_Wb1 (operands[1])
! 	   && operands[3] == CONST0_RTX (<VEL>mode))
      ;
    else
      operands[3] = force_reg (<VEL>mode, operands[3]);
***************
*** 2211,2341 ****
      operands[3] = gen_rtx_VEC_DUPLICATE (<MODE>mode, operands[3]);
  })
  
! (define_insn_and_split "*pred_broadcast<mode>"
!   [(set (match_operand:V_VLSI 0 "register_operand"                 "=vr, vr, vd, vd, vr, vr, vr, vr")
  	(if_then_else:V_VLSI
  	  (unspec:<VM>
! 	    [(match_operand:<VM> 1 "vector_broadcast_mask_operand" "Wc1,Wc1, vm, vm,Wc1,Wc1,Wb1,Wb1")
! 	     (match_operand 4 "vector_length_operand"              "rvl,rvl,rvl,rvl,rvl,rvl,rvl,rvl")
! 	     (match_operand 5 "const_int_operand"                  "  i,  i,  i,  i,  i,  i,  i,  i")
! 	     (match_operand 6 "const_int_operand"                  "  i,  i,  i,  i,  i,  i,  i,  i")
! 	     (match_operand 7 "const_int_operand"                  "  i,  i,  i,  i,  i,  i,  i,  i")
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
  	  (vec_duplicate:V_VLSI
! 	    (match_operand:<VEL> 3 "direct_broadcast_operand"       "rP,rP,Wdm,Wdm,Wdm,Wdm, rJ, rJ"))
! 	  (match_operand:V_VLSI 2 "vector_merge_operand"            "vu, 0, vu,  0, vu,  0, vu,  0")))]
    "TARGET_VECTOR"
    "@
     vmv.v.%o3\t%0,%3
     vmv.v.%o3\t%0,%3
-    vlse<sew>.v\t%0,%3,zero,%1.t
-    vlse<sew>.v\t%0,%3,zero,%1.t
-    vlse<sew>.v\t%0,%3,zero
-    vlse<sew>.v\t%0,%3,zero
     vmv.s.x\t%0,%z3
     vmv.s.x\t%0,%z3"
!   "(register_operand (operands[3], <VEL>mode)
!   || CONST_POLY_INT_P (operands[3]))
!   && GET_MODE_BITSIZE (<VEL>mode) > GET_MODE_BITSIZE (Pmode)"
!   [(const_int 0)]
!   {
!     gcc_assert (can_create_pseudo_p ());
!     if (CONST_POLY_INT_P (operands[3]))
!       {
! 	rtx tmp = gen_reg_rtx (<VEL>mode);
! 	emit_move_insn (tmp, operands[3]);
! 	operands[3] = tmp;
!       }
! 
!     /* For SEW = 64 in RV32 system, we expand vmv.s.x:
!        andi a2,a2,1
!        vsetvl zero,a2,e64
!        vlse64.v  */
!     if (satisfies_constraint_Wb1 (operands[1]))
!       {
! 	operands[4] = riscv_vector::gen_avl_for_scalar_move (operands[4]);
! 	operands[1] = CONSTM1_RTX (<VM>mode);
!       }
! 
!     /* If the target doesn't want a strided-load broadcast we go with a regular
!        V1DImode load and a broadcast gather.  */
!     if (strided_load_broadcast_p ())
!       {
! 	rtx mem = assign_stack_local (<VEL>mode, GET_MODE_SIZE (<VEL>mode),
! 				      GET_MODE_ALIGNMENT (<VEL>mode));
! 	mem = validize_mem (mem);
! 	emit_move_insn (mem, operands[3]);
! 	mem = gen_rtx_MEM (<VEL>mode, force_reg (Pmode, XEXP (mem, 0)));
! 
! 	emit_insn
! 	  (gen_pred_broadcast<mode>
! 	   (operands[0], operands[1], operands[2], mem,
! 	    operands[4], operands[5], operands[6], operands[7]));
!       }
!     else
!       {
! 	rtx tmp = gen_reg_rtx (V1DImode);
! 	emit_move_insn (tmp, lowpart_subreg (V1DImode, operands[3],
! 					     <VEL>mode));
! 	tmp = lowpart_subreg (<MODE>mode, tmp, V1DImode);
! 
! 	emit_insn
! 	  (gen_pred_gather<mode>_scalar
! 	   (operands[0], operands[1], operands[2], tmp, CONST0_RTX (Pmode),
! 	    operands[4], operands[5], operands[6], operands[7]));
!       }
!     DONE;
!   }
!   [(set_attr "type" "vimov,vimov,vlds,vlds,vlds,vlds,vimovxv,vimovxv")
     (set_attr "mode" "<MODE>")])
  
! (define_insn "*pred_broadcast<mode>_zvfh"
!   [(set (match_operand:V_VLSF    0 "register_operand"              "=vr,  vr,  vr,  vr")
  	(if_then_else:V_VLSF
  	  (unspec:<VM>
! 	    [(match_operand:<VM> 1 "vector_broadcast_mask_operand" "Wc1, Wc1, Wb1, Wb1")
! 	     (match_operand      4 "vector_length_operand"         "rvl, rvl, rvl, rvl")
! 	     (match_operand      5 "const_int_operand"             "  i,   i,   i,   i")
! 	     (match_operand      6 "const_int_operand"             "  i,   i,   i,   i")
! 	     (match_operand      7 "const_int_operand"             "  i,   i,   i,   i")
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
  	  (vec_duplicate:V_VLSF
! 	    (match_operand:<VEL> 3 "direct_broadcast_operand"      "  f,   f,   f,   f"))
! 	  (match_operand:V_VLSF  2 "vector_merge_operand"          " vu,   0,  vu,   0")))]
    "TARGET_VECTOR"
    "@
     vfmv.v.f\t%0,%3
     vfmv.v.f\t%0,%3
     vfmv.s.f\t%0,%3
     vfmv.s.f\t%0,%3"
    [(set_attr "type" "vfmov,vfmov,vfmovfv,vfmovfv")
     (set_attr "mode" "<MODE>")])
  
- (define_insn "*pred_broadcast<mode>_zvfhmin"
-   [(set (match_operand:V_VLSF_ZVFHMIN   0 "register_operand"              "=vr,  vr,  vr,  vr")
- 	(if_then_else:V_VLSF_ZVFHMIN
- 	  (unspec:<VM>
- 	    [(match_operand:<VM>        1 "vector_broadcast_mask_operand" " vm,  vm, Wc1, Wc1")
- 	     (match_operand             4 "vector_length_operand"         "rvl, rvl, rvl, rvl")
- 	     (match_operand             5 "const_int_operand"             "  i,   i,   i,   i")
- 	     (match_operand             6 "const_int_operand"             "  i,   i,   i,   i")
- 	     (match_operand             7 "const_int_operand"             "  i,   i,   i,   i")
- 	     (reg:SI VL_REGNUM)
- 	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
- 	  (vec_duplicate:V_VLSF_ZVFHMIN
- 	    (match_operand:<VEL>        3 "direct_broadcast_operand"      "  A,   A,   A,   A"))
- 	  (match_operand:V_VLSF_ZVFHMIN 2 "vector_merge_operand"          " vu,   0,  vu,   0")))]
-   "TARGET_VECTOR && strided_load_broadcast_p ()"
-   "@
-    vlse<sew>.v\t%0,%3,zero,%1.t
-    vlse<sew>.v\t%0,%3,zero,%1.t
-    vlse<sew>.v\t%0,%3,zero
-    vlse<sew>.v\t%0,%3,zero"
-   [(set_attr "type" "vlds,vlds,vlds,vlds")
-    (set_attr "mode" "<MODE>")])
- 
  (define_insn "*pred_broadcast<mode>_extended_scalar"
    [(set (match_operand:V_VLSI_D 0 "register_operand"               "=vr, vr, vr, vr")
  	(if_then_else:V_VLSI_D
--- 2203,2270 ----
      operands[3] = gen_rtx_VEC_DUPLICATE (<MODE>mode, operands[3]);
  })
  
! (define_insn_and_rewrite "*pred_broadcast<mode>"
!   [(set (match_operand:V_VLSI 0 "register_operand"                 "=vr, vr, vr, vr")
  	(if_then_else:V_VLSI
  	  (unspec:<VM>
! 	    [(match_operand:<VM> 1 "vector_broadcast_mask_operand" "Wc1,Wc1,Wb1,Wb1")
! 	     (match_operand 4 "vector_length_operand"		   "rvl,rvl,rvl,rvl")
! 	     (match_operand 5 "const_int_operand"                  "  i,  i,  i,  i")
! 	     (match_operand 6 "const_int_operand"                  "  i,  i,  i,  i")
! 	     (match_operand 7 "const_int_operand"                  "  i,  i,  i,  i")
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
  	  (vec_duplicate:V_VLSI
! 	    (match_operand:<VEL> 3 "direct_broadcast_operand"      " rP, rP, rJ, rJ"))
! 	  (match_operand:V_VLSI 2 "vector_merge_operand"           " vu,  0, vu,  0")))]
    "TARGET_VECTOR"
    "@
     vmv.v.%o3\t%0,%3
     vmv.v.%o3\t%0,%3
     vmv.s.x\t%0,%z3
     vmv.s.x\t%0,%z3"
!   "&& (operands[1] == CONSTM1_RTX (<VM>mode)
!        && operands[4] == CONST1_RTX (Pmode)
!        && (register_operand (operands[3], <VEL>mode)
!            || satisfies_constraint_J (operands[3])))"
! {
!   /* A broadcast of a single element is just a vmv.s.x.  */
!   operands[1] = riscv_vector::gen_scalar_move_mask (<VM>mode);
! }
!   [(set_attr "type" "vimov,vimov,vimovxv,vimovxv")
     (set_attr "mode" "<MODE>")])
  
! (define_insn_and_rewrite "pred_broadcast<mode>_zvfh"
!   [(set (match_operand:V_VLSF    0 "register_operand"              "=vr, vr, vr, vr")
  	(if_then_else:V_VLSF
  	  (unspec:<VM>
! 	    [(match_operand:<VM> 1 "vector_broadcast_mask_operand" "Wc1,Wc1,Wb1,Wb1")
! 	     (match_operand      4 "vector_length_operand"	   "rvl,rvl,rvl,rvl")
! 	     (match_operand      5 "const_int_operand"             "  i,  i,  i,  i")
! 	     (match_operand      6 "const_int_operand"             "  i,  i,  i,  i")
! 	     (match_operand      7 "const_int_operand"             "  i,  i,  i,  i")
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
  	  (vec_duplicate:V_VLSF
! 	    (match_operand:<VEL> 3 "direct_broadcast_operand"      "  f,  f,  f,  f"))
! 	  (match_operand:V_VLSF  2 "vector_merge_operand"          " vu,  0, vu,  0")))]
    "TARGET_VECTOR"
    "@
     vfmv.v.f\t%0,%3
     vfmv.v.f\t%0,%3
     vfmv.s.f\t%0,%3
     vfmv.s.f\t%0,%3"
+   "&& (operands[1] == CONSTM1_RTX (<VM>mode)
+        && operands[4] == CONST1_RTX (Pmode)
+        && (register_operand (operands[3], <VEL>mode)
+            || satisfies_constraint_J (operands[3])))"
+ {
+   /* A broadcast of a single element is just a vfmv.s.f.  */
+   operands[1] = riscv_vector::gen_scalar_move_mask (<VM>mode);
+ }
    [(set_attr "type" "vfmov,vfmov,vfmovfv,vfmovfv")
     (set_attr "mode" "<MODE>")])
  
  (define_insn "*pred_broadcast<mode>_extended_scalar"
    [(set (match_operand:V_VLSI_D 0 "register_operand"               "=vr, vr, vr, vr")
  	(if_then_else:V_VLSI_D
***************
*** 2398,2403 ****
--- 2327,2443 ----
    [(set_attr "type" "vimov,vimov")
     (set_attr "mode" "<MODE>")])
  
+ (define_expand "@pred_strided_broadcast<mode>"
+   [(set (match_operand:V_VLS 0 "register_operand")
+ 	(if_then_else:V_VLS
+ 	  (unspec:<VM>
+ 	    [(match_operand:<VM> 1 "strided_broadcast_mask_operand")
+ 	     (match_operand 4 "vector_length_operand")
+ 	     (match_operand 5 "const_int_operand")
+ 	     (match_operand 6 "const_int_operand")
+ 	     (match_operand 7 "const_int_operand")
+ 	     (reg:SI VL_REGNUM)
+ 	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+ 	  (vec_duplicate:V_VLS
+ 	    (match_operand:<VEL> 3 "strided_broadcast_operand"))
+ 	  (match_operand:V_VLS 2 "vector_merge_operand")))]
+   "TARGET_VECTOR"
+ {
+   if (satisfies_constraint_Wb1 (operands[1]))
+     {
+       /* If we're asked to set a single element (like vmv.s.x but we
+ 	 need to go via memory here) and the tail policy is agnostic
+ 	 we can overwrite all elements.
+ 	 Thus, set the mask to broadcast.  */
+       operands[1] = CONSTM1_RTX (<VM>mode);
+       if (!satisfies_constraint_vu (operands[2])
+ 	  && GET_MODE_SIZE (<VEL>mode) > UNITS_PER_WORD)
+ 	{
+ 	  /* Case 2: vmv.s.x (TU, x == memory) ==>
+ 	     vl = 0 or 1; + vlse.v (TU) in RV32 system  */
+ 	  /* In this case we must not overwrite the residual elements,
+ 	     so set the vector length to 0/1.  */
+ 	  operands[4] = riscv_vector::gen_avl_for_scalar_move (operands[4]);
+ 	}
+     }
+ })
+ 
+ (define_insn_and_split "*pred_strided_broadcast<mode>"
+   [(set (match_operand:V_VLSI 0 "register_operand"                  "=vd, vd, vr, vr")
+ 	(if_then_else:V_VLSI
+ 	  (unspec:<VM>
+ 	    [(match_operand:<VM> 1 "strided_broadcast_mask_operand" " vm, vm,Wc1,Wc1")
+ 	     (match_operand 4 "vector_length_operand"               "rvl,rvl,rvl,rvl")
+ 	     (match_operand 5 "const_int_operand"                   "  i,  i,  i,  i")
+ 	     (match_operand 6 "const_int_operand"                   "  i,  i,  i,  i")
+ 	     (match_operand 7 "const_int_operand"                   "  i,  i,  i,  i")
+ 	     (reg:SI VL_REGNUM)
+ 	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+ 	  (vec_duplicate:V_VLSI
+ 	    (match_operand:<VEL> 3 "strided_broadcast_operand"	    "  A,  A,  A,  A"))
+ 	  (match_operand:V_VLSI 2 "vector_merge_operand"            " vu,  0, vu,  0")))]
+   "TARGET_VECTOR"
+   "@
+    vlse<sew>.v\t%0,%3,zero,%1.t
+    vlse<sew>.v\t%0,%3,zero,%1.t
+    vlse<sew>.v\t%0,%3,zero
+    vlse<sew>.v\t%0,%3,zero"
+   "&& !strided_load_broadcast_p () && can_create_pseudo_p ()"
+   [(const_int 0)]
+   {
+     rtx tmp = gen_reg_rtx (V1DImode);
+     emit_move_insn (tmp, gen_lowpart (V1DImode, operands[3]));
+     tmp = lowpart_subreg (<MODE>mode, tmp, V1DImode);
+ 
+     emit_insn
+       (gen_pred_gather<mode>_scalar
+        (operands[0], operands[1], operands[2], tmp, CONST0_RTX (Pmode),
+ 	operands[4], operands[5], operands[6], operands[7]));
+     DONE;
+   }
+   [(set_attr "type" "vlds,vlds,vlds,vlds")
+    (set_attr "mode" "<MODE>")])
+ 
+ (define_insn_and_split "*pred_strided_broadcast<mode>_zvfhmin"
+   [(set (match_operand:V_VLSF_ZVFHMIN   0 "register_operand"               "=vr,  vr,  vr,  vr")
+ 	(if_then_else:V_VLSF_ZVFHMIN
+ 	  (unspec:<VM>
+ 	    [(match_operand:<VM>        1 "strided_broadcast_mask_operand" " vm,  vm, Wc1, Wc1")
+ 	     (match_operand             4 "vector_length_operand"          "rvl, rvl, rvl, rvl")
+ 	     (match_operand             5 "const_int_operand"              "  i,   i,   i,   i")
+ 	     (match_operand             6 "const_int_operand"              "  i,   i,   i,   i")
+ 	     (match_operand             7 "const_int_operand"              "  i,   i,   i,   i")
+ 	     (reg:SI VL_REGNUM)
+ 	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+ 	  (vec_duplicate:V_VLSF_ZVFHMIN
+ 	    (match_operand:<VEL>        3 "strided_broadcast_operand"	   "  A,   A,   A,   A"))
+ 	  (match_operand:V_VLSF_ZVFHMIN 2 "vector_merge_operand"           " vu,   0,  vu,   0")))]
+   "TARGET_VECTOR"
+   "@
+    vlse<sew>.v\t%0,%3,zero,%1.t
+    vlse<sew>.v\t%0,%3,zero,%1.t
+    vlse<sew>.v\t%0,%3,zero
+    vlse<sew>.v\t%0,%3,zero"
+   "&& !strided_load_broadcast_p ()
+    && <VEL>mode == HFmode
+    && can_create_pseudo_p ()"
+   [(const_int 0)]
+   {
+     poly_uint64 nunits = GET_MODE_NUNITS (<MODE>mode);
+     machine_mode vmodehi
+       = riscv_vector::get_vector_mode (HImode, nunits).require ();
+     rtx ops[] = {gen_lowpart (vmodehi, operands[0]),
+ 		 gen_lowpart (HImode, operands[3])};
+     riscv_vector::emit_avltype_insn (code_for_pred_broadcast (vmodehi),
+ 				     riscv_vector::UNARY_OP, ops,
+ 				     (riscv_vector::avl_type) INTVAL (operands[7]),
+ 				     operands[4]);
+     DONE;
+   }
+   [(set_attr "type" "vlds,vlds,vlds,vlds")
+    (set_attr "mode" "<MODE>")])
+ 
+ 
  ;; -------------------------------------------------------------------------------
  ;; ---- Predicated Strided loads/stores
  ;; -------------------------------------------------------------------------------
***************
*** 4639,4646 ****
  ;; Handle GET_MODE_INNER (mode) = DImode. We need to split them since
  ;; we need to deal with SEW = 64 in RV32 system.
  (define_expand "@pred_<sat_op><mode>_scalar"
!   [(set (match_operand:VI_D 0 "register_operand")
! 	(if_then_else:VI_D
  	  (unspec:<VM>
  	    [(match_operand:<VM> 1 "vector_mask_operand")
  	     (match_operand 5 "vector_length_operand")
--- 4679,4686 ----
  ;; Handle GET_MODE_INNER (mode) = DImode. We need to split them since
  ;; we need to deal with SEW = 64 in RV32 system.
  (define_expand "@pred_<sat_op><mode>_scalar"
!   [(set (match_operand:V_VLSI_D 0 "register_operand")
! 	(if_then_else:V_VLSI_D
  	  (unspec:<VM>
  	    [(match_operand:<VM> 1 "vector_mask_operand")
  	     (match_operand 5 "vector_length_operand")
***************
*** 4651,4660 ****
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)
  	     (reg:SI VXRM_REGNUM)] UNSPEC_VPREDICATE)
! 	  (unspec:VI_D
! 	    [(match_operand:VI_D 3 "register_operand")
  	     (match_operand:<VEL> 4 "reg_or_int_operand")] VSAT_ARITH_OP)
! 	  (match_operand:VI_D 2 "vector_merge_operand")))]
    "TARGET_VECTOR"
  {
    if (riscv_vector::sew64_scalar_helper (
--- 4691,4700 ----
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)
  	     (reg:SI VXRM_REGNUM)] UNSPEC_VPREDICATE)
! 	  (unspec:V_VLSI_D
! 	    [(match_operand:V_VLSI_D 3 "register_operand")
  	     (match_operand:<VEL> 4 "reg_or_int_operand")] VSAT_ARITH_OP)
! 	  (match_operand:V_VLSI_D 2 "vector_merge_operand")))]
    "TARGET_VECTOR"
  {
    if (riscv_vector::sew64_scalar_helper (
***************
*** 4673,4680 ****
  })
  
  (define_insn "*pred_<sat_op><mode>_scalar"
!   [(set (match_operand:VI_D 0 "register_operand"         "=vd, vr, vd, vr")
! 	(if_then_else:VI_D
  	  (unspec:<VM>
  	    [(match_operand:<VM> 1 "vector_mask_operand" " vm, vm,Wc1,Wc1")
  	     (match_operand 5 "vector_length_operand"    "rvl,rvl,rvl,rvl")
--- 4713,4720 ----
  })
  
  (define_insn "*pred_<sat_op><mode>_scalar"
!   [(set (match_operand:V_VLSI_D 0 "register_operand"         "=vd, vr, vd, vr")
! 	(if_then_else:V_VLSI_D
  	  (unspec:<VM>
  	    [(match_operand:<VM> 1 "vector_mask_operand" " vm, vm,Wc1,Wc1")
  	     (match_operand 5 "vector_length_operand"    "rvl,rvl,rvl,rvl")
***************
*** 4685,4702 ****
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)
  	     (reg:SI VXRM_REGNUM)] UNSPEC_VPREDICATE)
! 	  (unspec:VI_D
! 	    [(match_operand:VI_D 3 "register_operand"    " vr, vr, vr, vr")
  	     (match_operand:<VEL> 4 "reg_or_0_operand"   " rJ, rJ, rJ, rJ")] VSAT_ARITH_OP)
! 	  (match_operand:VI_D 2 "vector_merge_operand"   " vu,  0, vu,  0")))]
    "TARGET_VECTOR"
    "v<sat_op>.vx\t%0,%3,%z4%p1"
    [(set_attr "type" "<sat_insn_type>")
     (set_attr "mode" "<MODE>")])
  
  (define_insn "*pred_<sat_op><mode>_extended_scalar"
!   [(set (match_operand:VI_D 0 "register_operand"            "=vd, vr, vd, vr")
! 	(if_then_else:VI_D
  	  (unspec:<VM>
  	    [(match_operand:<VM> 1 "vector_mask_operand"    " vm, vm,Wc1,Wc1")
  	     (match_operand 5 "vector_length_operand"       "rvl,rvl,rvl,rvl")
--- 4725,4742 ----
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)
  	     (reg:SI VXRM_REGNUM)] UNSPEC_VPREDICATE)
! 	  (unspec:V_VLSI_D
! 	    [(match_operand:V_VLSI_D 3 "register_operand"    " vr, vr, vr, vr")
  	     (match_operand:<VEL> 4 "reg_or_0_operand"   " rJ, rJ, rJ, rJ")] VSAT_ARITH_OP)
! 	  (match_operand:V_VLSI_D 2 "vector_merge_operand"   " vu,  0, vu,  0")))]
    "TARGET_VECTOR"
    "v<sat_op>.vx\t%0,%3,%z4%p1"
    [(set_attr "type" "<sat_insn_type>")
     (set_attr "mode" "<MODE>")])
  
  (define_insn "*pred_<sat_op><mode>_extended_scalar"
!   [(set (match_operand:V_VLSI_D 0 "register_operand"            "=vd, vr, vd, vr")
! 	(if_then_else:V_VLSI_D
  	  (unspec:<VM>
  	    [(match_operand:<VM> 1 "vector_mask_operand"    " vm, vm,Wc1,Wc1")
  	     (match_operand 5 "vector_length_operand"       "rvl,rvl,rvl,rvl")
***************
*** 4707,4717 ****
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)
  	     (reg:SI VXRM_REGNUM)] UNSPEC_VPREDICATE)
! 	  (unspec:VI_D
! 	    [(match_operand:VI_D 3 "register_operand"       " vr, vr, vr, vr")
  	     (sign_extend:<VEL>
  	       (match_operand:<VSUBEL> 4 "reg_or_0_operand" " rJ, rJ, rJ, rJ"))] VSAT_ARITH_OP)
! 	  (match_operand:VI_D 2 "vector_merge_operand"      " vu,  0, vu,  0")))]
    "TARGET_VECTOR && !TARGET_64BIT"
    "v<sat_op>.vx\t%0,%3,%z4%p1"
    [(set_attr "type" "<sat_insn_type>")
--- 4747,4757 ----
  	     (reg:SI VL_REGNUM)
  	     (reg:SI VTYPE_REGNUM)
  	     (reg:SI VXRM_REGNUM)] UNSPEC_VPREDICATE)
! 	  (unspec:V_VLSI_D
! 	    [(match_operand:V_VLSI_D 3 "register_operand"       " vr, vr, vr, vr")
  	     (sign_extend:<VEL>
  	       (match_operand:<VSUBEL> 4 "reg_or_0_operand" " rJ, rJ, rJ, rJ"))] VSAT_ARITH_OP)
! 	  (match_operand:V_VLSI_D 2 "vector_merge_operand"      " vu,  0, vu,  0")))]
    "TARGET_VECTOR && !TARGET_64BIT"
    "v<sat_op>.vx\t%0,%3,%z4%p1"
    [(set_attr "type" "<sat_insn_type>")
diff -Nrcpad gcc-16-20250720/gcc/config/riscv/xiangshan.md gcc-16-20250727/gcc/config/riscv/xiangshan.md
*** gcc-16-20250720/gcc/config/riscv/xiangshan.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/riscv/xiangshan.md	Sun Jul 27 22:32:08 2025
***************
*** 107,113 ****
  ;; they are just dummies like this one.
  (define_insn_reservation "xiangshan_alu_unknown" 1
    (and (eq_attr "tune" "xiangshan")
!        (eq_attr "type" "zicond,min,max,minu,maxu,clz,ctz,cpop,ghost,rotate,clmul,condmove,crypto,mvpair,rdvlenb,rdvl,wrvxrm,wrfrm,rdfrm,vsetvl,vsetvl_pre,vlde,vste,vldm,vstm,vlds,vsts,vldux,vldox,vstux,vstox,vldff,vldr,vstr,vlsegde,vssegte,vlsegds,vssegts,vlsegdux,vlsegdox,vssegtux,vssegtox,vlsegdff,vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,vimul,vidiv,viwmul,vimuladd,sf_vqmacc,viwmuladd,vimerge,vimov,vsalu,vaalu,vsmul,vsshift,vnclip,sf_vfnrclip,vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp,vfcmp,vfminmax,vfsgnj,vfclass,vfmerge,vfmov,vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi,vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof,vired,viwred,vfredu,vfredo,vfwredu,vfwredo,vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,vfmovvf,vfmovfv,vslideup,vslidedown,vislide1up,vislide1down,vfslide1up,vfslide1down,vgather,vcompress,vmov,vector,vandn,vbrev,vbrev8,vrev8,vclz,vctz,vcpop,vrol,vror,vwsll,vclmul,vclmulh,vghsh,vgmul,vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz,vsha2ms,vsha2ch,vsha2cl,vsm4k,vsm4r,vsm3me,vsm3c,vfncvtbf16,vfwcvtbf16,vfwmaccbf16"))
    "xs_alu_rs")
  
  ;; ----------------------------------------------------
--- 107,114 ----
  ;; they are just dummies like this one.
  (define_insn_reservation "xiangshan_alu_unknown" 1
    (and (eq_attr "tune" "xiangshan")
!        (eq_attr "type" "zicond,min,max,minu,maxu,clz,ctz,cpop,ghost,rotate,clmul,condmove,crypto,mvpair,rdvlenb,rdvl,wrvxrm,wrfrm,rdfrm,vsetvl,vsetvl_pre,vlde,vste,vldm,vstm,vlds,vsts,vldux,vldox,vstux,vstox,vldff,vldr,vstr,vlsegde,vssegte,vlsegds,vssegts,vlsegdux,vlsegdox,vssegtux,vssegtox,vlsegdff,vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,vimul,vidiv,viwmul,vimuladd,sf_vqmacc,viwmuladd,vimerge,vimov,vsalu,vaalu,vsmul,vsshift,vnclip,sf_vfnrclip,vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp,vfcmp,vfminmax,vfsgnj,vfclass,vfmerge,vfmov,vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi,vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof,vired,viwred,vfredu,vfredo,vfwredu,vfwredo,vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,vfmovvf,vfmovfv,vslideup,vslidedown,vislide1up,vislide1down,vfslide1up,vfslide1down,vgather,vcompress,vmov,vector,vandn,vbrev,vbrev8,vrev8,vclz,vctz,vcpop,vrol,vror,vwsll,vclmul,vclmulh,vghsh,vgmul,vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz,vsha2ms,vsha2ch,vsha2cl,vsm4k,vsm4r,vsm3me,vsm3c,vfncvtbf16,vfwcvtbf16,vfwmaccbf16,sf_vc,sf_vc_se"))
! 
    "xs_alu_rs")
  
  ;; ----------------------------------------------------
diff -Nrcpad gcc-16-20250720/gcc/config/rs6000/rs6000.cc gcc-16-20250727/gcc/config/rs6000/rs6000.cc
*** gcc-16-20250720/gcc/config/rs6000/rs6000.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/rs6000/rs6000.cc	Sun Jul 27 22:32:08 2025
*************** static bool
*** 4951,4960 ****
  rs6000_builtin_support_vector_misalignment (machine_mode mode,
  					    const_tree type,
  					    int misalignment,
! 					    bool is_packed)
  {
    if (TARGET_VSX)
      {
        if (TARGET_EFFICIENT_UNALIGNED_VSX)
  	return true;
  
--- 4951,4969 ----
  rs6000_builtin_support_vector_misalignment (machine_mode mode,
  					    const_tree type,
  					    int misalignment,
! 					    bool is_packed,
! 					    bool is_gather_scatter)
  {
    if (TARGET_VSX)
      {
+       if (is_gather_scatter)
+ 	{
+ 	  if (TARGET_ALTIVEC && is_packed)
+ 	    return false;
+ 	  else
+ 	    return true;
+ 	}
+ 
        if (TARGET_EFFICIENT_UNALIGNED_VSX)
  	return true;
  
diff -Nrcpad gcc-16-20250720/gcc/config/s390/s390.cc gcc-16-20250727/gcc/config/s390/s390.cc
*** gcc-16-20250720/gcc/config/s390/s390.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/s390/s390.cc	Sun Jul 27 22:32:08 2025
*************** s390_valid_target_attribute_inner_p (tre
*** 16874,16881 ****
  	      generate_option (opt, NULL, value, CL_TARGET, &decoded);
  	      s390_handle_option (opts, new_opts_set, &decoded, input_location);
  	      set_option (opts, new_opts_set, opt, value,
! 			  p + opt_len, DK_UNSPECIFIED, input_location,
! 			  global_dc);
  	    }
  	  else
  	    {
--- 16874,16882 ----
  	      generate_option (opt, NULL, value, CL_TARGET, &decoded);
  	      s390_handle_option (opts, new_opts_set, &decoded, input_location);
  	      set_option (opts, new_opts_set, opt, value,
! 			  p + opt_len,
! 			  static_cast<int> (diagnostics::kind::unspecified),
! 			  input_location, global_dc);
  	    }
  	  else
  	    {
*************** s390_valid_target_attribute_inner_p (tre
*** 16892,16899 ****
  	  arg_ok = opt_enum_arg_to_value (opt, p + opt_len, &value, CL_TARGET);
  	  if (arg_ok)
  	    set_option (opts, new_opts_set, opt, value,
! 			p + opt_len, DK_UNSPECIFIED, input_location,
! 			global_dc);
  	  else
  	    {
  	      error ("attribute %<target%> argument %qs is unknown", orig_p);
--- 16893,16901 ----
  	  arg_ok = opt_enum_arg_to_value (opt, p + opt_len, &value, CL_TARGET);
  	  if (arg_ok)
  	    set_option (opts, new_opts_set, opt, value,
! 			p + opt_len,
! 			static_cast<int> (diagnostics::kind::unspecified),
! 			input_location, global_dc);
  	  else
  	    {
  	      error ("attribute %<target%> argument %qs is unknown", orig_p);
*************** static bool
*** 17345,17357 ****
  s390_support_vector_misalignment (machine_mode mode ATTRIBUTE_UNUSED,
  				  const_tree type ATTRIBUTE_UNUSED,
  				  int misalignment ATTRIBUTE_UNUSED,
! 				  bool is_packed ATTRIBUTE_UNUSED)
  {
    if (TARGET_VX)
      return true;
  
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed);
  }
  
  /* The vector ABI requires vector types to be aligned on an 8 byte
--- 17347,17361 ----
  s390_support_vector_misalignment (machine_mode mode ATTRIBUTE_UNUSED,
  				  const_tree type ATTRIBUTE_UNUSED,
  				  int misalignment ATTRIBUTE_UNUSED,
! 				  bool is_packed ATTRIBUTE_UNUSED,
! 				  bool is_gather_scatter ATTRIBUTE_UNUSED)
  {
    if (TARGET_VX)
      return true;
  
    return default_builtin_support_vector_misalignment (mode, type, misalignment,
! 						      is_packed,
! 						      is_gather_scatter);
  }
  
  /* The vector ABI requires vector types to be aligned on an 8 byte
*************** f_constraint_p (const char *constraint)
*** 17843,17851 ****
    for (size_t i = 0, c_len = strlen (constraint); i < c_len;
         i += CONSTRAINT_LEN (constraint[i], constraint + i))
      {
!       if (constraint[i] == 'f')
  	seen_f_p = true;
!       if (constraint[i] == 'v')
  	seen_v_p = true;
      }
  
--- 17847,17857 ----
    for (size_t i = 0, c_len = strlen (constraint); i < c_len;
         i += CONSTRAINT_LEN (constraint[i], constraint + i))
      {
!       if (constraint[i] == 'f'
! 	  || (constraint[i] == '{' && constraint[i + 1] == 'f'))
  	seen_f_p = true;
!       if (constraint[i] == 'v'
! 	  || (constraint[i] == '{' && constraint[i + 1] == 'v'))
  	seen_v_p = true;
      }
  
*************** s390_md_asm_adjust (vec<rtx> &outputs, v
*** 17935,17941 ****
  	continue;
        bool allows_mem, allows_reg, is_inout;
        bool ok = parse_output_constraint (&constraint, i, ninputs, noutputs,
! 					 &allows_mem, &allows_reg, &is_inout);
        gcc_assert (ok);
        if (!f_constraint_p (constraint))
  	/* Long double with a constraint other than "=f" - nothing to do.  */
--- 17941,17948 ----
  	continue;
        bool allows_mem, allows_reg, is_inout;
        bool ok = parse_output_constraint (&constraint, i, ninputs, noutputs,
! 					 &allows_mem, &allows_reg, &is_inout,
! 					 nullptr);
        gcc_assert (ok);
        if (!f_constraint_p (constraint))
  	/* Long double with a constraint other than "=f" - nothing to do.  */
*************** s390_md_asm_adjust (vec<rtx> &outputs, v
*** 17980,17986 ****
        bool allows_mem, allows_reg;
        bool ok = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
  					constraints.address (), &allows_mem,
! 					&allows_reg);
        gcc_assert (ok);
        if (!f_constraint_p (constraint))
  	/* Long double with a constraint other than "f" (or "=f" for inout
--- 17987,17993 ----
        bool allows_mem, allows_reg;
        bool ok = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
  					constraints.address (), &allows_mem,
! 					&allows_reg, nullptr);
        gcc_assert (ok);
        if (!f_constraint_p (constraint))
  	/* Long double with a constraint other than "f" (or "=f" for inout
diff -Nrcpad gcc-16-20250720/gcc/config/xtensa/xtensa.cc gcc-16-20250727/gcc/config/xtensa/xtensa.cc
*** gcc-16-20250720/gcc/config/xtensa/xtensa.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/xtensa/xtensa.cc	Sun Jul 27 22:32:08 2025
*************** constantpool_address_p (const_rtx addr)
*** 601,608 ****
  
        /* Make sure the address is word aligned.  */
        offset = XEXP (addr, 1);
!       if ((!CONST_INT_P (offset))
! 	  || ((INTVAL (offset) & 3) != 0))
  	return false;
  
        sym = XEXP (addr, 0);
--- 601,608 ----
  
        /* Make sure the address is word aligned.  */
        offset = XEXP (addr, 1);
!       if (! CONST_INT_P (offset)
! 	  || (INTVAL (offset) & 3) != 0)
  	return false;
  
        sym = XEXP (addr, 0);
*************** constantpool_address_p (const_rtx addr)
*** 611,616 ****
--- 611,617 ----
    if (SYMBOL_REF_P (sym)
        && CONSTANT_POOL_ADDRESS_P (sym))
      return true;
+ 
    return false;
  }
  
*************** xtensa_rtx_costs (rtx x, machine_mode mo
*** 4694,4722 ****
      }
  }
  
  static bool
  xtensa_is_insn_L32R_p (const rtx_insn *insn)
  {
!   rtx x = PATTERN (insn);
  
!   if (GET_CODE (x) != SET)
      return false;
  
!   x = XEXP (x, 1);
!   if (MEM_P (x))
!     {
!       x = XEXP (x, 0);
!       return (SYMBOL_REF_P (x) || CONST_INT_P (x))
! 	     && CONSTANT_POOL_ADDRESS_P (x);
!     }
! 
!   /* relaxed MOVI instructions, that will be converted to L32R by the
!      assembler.  */
!   if (CONST_INT_P (x)
!       && ! xtensa_simm12b (INTVAL (x)))
      return true;
  
!   return false;
  }
  
  /* Compute a relative costs of RTL insns.  This is necessary in order to
--- 4695,4726 ----
      }
  }
  
+ /* Return TRUE if the specified insn corresponds to one or more L32R machine
+    instructions.  */
+ 
  static bool
  xtensa_is_insn_L32R_p (const rtx_insn *insn)
  {
!   rtx pat, dest, src;
  
!   /* "PATTERN (insn)" can be used without checking, see insn_cost()
!      in gcc/rtlanal.cc.  */
!   if (GET_CODE (pat = PATTERN (insn)) != SET
!       || ! register_operand (dest = SET_DEST (pat), VOIDmode))
      return false;
  
!   if (constantpool_mem_p (src = SET_SRC (pat)))
      return true;
  
!   /* Return true if:
!      - CONST16 instruction is not configured, and
!      - the source is some constant, and also
!      - negation of "the source is integer and fits into the immediate
!        field".  */
!   return (!TARGET_CONST16
! 	  && CONSTANT_P (src)
! 	  && ! ((GET_MODE (dest) == SImode || GET_MODE (dest) == HImode)
! 		&& CONST_INT_P (src) && xtensa_simm12b (INTVAL (src))));
  }
  
  /* Compute a relative costs of RTL insns.  This is necessary in order to
*************** xtensa_is_insn_L32R_p (const rtx_insn *i
*** 4725,4731 ****
  static int
  xtensa_insn_cost (rtx_insn *insn, bool speed)
  {
!   if (!(recog_memoized (insn) < 0))
      {
        int len = get_attr_length (insn);
  
--- 4729,4735 ----
  static int
  xtensa_insn_cost (rtx_insn *insn, bool speed)
  {
!   if (! (recog_memoized (insn) < 0))
      {
        int len = get_attr_length (insn);
  
*************** xtensa_insn_cost (rtx_insn *insn, bool s
*** 4738,4744 ****
  
  	  /* "L32R" may be particular slow (implementation-dependent).  */
  	  if (xtensa_is_insn_L32R_p (insn))
! 	    return COSTS_N_INSNS (1 + xtensa_extra_l32r_costs);
  
  	  /* Cost based on the pipeline model.  */
  	  switch (get_attr_type (insn))
--- 4742,4748 ----
  
  	  /* "L32R" may be particular slow (implementation-dependent).  */
  	  if (xtensa_is_insn_L32R_p (insn))
! 	    return COSTS_N_INSNS ((1 + xtensa_extra_l32r_costs) * n);
  
  	  /* Cost based on the pipeline model.  */
  	  switch (get_attr_type (insn))
*************** xtensa_insn_cost (rtx_insn *insn, bool s
*** 4783,4789 ****
  	    {
  	      /* "L32R" itself plus constant in litpool.  */
  	      if (xtensa_is_insn_L32R_p (insn))
! 		len = 3 + 4;
  
  	      /* Consider fractional instruction length (for example, ".n"
  		 short instructions or "L32R" litpool constants.  */
--- 4787,4793 ----
  	    {
  	      /* "L32R" itself plus constant in litpool.  */
  	      if (xtensa_is_insn_L32R_p (insn))
! 		len += (len / 3) * 4;
  
  	      /* Consider fractional instruction length (for example, ".n"
  		 short instructions or "L32R" litpool constants.  */
diff -Nrcpad gcc-16-20250720/gcc/config/xtensa/xtensa.md gcc-16-20250727/gcc/config/xtensa/xtensa.md
*** gcc-16-20250720/gcc/config/xtensa/xtensa.md	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/config/xtensa/xtensa.md	Sun Jul 27 22:32:08 2025
***************
*** 1297,1303 ****
        std::swap (operands[0], operands[1]);
        std::swap (operands[2], operands[3]);
      }
! })
  
  (define_split
    [(set (match_operand:DI 0 "register_operand")
--- 1297,1306 ----
        std::swap (operands[0], operands[1]);
        std::swap (operands[2], operands[3]);
      }
! }
!   [(set_attr "type"	"move,move,load,load,store")
!    (set_attr "mode"	"DI")
!    (set_attr "length"	"6,12,6,6,6")])
  
  (define_split
    [(set (match_operand:DI 0 "register_operand")
***************
*** 1344,1350 ****
     %v0s32i\t%1, %0
     rsr\t%0, ACCLO
     wsr\t%1, ACCLO"
!   [(set_attr "type"	"move,move,move,load,store,store,move,move,move,move,move,load,load,store,rsr,wsr")
     (set_attr "mode"	"SI")
     (set_attr "length"	"2,2,2,2,2,2,3,3,3,3,6,3,3,3,3,3")])
  
--- 1347,1353 ----
     %v0s32i\t%1, %0
     rsr\t%0, ACCLO
     wsr\t%1, ACCLO"
!   [(set_attr "type"	"move,move,move,load,store,store,move,move,move,load,move,load,load,store,rsr,wsr")
     (set_attr "mode"	"SI")
     (set_attr "length"	"2,2,2,2,2,2,3,3,3,3,6,3,3,3,3,3")])
  
***************
*** 1410,1416 ****
     %v0s16i\t%1, %0
     rsr\t%0, ACCLO
     wsr\t%1, ACCLO"
!   [(set_attr "type"	"move,move,move,move,move,load,load,store,rsr,wsr")
     (set_attr "mode"	"HI")
     (set_attr "length"	"2,2,3,3,3,3,3,3,3,3")])
  
--- 1413,1419 ----
     %v0s16i\t%1, %0
     rsr\t%0, ACCLO
     wsr\t%1, ACCLO"
!   [(set_attr "type"	"move,move,move,move,load,load,load,store,rsr,wsr")
     (set_attr "mode"	"HI")
     (set_attr "length"	"2,2,3,3,3,3,3,3,3,3")])
  
***************
*** 1519,1525 ****
     const16\t%0, %t1\;const16\t%0, %b1
     %v1l32i\t%0, %1
     %v0s32i\t%1, %0"
!   [(set_attr "type"	"farith,fload,fstore,move,load,load,store,move,farith,farith,move,move,load,store")
     (set_attr "mode"	"SF")
     (set_attr "length"	"3,3,3,2,3,2,2,3,3,3,3,6,3,3")])
  
--- 1522,1528 ----
     const16\t%0, %t1\;const16\t%0, %b1
     %v1l32i\t%0, %1
     %v0s32i\t%1, %0"
!   [(set_attr "type"	"farith,fload,fstore,move,load,load,store,move,farith,farith,load,move,load,store")
     (set_attr "mode"	"SF")
     (set_attr "length"	"3,3,3,2,3,2,2,3,3,3,3,6,3,3")])
  
***************
*** 1643,1649 ****
        std::swap (operands[0], operands[1]);
        std::swap (operands[2], operands[3]);
      }
! })
  
  ;; Block moves
  
--- 1646,1655 ----
        std::swap (operands[0], operands[1]);
        std::swap (operands[2], operands[3]);
      }
! }
!   [(set_attr "type"	"move,load,move,load,load,store")
!    (set_attr "mode"	"DF")
!    (set_attr "length"	"6,6,12,6,6,6")])
  
  ;; Block moves
  
diff -Nrcpad gcc-16-20250720/gcc/config.gcc gcc-16-20250727/gcc/config.gcc
*** gcc-16-20250720/gcc/config.gcc	Sun Jul 20 22:32:08 2025
--- gcc-16-20250727/gcc/config.gcc	Sun Jul 27 22:32:08 2025
*************** sparc*-*-solaris2*)
*** 3504,3513 ****
  	    sparc64-*-* | sparcv9-*-*)
  		tm_file="sparc/default64.h ${tm_file}"
  		;;
- 	    *)
- 		test x$with_cpu != x || with_cpu=v9
- 		;;
  	esac
  	tmake_file="${tmake_file} sparc/t-sparc sparc/t-sol2"
  	;;
  sparc-wrs-vxworks)
--- 3504,3512 ----
  	    sparc64-*-* | sparcv9-*-*)
  		tm_file="sparc/default64.h ${tm_file}"
  		;;
  	esac
+ 	# Match Studio 12.6 cc.
+ 	with_cpu=${with_cpu:-ultrasparc3}
  	tmake_file="${tmake_file} sparc/t-sparc sparc/t-sol2"
  	;;
  sparc-wrs-vxworks)
diff -Nrcpad gcc-16-20250720/gcc/configure gcc-16-20250727/gcc/configure
*** gcc-16-20250720/gcc/configure	Sun Jul 20 22:32:56 2025
--- gcc-16-20250727/gcc/configure	Sun Jul 27 22:32:21 2025
*************** $as_echo "$as_me: executing $ac_file com
*** 36498,36504 ****
      "depdir":C) $SHELL $ac_aux_dir/mkinstalldirs $DEPDIR ;;
      "gccdepdir":C)
    ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
!   for lang in $subdirs c-family common analyzer text-art rtl-ssa sym-exec
    do
        ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR
    done ;;
--- 36498,36504 ----
      "depdir":C) $SHELL $ac_aux_dir/mkinstalldirs $DEPDIR ;;
      "gccdepdir":C)
    ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
!   for lang in $subdirs c-family common analyzer diagnostics text-art rtl-ssa sym-exec
    do
        ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR
    done ;;
diff -Nrcpad gcc-16-20250720/gcc/configure.ac gcc-16-20250727/gcc/configure.ac
*** gcc-16-20250720/gcc/configure.ac	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/configure.ac	Sun Jul 27 22:32:08 2025
*************** AC_CHECK_HEADERS(ext/hash_map)
*** 1397,1403 ****
  ZW_CREATE_DEPDIR
  AC_CONFIG_COMMANDS([gccdepdir],[
    ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
!   for lang in $subdirs c-family common analyzer text-art rtl-ssa sym-exec
    do
        ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR
    done], [subdirs="$subdirs" ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR])
--- 1397,1403 ----
  ZW_CREATE_DEPDIR
  AC_CONFIG_COMMANDS([gccdepdir],[
    ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
!   for lang in $subdirs c-family common analyzer diagnostics text-art rtl-ssa sym-exec
    do
        ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR
    done], [subdirs="$subdirs" ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR])
diff -Nrcpad gcc-16-20250720/gcc/coretypes.h gcc-16-20250727/gcc/coretypes.h
*** gcc-16-20250720/gcc/coretypes.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/coretypes.h	Sun Jul 27 22:32:08 2025
*************** struct cl_option;
*** 164,171 ****
  struct cl_decoded_option;
  struct cl_option_handlers;
  class rich_location;
! class diagnostic_context;
! class diagnostic_text_output_format;
  class pretty_printer;
  class diagnostic_event_id_t;
  typedef const char * (*diagnostic_input_charset_callback)(const char *);
--- 164,173 ----
  struct cl_decoded_option;
  struct cl_option_handlers;
  class rich_location;
! namespace diagnostics {
!   class context;
!   class text_sink;
! } // namespace diagnostics
  class pretty_printer;
  class diagnostic_event_id_t;
  typedef const char * (*diagnostic_input_charset_callback)(const char *);
diff -Nrcpad gcc-16-20250720/gcc/cp/ChangeLog gcc-16-20250727/gcc/cp/ChangeLog
*** gcc-16-20250720/gcc/cp/ChangeLog	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/ChangeLog	Sun Jul 27 22:32:08 2025
***************
*** 1,3 ****
--- 1,173 ----
+ 2025-07-27  Nathaniel Shead  <nathanieloshead@gmail.com>
+ 
+ 	* cp-tree.h (struct lang_type): Add comment mentioning modules.
+ 	* module.cc (trees_out::lang_type_bools): Stream new flags, use
+ 	gcc_checking_assert.
+ 	(trees_in::lang_type_bools): Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* constexpr.cc: Update usage of "diagnostic_info" to explicitly
+ 	refer to "diagnostics::diagnostic_info".
+ 	* cp-tree.h: Likewise.
+ 	* error.cc: Likewise.
+ 	* module.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* call.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* constexpr.cc: Likewise.
+ 	* cp-tree.h: Likewise.
+ 	* decl.cc: Likewise.
+ 	* error.cc: Likewise.
+ 	* init.cc: Likewise.
+ 	* method.cc: Likewise.
+ 	* module.cc: Likewise.
+ 	* parser.cc: Likewise.
+ 	* pt.cc: Likewise.
+ 	* semantics.cc: Likewise.
+ 	* typeck.cc: Likewise.
+ 	* typeck2.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* cp-tree.h: Update for renaming of diagnostic_option_id to
+ 	diagnostics::option_id.
+ 	* decl.cc: Likewise.
+ 	* error.cc: Likewise.
+ 	* name-lookup.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* error.cc: Update for move of diagnostic-color.h to
+ 	diagnostics/color.h.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* cp-tree.h: Update for diagnostic_context becoming
+ 	diagnostics::context.
+ 	* error.cc: Likewise.
+ 	* module.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* constexpr.cc: Update to add "m_" prefix to fields of
+ 	diagnostic_info throughout.
+ 	* error.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* cp-tree.h: Update for move of diagnostics output formats into
+ 	namespace "diagnostics" as "sinks".
+ 	* error.cc: Likewise.
+ 
+ 2025-07-25  Patrick Palka  <ppalka@redhat.com>
+ 
+ 	* call.cc (build_new_op): If the selected candidate is
+ 	rewritten, communicate the LOOKUP_REWRITTEN/REVERSED flags to
+ 	the caller via the 'overload' out-parameter, and stop clearing
+ 	'*overload' in that case.
+ 	* tree.cc (build_min_non_dep_op_overload): Handle rebuilding all
+ 	C++20 rewritten comparison operator expressions.
+ 
+ 2025-07-25  Iain Sandoe  <iain@sandoe.co.uk>
+ 
+ 	PR c++/121219
+ 	* coroutines.cc
+ 	(cp_coroutine_transform::build_ramp_function): Reorder the return
+ 	expressions for the 'normal' and 'allocation failed' cases so that
+ 	NRV constraints are met.
+ 
+ 2025-07-24  Nathaniel Shead  <nathanieloshead@gmail.com>
+ 
+ 	PR c++/117294
+ 	PR c++/113854
+ 	* call.cc (implicit_conversion_error): Hide label when printing
+ 	a stub object.
+ 	(convert_like_internal): Likewise, and nest candidate
+ 	diagnostics.
+ 	* constexpr.cc (diagnose_failing_condition): Nest diagnostics,
+ 	attempt to provide more helpful diagnostics for traits.
+ 	* constraint.cc (satisfy_atom): Pass result before constant
+ 	evaluation to diagnose_atomic_constraint.
+ 	(diagnose_trait_expr): Adjust diagnostics for clarity and
+ 	detail.
+ 	(maybe_diagnose_standard_trait): New function.
+ 	(diagnose_atomic_constraint): Attempt to provide more helpful
+ 	diagnostics for more traits.
+ 	* cp-tree.h (explain_not_noexcept): Declare new function.
+ 	(is_trivially_xible): Add parameter.
+ 	(is_nothrow_xible): Likewise.
+ 	(is_xible): Likewise.
+ 	(is_convertible): Likewise.
+ 	(is_nothrow_convertible): Likewise.
+ 	(diagnose_trait_expr): Declare new function.
+ 	(maybe_diagnose_standard_trait): Declare new function.
+ 	* error.cc (dump_type) <case TREE_VEC>: Handle trait types.
+ 	* except.cc (explain_not_noexcept): New function.
+ 	* method.cc (build_trait_object): Add complain parameter.
+ 	(build_invoke): Propagate complain parameter.
+ 	(assignable_expr): Add explain parameter to show diagnostics.
+ 	(constructible_expr): Likewise.
+ 	(destructible_expr): Likewise.
+ 	(is_xible_helper): Replace trivial flag with explain flag,
+ 	add diagnostics.
+ 	(is_trivially_xible): New explain flag.
+ 	(is_nothrow_xible): Likewise.
+ 	(is_xible): Likewise.
+ 	(is_convertible_helper): Add complain flag.
+ 	(is_convertible): New explain flag.
+ 	(is_nothrow_convertible): Likewise.
+ 	* typeck.cc (cp_build_function_call_vec): Add handling for stub
+ 	objects.
+ 	(convert_arguments): Always return -1 on error.
+ 	* typeck2.cc (cxx_readonly_error): Add handling for stub
+ 	objects.
+ 
+ 2025-07-24  Jason Merrill  <jason@redhat.com>
+ 
+ 	* pt.cc (tsubst_lambda_expr): Revert r9-5971 change.
+ 
+ 2025-07-24  Jason Merrill  <jason@redhat.com>
+ 
+ 	PR c++/114632
+ 	PR c++/101233
+ 	* lambda.cc (maybe_add_lambda_conv_op): Not for xobj lambda.
+ 	* pt.cc (tsubst_function_decl): Add cp_evaluated.
+ 	(alias_ctad_tweaks): Revert PR101233 fix.
+ 
+ 2025-07-24  Nathaniel Shead  <nathanieloshead@gmail.com>
+ 
+ 	PR c++/120412
+ 	* module.cc (trees_out::core_vals): Write TU_LOCAL_ENTITY bits.
+ 	(trees_in::core_vals): Read it.
+ 	(trees_in::tree_node): Handle TU_LOCAL_ENTITY typedefs.
+ 
+ 2025-07-23  Patrick Palka  <ppalka@redhat.com>
+ 
+ 	PR c++/121179
+ 	* call.cc (build_new_op): Don't clear *overload for a simple
+ 	!= to == rewrite.
+ 	* tree.cc (build_min_non_dep_op_overload): Handle TRUTH_NOT_EXPR
+ 	appearing in a rewritten operator expression.
+ 
+ 2025-07-23  Patrick Palka  <ppalka@redhat.com>
+ 
+ 	PR c++/121055
+ 	* method.cc (build_invoke): Correct reference_wrapper handling.
+ 
+ 2025-07-22  Jason Merrill  <jason@redhat.com>
+ 
+ 	PR c++/121068
+ 	* constexpr.cc (cxx_eval_store_expression): Allow ARRAY_REFs
+ 	when activating an array member of a union.
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* semantics.cc (finish_asm_stmt): Pass null pointer to
+ 	parse_{input,output}_constraint().
+ 
  2025-07-16  Kwok Cheung Yeung  <kcyeung@baylibre.com>
  
  	* pt.cc (tsubst_omp_clause_decl): Use OMP_ITERATOR_DECL_P.
diff -Nrcpad gcc-16-20250720/gcc/cp/call.cc gcc-16-20250727/gcc/cp/call.cc
*** gcc-16-20250720/gcc/cp/call.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/call.cc	Sun Jul 27 22:32:08 2025
*************** static void add_candidates (tree, tree,
*** 220,226 ****
  			    bool, tree, tree, int, struct z_candidate **,
  			    tsubst_flags_t);
  static conversion *merge_conversion_sequences (conversion *, conversion *);
! static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
  static conversion *build_identity_conv (tree, tree);
  static inline bool conv_binds_to_array_of_unknown_bound (conversion *);
  static bool conv_is_prvalue (conversion *);
--- 220,227 ----
  			    bool, tree, tree, int, struct z_candidate **,
  			    tsubst_flags_t);
  static conversion *merge_conversion_sequences (conversion *, conversion *);
! static tree build_temp (tree, tree, int, enum diagnostics::kind *,
! 			tsubst_flags_t);
  static conversion *build_identity_conv (tree, tree);
  static inline bool conv_binds_to_array_of_unknown_bound (conversion *);
  static bool conv_is_prvalue (conversion *);
*************** implicit_conversion_error (location_t lo
*** 4927,4932 ****
--- 4928,4938 ----
  	   && !CP_AGGREGATE_TYPE_P (type))
      error_at (loc, "designated initializers cannot be used with a "
  	      "non-aggregate type %qT", type);
+   else if (is_stub_object (expr))
+     /* The expression is generated by a trait check, we don't have
+        a useful location to highlight the label.  */
+     error_at (loc, "could not convert %qH to %qI",
+ 	      TREE_TYPE (expr), type);
    else
      {
        range_label_for_type_mismatch label (TREE_TYPE (expr), type);
*************** build_conditional_expr (const op_locatio
*** 6455,6461 ****
  	       types when the enumeration is still being defined.  */;
  	  else if (complain & (cxx_dialect >= cxx26
  			       ? tf_warning_or_error : tf_warning))
! 	    emit_diagnostic (cxx_dialect >= cxx26 ? DK_PEDWARN : DK_WARNING,
  			     loc, OPT_Wenum_compare, "enumerated mismatch "
  			     "in conditional expression: %qT vs %qT",
  			     arg2_type, arg3_type);
--- 6461,6469 ----
  	       types when the enumeration is still being defined.  */;
  	  else if (complain & (cxx_dialect >= cxx26
  			       ? tf_warning_or_error : tf_warning))
! 	    emit_diagnostic ((cxx_dialect >= cxx26
! 			      ? diagnostics::kind::pedwarn
! 			      : diagnostics::kind::warning),
  			     loc, OPT_Wenum_compare, "enumerated mismatch "
  			     "in conditional expression: %qT vs %qT",
  			     arg2_type, arg3_type);
*************** build_new_op (const op_location_t &loc,
*** 7486,7492 ****
        else if (TREE_CODE (cand->fn) == FUNCTION_DECL)
  	{
  	  if (overload)
! 	    *overload = cand->fn;
  
  	  if (resolve_args (arglist, complain) == NULL)
  	    result = error_mark_node;
--- 7494,7509 ----
        else if (TREE_CODE (cand->fn) == FUNCTION_DECL)
  	{
  	  if (overload)
! 	    {
! 	      if (cand->rewritten ())
! 		/* build_min_non_dep_op_overload needs to know whether the
! 		   candidate is rewritten/reversed.  */
! 		*overload = build_tree_list (build_int_cst (integer_type_node,
! 							    cand->flags),
! 					     cand->fn);
! 	      else
! 		*overload = cand->fn;
! 	    }
  
  	  if (resolve_args (arglist, complain) == NULL)
  	    result = error_mark_node;
*************** build_new_op (const op_location_t &loc,
*** 7535,7543 ****
  	  /* If this was a C++20 rewritten comparison, adjust the result.  */
  	  if (cand->rewritten ())
  	    {
- 	      /* FIXME build_min_non_dep_op_overload can't handle rewrites.  */
- 	      if (overload)
- 		*overload = NULL_TREE;
  	      switch (code)
  		{
  		case EQ_EXPR:
--- 7552,7557 ----
*************** build_new_op (const op_location_t &loc,
*** 7636,7643 ****
  		      && (complain & tf_warning_or_error) == 0)
  		    result = error_mark_node;
  		  else if (cxx_dialect >= cxx26 || (complain & tf_warning))
! 		    emit_diagnostic (cxx_dialect >= cxx26
! 				     ? DK_PEDWARN : DK_WARNING,
  				     loc, OPT_Wenum_compare,
  				     "comparison between %q#T and %q#T",
  				     arg1_type, arg2_type);
--- 7650,7658 ----
  		      && (complain & tf_warning_or_error) == 0)
  		    result = error_mark_node;
  		  else if (cxx_dialect >= cxx26 || (complain & tf_warning))
! 		    emit_diagnostic ((cxx_dialect >= cxx26
! 				      ? diagnostics::kind::pedwarn
! 				      : diagnostics::kind::warning),
  				     loc, OPT_Wenum_compare,
  				     "comparison between %q#T and %q#T",
  				     arg1_type, arg2_type);
*************** complain_about_access (tree decl, tree d
*** 8451,8461 ****
  
  static tree
  build_temp (tree expr, tree type, int flags,
! 	    diagnostic_t *diagnostic_kind, tsubst_flags_t complain)
  {
    int savew, savee;
  
!   *diagnostic_kind = DK_UNSPECIFIED;
  
    /* If the source is a packed field, calling the copy constructor will require
       binding the field to the reference parameter to the copy constructor, and
--- 8466,8476 ----
  
  static tree
  build_temp (tree expr, tree type, int flags,
! 	    enum diagnostics::kind *diagnostic_kind, tsubst_flags_t complain)
  {
    int savew, savee;
  
!   *diagnostic_kind = diagnostics::kind::unspecified;
  
    /* If the source is a packed field, calling the copy constructor will require
       binding the field to the reference parameter to the copy constructor, and
*************** build_temp (tree expr, tree type, int fl
*** 8479,8487 ****
    expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
  				    &args, type, flags, complain);
    if (warningcount + werrorcount > savew)
!     *diagnostic_kind = DK_WARNING;
    else if (errorcount > savee)
!     *diagnostic_kind = DK_ERROR;
    return expr;
  }
  
--- 8494,8502 ----
    expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
  				    &args, type, flags, complain);
    if (warningcount + werrorcount > savew)
!     *diagnostic_kind = diagnostics::kind::warning;
    else if (errorcount > savee)
!     *diagnostic_kind = diagnostics::kind::error;
    return expr;
  }
  
*************** convert_like_internal (conversion *convs
*** 8693,8701 ****
  		       bool nested_p, tsubst_flags_t complain)
  {
    tree totype = convs->type;
!   diagnostic_t diag_kind;
    int flags;
    location_t loc = cp_expr_loc_or_input_loc (expr);
  
    if (convs->bad_p && !(complain & tf_error))
      return error_mark_node;
--- 8708,8717 ----
  		       bool nested_p, tsubst_flags_t complain)
  {
    tree totype = convs->type;
!   enum diagnostics::kind diag_kind;
    int flags;
    location_t loc = cp_expr_loc_or_input_loc (expr);
+   const bool stub_object_p = is_stub_object (expr);
  
    if (convs->bad_p && !(complain & tf_error))
      return error_mark_node;
*************** convert_like_internal (conversion *convs
*** 8772,8778 ****
  				      "from %qH to %qI", TREE_TYPE (expr),
  				      totype);
  	      if (complained)
! 		print_z_candidate (loc, N_("candidate is:"), t->cand);
  	      expr = convert_like (t, expr, fn, argnum,
  				   /*issue_conversion_warnings=*/false,
  				   /*c_cast_p=*/false, /*nested_p=*/true,
--- 8788,8797 ----
  				      "from %qH to %qI", TREE_TYPE (expr),
  				      totype);
  	      if (complained)
! 		{
! 		  auto_diagnostic_nesting_level sentinel;
! 		  print_z_candidate (loc, N_("candidate is:"), t->cand);
! 		}
  	      expr = convert_like (t, expr, fn, argnum,
  				   /*issue_conversion_warnings=*/false,
  				   /*c_cast_p=*/false, /*nested_p=*/true,
*************** convert_like_internal (conversion *convs
*** 8797,8803 ****
  	  else if (t->kind == ck_identity)
  	    break;
  	}
!       if (!complained && expr != error_mark_node)
  	{
  	  range_label_for_type_mismatch label (TREE_TYPE (expr), totype);
  	  gcc_rich_location richloc (loc, &label, highlight_colors::percent_h);
--- 8816,8829 ----
  	  else if (t->kind == ck_identity)
  	    break;
  	}
!       if (!complained && stub_object_p)
! 	{
! 	  /* An error diagnosed within a trait, don't give extra labels.  */
! 	  error_at (loc, "invalid conversion from %qH to %qI",
! 		    TREE_TYPE (expr), totype);
! 	  complained = 1;
! 	}
!       else if (!complained && expr != error_mark_node)
  	{
  	  range_label_for_type_mismatch label (TREE_TYPE (expr), totype);
  	  gcc_rich_location richloc (loc, &label, highlight_colors::percent_h);
*************** convert_like_internal (conversion *convs
*** 9220,9226 ****
        if (convs->copy_init_p)
  	flags |= LOOKUP_ONLYCONVERTING;
        expr = build_temp (expr, totype, flags, &diag_kind, complain);
!       if (diag_kind && complain)
  	{
  	  auto_diagnostic_group d;
  	  maybe_print_user_conv_context (convs);
--- 9246,9252 ----
        if (convs->copy_init_p)
  	flags |= LOOKUP_ONLYCONVERTING;
        expr = build_temp (expr, totype, flags, &diag_kind, complain);
!       if (diag_kind != diagnostics::kind::unspecified && complain)
  	{
  	  auto_diagnostic_group d;
  	  maybe_print_user_conv_context (convs);
diff -Nrcpad gcc-16-20250720/gcc/cp/constexpr.cc gcc-16-20250727/gcc/cp/constexpr.cc
*** gcc-16-20250720/gcc/cp/constexpr.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/constexpr.cc	Sun Jul 27 22:32:08 2025
*************** static bool
*** 153,159 ****
  constexpr_error (location_t location, bool constexpr_fundef_p,
  		 const char *gmsgid, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
    va_start (ap, gmsgid);
--- 153,159 ----
  constexpr_error (location_t location, bool constexpr_fundef_p,
  		 const char *gmsgid, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
    va_start (ap, gmsgid);
*************** constexpr_error (location_t location, bo
*** 161,174 ****
    if (!constexpr_fundef_p)
      {
        /* Report an error that cannot be suppressed.  */
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ERROR);
        ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    else if (warn_invalid_constexpr)
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
! 			   cxx_dialect < cxx23 ? DK_PEDWARN : DK_WARNING);
!       diagnostic.option_id = OPT_Winvalid_constexpr;
        ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    else
--- 161,177 ----
    if (!constexpr_fundef_p)
      {
        /* Report an error that cannot be suppressed.  */
!       diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
! 			   diagnostics::kind::error);
        ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    else if (warn_invalid_constexpr)
      {
        diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
! 			   (cxx_dialect < cxx23
! 			    ? diagnostics::kind::pedwarn
! 			    : diagnostics::kind::warning));
!       diagnostic.m_option_id = OPT_Winvalid_constexpr;
        ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
    else
*************** diagnose_failing_condition (tree bad, lo
*** 2883,2892 ****
--- 2886,2900 ----
    if (TREE_CODE (bad) == CLEANUP_POINT_EXPR)
      bad = TREE_OPERAND (bad, 0);
  
+   auto_diagnostic_nesting_level sentinel;
+ 
    /* Actually explain the failure if this is a concept check or a
       requires-expression.  */
    if (concept_check_p (bad) || TREE_CODE (bad) == REQUIRES_EXPR)
      diagnose_constraints (cloc, bad, NULL_TREE);
+   /* Similarly if this is a standard trait.  */
+   else if (maybe_diagnose_standard_trait (cloc, bad))
+     ;
    else if (COMPARISON_CLASS_P (bad)
  	   && ARITHMETIC_TYPE_P (TREE_TYPE (TREE_OPERAND (bad, 0))))
      {
*************** cxx_eval_store_expression (const constex
*** 7736,7748 ****
  	  CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (*valp), first, NULL_TREE);
  
        /* Check for implicit change of active member for a union.  */
        if (code == UNION_TYPE
  	  && (CONSTRUCTOR_NELTS (*valp) == 0
  	      || CONSTRUCTOR_ELT (*valp, 0)->index != index)
  	  /* An INIT_EXPR of the last member in an access chain is always OK,
  	     but still check implicit change of members earlier on; see
  	     cpp2a/constexpr-union6.C.  */
! 	  && !(TREE_CODE (t) == INIT_EXPR && refs->is_empty ()))
  	{
  	  bool has_active_member = CONSTRUCTOR_NELTS (*valp) != 0;
  	  tree inner = strip_array_types (reftype);
--- 7744,7767 ----
  	  CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (*valp), first, NULL_TREE);
  
        /* Check for implicit change of active member for a union.  */
+ 
+       /* LWG3436, CWG2675, c++/121068: The array object model is confused.  For
+ 	 now allow initializing an array element to activate the array.  */
+       auto only_array_refs = [](const releasing_vec &refs)
+       {
+ 	for (unsigned i = 1; i < refs->length(); i += 3)
+ 	  if (TREE_CODE ((*refs)[i]) != INTEGER_CST)
+ 	    return false;
+ 	return true;
+       };
+ 
        if (code == UNION_TYPE
  	  && (CONSTRUCTOR_NELTS (*valp) == 0
  	      || CONSTRUCTOR_ELT (*valp, 0)->index != index)
  	  /* An INIT_EXPR of the last member in an access chain is always OK,
  	     but still check implicit change of members earlier on; see
  	     cpp2a/constexpr-union6.C.  */
! 	  && !(TREE_CODE (t) == INIT_EXPR && only_array_refs (refs)))
  	{
  	  bool has_active_member = CONSTRUCTOR_NELTS (*valp) != 0;
  	  tree inner = strip_array_types (reftype);
diff -Nrcpad gcc-16-20250720/gcc/cp/constraint.cc gcc-16-20250727/gcc/cp/constraint.cc
*** gcc-16-20250720/gcc/cp/constraint.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/constraint.cc	Sun Jul 27 22:32:08 2025
*************** satisfy_atom (tree t, tree args, sat_inf
*** 2490,2499 ****
    result = force_rvalue (result, info.complain);
    if (result == error_mark_node)
      return cache.save (inst_cache.save (error_mark_node));
    if (!same_type_p (TREE_TYPE (result), boolean_type_node))
      {
        if (info.noisy ())
! 	diagnose_atomic_constraint (t, args, result, info);
        return cache.save (inst_cache.save (error_mark_node));
      }
  
--- 2490,2500 ----
    result = force_rvalue (result, info.complain);
    if (result == error_mark_node)
      return cache.save (inst_cache.save (error_mark_node));
+   tree substituted = result;
    if (!same_type_p (TREE_TYPE (result), boolean_type_node))
      {
        if (info.noisy ())
! 	diagnose_atomic_constraint (t, args, substituted, info);
        return cache.save (inst_cache.save (error_mark_node));
      }
  
*************** satisfy_atom (tree t, tree args, sat_inf
*** 2511,2517 ****
      }
    result = satisfaction_value (result);
    if (result == boolean_false_node && info.diagnose_unsatisfaction_p ())
!     diagnose_atomic_constraint (t, args, result, info);
  
    return cache.save (inst_cache.save (result));
  }
--- 2512,2518 ----
      }
    result = satisfaction_value (result);
    if (result == boolean_false_node && info.diagnose_unsatisfaction_p ())
!     diagnose_atomic_constraint (t, args, substituted, info);
  
    return cache.save (inst_cache.save (result));
  }
*************** get_constraint_error_location (tree t)
*** 3063,3073 ****
  
  /* Emit a diagnostic for a failed trait.  */
  
! static void
! diagnose_trait_expr (tree expr, tree args)
  {
-   location_t loc = cp_expr_location (expr);
- 
    /* Build a "fake" version of the instantiated trait, so we can
       get the instantiated types from result.  */
    ++processing_template_decl;
--- 3064,3072 ----
  
  /* Emit a diagnostic for a failed trait.  */
  
! void
! diagnose_trait_expr (location_t loc, tree expr, tree args)
  {
    /* Build a "fake" version of the instantiated trait, so we can
       get the instantiated types from result.  */
    ++processing_template_decl;
*************** diagnose_trait_expr (tree expr, tree arg
*** 3076,3293 ****
  
    tree t1 = TRAIT_EXPR_TYPE1 (expr);
    tree t2 = TRAIT_EXPR_TYPE2 (expr);
!   if (t2 && TREE_CODE (t2) == TREE_VEC)
!     {
!       /* Convert the TREE_VEC of arguments into a TREE_LIST, since we can't
! 	 directly print a TREE_VEC but we can a TREE_LIST via the E format
! 	 specifier.  */
!       tree list = NULL_TREE;
!       for (tree t : tree_vec_range (t2))
! 	list = tree_cons (NULL_TREE, t, list);
!       t2 = nreverse (list);
!     }
    switch (TRAIT_EXPR_KIND (expr))
      {
      case CPTK_HAS_NOTHROW_ASSIGN:
!       inform (loc, "  %qT is not nothrow copy assignable", t1);
        break;
      case CPTK_HAS_NOTHROW_CONSTRUCTOR:
!       inform (loc, "  %qT is not nothrow default constructible", t1);
        break;
      case CPTK_HAS_NOTHROW_COPY:
!       inform (loc, "  %qT is not nothrow copy constructible", t1);
        break;
      case CPTK_HAS_TRIVIAL_ASSIGN:
!       inform (loc, "  %qT is not trivially copy assignable", t1);
        break;
      case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
!       inform (loc, "  %qT is not trivially default constructible", t1);
        break;
      case CPTK_HAS_TRIVIAL_COPY:
!       inform (loc, "  %qT is not trivially copy constructible", t1);
        break;
      case CPTK_HAS_TRIVIAL_DESTRUCTOR:
!       inform (loc, "  %qT is not trivially destructible", t1);
        break;
      case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
!       inform (loc, "  %qT does not have unique object representations", t1);
        break;
      case CPTK_HAS_VIRTUAL_DESTRUCTOR:
!       inform (loc, "  %qT does not have a virtual destructor", t1);
        break;
      case CPTK_IS_ABSTRACT:
!       inform (loc, "  %qT is not an abstract class", t1);
        break;
      case CPTK_IS_AGGREGATE:
!       inform (loc, "  %qT is not an aggregate", t1);
        break;
      case CPTK_IS_ARRAY:
!       inform (loc, "  %qT is not an array", t1);
        break;
      case CPTK_IS_ASSIGNABLE:
!       inform (loc, "  %qT is not assignable from %qT", t1, t2);
        break;
      case CPTK_IS_BASE_OF:
!       inform (loc, "  %qT is not a base of %qT", t1, t2);
        break;
      case CPTK_IS_BOUNDED_ARRAY:
!       inform (loc, "  %qT is not a bounded array", t1);
        break;
      case CPTK_IS_CLASS:
!       inform (loc, "  %qT is not a class", t1);
        break;
      case CPTK_IS_CONST:
!       inform (loc, "  %qT is not a const type", t1);
        break;
      case CPTK_IS_CONSTRUCTIBLE:
!       if (!t2)
! 	inform (loc, "  %qT is not default constructible", t1);
        else
! 	inform (loc, "  %qT is not constructible from %qE", t1, t2);
        break;
      case CPTK_IS_CONVERTIBLE:
!       inform (loc, "  %qT is not convertible from %qE", t2, t1);
        break;
      case CPTK_IS_DESTRUCTIBLE:
!       inform (loc, "  %qT is not destructible", t1);
        break;
      case CPTK_IS_EMPTY:
!       inform (loc, "  %qT is not an empty class", t1);
        break;
      case CPTK_IS_ENUM:
!       inform (loc, "  %qT is not an enum", t1);
        break;
      case CPTK_IS_FINAL:
!       inform (loc, "  %qT is not a final class", t1);
        break;
      case CPTK_IS_FUNCTION:
!       inform (loc, "  %qT is not a function", t1);
        break;
      case CPTK_IS_INVOCABLE:
!       if (!t2)
! 	inform (loc, "  %qT is not invocable", t1);
!       else
! 	inform (loc, "  %qT is not invocable by %qE", t1, t2);
        break;
      case CPTK_IS_LAYOUT_COMPATIBLE:
!       inform (loc, "  %qT is not layout compatible with %qT", t1, t2);
        break;
      case CPTK_IS_LITERAL_TYPE:
!       inform (loc, "  %qT is not a literal type", t1);
        break;
      case CPTK_IS_MEMBER_FUNCTION_POINTER:
!       inform (loc, "  %qT is not a member function pointer", t1);
        break;
      case CPTK_IS_MEMBER_OBJECT_POINTER:
!       inform (loc, "  %qT is not a member object pointer", t1);
        break;
      case CPTK_IS_MEMBER_POINTER:
!       inform (loc, "  %qT is not a member pointer", t1);
        break;
      case CPTK_IS_NOTHROW_ASSIGNABLE:
!       inform (loc, "  %qT is not nothrow assignable from %qT", t1, t2);
        break;
      case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
!       if (!t2)
! 	inform (loc, "  %qT is not nothrow default constructible", t1);
        else
! 	inform (loc, "  %qT is not nothrow constructible from %qE", t1, t2);
        break;
      case CPTK_IS_NOTHROW_CONVERTIBLE:
!       inform (loc, "  %qT is not nothrow convertible from %qE", t2, t1);
        break;
      case CPTK_IS_NOTHROW_DESTRUCTIBLE:
!       inform (loc, "  %qT is not nothrow destructible", t1);
        break;
      case CPTK_IS_NOTHROW_INVOCABLE:
!       if (!t2)
! 	inform (loc, "  %qT is not nothrow invocable", t1);
!       else
! 	inform (loc, "  %qT is not nothrow invocable by %qE", t1, t2);
        break;
      case CPTK_IS_NOTHROW_RELOCATABLE:
!       inform (loc, "  %qT is not nothrow relocatable", t1);
        break;
      case CPTK_IS_OBJECT:
!       inform (loc, "  %qT is not an object type", t1);
        break;
      case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF:
!       inform (loc, "  %qT is not pointer-interconvertible base of %qT",
  	      t1, t2);
        break;
      case CPTK_IS_POD:
!       inform (loc, "  %qT is not a POD type", t1);
        break;
      case CPTK_IS_POINTER:
!       inform (loc, "  %qT is not a pointer", t1);
        break;
      case CPTK_IS_POLYMORPHIC:
!       inform (loc, "  %qT is not a polymorphic type", t1);
        break;
      case CPTK_IS_REFERENCE:
!       inform (loc, "  %qT is not a reference", t1);
        break;
      case CPTK_IS_REPLACEABLE:
!       inform (loc, "  %qT is not replaceable", t1);
        break;
      case CPTK_IS_SAME:
!       inform (loc, "  %qT is not the same as %qT", t1, t2);
        break;
      case CPTK_IS_SCOPED_ENUM:
!       inform (loc, "  %qT is not a scoped enum", t1);
        break;
      case CPTK_IS_STD_LAYOUT:
!       inform (loc, "  %qT is not an standard layout type", t1);
        break;
      case CPTK_IS_TRIVIAL:
!       inform (loc, "  %qT is not a trivial type", t1);
        break;
      case CPTK_IS_TRIVIALLY_ASSIGNABLE:
!       inform (loc, "  %qT is not trivially assignable from %qT", t1, t2);
        break;
      case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
!       if (!t2)
! 	inform (loc, "  %qT is not trivially default constructible", t1);
        else
! 	inform (loc, "  %qT is not trivially constructible from %qE", t1, t2);
        break;
      case CPTK_IS_TRIVIALLY_COPYABLE:
!       inform (loc, "  %qT is not trivially copyable", t1);
        break;
      case CPTK_IS_TRIVIALLY_DESTRUCTIBLE:
!       inform (loc, "  %qT is not trivially destructible", t1);
        break;
      case CPTK_IS_TRIVIALLY_RELOCATABLE:
!       inform (loc, "  %qT is not trivially relocatable", t1);
        break;
      case CPTK_IS_UNBOUNDED_ARRAY:
!       inform (loc, "  %qT is not an unbounded array", t1);
        break;
      case CPTK_IS_UNION:
!       inform (loc, "  %qT is not a union", t1);
        break;
      case CPTK_IS_VIRTUAL_BASE_OF:
!       inform (loc, "  %qT is not a virtual base of %qT", t1, t2);
        break;
      case CPTK_IS_VOLATILE:
!       inform (loc, "  %qT is not a volatile type", t1);
        break;
      case CPTK_RANK:
!       inform (loc, "  %qT cannot yield a rank", t1);
        break;
      case CPTK_TYPE_ORDER:
!       inform (loc, "  %qT and %qT cannot be ordered", t1, t2);
        break;
      case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
!       inform (loc, "  %qT is not a reference that binds to a temporary "
  	      "object of type %qT (direct-initialization)", t1, t2);
        break;
      case CPTK_REF_CONVERTS_FROM_TEMPORARY:
!       inform (loc, "  %qT is not a reference that binds to a temporary "
  	      "object of type %qT (copy-initialization)", t1, t2);
        break;
      case CPTK_IS_DEDUCIBLE:
!       inform (loc, "  %qD is not deducible from %qT", t1, t2);
        break;
  #define DEFTRAIT_TYPE(CODE, NAME, ARITY) \
      case CPTK_##CODE:
--- 3075,3320 ----
  
    tree t1 = TRAIT_EXPR_TYPE1 (expr);
    tree t2 = TRAIT_EXPR_TYPE2 (expr);
! 
!   /* For traits intrinsically about the properties of user-defined types,
!      decl_loc will point to the declaration of that type.  */
!   location_t decl_loc = location_of (t1);
!   if (decl_loc == input_location)
!     decl_loc = loc;
! 
    switch (TRAIT_EXPR_KIND (expr))
      {
      case CPTK_HAS_NOTHROW_ASSIGN:
!       inform (decl_loc, "%qT is not nothrow copy assignable", t1);
        break;
      case CPTK_HAS_NOTHROW_CONSTRUCTOR:
!       inform (decl_loc, "%qT is not nothrow default constructible", t1);
        break;
      case CPTK_HAS_NOTHROW_COPY:
!       inform (decl_loc, "%qT is not nothrow copy constructible", t1);
        break;
      case CPTK_HAS_TRIVIAL_ASSIGN:
!       inform (decl_loc, "%qT is not trivially copy assignable", t1);
        break;
      case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
!       inform (decl_loc, "%qT is not trivially default constructible", t1);
        break;
      case CPTK_HAS_TRIVIAL_COPY:
!       inform (decl_loc, "%qT is not trivially copy constructible", t1);
        break;
      case CPTK_HAS_TRIVIAL_DESTRUCTOR:
!       inform (decl_loc, "%qT is not trivially destructible", t1);
        break;
      case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
!       inform (decl_loc, "%qT does not have unique object representations", t1);
        break;
      case CPTK_HAS_VIRTUAL_DESTRUCTOR:
!       {
! 	location_t dtor_loc = decl_loc;
! 	if (NON_UNION_CLASS_TYPE_P (t1))
! 	  if (tree dtor = CLASSTYPE_DESTRUCTOR (t1))
! 	    dtor_loc = DECL_SOURCE_LOCATION (dtor);
! 	inform (dtor_loc, "%qT does not have a virtual destructor", t1);
!       }
        break;
      case CPTK_IS_ABSTRACT:
!       inform (decl_loc, "%qT is not an abstract class", t1);
        break;
      case CPTK_IS_AGGREGATE:
!       inform (decl_loc, "%qT is not an aggregate", t1);
        break;
      case CPTK_IS_ARRAY:
!       inform (loc, "%qT is not an array", t1);
        break;
      case CPTK_IS_ASSIGNABLE:
!       inform (loc, "%qT is not assignable from %qT, because", t1, t2);
!       is_xible (MODIFY_EXPR, t1, t2, /*explain=*/true);
        break;
      case CPTK_IS_BASE_OF:
!       inform (decl_loc, "%qT is not a base of %qT", t1, t2);
        break;
      case CPTK_IS_BOUNDED_ARRAY:
!       inform (loc, "%qT is not a bounded array", t1);
        break;
      case CPTK_IS_CLASS:
!       inform (decl_loc, "%qT is not a class", t1);
        break;
      case CPTK_IS_CONST:
!       inform (loc, "%qT is not a const type", t1);
        break;
      case CPTK_IS_CONSTRUCTIBLE:
!       if (!TREE_VEC_LENGTH (t2))
! 	inform (loc, "%qT is not default constructible, because", t1);
        else
! 	inform (loc, "%qT is not constructible from %qT, because", t1, t2);
!       is_xible (INIT_EXPR, t1, t2, /*explain=*/true);
        break;
      case CPTK_IS_CONVERTIBLE:
!       /* The errors produced here all seem to mention "convertible" in the
! 	 diagnostic, so an extra inform here appears redundant.  */
!       is_convertible (t1, t2, /*explain=*/true);
        break;
      case CPTK_IS_DESTRUCTIBLE:
!       inform (loc, "%qT is not destructible, because", t1);
!       is_xible (BIT_NOT_EXPR, t1, NULL_TREE, /*explain=*/true);
        break;
      case CPTK_IS_EMPTY:
!       inform (decl_loc, "%qT is not an empty class", t1);
        break;
      case CPTK_IS_ENUM:
!       inform (decl_loc, "%qT is not an enum", t1);
        break;
      case CPTK_IS_FINAL:
!       inform (decl_loc, "%qT is not a final class", t1);
        break;
      case CPTK_IS_FUNCTION:
!       inform (loc, "%qT is not a function", t1);
        break;
      case CPTK_IS_INVOCABLE:
!       {
! 	if (!TREE_VEC_LENGTH (t2))
! 	  inform (loc, "%qT is not invocable, because", t1);
! 	else
! 	  inform (loc, "%qT is not invocable by %qT, because", t1, t2);
! 	tree call = build_invoke (t1, t2, tf_error);
! 	gcc_assert (call == error_mark_node);
!       }
        break;
      case CPTK_IS_LAYOUT_COMPATIBLE:
!       inform (loc, "%qT is not layout compatible with %qT", t1, t2);
        break;
      case CPTK_IS_LITERAL_TYPE:
!       inform (decl_loc, "%qT is not a literal type", t1);
        break;
      case CPTK_IS_MEMBER_FUNCTION_POINTER:
!       inform (loc, "%qT is not a member function pointer", t1);
        break;
      case CPTK_IS_MEMBER_OBJECT_POINTER:
!       inform (loc, "%qT is not a member object pointer", t1);
        break;
      case CPTK_IS_MEMBER_POINTER:
!       inform (loc, "%qT is not a member pointer", t1);
        break;
      case CPTK_IS_NOTHROW_ASSIGNABLE:
!       inform (loc, "%qT is not nothrow assignable from %qT, because", t1, t2);
!       is_nothrow_xible (MODIFY_EXPR, t1, t2, /*explain=*/true);
        break;
      case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
!       if (!TREE_VEC_LENGTH (t2))
! 	inform (loc, "%qT is not nothrow default constructible, because", t1);
        else
! 	inform (loc, "%qT is not nothrow constructible from %qT, because",
! 		t1, t2);
!       is_nothrow_xible (INIT_EXPR, t1, t2, /*explain=*/true);
        break;
      case CPTK_IS_NOTHROW_CONVERTIBLE:
!       inform (loc, "%qT is not nothrow convertible from %qT, because", t1, t2);
!       is_nothrow_convertible (t1, t2, /*explain=*/true);
        break;
      case CPTK_IS_NOTHROW_DESTRUCTIBLE:
!       inform (loc, "%qT is not nothrow destructible, because", t1);
!       is_nothrow_xible (BIT_NOT_EXPR, t1, NULL_TREE, /*explain=*/true);
        break;
      case CPTK_IS_NOTHROW_INVOCABLE:
!       {
! 	if (!TREE_VEC_LENGTH (t2))
! 	  inform (loc, "%qT is not nothrow invocable, because", t1);
! 	else
! 	  inform (loc, "%qT is not nothrow invocable by %qT, because", t1, t2);
! 	tree call = build_invoke (t1, t2, tf_error);
! 	if (call != error_mark_node)
! 	  explain_not_noexcept (call);
!       }
        break;
      case CPTK_IS_NOTHROW_RELOCATABLE:
!       inform (loc, "%qT is not nothrow relocatable", t1);
        break;
      case CPTK_IS_OBJECT:
!       inform (loc, "%qT is not an object type", t1);
        break;
      case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF:
!       inform (decl_loc, "%qT is not a pointer-interconvertible base of %qT",
  	      t1, t2);
        break;
      case CPTK_IS_POD:
!       inform (loc, "%qT is not a POD type", t1);
        break;
      case CPTK_IS_POINTER:
!       inform (loc, "%qT is not a pointer", t1);
        break;
      case CPTK_IS_POLYMORPHIC:
!       inform (decl_loc, "%qT is not a polymorphic type", t1);
        break;
      case CPTK_IS_REFERENCE:
!       inform (loc, "%qT is not a reference", t1);
        break;
      case CPTK_IS_REPLACEABLE:
!       inform (loc, "%qT is not replaceable", t1);
        break;
      case CPTK_IS_SAME:
!       inform (loc, "%q#T is not the same as %q#T", t1, t2);
        break;
      case CPTK_IS_SCOPED_ENUM:
!       inform (decl_loc, "%qT is not a scoped enum", t1);
        break;
      case CPTK_IS_STD_LAYOUT:
!       inform (decl_loc, "%qT is not a standard layout type", t1);
        break;
      case CPTK_IS_TRIVIAL:
!       inform (decl_loc, "%qT is not a trivial type", t1);
        break;
      case CPTK_IS_TRIVIALLY_ASSIGNABLE:
!       inform (loc, "%qT is not trivially assignable from %qT, because", t1, t2);
!       is_trivially_xible (MODIFY_EXPR, t1, t2, /*explain=*/true);
        break;
      case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
!       if (!TREE_VEC_LENGTH (t2))
! 	inform (loc, "%qT is not trivially default constructible, because", t1);
        else
! 	inform (loc, "%qT is not trivially constructible from %qT, because",
! 		t1, t2);
!       is_trivially_xible (INIT_EXPR, t1, t2, /*explain=*/true);
        break;
      case CPTK_IS_TRIVIALLY_COPYABLE:
!       inform (decl_loc, "%qT is not trivially copyable", t1);
        break;
      case CPTK_IS_TRIVIALLY_DESTRUCTIBLE:
!       inform (loc, "%qT is not trivially destructible, because", t1);
!       is_trivially_xible (BIT_NOT_EXPR, t1, NULL_TREE, /*explain=*/true);
        break;
      case CPTK_IS_TRIVIALLY_RELOCATABLE:
!       inform (loc, "%qT is not trivially relocatable", t1);
        break;
      case CPTK_IS_UNBOUNDED_ARRAY:
!       inform (loc, "%qT is not an unbounded array", t1);
        break;
      case CPTK_IS_UNION:
!       inform (decl_loc, "%qT is not a union", t1);
        break;
      case CPTK_IS_VIRTUAL_BASE_OF:
!       inform (decl_loc, "%qT is not a virtual base of %qT", t1, t2);
!       if (CLASS_TYPE_P (t2))
! 	inform (location_of (t2), "%qT declared here", t2);
        break;
      case CPTK_IS_VOLATILE:
!       inform (loc, "%qT is not a volatile type", t1);
        break;
      case CPTK_RANK:
!       inform (loc, "%qT cannot yield a rank", t1);
        break;
      case CPTK_TYPE_ORDER:
!       inform (loc, "%qT and %qT cannot be ordered", t1, t2);
        break;
      case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
!       inform (loc, "%qT is not a reference that binds to a temporary "
  	      "object of type %qT (direct-initialization)", t1, t2);
        break;
      case CPTK_REF_CONVERTS_FROM_TEMPORARY:
!       inform (loc, "%qT is not a reference that binds to a temporary "
  	      "object of type %qT (copy-initialization)", t1, t2);
        break;
      case CPTK_IS_DEDUCIBLE:
!       inform (loc, "%qD is not deducible from %qT", t1, t2);
        break;
  #define DEFTRAIT_TYPE(CODE, NAME, ARITY) \
      case CPTK_##CODE:
*************** diagnose_trait_expr (tree expr, tree arg
*** 3300,3309 ****
      }
  }
  
  /* Diagnose a substitution failure in the atomic constraint T using ARGS.  */
  
  static void
! diagnose_atomic_constraint (tree t, tree args, tree result, sat_info info)
  {
    /* If the constraint is already ill-formed, we've previously diagnosed
       the reason.  We should still say why the constraints aren't satisfied.  */
--- 3327,3376 ----
      }
  }
  
+ /* Attempt to detect if this is a standard type trait, defined in terms
+    of a compiler builtin (above).  If so, this will allow us to provide
+    more helpful diagnostics.   */
+ 
+ bool
+ maybe_diagnose_standard_trait (location_t loc, tree expr)
+ {
+   gcc_assert (TREE_CODE (expr) != TRAIT_EXPR);
+   expr = tree_strip_nop_conversions (expr);
+ 
+   /* TODO: in some cases it would be possible to provide more helpful
+      diagnostics for negations of traits, e.g. '!is_same_v<T1, T2>'.  */
+ 
+   tree args = NULL_TREE;
+   if (VAR_P (expr) && DECL_LANG_SPECIFIC (expr) && DECL_USE_TEMPLATE (expr))
+     {
+       tree tinfo = DECL_TEMPLATE_INFO (expr);
+       if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo)) && TI_PARTIAL_INFO (tinfo))
+ 	tinfo = TI_PARTIAL_INFO (tinfo);
+       else if (DECL_TEMPLATE_SPECIALIZATION (expr))
+ 	/* In an explicit specialisation we no longer know what the original
+ 	   initializer looked like.  */
+ 	tinfo = NULL_TREE;
+ 
+       if (tinfo)
+ 	{
+ 	  expr = DECL_INITIAL (DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo)));
+ 	  args = TI_ARGS (tinfo);
+ 	}
+     }
+ 
+   if (TREE_CODE (expr) == TRAIT_EXPR)
+     {
+       diagnose_trait_expr (loc, expr, args);
+       return true;
+     }
+ 
+   return false;
+ }
+ 
  /* Diagnose a substitution failure in the atomic constraint T using ARGS.  */
  
  static void
! diagnose_atomic_constraint (tree t, tree args, tree substituted, sat_info info)
  {
    /* If the constraint is already ill-formed, we've previously diagnosed
       the reason.  We should still say why the constraints aren't satisfied.  */
*************** diagnose_atomic_constraint (tree t, tree
*** 3324,3348 ****
    /* Generate better diagnostics for certain kinds of expressions.  */
    tree expr = ATOMIC_CONSTR_EXPR (t);
    STRIP_ANY_LOCATION_WRAPPER (expr);
!   switch (TREE_CODE (expr))
      {
-     case TRAIT_EXPR:
-       diagnose_trait_expr (expr, args);
-       break;
-     case REQUIRES_EXPR:
        gcc_checking_assert (info.diagnose_unsatisfaction_p ());
        /* Clear in_decl before replaying the substitution to avoid emitting
  	 seemingly unhelpful "in declaration ..." notes that follow some
  	 substitution failure error messages.  */
        info.in_decl = NULL_TREE;
        tsubst_requires_expr (expr, args, info);
!       break;
!     default:
!       if (!same_type_p (TREE_TYPE (result), boolean_type_node))
! 	error_at (loc, "constraint %qE has type %qT, not %<bool%>",
! 		  t, TREE_TYPE (result));
        else
! 	inform (loc, "the expression %qE evaluated to %<false%>", t);
      }
  }
  
--- 3391,3416 ----
    /* Generate better diagnostics for certain kinds of expressions.  */
    tree expr = ATOMIC_CONSTR_EXPR (t);
    STRIP_ANY_LOCATION_WRAPPER (expr);
! 
!   if (TREE_CODE (expr) == REQUIRES_EXPR)
      {
        gcc_checking_assert (info.diagnose_unsatisfaction_p ());
        /* Clear in_decl before replaying the substitution to avoid emitting
  	 seemingly unhelpful "in declaration ..." notes that follow some
  	 substitution failure error messages.  */
        info.in_decl = NULL_TREE;
        tsubst_requires_expr (expr, args, info);
!     }
!   else if (!same_type_p (TREE_TYPE (substituted), boolean_type_node))
!     error_at (loc, "constraint %qE has type %qT, not %<bool%>",
! 	      t, TREE_TYPE (substituted));
!   else
!     {
!       inform (loc, "the expression %qE evaluated to %<false%>", t);
!       if (TREE_CODE (expr) == TRAIT_EXPR)
! 	diagnose_trait_expr (loc, expr, args);
        else
! 	maybe_diagnose_standard_trait (loc, substituted);
      }
  }
  
diff -Nrcpad gcc-16-20250720/gcc/cp/coroutines.cc gcc-16-20250727/gcc/cp/coroutines.cc
*** gcc-16-20250720/gcc/cp/coroutines.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/coroutines.cc	Sun Jul 27 22:32:08 2025
*************** cp_coroutine_transform::build_ramp_funct
*** 5050,5055 ****
--- 5050,5057 ----
       check the returned pointer and call the func if it's null.
       Otherwise, no check, and we fail for noexcept/fno-exceptions cases.  */
  
+   tree grooaf_if_stmt = NULL_TREE;
+   tree alloc_ok_scope = NULL_TREE;
    if (grooaf)
      {
        /* [dcl.fct.def.coroutine] / 10 (part 3)
*************** cp_coroutine_transform::build_ramp_funct
*** 5057,5076 ****
  	 control to the caller of the coroutine and the return value is
  	 obtained by a call to T::get_return_object_on_allocation_failure(),
  	 where T is the promise type.  */
-       tree if_stmt = begin_if_stmt ();
        tree cond = build1 (CONVERT_EXPR, frame_ptr_type, nullptr_node);
!       cond = build2 (EQ_EXPR, boolean_type_node, coro_fp, cond);
!       finish_if_stmt_cond (cond, if_stmt);
!       r = NULL_TREE;
!       if (void_ramp_p)
! 	/* Execute the get-return-object-on-alloc-fail call...  */
! 	finish_expr_stmt (grooaf);
!       else
! 	/* Get the fallback return object.  */
! 	r = grooaf;
!       finish_return_stmt (r);
!       finish_then_clause (if_stmt);
!       finish_if_stmt (if_stmt);
      }
  
    /* Dereference the frame pointer, to use in member access code.  */
--- 5059,5069 ----
  	 control to the caller of the coroutine and the return value is
  	 obtained by a call to T::get_return_object_on_allocation_failure(),
  	 where T is the promise type.  */
        tree cond = build1 (CONVERT_EXPR, frame_ptr_type, nullptr_node);
!       cond = build2 (NE_EXPR, boolean_type_node, coro_fp, cond);
!       grooaf_if_stmt = begin_if_stmt ();
!       finish_if_stmt_cond (cond, grooaf_if_stmt);
!       alloc_ok_scope = begin_compound_stmt (BCS_NORMAL);
      }
  
    /* Dereference the frame pointer, to use in member access code.  */
*************** cp_coroutine_transform::build_ramp_funct
*** 5295,5301 ****
  	 a temp which is then used to intialize the return object, including
  	 NVRO.  */
  
-       /* Temporary var to hold the g_r_o across the function body.  */
        coro_gro
  	= coro_build_and_push_artificial_var (loc, "_Coro_gro", gro_type,
  					      orig_fn_decl, NULL_TREE);
--- 5288,5293 ----
*************** cp_coroutine_transform::build_ramp_funct
*** 5328,5336 ****
--- 5320,5347 ----
    /* The ramp is done, we just need the return statement, which we build from
       the return object we constructed before we called the actor.  */
  
+   /* This is our 'normal' exit.  */
    r = void_ramp_p ? NULL_TREE : convert_from_reference (coro_gro);
    finish_return_stmt (r);
  
+   if (grooaf)
+     {
+       finish_compound_stmt (alloc_ok_scope);
+       finish_then_clause (grooaf_if_stmt);
+ 
+       begin_else_clause (grooaf_if_stmt);
+       /* We come here if the frame allocation failed.  */
+       r = NULL_TREE;
+       if (void_ramp_p)
+ 	/* Execute the get-return-object-on-alloc-fail call...  */
+ 	finish_expr_stmt (grooaf);
+       else
+ 	/* Get the fallback return object.  */
+ 	r = grooaf;
+       finish_return_stmt (r);
+       finish_if_stmt (grooaf_if_stmt);
+     }
+ 
    finish_compound_stmt (ramp_fnbody);
    return true;
  }
diff -Nrcpad gcc-16-20250720/gcc/cp/cp-tree.h gcc-16-20250727/gcc/cp/cp-tree.h
*** gcc-16-20250720/gcc/cp/cp-tree.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/cp-tree.h	Sun Jul 27 22:32:08 2025
*************** struct GTY(()) lang_type {
*** 2508,2514 ****
  
    /* When adding a flag here, consider whether or not it ought to
       apply to a template instance if it applies to the template.  If
!      so, make sure to copy it in instantiate_class_template!  */
  
    /* There are some bits left to fill out a 32-bit word.  Keep track
       of this by updating the size of this bitfield whenever you add or
--- 2508,2516 ----
  
    /* When adding a flag here, consider whether or not it ought to
       apply to a template instance if it applies to the template.  If
!      so, make sure to copy it in instantiate_class_template!
! 
!      Also make sure new flags here are streamed in module.cc.  */
  
    /* There are some bits left to fill out a 32-bit word.  Keep track
       of this by updating the size of this bitfield whenever you add or
*************** extern void maybe_warn_variadic_template
*** 7455,7461 ****
  extern void maybe_warn_cpp0x			(cpp0x_warn_str str,
  						 location_t = input_location);
  extern bool pedwarn_cxx98                       (location_t,
! 						 diagnostic_option_id option_id,
  						 const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
  extern location_t location_of                   (tree);
  extern void qualified_name_lookup_error		(tree, tree, tree,
--- 7457,7463 ----
  extern void maybe_warn_cpp0x			(cpp0x_warn_str str,
  						 location_t = input_location);
  extern bool pedwarn_cxx98                       (location_t,
! 						 diagnostics::option_id option_id,
  						 const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
  extern location_t location_of                   (tree);
  extern void qualified_name_lookup_error		(tree, tree, tree,
*************** extern int nothrow_libfn_p			(const_tree
*** 7481,7486 ****
--- 7483,7489 ----
  extern void check_handlers			(tree);
  extern tree finish_noexcept_expr		(tree, tsubst_flags_t);
  extern bool expr_noexcept_p			(tree, tsubst_flags_t);
+ extern void explain_not_noexcept		(tree);
  extern void perform_deferred_noexcept_checks	(void);
  extern bool nothrow_spec_p			(const_tree);
  extern bool type_noexcept_p			(const_tree);
*************** extern void finish_thunk			(tree);
*** 7602,7612 ****
  extern void use_thunk				(tree, bool);
  extern bool trivial_fn_p			(tree);
  extern tree forward_parm			(tree);
! extern bool is_trivially_xible			(enum tree_code, tree, tree);
! extern bool is_nothrow_xible			(enum tree_code, tree, tree);
! extern bool is_xible				(enum tree_code, tree, tree);
! extern bool is_convertible			(tree, tree);
! extern bool is_nothrow_convertible		(tree, tree);
  extern bool ref_xes_from_temporary		(tree, tree, bool);
  extern tree get_defaulted_eh_spec		(tree, tsubst_flags_t = tf_warning_or_error);
  extern bool maybe_explain_implicit_delete	(tree);
--- 7605,7618 ----
  extern void use_thunk				(tree, bool);
  extern bool trivial_fn_p			(tree);
  extern tree forward_parm			(tree);
! extern bool is_trivially_xible			(enum tree_code, tree, tree,
! 						 bool = false);
! extern bool is_nothrow_xible			(enum tree_code, tree, tree,
! 						 bool = false);
! extern bool is_xible				(enum tree_code, tree, tree,
! 						 bool = false);
! extern bool is_convertible			(tree, tree, bool = false);
! extern bool is_nothrow_convertible		(tree, tree, bool = false);
  extern bool ref_xes_from_temporary		(tree, tree, bool);
  extern tree get_defaulted_eh_spec		(tree, tsubst_flags_t = tf_warning_or_error);
  extern bool maybe_explain_implicit_delete	(tree);
*************** extern void cxx_print_xnode			(FILE *, t
*** 8459,8467 ****
  extern void cxx_print_decl			(FILE *, tree, int);
  extern void cxx_print_type			(FILE *, tree, int);
  extern void cxx_print_identifier		(FILE *, tree, int);
! extern void cxx_print_error_function		(diagnostic_text_output_format &,
  						 const char *,
! 						 const diagnostic_info *);
  
  /* in typeck.cc */
  /* Says how we should behave when comparing two arrays one of which
--- 8465,8473 ----
  extern void cxx_print_decl			(FILE *, tree, int);
  extern void cxx_print_type			(FILE *, tree, int);
  extern void cxx_print_identifier		(FILE *, tree, int);
! extern void cxx_print_error_function		(diagnostics::text_sink &,
  						 const char *,
! 						 const diagnostics::diagnostic_info *);
  
  /* in typeck.cc */
  /* Says how we should behave when comparing two arrays one of which
*************** extern void maybe_warn_pessimizing_move
*** 8648,8654 ****
  /* in typeck2.cc */
  extern void require_complete_eh_spec_types	(tree, tree);
  extern bool cxx_incomplete_type_diagnostic	(location_t, const_tree,
! 						 const_tree, diagnostic_t);
  inline location_t
  loc_or_input_loc (location_t loc)
  {
--- 8654,8660 ----
  /* in typeck2.cc */
  extern void require_complete_eh_spec_types	(tree, tree);
  extern bool cxx_incomplete_type_diagnostic	(location_t, const_tree,
! 						 const_tree, enum diagnostics::kind);
  inline location_t
  loc_or_input_loc (location_t loc)
  {
*************** cp_expr_loc_or_input_loc (const_tree t)
*** 8696,8702 ****
  
  inline bool
  cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
! 				diagnostic_t diag_kind)
  {
    return cxx_incomplete_type_diagnostic (cp_expr_loc_or_input_loc (value),
  					 value, type, diag_kind);
--- 8702,8708 ----
  
  inline bool
  cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
! 				enum diagnostics::kind diag_kind)
  {
    return cxx_incomplete_type_diagnostic (cp_expr_loc_or_input_loc (value),
  					 value, type, diag_kind);
*************** extern void cxx_incomplete_type_error		(
*** 8707,8713 ****
  inline void
  cxx_incomplete_type_error (const_tree value, const_tree type)
  {
!   cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
  }
  
  extern void cxx_incomplete_type_inform 	        (const_tree);
--- 8713,8719 ----
  inline void
  cxx_incomplete_type_error (const_tree value, const_tree type)
  {
!   cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error);
  }
  
  extern void cxx_incomplete_type_inform 	        (const_tree);
*************** extern alias_set_type cxx_get_alias_set
*** 8778,8784 ****
  extern bool cxx_warn_unused_global_decl		(const_tree);
  extern size_t cp_tree_size			(enum tree_code);
  extern bool cp_var_mod_type_p			(tree, tree);
! extern void cxx_initialize_diagnostics		(diagnostic_context *);
  extern int cxx_types_compatible_p		(tree, tree);
  extern bool cxx_block_may_fallthru		(const_tree);
  
--- 8784,8790 ----
  extern bool cxx_warn_unused_global_decl		(const_tree);
  extern size_t cp_tree_size			(enum tree_code);
  extern bool cp_var_mod_type_p			(tree, tree);
! extern void cxx_initialize_diagnostics		(diagnostics::context *);
  extern int cxx_types_compatible_p		(tree, tree);
  extern bool cxx_block_may_fallthru		(const_tree);
  
*************** extern bool constraints_equivalent_p
*** 8923,8928 ****
--- 8929,8936 ----
  extern bool atomic_constraints_identical_p	(tree, tree);
  extern hashval_t iterative_hash_constraint      (tree, hashval_t);
  extern hashval_t hash_atomic_constraint         (tree);
+ extern void diagnose_trait_expr			(location_t, tree, tree);
+ extern bool maybe_diagnose_standard_trait	(location_t, tree);
  extern void diagnose_constraints                (location_t, tree, tree);
  
  extern void note_failed_type_completion		(tree, tsubst_flags_t);
diff -Nrcpad gcc-16-20250720/gcc/cp/decl.cc gcc-16-20250727/gcc/cp/decl.cc
*** gcc-16-20250720/gcc/cp/decl.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/decl.cc	Sun Jul 27 22:32:08 2025
*************** static void initialize_local_var (tree,
*** 110,116 ****
  static void expand_static_init (tree, tree);
  static location_t smallest_type_location (const cp_decl_specifier_seq*);
  static bool identify_goto (tree, location_t, const location_t *,
! 			   diagnostic_t, bool);
  
  /* The following symbols are subsumed in the cp_global_trees array, and
     listed here individually for documentation purposes.
--- 110,116 ----
  static void expand_static_init (tree, tree);
  static location_t smallest_type_location (const cp_decl_specifier_seq*);
  static bool identify_goto (tree, location_t, const location_t *,
! 			   enum diagnostics::kind, bool);
  
  /* The following symbols are subsumed in the cp_global_trees array, and
     listed here individually for documentation purposes.
*************** decl_jump_unsafe (tree decl)
*** 3737,3746 ****
  
  static bool
  identify_goto (tree decl, location_t loc, const location_t *locus,
! 	       diagnostic_t diag_kind, bool computed)
  {
    if (computed)
!     diag_kind = DK_WARNING;
    bool complained
      = emit_diagnostic (diag_kind, loc, 0,
  		       decl ? G_("jump to label %qD")
--- 3737,3746 ----
  
  static bool
  identify_goto (tree decl, location_t loc, const location_t *locus,
! 	       enum diagnostics::kind diag_kind, bool computed)
  {
    if (computed)
!     diag_kind = diagnostics::kind::warning;
    bool complained
      = emit_diagnostic (diag_kind, loc, 0,
  		       decl ? G_("jump to label %qD")
*************** check_previous_goto_1 (tree decl, cp_bin
*** 3776,3782 ****
  
    if (exited_omp)
      {
!       complained = identify_goto (decl, input_location, locus, DK_ERROR,
  				  computed);
        if (complained)
  	inform (input_location, "  exits OpenMP structured block");
--- 3776,3783 ----
  
    if (exited_omp)
      {
!       complained = identify_goto (decl, input_location, locus,
! 				  diagnostics::kind::error,
  				  computed);
        if (complained)
  	inform (input_location, "  exits OpenMP structured block");
*************** check_previous_goto_1 (tree decl, cp_bin
*** 3798,3804 ****
  
  	  if (!identified)
  	    {
! 	      complained = identify_goto (decl, input_location, locus, DK_ERROR,
  					  computed);
  	      identified = 2;
  	    }
--- 3799,3806 ----
  
  	  if (!identified)
  	    {
! 	      complained = identify_goto (decl, input_location, locus,
! 					  diagnostics::kind::error,
  					  computed);
  	      identified = 2;
  	    }
*************** check_previous_goto_1 (tree decl, cp_bin
*** 3866,3872 ****
        if (inf)
  	{
  	  if (identified < 2)
! 	    complained = identify_goto (decl, input_location, locus, DK_ERROR,
  					computed);
  	  identified = 2;
  	  if (complained)
--- 3868,3875 ----
        if (inf)
  	{
  	  if (identified < 2)
! 	    complained = identify_goto (decl, input_location, locus,
! 					diagnostics::kind::error,
  					computed);
  	  identified = 2;
  	  if (complained)
*************** check_previous_goto_1 (tree decl, cp_bin
*** 3877,3883 ****
    if (!vec_safe_is_empty (computed))
      {
        if (!identified)
! 	complained = identify_goto (decl, input_location, locus, DK_ERROR,
  				    computed);
        identified = 2;
        if (complained)
--- 3880,3887 ----
    if (!vec_safe_is_empty (computed))
      {
        if (!identified)
! 	complained = identify_goto (decl, input_location, locus,
! 				    diagnostics::kind::error,
  				    computed);
        identified = 2;
        if (complained)
*************** check_goto_1 (named_label_entry *ent, bo
*** 3949,3962 ****
        || ent->in_omp_scope || ent->in_stmt_expr
        || !vec_safe_is_empty (ent->bad_decls))
      {
!       diagnostic_t diag_kind = DK_PERMERROR;
        if (ent->in_try_scope || ent->in_catch_scope || ent->in_constexpr_if
  	  || ent->in_consteval_if || ent->in_transaction_scope
  	  || ent->in_omp_scope || ent->in_stmt_expr)
! 	diag_kind = DK_ERROR;
        complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
  				  &input_location, diag_kind, computed);
!       identified = 1 + (diag_kind == DK_ERROR);
      }
  
    FOR_EACH_VEC_SAFE_ELT (ent->bad_decls, ix, bad)
--- 3953,3966 ----
        || ent->in_omp_scope || ent->in_stmt_expr
        || !vec_safe_is_empty (ent->bad_decls))
      {
!       enum diagnostics::kind diag_kind = diagnostics::kind::permerror;
        if (ent->in_try_scope || ent->in_catch_scope || ent->in_constexpr_if
  	  || ent->in_consteval_if || ent->in_transaction_scope
  	  || ent->in_omp_scope || ent->in_stmt_expr)
! 	diag_kind = diagnostics::kind::error;
        complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
  				  &input_location, diag_kind, computed);
!       identified = 1 + (diag_kind == diagnostics::kind::error);
      }
  
    FOR_EACH_VEC_SAFE_ELT (ent->bad_decls, ix, bad)
*************** check_goto_1 (named_label_entry *ent, bo
*** 3969,3975 ****
  	  if (identified == 1)
  	    {
  	      complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
! 					  &input_location, DK_ERROR, computed);
  	      identified = 2;
  	    }
  	  if (complained)
--- 3973,3981 ----
  	  if (identified == 1)
  	    {
  	      complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
! 					  &input_location,
! 					  diagnostics::kind::error,
! 					  computed);
  	      identified = 2;
  	    }
  	  if (complained)
*************** check_goto_1 (named_label_entry *ent, bo
*** 4013,4019 ****
  	      {
  		complained = identify_goto (decl,
  					    DECL_SOURCE_LOCATION (decl),
! 					    &input_location, DK_ERROR,
  					    computed);
  		identified = 2;
  	      }
--- 4019,4026 ----
  	      {
  		complained = identify_goto (decl,
  					    DECL_SOURCE_LOCATION (decl),
! 					    &input_location,
! 					    diagnostics::kind::error,
  					    computed);
  		identified = 2;
  	      }
*************** check_goto_1 (named_label_entry *ent, bo
*** 4037,4043 ****
  		{
  		  complained
  		    = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
! 				     &input_location, DK_ERROR, computed);
  		  identified = 2;
  		}
  	      if (complained)
--- 4044,4051 ----
  		{
  		  complained
  		    = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
! 				     &input_location, diagnostics::kind::error,
! 				     computed);
  		  identified = 2;
  		}
  	      if (complained)
*************** check_goto_1 (named_label_entry *ent, bo
*** 4053,4059 ****
  		    {
  		      complained
  			= identify_goto (decl, DECL_SOURCE_LOCATION (decl),
! 					 &input_location, DK_ERROR, computed);
  		      identified = 2;
  		    }
  		  if (complained)
--- 4061,4068 ----
  		    {
  		      complained
  			= identify_goto (decl, DECL_SOURCE_LOCATION (decl),
! 					 &input_location, diagnostics::kind::error,
! 					 computed);
  		      identified = 2;
  		    }
  		  if (complained)
*************** grokfndecl (tree ctype,
*** 11275,11286 ****
  	   t && t != void_list_node; t = TREE_CHAIN (t))
  	if (TREE_PURPOSE (t))
  	  {
! 	    diagnostic_t diag_kind = DK_PERMERROR;
  	    /* For templates, mark the default argument as erroneous and give a
  	       hard error.  */
  	    if (processing_template_decl)
  	      {
! 		diag_kind = DK_ERROR;
  		TREE_PURPOSE (t) = error_mark_node;
  	      }
  	    if (!has_errored)
--- 11284,11295 ----
  	   t && t != void_list_node; t = TREE_CHAIN (t))
  	if (TREE_PURPOSE (t))
  	  {
! 	    enum diagnostics::kind diag_kind = diagnostics::kind::permerror;
  	    /* For templates, mark the default argument as erroneous and give a
  	       hard error.  */
  	    if (processing_template_decl)
  	      {
! 		diag_kind = diagnostics::kind::error;
  		TREE_PURPOSE (t) = error_mark_node;
  	      }
  	    if (!has_errored)
*************** grokfndecl (tree ctype,
*** 11288,11294 ****
  		has_errored = true;
  		emit_diagnostic (diag_kind,
  				 DECL_SOURCE_LOCATION (decl),
! 				 /*diagnostic_option_id=*/0,
  				 "friend declaration of %qD specifies default "
  				 "arguments and isn%'t a definition", decl);
  	      }
--- 11297,11303 ----
  		has_errored = true;
  		emit_diagnostic (diag_kind,
  				 DECL_SOURCE_LOCATION (decl),
! 				 /*diagnostics::option_id=*/0,
  				 "friend declaration of %qD specifies default "
  				 "arguments and isn%'t a definition", decl);
  	      }
*************** xref_basetypes (tree ref, tree base_list
*** 17397,17403 ****
  	 compatibility.  */
        if (processing_template_decl
  	  && CLASS_TYPE_P (basetype) && TYPE_BEING_DEFINED (basetype))
! 	cxx_incomplete_type_diagnostic (NULL_TREE, basetype, DK_PEDWARN);
        if (!dependent_type_p (basetype)
  	  && !complete_type_or_else (basetype, NULL))
  	/* An incomplete type.  Remove it from the list.  */
--- 17406,17413 ----
  	 compatibility.  */
        if (processing_template_decl
  	  && CLASS_TYPE_P (basetype) && TYPE_BEING_DEFINED (basetype))
! 	cxx_incomplete_type_diagnostic (NULL_TREE, basetype,
! 					diagnostics::kind::pedwarn);
        if (!dependent_type_p (basetype)
  	  && !complete_type_or_else (basetype, NULL))
  	/* An incomplete type.  Remove it from the list.  */
diff -Nrcpad gcc-16-20250720/gcc/cp/error.cc gcc-16-20250727/gcc/cp/error.cc
*** gcc-16-20250720/gcc/cp/error.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/error.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 24,30 ****
  #include "cp-tree.h"
  #include "stringpool.h"
  #include "tree-diagnostic.h"
! #include "diagnostic-color.h"
  #include "langhooks-def.h"
  #include "intl.h"
  #include "cxx-pretty-print.h"
--- 24,30 ----
  #include "cp-tree.h"
  #include "stringpool.h"
  #include "tree-diagnostic.h"
! #include "diagnostics/color.h"
  #include "langhooks-def.h"
  #include "intl.h"
  #include "cxx-pretty-print.h"
*************** along with GCC; see the file COPYING3.
*** 38,44 ****
  #include "cp-name-hint.h"
  #include "attribs.h"
  #include "pretty-print-format-impl.h"
! #include "diagnostic-format-text.h"
  
  #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
  #define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
--- 38,44 ----
  #include "cp-name-hint.h"
  #include "attribs.h"
  #include "pretty-print-format-impl.h"
! #include "diagnostics/text-sink.h"
  
  #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
  #define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
*************** static void dump_scope (cxx_pretty_print
*** 96,112 ****
  static void dump_template_parms (cxx_pretty_printer *, tree, int, int);
  static int get_non_default_template_args_count (tree, int);
  static const char *function_category (tree);
! static void maybe_print_constexpr_context (diagnostic_text_output_format &);
! static void maybe_print_instantiation_context (diagnostic_text_output_format &);
! static void print_instantiation_full_context (diagnostic_text_output_format &);
! static void print_instantiation_partial_context (diagnostic_text_output_format &,
  						 struct tinst_level *,
  						 location_t);
! static void maybe_print_constraint_context (diagnostic_text_output_format &);
! static void cp_diagnostic_text_starter (diagnostic_text_output_format &,
! 					const diagnostic_info *);
! static void cp_print_error_function (diagnostic_text_output_format &,
! 				     const diagnostic_info *);
  
  static bool cp_printer (pretty_printer *, text_info *, const char *,
  			int, bool, bool, bool, bool *, pp_token_list &);
--- 96,112 ----
  static void dump_template_parms (cxx_pretty_printer *, tree, int, int);
  static int get_non_default_template_args_count (tree, int);
  static const char *function_category (tree);
! static void maybe_print_constexpr_context (diagnostics::text_sink &);
! static void maybe_print_instantiation_context (diagnostics::text_sink &);
! static void print_instantiation_full_context (diagnostics::text_sink &);
! static void print_instantiation_partial_context (diagnostics::text_sink &,
  						 struct tinst_level *,
  						 location_t);
! static void maybe_print_constraint_context (diagnostics::text_sink &);
! static void cp_diagnostic_text_starter (diagnostics::text_sink &,
! 					const diagnostics::diagnostic_info *);
! static void cp_print_error_function (diagnostics::text_sink &,
! 				     const diagnostics::diagnostic_info *);
  
  static bool cp_printer (pretty_printer *, text_info *, const char *,
  			int, bool, bool, bool, bool *, pp_token_list &);
*************** get_current_template ()
*** 242,248 ****
  
  erroneous_templates_t *erroneous_templates;
  
! /* Callback function diagnostic_context::m_adjust_diagnostic_info.
  
     Errors issued when parsing a template are automatically treated like
     permerrors associated with the -Wtemplate-body flag and can be
--- 242,248 ----
  
  erroneous_templates_t *erroneous_templates;
  
! /* Callback function diagnostics::context::m_adjust_diagnostic_info.
  
     Errors issued when parsing a template are automatically treated like
     permerrors associated with the -Wtemplate-body flag and can be
*************** erroneous_templates_t *erroneous_templat
*** 250,265 ****
     issue an error if we later need to instantiate the template.  */
  
  static void
! cp_adjust_diagnostic_info (diagnostic_context *context,
! 			   diagnostic_info *diagnostic)
  {
!   if (diagnostic->kind == DK_ERROR)
      if (tree tmpl = get_current_template ())
        {
! 	diagnostic->option_id = OPT_Wtemplate_body;
  
  	if (context->m_permissive)
! 	  diagnostic->kind = DK_WARNING;
  
  	bool existed;
  	location_t &error_loc
--- 250,265 ----
     issue an error if we later need to instantiate the template.  */
  
  static void
! cp_adjust_diagnostic_info (diagnostics::context *context,
! 			   diagnostics::diagnostic_info *diagnostic)
  {
!   if (diagnostic->m_kind == diagnostics::kind::error)
      if (tree tmpl = get_current_template ())
        {
! 	diagnostic->m_option_id = OPT_Wtemplate_body;
  
  	if (context->m_permissive)
! 	  diagnostic->m_kind = diagnostics::kind::warning;
  
  	bool existed;
  	location_t &error_loc
*************** cp_adjust_diagnostic_info (diagnostic_co
*** 269,275 ****
  	  /* Remember that this template had a parse-time error so
  	     that we'll ensure a hard error has been issued upon
  	     its instantiation.  */
! 	  error_loc = diagnostic->richloc->get_loc ();
        }
  }
  
--- 269,275 ----
  	  /* Remember that this template had a parse-time error so
  	     that we'll ensure a hard error has been issued upon
  	     its instantiation.  */
! 	  error_loc = diagnostic->m_richloc->get_loc ();
        }
  }
  
*************** cp_seen_error ()
*** 298,311 ****
     capacities.  */
  
  void
! cxx_initialize_diagnostics (diagnostic_context *context)
  {
    cxx_pretty_printer *pp = new cxx_pretty_printer ();
    pp->set_format_postprocessor (std::make_unique<cxx_format_postprocessor> ());
    context->set_pretty_printer (std::unique_ptr<pretty_printer> (pp));
  
    c_common_diagnostics_set_defaults (context);
!   diagnostic_text_starter (context) = cp_diagnostic_text_starter;
    /* diagnostic_finalizer is already c_diagnostic_text_finalizer.  */
    context->set_format_decoder (cp_printer);
    context->set_adjust_diagnostic_info_callback (cp_adjust_diagnostic_info);
--- 298,311 ----
     capacities.  */
  
  void
! cxx_initialize_diagnostics (diagnostics::context *context)
  {
    cxx_pretty_printer *pp = new cxx_pretty_printer ();
    pp->set_format_postprocessor (std::make_unique<cxx_format_postprocessor> ());
    context->set_pretty_printer (std::unique_ptr<pretty_printer> (pp));
  
    c_common_diagnostics_set_defaults (context);
!   diagnostics::text_starter (context) = cp_diagnostic_text_starter;
    /* diagnostic_finalizer is already c_diagnostic_text_finalizer.  */
    context->set_format_decoder (cp_printer);
    context->set_adjust_diagnostic_info_callback (cp_adjust_diagnostic_info);
*************** dump_type (cxx_pretty_printer *pp, tree
*** 704,709 ****
--- 704,723 ----
  	}
        break;
  
+     case TREE_VEC:
+       {
+ 	/* A list of types used for a trait.  */
+ 	bool need_comma = false;
+ 	for (tree arg : tree_vec_range (t))
+ 	  {
+ 	    if (need_comma)
+ 	      pp_separate_with_comma (pp);
+ 	    dump_type (pp, arg, flags);
+ 	    need_comma = true;
+ 	  }
+       }
+       break;
+ 
      case TREE_LIST:
        /* A list of function parms.  */
        dump_parameters (pp, t, flags);
*************** eh_spec_to_string (tree p, int /*v*/)
*** 3747,3755 ****
  
  /* Langhook for print_error_function.  */
  void
! cxx_print_error_function (diagnostic_text_output_format &text_output,
  			  const char *file,
! 			  const diagnostic_info *diagnostic)
  {
    char *prefix;
    if (file)
--- 3761,3769 ----
  
  /* Langhook for print_error_function.  */
  void
! cxx_print_error_function (diagnostics::text_sink &text_output,
  			  const char *file,
! 			  const diagnostics::diagnostic_info *diagnostic)
  {
    char *prefix;
    if (file)
*************** cxx_print_error_function (diagnostic_tex
*** 3763,3770 ****
  }
  
  static void
! cp_diagnostic_text_starter (diagnostic_text_output_format &text_output,
! 			    const diagnostic_info *diagnostic)
  {
    pp_set_prefix (text_output.get_printer (),
  		 text_output.build_indent_prefix (true));
--- 3777,3784 ----
  }
  
  static void
! cp_diagnostic_text_starter (diagnostics::text_sink &text_output,
! 			    const diagnostics::diagnostic_info *diagnostic)
  {
    pp_set_prefix (text_output.get_printer (),
  		 text_output.build_indent_prefix (true));
*************** cp_diagnostic_text_starter (diagnostic_t
*** 3780,3787 ****
  /* Print current function onto BUFFER, in the process of reporting
     a diagnostic message.  Called from cp_diagnostic_starter.  */
  static void
! cp_print_error_function (diagnostic_text_output_format &text_output,
! 			 const diagnostic_info *diagnostic)
  {
    /* If we are in an instantiation context, current_function_decl is likely
       to be wrong, so just rely on print_instantiation_full_context.  */
--- 3794,3801 ----
  /* Print current function onto BUFFER, in the process of reporting
     a diagnostic message.  Called from cp_diagnostic_starter.  */
  static void
! cp_print_error_function (diagnostics::text_sink &text_output,
! 			 const diagnostics::diagnostic_info *diagnostic)
  {
    /* If we are in an instantiation context, current_function_decl is likely
       to be wrong, so just rely on print_instantiation_full_context.  */
*************** cp_print_error_function (diagnostic_text
*** 3790,3796 ****
    /* The above is true for constraint satisfaction also.  */
    if (current_failed_constraint)
      return;
!   diagnostic_context *const context = &text_output.get_context ();
    if (diagnostic_last_function_changed (context, diagnostic))
      {
        pretty_printer *const pp = text_output.get_printer ();
--- 3804,3810 ----
    /* The above is true for constraint satisfaction also.  */
    if (current_failed_constraint)
      return;
!   diagnostics::context *const context = &text_output.get_context ();
    if (diagnostic_last_function_changed (context, diagnostic))
      {
        pretty_printer *const pp = text_output.get_printer ();
*************** function_category (tree fn)
*** 3928,3934 ****
  /* Report the full context of a current template instantiation,
     onto BUFFER.  */
  static void
! print_instantiation_full_context (diagnostic_text_output_format &text_output)
  {
    struct tinst_level *p = current_instantiation ();
    location_t location = input_location;
--- 3942,3948 ----
  /* Report the full context of a current template instantiation,
     onto BUFFER.  */
  static void
! print_instantiation_full_context (diagnostics::text_sink &text_output)
  {
    struct tinst_level *p = current_instantiation ();
    location_t location = input_location;
*************** print_instantiation_full_context (diagno
*** 3956,3962 ****
  }
  
  static void
! print_location (diagnostic_text_output_format &text_output,
  		location_t loc)
  {
    expanded_location xloc = expand_location (loc);
--- 3970,3976 ----
  }
  
  static void
! print_location (diagnostics::text_sink &text_output,
  		location_t loc)
  {
    expanded_location xloc = expand_location (loc);
*************** print_location (diagnostic_text_output_f
*** 3970,3976 ****
  }
  
  /* A RAII class for use when emitting a line of contextual information
!    via pp_verbatim to a diagnostic_text_output_format to add before/after
     behaviors to the pp_verbatim calls.
  
     If the text output has show_nesting_p (), then the ctor prints
--- 3984,3990 ----
  }
  
  /* A RAII class for use when emitting a line of contextual information
!    via pp_verbatim to a diagnostics::text_sink to add before/after
     behaviors to the pp_verbatim calls.
  
     If the text output has show_nesting_p (), then the ctor prints
*************** print_location (diagnostic_text_output_f
*** 3985,3991 ****
  class auto_context_line
  {
  public:
!   auto_context_line (diagnostic_text_output_format &text_output,
  		     location_t loc,
  		     bool show_locus = false)
    : m_text_output (text_output),
--- 3999,4005 ----
  class auto_context_line
  {
  public:
!   auto_context_line (diagnostics::text_sink &text_output,
  		     location_t loc,
  		     bool show_locus = false)
    : m_text_output (text_output),
*************** public:
*** 4016,4022 ****
  	    diagnostic_show_locus (&m_text_output.get_context (),
  				   m_text_output.get_source_printing_options (),
  				   &rich_loc,
! 				   DK_NOTE, pp);
  	    pp_set_prefix (pp, saved_prefix);
  	  }
        }
--- 4030,4036 ----
  	    diagnostic_show_locus (&m_text_output.get_context (),
  				   m_text_output.get_source_printing_options (),
  				   &rich_loc,
! 				   diagnostics::kind::note, pp);
  	    pp_set_prefix (pp, saved_prefix);
  	  }
        }
*************** public:
*** 4028,4039 ****
  	diagnostic_show_locus (&m_text_output.get_context (),
  			       m_text_output.get_source_printing_options (),
  			       &rich_loc,
! 			       DK_NOTE, pp);
  	pp_set_prefix (pp, saved_prefix);
        }
    }
  private:
!   diagnostic_text_output_format &m_text_output;
    location_t m_loc;
    bool m_show_locus;
  };
--- 4042,4053 ----
  	diagnostic_show_locus (&m_text_output.get_context (),
  			       m_text_output.get_source_printing_options (),
  			       &rich_loc,
! 			       diagnostics::kind::note, pp);
  	pp_set_prefix (pp, saved_prefix);
        }
    }
  private:
!   diagnostics::text_sink &m_text_output;
    location_t m_loc;
    bool m_show_locus;
  };
*************** private:
*** 4042,4048 ****
     prints a single line of instantiation context.  */
  
  static void
! print_instantiation_partial_context_line (diagnostic_text_output_format &text_output,
  					  struct tinst_level *t,
  					  location_t loc, bool recursive_p)
  {
--- 4056,4062 ----
     prints a single line of instantiation context.  */
  
  static void
! print_instantiation_partial_context_line (diagnostics::text_sink &text_output,
  					  struct tinst_level *t,
  					  location_t loc, bool recursive_p)
  {
*************** print_instantiation_partial_context_line
*** 4080,4086 ****
  /* Same as print_instantiation_full_context but less verbose.  */
  
  static void
! print_instantiation_partial_context (diagnostic_text_output_format &text_output,
  				     struct tinst_level *t0, location_t loc)
  {
    struct tinst_level *t;
--- 4094,4100 ----
  /* Same as print_instantiation_full_context but less verbose.  */
  
  static void
! print_instantiation_partial_context (diagnostics::text_sink &text_output,
  				     struct tinst_level *t0, location_t loc)
  {
    struct tinst_level *t;
*************** print_instantiation_partial_context (dia
*** 4151,4157 ****
  
  /* Called from cp_thing to print the template context for an error.  */
  static void
! maybe_print_instantiation_context (diagnostic_text_output_format &text_output)
  {
    if (!problematic_instantiation_changed () || current_instantiation () == 0)
      return;
--- 4165,4171 ----
  
  /* Called from cp_thing to print the template context for an error.  */
  static void
! maybe_print_instantiation_context (diagnostics::text_sink &text_output)
  {
    if (!problematic_instantiation_changed () || current_instantiation () == 0)
      return;
*************** maybe_print_instantiation_context (diagn
*** 4163,4169 ****
  /* Report what constexpr call(s) we're trying to expand, if any.  */
  
  void
! maybe_print_constexpr_context (diagnostic_text_output_format &text_output)
  {
    vec<tree> call_stack = cx_error_context ();
    unsigned ix;
--- 4177,4183 ----
  /* Report what constexpr call(s) we're trying to expand, if any.  */
  
  void
! maybe_print_constexpr_context (diagnostics::text_sink &text_output)
  {
    vec<tree> call_stack = cx_error_context ();
    unsigned ix;
*************** maybe_print_constexpr_context (diagnosti
*** 4183,4189 ****
  
  
  static void
! print_constrained_decl_info (diagnostic_text_output_format &text_output,
  			     tree decl)
  {
    auto_context_line sentinel (text_output, DECL_SOURCE_LOCATION (decl));
--- 4197,4203 ----
  
  
  static void
! print_constrained_decl_info (diagnostics::text_sink &text_output,
  			     tree decl)
  {
    auto_context_line sentinel (text_output, DECL_SOURCE_LOCATION (decl));
*************** print_constrained_decl_info (diagnostic_
*** 4192,4198 ****
  }
  
  static void
! print_concept_check_info (diagnostic_text_output_format &text_output,
  			  tree expr, tree map, tree args)
  {
    gcc_assert (concept_check_p (expr));
--- 4206,4212 ----
  }
  
  static void
! print_concept_check_info (diagnostics::text_sink &text_output,
  			  tree expr, tree map, tree args)
  {
    gcc_assert (concept_check_p (expr));
*************** print_concept_check_info (diagnostic_tex
*** 4217,4223 ****
     context, if any.  */
  
  static tree
! print_constraint_context_head (diagnostic_text_output_format &text_output,
  			       tree cxt, tree args)
  {
    tree src = TREE_VALUE (cxt);
--- 4231,4237 ----
     context, if any.  */
  
  static tree
! print_constraint_context_head (diagnostics::text_sink &text_output,
  			       tree cxt, tree args)
  {
    tree src = TREE_VALUE (cxt);
*************** print_constraint_context_head (diagnosti
*** 4241,4247 ****
  }
  
  static void
! print_requires_expression_info (diagnostic_text_output_format &text_output,
  				tree constr, tree args)
  {
  
--- 4255,4261 ----
  }
  
  static void
! print_requires_expression_info (diagnostics::text_sink &text_output,
  				tree constr, tree args)
  {
  
*************** print_requires_expression_info (diagnost
*** 4271,4277 ****
  }
  
  void
! maybe_print_single_constraint_context (diagnostic_text_output_format &text_output,
  				       tree failed)
  {
    if (!failed)
--- 4285,4291 ----
  }
  
  void
! maybe_print_single_constraint_context (diagnostics::text_sink &text_output,
  				       tree failed)
  {
    if (!failed)
*************** maybe_print_single_constraint_context (d
*** 4302,4308 ****
  }
  
  void
! maybe_print_constraint_context (diagnostic_text_output_format &text_output)
  {
    if (!current_failed_constraint)
      return;
--- 4316,4322 ----
  }
  
  void
! maybe_print_constraint_context (diagnostics::text_sink &text_output)
  {
    if (!current_failed_constraint)
      return;
*************** maybe_warn_variadic_templates (void)
*** 4915,4932 ****
     C++0x.  */
  bool
  pedwarn_cxx98 (location_t location,
! 	       diagnostic_option_id option_id,
  	       const char *gmsgid, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    bool ret;
    rich_location richloc (line_table, location);
  
    va_start (ap, gmsgid);
    diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
! 		       (cxx_dialect == cxx98) ? DK_PEDWARN : DK_WARNING);
!   diagnostic.option_id = option_id;
    ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
    va_end (ap);
    return ret;
--- 4929,4948 ----
     C++0x.  */
  bool
  pedwarn_cxx98 (location_t location,
! 	       diagnostics::option_id option_id,
  	       const char *gmsgid, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    bool ret;
    rich_location richloc (line_table, location);
  
    va_start (ap, gmsgid);
    diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
! 		       (cxx_dialect == cxx98
! 			? diagnostics::kind::pedwarn
! 			: diagnostics::kind::warning));
!   diagnostic.m_option_id = option_id;
    ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
    va_end (ap);
    return ret;
diff -Nrcpad gcc-16-20250720/gcc/cp/except.cc gcc-16-20250727/gcc/cp/except.cc
*** gcc-16-20250720/gcc/cp/except.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/except.cc	Sun Jul 27 22:32:08 2025
*************** expr_noexcept_p (tree expr, tsubst_flags
*** 1218,1223 ****
--- 1218,1235 ----
      return true;
  }
  
+ /* Explain why EXPR is not noexcept.  */
+ 
+ void explain_not_noexcept (tree expr)
+ {
+   tree fn = cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0);
+   gcc_assert (fn);
+   if (DECL_P (fn))
+     inform (DECL_SOURCE_LOCATION (fn), "%qD is not %<noexcept%>", fn);
+   else
+     inform (location_of (fn), "%qT is not %<noexcept%>", TREE_TYPE (fn));
+ }
+ 
  /* Return true iff SPEC is throw() or noexcept(true).  */
  
  bool
diff -Nrcpad gcc-16-20250720/gcc/cp/init.cc gcc-16-20250727/gcc/cp/init.cc
*** gcc-16-20250720/gcc/cp/init.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/init.cc	Sun Jul 27 22:32:08 2025
*************** build_vec_delete_1 (location_t loc, tree
*** 4181,4187 ****
  			  "possible problem detected in invocation of "
  			  "operator %<delete []%>"))
  	    {
! 	      cxx_incomplete_type_diagnostic (base, type, DK_WARNING);
  	      inform (loc, "neither the destructor nor the "
  		      "class-specific operator %<delete []%> will be called, "
  		      "even if they are declared when the class is defined");
--- 4181,4188 ----
  			  "possible problem detected in invocation of "
  			  "operator %<delete []%>"))
  	    {
! 	      cxx_incomplete_type_diagnostic (base, type,
! 					      diagnostics::kind::warning);
  	      inform (loc, "neither the destructor nor the "
  		      "class-specific operator %<delete []%> will be called, "
  		      "even if they are declared when the class is defined");
*************** build_delete (location_t loc, tree otype
*** 5286,5292 ****
  				  "possible problem detected in invocation of "
  				  "%<operator delete%>"))
  		    {
! 		      cxx_incomplete_type_diagnostic (addr, type, DK_WARNING);
  		      inform (loc,
  			      "neither the destructor nor the class-specific "
  			      "%<operator delete%> will be called, even if "
--- 5287,5294 ----
  				  "possible problem detected in invocation of "
  				  "%<operator delete%>"))
  		    {
! 		      cxx_incomplete_type_diagnostic (addr, type,
! 						      diagnostics::kind::warning);
  		      inform (loc,
  			      "neither the destructor nor the class-specific "
  			      "%<operator delete%> will be called, even if "
diff -Nrcpad gcc-16-20250720/gcc/cp/lambda.cc gcc-16-20250727/gcc/cp/lambda.cc
*** gcc-16-20250720/gcc/cp/lambda.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/lambda.cc	Sun Jul 27 22:32:08 2025
*************** maybe_add_lambda_conv_op (tree type)
*** 1143,1149 ****
    tree lam = CLASSTYPE_LAMBDA_EXPR (type);
  
    if (LAMBDA_EXPR_CAPTURE_LIST (lam) != NULL_TREE
!       || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) != CPLD_NONE)
      return;
  
    if (processing_template_decl)
--- 1143,1151 ----
    tree lam = CLASSTYPE_LAMBDA_EXPR (type);
  
    if (LAMBDA_EXPR_CAPTURE_LIST (lam) != NULL_TREE
!       || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) != CPLD_NONE
!       /* CWG2561 ...and no explicit object parameter.  */
!       || DECL_XOBJ_MEMBER_FUNCTION_P (callop))
      return;
  
    if (processing_template_decl)
diff -Nrcpad gcc-16-20250720/gcc/cp/method.cc gcc-16-20250727/gcc/cp/method.cc
*** gcc-16-20250720/gcc/cp/method.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/method.cc	Sun Jul 27 22:32:08 2025
*************** early_check_defaulted_comparison (tree f
*** 1187,1201 ****
    if (!DECL_OVERLOADED_OPERATOR_IS (fn, SPACESHIP_EXPR)
        && !same_type_p (TREE_TYPE (TREE_TYPE (fn)), boolean_type_node))
      {
!       diagnostic_t kind = DK_UNSPECIFIED;
        int opt = 0;
        if (is_auto (TREE_TYPE (fn)))
! 	kind = DK_PEDWARN;
        else
! 	kind = DK_ERROR;
        emit_diagnostic (kind, loc, opt,
  		       "defaulted %qD must return %<bool%>", fn);
!       if (kind == DK_ERROR)
  	ok = false;
      }
  
--- 1187,1201 ----
    if (!DECL_OVERLOADED_OPERATOR_IS (fn, SPACESHIP_EXPR)
        && !same_type_p (TREE_TYPE (TREE_TYPE (fn)), boolean_type_node))
      {
!       enum diagnostics::kind kind = diagnostics::kind::unspecified;
        int opt = 0;
        if (is_auto (TREE_TYPE (fn)))
! 	kind = diagnostics::kind::pedwarn;
        else
! 	kind = diagnostics::kind::error;
        emit_diagnostic (kind, loc, opt,
  		       "defaulted %qD must return %<bool%>", fn);
!       if (kind == diagnostics::kind::error)
  	ok = false;
      }
  
*************** is_stub_object (tree expr)
*** 1928,1935 ****
  
  /* Build a std::declval<TYPE>() expression and return it.  */
  
! tree
! build_trait_object (tree type)
  {
    /* TYPE can't be a function with cv-/ref-qualifiers: std::declval is
       defined as
--- 1928,1935 ----
  
  /* Build a std::declval<TYPE>() expression and return it.  */
  
! static tree
! build_trait_object (tree type, tsubst_flags_t complain)
  {
    /* TYPE can't be a function with cv-/ref-qualifiers: std::declval is
       defined as
*************** build_trait_object (tree type)
*** 1942,1948 ****
    if (FUNC_OR_METHOD_TYPE_P (type)
        && (type_memfn_quals (type) != TYPE_UNQUALIFIED
  	  || type_memfn_rqual (type) != REF_QUAL_NONE))
!     return error_mark_node;
  
    return build_stub_object (type);
  }
--- 1942,1952 ----
    if (FUNC_OR_METHOD_TYPE_P (type)
        && (type_memfn_quals (type) != TYPE_UNQUALIFIED
  	  || type_memfn_rqual (type) != REF_QUAL_NONE))
!     {
!       if (complain & tf_error)
! 	error ("object cannot have qualified function type %qT", type);
!       return error_mark_node;
!     }
  
    return build_stub_object (type);
  }
*************** build_invoke (tree fn_type, const_tree a
*** 2036,2057 ****
  	      const_tree name = DECL_NAME (datum_decl);
  	      if (name && (id_equal (name, "reference_wrapper")))
  		{
! 		  /* 1.2 & 1.5: Retrieve T from std::reference_wrapper<T>,
  		     i.e., decltype(datum.get()).  */
  		  datum_type =
  		    TREE_VEC_ELT (TYPE_TI_ARGS (non_ref_datum_type), 0);
  		  datum_is_refwrap = true;
  		}
  	    }
  	}
  
!       tree datum_expr = build_trait_object (datum_type);
        if (!ptrmem_is_same_or_base_of_datum && !datum_is_refwrap)
  	/* 1.3 & 1.6: Try to dereference datum_expr.  */
  	datum_expr = build_x_indirect_ref (UNKNOWN_LOCATION, datum_expr,
  					   RO_UNARY_STAR, NULL_TREE, complain);
  
!       tree fn_expr = build_trait_object (fn_type);
        ptrmem_expr = build_m_component_ref (datum_expr, fn_expr, complain);
  
        if (error_operand_p (ptrmem_expr))
--- 2040,2065 ----
  	      const_tree name = DECL_NAME (datum_decl);
  	      if (name && (id_equal (name, "reference_wrapper")))
  		{
! 		  /* 1.2 & 1.5: Retrieve T& from std::reference_wrapper<T>,
  		     i.e., decltype(datum.get()).  */
  		  datum_type =
  		    TREE_VEC_ELT (TYPE_TI_ARGS (non_ref_datum_type), 0);
+ 		  datum_type = cp_build_reference_type (datum_type, false);
  		  datum_is_refwrap = true;
  		}
  	    }
  	}
  
!       tree datum_expr = build_trait_object (datum_type, complain);
        if (!ptrmem_is_same_or_base_of_datum && !datum_is_refwrap)
  	/* 1.3 & 1.6: Try to dereference datum_expr.  */
  	datum_expr = build_x_indirect_ref (UNKNOWN_LOCATION, datum_expr,
  					   RO_UNARY_STAR, NULL_TREE, complain);
  
!       if (error_operand_p (datum_expr))
! 	return error_mark_node;
! 
!       tree fn_expr = build_trait_object (fn_type, complain);
        ptrmem_expr = build_m_component_ref (datum_expr, fn_expr, complain);
  
        if (error_operand_p (ptrmem_expr))
*************** build_invoke (tree fn_type, const_tree a
*** 2068,2074 ****
    for (int i = is_ptrmemfunc ? 1 : 0; i < TREE_VEC_LENGTH (arg_types); ++i)
      {
        tree arg_type = TREE_VEC_ELT (arg_types, i);
!       tree arg = build_trait_object (arg_type);
        vec_safe_push (args, arg);
      }
  
--- 2076,2084 ----
    for (int i = is_ptrmemfunc ? 1 : 0; i < TREE_VEC_LENGTH (arg_types); ++i)
      {
        tree arg_type = TREE_VEC_ELT (arg_types, i);
!       tree arg = build_trait_object (arg_type, complain);
!       if (error_operand_p (arg))
! 	return error_mark_node;
        vec_safe_push (args, arg);
      }
  
*************** build_invoke (tree fn_type, const_tree a
*** 2077,2084 ****
      invoke_expr = build_offset_ref_call_from_tree (ptrmem_expr, &args,
  						   complain);
    else  /* 1.7.  */
!     invoke_expr = finish_call_expr (build_trait_object (fn_type), &args, false,
! 				    false, complain);
    return invoke_expr;
  }
  
--- 2087,2094 ----
      invoke_expr = build_offset_ref_call_from_tree (ptrmem_expr, &args,
  						   complain);
    else  /* 1.7.  */
!     invoke_expr = finish_call_expr (build_trait_object (fn_type, complain),
! 				    &args, false, false, complain);
    return invoke_expr;
  }
  
*************** check_nontriv (tree *tp, int *, void *)
*** 2227,2238 ****
  /* Return declval<T>() = declval<U>() treated as an unevaluated operand.  */
  
  static tree
! assignable_expr (tree to, tree from)
  {
    cp_unevaluated cp_uneval_guard;
!   to = build_trait_object (to);
!   from = build_trait_object (from);
!   tree r = cp_build_modify_expr (input_location, to, NOP_EXPR, from, tf_none);
    return r;
  }
  
--- 2237,2256 ----
  /* Return declval<T>() = declval<U>() treated as an unevaluated operand.  */
  
  static tree
! assignable_expr (tree to, tree from, bool explain)
  {
    cp_unevaluated cp_uneval_guard;
!   tsubst_flags_t complain = explain ? tf_error : tf_none;
! 
!   to = build_trait_object (to, complain);
!   if (to == error_mark_node)
!     return error_mark_node;
! 
!   from = build_trait_object (from, complain);
!   if (from == error_mark_node)
!     return error_mark_node;
! 
!   tree r = cp_build_modify_expr (input_location, to, NOP_EXPR, from, complain);
    return r;
  }
  
*************** assignable_expr (tree to, tree from)
*** 2244,2253 ****
     Return something equivalent in well-formedness and triviality.  */
  
  static tree
! constructible_expr (tree to, tree from)
  {
    tree expr;
    cp_unevaluated cp_uneval_guard;
    const int len = TREE_VEC_LENGTH (from);
    if (CLASS_TYPE_P (to))
      {
--- 2262,2272 ----
     Return something equivalent in well-formedness and triviality.  */
  
  static tree
! constructible_expr (tree to, tree from, bool explain)
  {
    tree expr;
    cp_unevaluated cp_uneval_guard;
+   tsubst_flags_t complain = explain ? tf_error : tf_none;
    const int len = TREE_VEC_LENGTH (from);
    if (CLASS_TYPE_P (to))
      {
*************** constructible_expr (tree to, tree from)
*** 2259,2272 ****
  	to = cp_build_reference_type (to, /*rval*/false);
        tree ob = build_stub_object (to);
        if (len == 0)
! 	expr = build_value_init (ctype, tf_none);
        else
  	{
  	  vec_alloc (args, len);
  	  for (tree arg : tree_vec_range (from))
  	    args->quick_push (build_stub_object (arg));
  	  expr = build_special_member_call (ob, complete_ctor_identifier, &args,
! 					    ctype, LOOKUP_NORMAL, tf_none);
  	}
        if (expr == error_mark_node)
  	return error_mark_node;
--- 2278,2291 ----
  	to = cp_build_reference_type (to, /*rval*/false);
        tree ob = build_stub_object (to);
        if (len == 0)
! 	expr = build_value_init (ctype, complain);
        else
  	{
  	  vec_alloc (args, len);
  	  for (tree arg : tree_vec_range (from))
  	    args->quick_push (build_stub_object (arg));
  	  expr = build_special_member_call (ob, complete_ctor_identifier, &args,
! 					    ctype, LOOKUP_NORMAL, complain);
  	}
        if (expr == error_mark_node)
  	return error_mark_node;
*************** constructible_expr (tree to, tree from)
*** 2276,2282 ****
  	{
  	  tree dtor = build_special_member_call (ob, complete_dtor_identifier,
  						 NULL, ctype, LOOKUP_NORMAL,
! 						 tf_none);
  	  if (dtor == error_mark_node)
  	    return error_mark_node;
  	  if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (ctype))
--- 2295,2301 ----
  	{
  	  tree dtor = build_special_member_call (ob, complete_dtor_identifier,
  						 NULL, ctype, LOOKUP_NORMAL,
! 						 complain);
  	  if (dtor == error_mark_node)
  	    return error_mark_node;
  	  if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (ctype))
*************** constructible_expr (tree to, tree from)
*** 2286,2297 ****
    else
      {
        if (len == 0)
! 	return build_value_init (strip_array_types (to), tf_none);
        if (len > 1)
  	{
  	  if (cxx_dialect < cxx20)
! 	    /* Too many initializers.  */
! 	    return error_mark_node;
  
  	  /* In C++20 this is well-formed:
  	       using T = int[2];
--- 2305,2319 ----
    else
      {
        if (len == 0)
! 	return build_value_init (strip_array_types (to), complain);
        if (len > 1)
  	{
  	  if (cxx_dialect < cxx20)
! 	    {
! 	      if (explain)
! 		error ("too many initializers for non-class type %qT", to);
! 	      return error_mark_node;
! 	    }
  
  	  /* In C++20 this is well-formed:
  	       using T = int[2];
*************** constructible_expr (tree to, tree from)
*** 2312,2320 ****
  	}
        else
  	from = build_stub_object (TREE_VEC_ELT (from, 0));
        expr = perform_direct_initialization_if_possible (to, from,
  							/*cast*/false,
! 							tf_none);
        /* If t(e) didn't work, maybe t{e} will.  */
        if (expr == NULL_TREE
  	  && len == 1
--- 2334,2344 ----
  	}
        else
  	from = build_stub_object (TREE_VEC_ELT (from, 0));
+ 
+       tree orig_from = from;
        expr = perform_direct_initialization_if_possible (to, from,
  							/*cast*/false,
! 							complain);
        /* If t(e) didn't work, maybe t{e} will.  */
        if (expr == NULL_TREE
  	  && len == 1
*************** constructible_expr (tree to, tree from)
*** 2326,2332 ****
  	  CONSTRUCTOR_IS_PAREN_INIT (from) = true;
  	  expr = perform_direct_initialization_if_possible (to, from,
  							    /*cast*/false,
! 							    tf_none);
  	}
      }
    return expr;
--- 2350,2373 ----
  	  CONSTRUCTOR_IS_PAREN_INIT (from) = true;
  	  expr = perform_direct_initialization_if_possible (to, from,
  							    /*cast*/false,
! 							    complain);
! 	}
! 
!       if (expr == NULL_TREE && explain)
! 	{
! 	  if (len > 1)
! 	    error ("too many initializers for non-class type %qT", to);
! 	  else
! 	    {
! 	      /* Redo the implicit conversion for diagnostics.  */
! 	      int count = errorcount + warningcount;
! 	      perform_implicit_conversion_flags (to, orig_from, complain,
! 						 LOOKUP_NORMAL);
! 	      if (count == errorcount + warningcount)
! 		/* The message may have been suppressed due to -w + -fpermissive,
! 		   emit a generic response instead.  */
! 		error ("the conversion is invalid");
! 	    }
  	}
      }
    return expr;
*************** constructible_expr (tree to, tree from)
*** 2340,2359 ****
     valid or error_mark_node if not.  */
  
  static tree
! destructible_expr (tree to)
  {
    cp_unevaluated cp_uneval_guard;
    int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
    if (TYPE_REF_P (to))
      return void_node;
    if (!COMPLETE_TYPE_P (complete_type (to)))
!     return error_mark_node;
    to = strip_array_types (to);
    if (CLASS_TYPE_P (to))
      {
!       to = build_trait_object (to);
        return build_delete (input_location, TREE_TYPE (to), to,
! 			     sfk_complete_destructor, flags, 0, tf_none);
      }
    /* [expr.prim.id.dtor] If the id-expression names a pseudo-destructor, T
       shall be a scalar type.... */
--- 2381,2405 ----
     valid or error_mark_node if not.  */
  
  static tree
! destructible_expr (tree to, bool explain)
  {
    cp_unevaluated cp_uneval_guard;
+   tsubst_flags_t complain = explain ? tf_error : tf_none;
    int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
    if (TYPE_REF_P (to))
      return void_node;
    if (!COMPLETE_TYPE_P (complete_type (to)))
!     {
!       if (explain)
! 	error_at (location_of (to), "%qT is incomplete", to);
!       return error_mark_node;
!     }
    to = strip_array_types (to);
    if (CLASS_TYPE_P (to))
      {
!       to = build_trait_object (to, complain);
        return build_delete (input_location, TREE_TYPE (to), to,
! 			   sfk_complete_destructor, flags, 0, complain);
      }
    /* [expr.prim.id.dtor] If the id-expression names a pseudo-destructor, T
       shall be a scalar type.... */
*************** destructible_expr (tree to)
*** 2365,2434 ****
  
  /* Returns a tree iff TO is assignable (if CODE is MODIFY_EXPR) or
     constructible (otherwise) from FROM, which is a single type for
!    assignment or a list of types for construction.  */
  
  static tree
! is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
  {
    to = complete_type (to);
    deferring_access_check_sentinel acs (dk_no_deferred);
!   if (VOID_TYPE_P (to)
!       || (from && FUNC_OR_METHOD_TYPE_P (from)
! 	  && (TYPE_READONLY (from) || FUNCTION_REF_QUALIFIED (from))))
!     return error_mark_node;
    tree expr;
    if (code == MODIFY_EXPR)
!     expr = assignable_expr (to, from);
    else if (code == BIT_NOT_EXPR)
!     expr = destructible_expr (to);
!   else if (trivial && TREE_VEC_LENGTH (from) > 1
! 	   && cxx_dialect < cxx20)
!     return error_mark_node; // only 0- and 1-argument ctors can be trivial
! 			    // before C++20 aggregate paren init
    else if (TREE_CODE (to) == ARRAY_TYPE && !TYPE_DOMAIN (to))
!     return error_mark_node; // can't construct an array of unknown bound
    else
!     expr = constructible_expr (to, from);
    return expr;
  }
  
  /* Returns true iff TO is trivially assignable (if CODE is MODIFY_EXPR) or
     constructible (otherwise) from FROM, which is a single type for
!    assignment or a list of types for construction.  */
  
  bool
! is_trivially_xible (enum tree_code code, tree to, tree from)
  {
!   tree expr = is_xible_helper (code, to, from, /*trivial*/true);
    if (expr == NULL_TREE || expr == error_mark_node)
      return false;
    tree nt = cp_walk_tree_without_duplicates (&expr, check_nontriv, NULL);
    return !nt;
  }
  
  /* Returns true iff TO is nothrow assignable (if CODE is MODIFY_EXPR) or
     constructible (otherwise) from FROM, which is a single type for
!    assignment or a list of types for construction.  */
  
  bool
! is_nothrow_xible (enum tree_code code, tree to, tree from)
  {
    ++cp_noexcept_operand;
!   tree expr = is_xible_helper (code, to, from, /*trivial*/false);
    --cp_noexcept_operand;
    if (expr == NULL_TREE || expr == error_mark_node)
      return false;
!   return expr_noexcept_p (expr, tf_none);
  }
  
  /* Returns true iff TO is assignable (if CODE is MODIFY_EXPR) or
     constructible (otherwise) from FROM, which is a single type for
!    assignment or a list of types for construction.  */
  
  bool
! is_xible (enum tree_code code, tree to, tree from)
  {
!   tree expr = is_xible_helper (code, to, from, /*trivial*/false);
    if (expr == error_mark_node)
      return false;
    return !!expr;
--- 2411,2519 ----
  
  /* Returns a tree iff TO is assignable (if CODE is MODIFY_EXPR) or
     constructible (otherwise) from FROM, which is a single type for
!    assignment or a list of types for construction.  If EXPLAIN is
!    set, emit a diagnostic explaining why the operation failed.  */
  
  static tree
! is_xible_helper (enum tree_code code, tree to, tree from, bool explain)
  {
    to = complete_type (to);
    deferring_access_check_sentinel acs (dk_no_deferred);
! 
!   if (VOID_TYPE_P (to))
!     {
!       if (explain)
! 	error_at (location_of (to), "%qT is incomplete", to);
!       return error_mark_node;
!     }
!   if (from
!       && FUNC_OR_METHOD_TYPE_P (from)
!       && (TYPE_READONLY (from) || FUNCTION_REF_QUALIFIED (from)))
!     {
!       if (explain)
! 	error ("%qT is a qualified function type", from);
!       return error_mark_node;
!     }
! 
    tree expr;
    if (code == MODIFY_EXPR)
!     expr = assignable_expr (to, from, explain);
    else if (code == BIT_NOT_EXPR)
!     expr = destructible_expr (to, explain);
    else if (TREE_CODE (to) == ARRAY_TYPE && !TYPE_DOMAIN (to))
!     {
!       if (explain)
! 	error ("cannot construct an array of unknown bound");
!       return error_mark_node;
!     }
    else
!     expr = constructible_expr (to, from, explain);
    return expr;
  }
  
  /* Returns true iff TO is trivially assignable (if CODE is MODIFY_EXPR) or
     constructible (otherwise) from FROM, which is a single type for
!    assignment or a list of types for construction.  If EXPLAIN, diagnose
!    why we returned false.  */
  
  bool
! is_trivially_xible (enum tree_code code, tree to, tree from,
! 		    bool explain/*=false*/)
  {
!   /* In some cases, when producing errors is_xible_helper may not return
!      error_mark_node, so check if it looks like we've already emitted any
!      diagnostics to ensure we don't do so multiple times.  */
!   int errs = errorcount + sorrycount;
! 
!   tree expr = is_xible_helper (code, to, from, explain);
    if (expr == NULL_TREE || expr == error_mark_node)
      return false;
+ 
    tree nt = cp_walk_tree_without_duplicates (&expr, check_nontriv, NULL);
+   if (explain && errs == (errorcount + sorrycount))
+     {
+       gcc_assert (nt);
+       inform (location_of (nt), "%qE is non-trivial", nt);
+     }
    return !nt;
  }
  
  /* Returns true iff TO is nothrow assignable (if CODE is MODIFY_EXPR) or
     constructible (otherwise) from FROM, which is a single type for
!    assignment or a list of types for construction.  If EXPLAIN, diagnose
!    why we returned false.  */
  
  bool
! is_nothrow_xible (enum tree_code code, tree to, tree from,
! 		  bool explain/*=false*/)
  {
+   /* As with is_trivially_xible.  */
+   int errs = errorcount + sorrycount;
+ 
    ++cp_noexcept_operand;
!   tree expr = is_xible_helper (code, to, from, explain);
    --cp_noexcept_operand;
    if (expr == NULL_TREE || expr == error_mark_node)
      return false;
! 
!   bool is_noexcept = expr_noexcept_p (expr, tf_none);
!   if (explain && errs == (errorcount + sorrycount))
!     {
!       gcc_assert (!is_noexcept);
!       explain_not_noexcept (expr);
!     }
!   return is_noexcept;
  }
  
  /* Returns true iff TO is assignable (if CODE is MODIFY_EXPR) or
     constructible (otherwise) from FROM, which is a single type for
!    assignment or a list of types for construction.  If EXPLAIN, diagnose
!    why we returned false.  */
  
  bool
! is_xible (enum tree_code code, tree to, tree from, bool explain/*=false*/)
  {
!   tree expr = is_xible_helper (code, to, from, explain);
    if (expr == error_mark_node)
      return false;
    return !!expr;
*************** ref_xes_from_temporary (tree to, tree fr
*** 2453,2459 ****
      return false;
    /* We don't check is_constructible<T, U>: if T isn't constructible
       from U, we won't be able to create a conversion.  */
!   tree val = build_trait_object (from);
    if (val == error_mark_node)
      return false;
    if (!TYPE_REF_P (from) && TREE_CODE (from) != FUNCTION_TYPE)
--- 2538,2544 ----
      return false;
    /* We don't check is_constructible<T, U>: if T isn't constructible
       from U, we won't be able to create a conversion.  */
!   tree val = build_trait_object (from, tf_none);
    if (val == error_mark_node)
      return false;
    if (!TYPE_REF_P (from) && TREE_CODE (from) != FUNCTION_TYPE)
*************** ref_xes_from_temporary (tree to, tree fr
*** 2462,2486 ****
  }
  
  /* Worker for is_{,nothrow_}convertible.  Attempt to perform an implicit
!    conversion from FROM to TO and return the result.  */
  
  static tree
! is_convertible_helper (tree from, tree to)
  {
    if (VOID_TYPE_P (from) && VOID_TYPE_P (to))
      return integer_one_node;
    cp_unevaluated u;
!   tree expr = build_trait_object (from);
    /* std::is_{,nothrow_}convertible test whether the imaginary function
       definition
  
         To test() { return std::declval<From>(); }
  
       is well-formed.  A function can't return a function.  */
!   if (FUNC_OR_METHOD_TYPE_P (to) || expr == error_mark_node)
      return error_mark_node;
    deferring_access_check_sentinel acs (dk_no_deferred);
!   return perform_implicit_conversion (to, expr, tf_none);
  }
  
  /* Return true if FROM can be converted to TO using implicit conversions,
--- 2547,2582 ----
  }
  
  /* Worker for is_{,nothrow_}convertible.  Attempt to perform an implicit
!    conversion from FROM to TO and return the result.  If EXPLAIN, emit a
!    diagnostic about why the conversion failed.  */
  
  static tree
! is_convertible_helper (tree from, tree to, bool explain)
  {
    if (VOID_TYPE_P (from) && VOID_TYPE_P (to))
      return integer_one_node;
    cp_unevaluated u;
!   tsubst_flags_t complain = explain ? tf_error : tf_none;
! 
    /* std::is_{,nothrow_}convertible test whether the imaginary function
       definition
  
         To test() { return std::declval<From>(); }
  
       is well-formed.  A function can't return a function.  */
!   if (FUNC_OR_METHOD_TYPE_P (to))
!     {
!       if (explain)
! 	error ("%qT is a function type", to);
!       return error_mark_node;
!     }
! 
!   tree expr = build_trait_object (from, complain);
!   if (expr == error_mark_node)
      return error_mark_node;
+ 
    deferring_access_check_sentinel acs (dk_no_deferred);
!   return perform_implicit_conversion (to, expr, complain);
  }
  
  /* Return true if FROM can be converted to TO using implicit conversions,
*************** is_convertible_helper (tree from, tree t
*** 2489,2497 ****
     to either type" restriction.  */
  
  bool
! is_convertible (tree from, tree to)
  {
!   tree expr = is_convertible_helper (from, to);
    if (expr == error_mark_node)
      return false;
    return !!expr;
--- 2585,2593 ----
     to either type" restriction.  */
  
  bool
! is_convertible (tree from, tree to, bool explain/*=false*/)
  {
!   tree expr = is_convertible_helper (from, to, explain);
    if (expr == error_mark_node)
      return false;
    return !!expr;
*************** is_convertible (tree from, tree to)
*** 2500,2511 ****
  /* Like is_convertible, but the conversion is also noexcept.  */
  
  bool
! is_nothrow_convertible (tree from, tree to)
  {
!   tree expr = is_convertible_helper (from, to);
    if (expr == NULL_TREE || expr == error_mark_node)
      return false;
!   return expr_noexcept_p (expr, tf_none);
  }
  
  /* Categorize various special_function_kinds.  */
--- 2596,2613 ----
  /* Like is_convertible, but the conversion is also noexcept.  */
  
  bool
! is_nothrow_convertible (tree from, tree to, bool explain/*=false*/)
  {
!   tree expr = is_convertible_helper (from, to, explain);
    if (expr == NULL_TREE || expr == error_mark_node)
      return false;
!   bool is_noexcept = expr_noexcept_p (expr, tf_none);
!   if (explain)
!     {
!       gcc_assert (!is_noexcept);
!       explain_not_noexcept (expr);
!     }
!   return is_noexcept;
  }
  
  /* Categorize various special_function_kinds.  */
*************** maybe_delete_defaulted_fn (tree fn, tree
*** 3586,3606 ****
  	      the program is ill-formed"  */
  	   || !TYPE_REF_P (parmtype)));
    /* Decide if we want to emit a pedwarn, error, or a warning.  */
!   diagnostic_t diag_kind;
    int opt;
    if (illformed_p)
      {
!       diag_kind = DK_ERROR;
        opt = 0;
      }
    else
      {
!       diag_kind = cxx_dialect >= cxx20 ? DK_WARNING : DK_PEDWARN;
        opt = OPT_Wdefaulted_function_deleted;
      }
  
    /* Don't warn for template instantiations.  */
!   if (DECL_TEMPLATE_INSTANTIATION (fn) && diag_kind == DK_WARNING)
      return;
  
    const char *wmsg;
--- 3688,3711 ----
  	      the program is ill-formed"  */
  	   || !TYPE_REF_P (parmtype)));
    /* Decide if we want to emit a pedwarn, error, or a warning.  */
!   enum diagnostics::kind diag_kind;
    int opt;
    if (illformed_p)
      {
!       diag_kind = diagnostics::kind::error;
        opt = 0;
      }
    else
      {
!       diag_kind = (cxx_dialect >= cxx20
! 		   ? diagnostics::kind::warning
! 		   : diagnostics::kind::pedwarn);
        opt = OPT_Wdefaulted_function_deleted;
      }
  
    /* Don't warn for template instantiations.  */
!   if (DECL_TEMPLATE_INSTANTIATION (fn)
!       && diag_kind == diagnostics::kind::warning)
      return;
  
    const char *wmsg;
diff -Nrcpad gcc-16-20250720/gcc/cp/module.cc gcc-16-20250727/gcc/cp/module.cc
*** gcc-16-20250720/gcc/cp/module.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/module.cc	Sun Jul 27 22:32:08 2025
*************** class GTY((chain_next ("%h.parent"), for
*** 3883,3891 ****
    void write_macro_maps (elf_out *to, range_t &, unsigned *crc_ptr);
    bool read_macro_maps (line_map_uint_t);
  
!   void write_diagnostic_classification (elf_out *, diagnostic_context *,
  					unsigned *);
!   bool read_diagnostic_classification (diagnostic_context *);
  
   private:
    void write_define (bytes_out &, const cpp_macro *);
--- 3883,3891 ----
    void write_macro_maps (elf_out *to, range_t &, unsigned *crc_ptr);
    bool read_macro_maps (line_map_uint_t);
  
!   void write_diagnostic_classification (elf_out *, diagnostics::context *,
  					unsigned *);
!   bool read_diagnostic_classification (diagnostics::context *);
  
   private:
    void write_define (bytes_out &, const cpp_macro *);
*************** noisy_p ()
*** 4822,4828 ****
      return false;
  
    pp_needs_newline (global_dc->get_reference_printer ()) = true;
!   diagnostic_set_last_function (global_dc, (diagnostic_info *) NULL);
  
    return true;
  }
--- 4822,4829 ----
      return false;
  
    pp_needs_newline (global_dc->get_reference_printer ()) = true;
!   diagnostic_set_last_function (global_dc,
! 				(diagnostics::diagnostic_info *) nullptr);
  
    return true;
  }
*************** trees_out::lang_type_bools (tree t, bits
*** 6157,6163 ****
    WB (lang->declared_class);
    WB (lang->diamond_shaped);
    WB (lang->repeated_base);
!   gcc_assert (!lang->being_defined);
    // lang->debug_requested
    WB (lang->fields_readonly);
    WB (lang->ptrmemfunc_flag);
--- 6158,6164 ----
    WB (lang->declared_class);
    WB (lang->diamond_shaped);
    WB (lang->repeated_base);
!   gcc_checking_assert (!lang->being_defined);
    // lang->debug_requested
    WB (lang->fields_readonly);
    WB (lang->ptrmemfunc_flag);
*************** trees_out::lang_type_bools (tree t, bits
*** 6183,6188 ****
--- 6184,6197 ----
    WB (lang->has_constexpr_ctor);
    WB (lang->unique_obj_representations);
    WB (lang->unique_obj_representations_set);
+   gcc_checking_assert (!lang->erroneous);
+   WB (lang->non_pod_aggregate);
+   WB (lang->non_aggregate_pod);
+   WB (lang->trivially_relocatable);
+   WB (lang->trivially_relocatable_computed);
+ 
+   WB (lang->replaceable);
+   WB (lang->replaceable_computed);
  #undef WB
  }
  
*************** trees_in::lang_type_bools (tree t, bits_
*** 6227,6234 ****
    RB (lang->declared_class);
    RB (lang->diamond_shaped);
    RB (lang->repeated_base);
!   gcc_assert (!lang->being_defined);
!   gcc_assert (!lang->debug_requested);
    RB (lang->fields_readonly);
    RB (lang->ptrmemfunc_flag);
  
--- 6236,6243 ----
    RB (lang->declared_class);
    RB (lang->diamond_shaped);
    RB (lang->repeated_base);
!   gcc_checking_assert (!lang->being_defined);
!   gcc_checking_assert (!lang->debug_requested);
    RB (lang->fields_readonly);
    RB (lang->ptrmemfunc_flag);
  
*************** trees_in::lang_type_bools (tree t, bits_
*** 6253,6258 ****
--- 6262,6275 ----
    RB (lang->has_constexpr_ctor);
    RB (lang->unique_obj_representations);
    RB (lang->unique_obj_representations_set);
+   gcc_checking_assert (!lang->erroneous);
+   RB (lang->non_pod_aggregate);
+   RB (lang->non_aggregate_pod);
+   RB (lang->trivially_relocatable);
+   RB (lang->trivially_relocatable_computed);
+ 
+   RB (lang->replaceable);
+   RB (lang->replaceable_computed);
  #undef RB
    return !get_overrun ();
  }
*************** trees_out::core_vals (tree t)
*** 6785,6790 ****
--- 6802,6814 ----
        if (streaming_p ())
  	WU (((lang_tree_node *)t)->trait_expression.kind);
        break;
+ 
+     case TU_LOCAL_ENTITY:
+       WT (((lang_tree_node *)t)->tu_local_entity.name);
+       if (state)
+ 	state->write_location
+ 	  (*this, ((lang_tree_node *)t)->tu_local_entity.loc);
+       break;
      }
  
    if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
*************** trees_in::core_vals (tree t)
*** 7328,7333 ****
--- 7352,7362 ----
        RT (((lang_tree_node *)t)->trait_expression.type2);
        RUC (cp_trait_kind, ((lang_tree_node *)t)->trait_expression.kind);
        break;
+ 
+     case TU_LOCAL_ENTITY:
+       RT (((lang_tree_node *)t)->tu_local_entity.name);
+       ((lang_tree_node *)t)->tu_local_entity.loc
+ 	= state->read_location (*this);
      }
  
    if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
*************** trees_in::tree_node (bool is_use)
*** 10268,10274 ****
  	    && dump ("Read %stypedef %C:%N",
  		     DECL_IMPLICIT_TYPEDEF_P (res) ? "implicit " : "",
  		     TREE_CODE (res), res);
! 	  res = TREE_TYPE (res);
  	}
        break;
  
--- 10297,10304 ----
  	    && dump ("Read %stypedef %C:%N",
  		     DECL_IMPLICIT_TYPEDEF_P (res) ? "implicit " : "",
  		     TREE_CODE (res), res);
! 	  if (TREE_CODE (res) != TU_LOCAL_ENTITY)
! 	    res = TREE_TYPE (res);
  	}
        break;
  
*************** module_state::write_ordinary_maps (elf_o
*** 18325,18346 ****
  /* Return the prefix to use for dumping a #pragma diagnostic change to DK.  */
  
  static const char *
! dk_string (diagnostic_t dk)
  {
!   gcc_assert (dk > DK_UNSPECIFIED && dk < DK_LAST_DIAGNOSTIC_KIND);
!   if (dk == DK_IGNORED)
!     /* diagnostic.def has an empty string for ignored.  */
      return "ignored: ";
    else
!     return get_diagnostic_kind_text (dk);
  }
  
  /* Dump one #pragma GCC diagnostic entry.  */
  
  static bool
! dump_dc_change (unsigned index, unsigned opt, diagnostic_t dk)
  {
!   if (dk == DK_POP)
      return dump (" Index %u: pop from %d", index, opt);
    else
      return dump (" Index %u: %s%s", index, dk_string (dk),
--- 18355,18377 ----
  /* Return the prefix to use for dumping a #pragma diagnostic change to DK.  */
  
  static const char *
! dk_string (enum diagnostics::kind dk)
  {
!   gcc_assert (dk > diagnostics::kind::unspecified
! 	      && dk < diagnostics::kind::last_diagnostic_kind);
!   if (dk == diagnostics::kind::ignored)
!     /* diagnostics/kinds.def has an empty string for ignored.  */
      return "ignored: ";
    else
!     return diagnostics::get_text_for_kind (dk);
  }
  
  /* Dump one #pragma GCC diagnostic entry.  */
  
  static bool
! dump_dc_change (unsigned index, unsigned opt, enum diagnostics::kind dk)
  {
!   if (dk == diagnostics::kind::pop)
      return dump (" Index %u: pop from %d", index, opt);
    else
      return dump (" Index %u: %s%s", index, dk_string (dk),
*************** dump_dc_change (unsigned index, unsigned
*** 18351,18357 ****
  
  void
  module_state::write_diagnostic_classification (elf_out *to,
! 					       diagnostic_context *dc,
  					       unsigned *crc_p)
  {
    auto &changes = dc->get_classification_history ();
--- 18382,18388 ----
  
  void
  module_state::write_diagnostic_classification (elf_out *to,
! 					       diagnostics::context *dc,
  					       unsigned *crc_p)
  {
    auto &changes = dc->get_classification_history ();
*************** module_state::write_diagnostic_classific
*** 18367,18375 ****
    unsigned len = changes.length ();
  
    /* We don't want to write out any entries that came from one of our imports.
!      But then we need to adjust the total, and change DK_POP targets to match
!      the index in our actual output.  So remember how many lines we had skipped
!      at each step, where -1 means this line itself is skipped.  */
    int skips = 0;
    auto_vec<int> skips_at (len);
    skips_at.safe_grow (len);
--- 18398,18407 ----
    unsigned len = changes.length ();
  
    /* We don't want to write out any entries that came from one of our imports.
!      But then we need to adjust the total, and change diagnostics::kind::pop
!      targets to match the index in our actual output.  So remember how many
!      lines we had skipped at each step, where -1 means this line itself
!      is skipped.  */
    int skips = 0;
    auto_vec<int> skips_at (len);
    skips_at.safe_grow (len);
*************** module_state::write_diagnostic_classific
*** 18402,18411 ****
        if (sec.streaming_p ())
  	{
  	  unsigned opt = c.option;
! 	  if (c.kind == DK_POP)
  	    opt -= skips_at[opt];
  	  sec.u (opt);
! 	  sec.u (c.kind);
  	  dump () && dump_dc_change (i - skips_at[i], opt, c.kind);
  	}
      }
--- 18434,18443 ----
        if (sec.streaming_p ())
  	{
  	  unsigned opt = c.option;
! 	  if (c.kind == diagnostics::kind::pop)
  	    opt -= skips_at[opt];
  	  sec.u (opt);
! 	  sec.u (static_cast<unsigned> (c.kind));
  	  dump () && dump_dc_change (i - skips_at[i], opt, c.kind);
  	}
      }
*************** module_state::write_diagnostic_classific
*** 18420,18426 ****
  /* Read any #pragma GCC diagnostic info from the .dgc section.  */
  
  bool
! module_state::read_diagnostic_classification (diagnostic_context *dc)
  {
    bytes_in sec;
  
--- 18452,18458 ----
  /* Read any #pragma GCC diagnostic info from the .dgc section.  */
  
  bool
! module_state::read_diagnostic_classification (diagnostics::context *dc)
  {
    bytes_in sec;
  
*************** module_state::read_diagnostic_classifica
*** 18440,18447 ****
      {
        location_t loc = read_location (sec);
        int opt = sec.u ();
!       diagnostic_t kind = (diagnostic_t) sec.u ();
!       if (kind == DK_POP)
  	/* For a pop, opt is the 'changes' index to return to.  */
  	opt += offset;
        changes.quick_push ({ loc, opt, kind });
--- 18472,18479 ----
      {
        location_t loc = read_location (sec);
        int opt = sec.u ();
!       enum diagnostics::kind kind = (enum diagnostics::kind) sec.u ();
!       if (kind == diagnostics::kind::pop)
  	/* For a pop, opt is the 'changes' index to return to.  */
  	opt += offset;
        changes.quick_push ({ loc, opt, kind });
*************** module_state::read_diagnostic_classifica
*** 18456,18462 ****
  	gcc_checking_assert (i >= offset);
  
  	const auto &c = changes[i];
! 	if (c.kind != DK_POP)
  	  break;
  	else if (c.option == offset)
  	  {
--- 18488,18494 ----
  	gcc_checking_assert (i >= offset);
  
  	const auto &c = changes[i];
! 	if (c.kind != diagnostics::kind::pop)
  	  break;
  	else if (c.option == offset)
  	  {
*************** module_state::read_diagnostic_classifica
*** 18473,18479 ****
        /* It didn't, so add a pop at its last location to avoid affecting later
  	 imports.  */
        location_t last_loc = ordinary_locs.first + ordinary_locs.second - 1;
!       changes.quick_push ({ last_loc, offset, DK_POP });
        dump () && dump (" Adding final pop from index %d", offset);
      }
  
--- 18505,18511 ----
        /* It didn't, so add a pop at its last location to avoid affecting later
  	 imports.  */
        location_t last_loc = ordinary_locs.first + ordinary_locs.second - 1;
!       changes.quick_push ({ last_loc, offset, diagnostics::kind::pop });
        dump () && dump (" Adding final pop from index %d", offset);
      }
  
diff -Nrcpad gcc-16-20250720/gcc/cp/name-lookup.cc gcc-16-20250727/gcc/cp/name-lookup.cc
*** gcc-16-20250720/gcc/cp/name-lookup.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/name-lookup.cc	Sun Jul 27 22:32:08 2025
*************** suggest_alternatives_for_1 (location_t l
*** 7195,7201 ****
    /* Look for exact matches for builtin defines that would have been
       defined if the user had passed a command-line option (e.g. -fopenmp
       for "_OPENMP").  */
!   diagnostic_option_id option_id
      = get_option_for_builtin_define (IDENTIFIER_POINTER (name));
    if (option_id.m_idx > 0)
      return name_hint
--- 7195,7201 ----
    /* Look for exact matches for builtin defines that would have been
       defined if the user had passed a command-line option (e.g. -fopenmp
       for "_OPENMP").  */
!   diagnostics::option_id option_id
      = get_option_for_builtin_define (IDENTIFIER_POINTER (name));
    if (option_id.m_idx > 0)
      return name_hint
diff -Nrcpad gcc-16-20250720/gcc/cp/parser.cc gcc-16-20250727/gcc/cp/parser.cc
*** gcc-16-20250720/gcc/cp/parser.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/parser.cc	Sun Jul 27 22:32:08 2025
*************** cp_parser_userdef_numeric_literal (cp_pa
*** 5266,5272 ****
  	      && (id_equal (suffix_id, "i")
  		  || id_equal (suffix_id, "if")
  		  || id_equal (suffix_id, "il")));
!   diagnostic_t kind = DK_ERROR;
    int opt = 0;
  
    if (i14 && ext)
--- 5266,5272 ----
  	      && (id_equal (suffix_id, "i")
  		  || id_equal (suffix_id, "if")
  		  || id_equal (suffix_id, "il")));
!   enum diagnostics::kind kind = diagnostics::kind::error;
    int opt = 0;
  
    if (i14 && ext)
*************** cp_parser_userdef_numeric_literal (cp_pa
*** 5276,5282 ****
        if (cxlit == error_mark_node)
  	{
  	  /* No <complex>, so pedwarn and use GNU semantics.  */
! 	  kind = DK_PEDWARN;
  	  opt = OPT_Wpedantic;
  	}
      }
--- 5276,5282 ----
        if (cxlit == error_mark_node)
  	{
  	  /* No <complex>, so pedwarn and use GNU semantics.  */
! 	  kind = diagnostics::kind::pedwarn;
  	  opt = OPT_Wpedantic;
  	}
      }
*************** cp_parser_userdef_numeric_literal (cp_pa
*** 5303,5309 ****
  	      "to enable more built-in suffixes");
    }
  
!   if (kind == DK_ERROR)
      value = error_mark_node;
    else
      {
--- 5303,5309 ----
  	      "to enable more built-in suffixes");
    }
  
!   if (kind == diagnostics::kind::error)
      value = error_mark_node;
    else
      {
*************** cp_parser_primary_expression (cp_parser
*** 6647,6653 ****
     member template.  */
  
  static void
! missing_template_diag (location_t loc, diagnostic_t diag_kind = DK_WARNING)
  {
    if (warning_suppressed_at (loc, OPT_Wmissing_template_keyword))
      return;
--- 6647,6654 ----
     member template.  */
  
  static void
! missing_template_diag (location_t loc,
! 		       enum diagnostics::kind diag_kind = diagnostics::kind::warning)
  {
    if (warning_suppressed_at (loc, OPT_Wmissing_template_keyword))
      return;
*************** cp_parser_dot_deref_incomplete (tree *sc
*** 8854,8861 ****
  {
    /* In a template, be permissive by treating an object expression
       of incomplete type as dependent (after a pedwarn).  */
!   diagnostic_t kind = (processing_template_decl
! 		       && MAYBE_CLASS_TYPE_P (*scope) ? DK_PEDWARN : DK_ERROR);
  
    switch (TREE_CODE (*postfix_expression))
      {
--- 8855,8864 ----
  {
    /* In a template, be permissive by treating an object expression
       of incomplete type as dependent (after a pedwarn).  */
!   enum diagnostics::kind kind = ((processing_template_decl
! 				  && MAYBE_CLASS_TYPE_P (*scope))
! 				 ? diagnostics::kind::pedwarn
! 				 : diagnostics::kind::error);
  
    switch (TREE_CODE (*postfix_expression))
      {
*************** cp_parser_dot_deref_incomplete (tree *sc
*** 8867,8893 ****
      case IMPLICIT_CONV_EXPR:
      case VIEW_CONVERT_EXPR:
      case NON_LVALUE_EXPR:
!       kind = DK_ERROR;
        break;
      case OVERLOAD:
        /* Don't emit any diagnostic for OVERLOADs.  */
!       kind = DK_IGNORED;
        break;
      default:
        /* Avoid clobbering e.g. DECLs.  */
        if (!EXPR_P (*postfix_expression))
! 	kind = DK_ERROR;
        break;
      }
  
!   if (kind == DK_IGNORED)
      return false;
  
    location_t exploc = location_of (*postfix_expression);
    cxx_incomplete_type_diagnostic (exploc, *postfix_expression, *scope, kind);
    if (!MAYBE_CLASS_TYPE_P (*scope))
      return true;
!   if (kind == DK_ERROR)
      *scope = *postfix_expression = error_mark_node;
    else if (processing_template_decl)
      {
--- 8870,8896 ----
      case IMPLICIT_CONV_EXPR:
      case VIEW_CONVERT_EXPR:
      case NON_LVALUE_EXPR:
!       kind = diagnostics::kind::error;
        break;
      case OVERLOAD:
        /* Don't emit any diagnostic for OVERLOADs.  */
!       kind = diagnostics::kind::ignored;
        break;
      default:
        /* Avoid clobbering e.g. DECLs.  */
        if (!EXPR_P (*postfix_expression))
! 	kind = diagnostics::kind::error;
        break;
      }
  
!   if (kind == diagnostics::kind::ignored)
      return false;
  
    location_t exploc = location_of (*postfix_expression);
    cxx_incomplete_type_diagnostic (exploc, *postfix_expression, *scope, kind);
    if (!MAYBE_CLASS_TYPE_P (*scope))
      return true;
!   if (kind == diagnostics::kind::error)
      *scope = *postfix_expression = error_mark_node;
    else if (processing_template_decl)
      {
*************** cp_parser_unary_expression (cp_parser *p
*** 9510,9516 ****
  	    diagnostic_push_diagnostics (global_dc, input_location);
  	    diagnostic_classify_diagnostic
  	      (global_dc, OPT_Wconditionally_supported,
! 	       DK_IGNORED, input_location);
  	    /* Parse the cast-expression.  */
  	    expr = cp_parser_simple_cast_expression (parser);
  	    /* Restore the PEDANTIC flag.  */
--- 9513,9519 ----
  	    diagnostic_push_diagnostics (global_dc, input_location);
  	    diagnostic_classify_diagnostic
  	      (global_dc, OPT_Wconditionally_supported,
! 	       diagnostics::kind::ignored, input_location);
  	    /* Parse the cast-expression.  */
  	    expr = cp_parser_simple_cast_expression (parser);
  	    /* Restore the PEDANTIC flag.  */
*************** cp_parser_constructor_declarator_p (cp_p
*** 33706,33712 ****
        && cp_lexer_peek_token (parser->lexer)->type == CPP_TEMPLATE_ID)
      {
        auto_diagnostic_group d;
!       if (emit_diagnostic (cxx_dialect >= cxx20 ? DK_PEDWARN : DK_WARNING,
  			   input_location, OPT_Wtemplate_id_cdtor,
  			   "template-id not allowed for constructor in C++20"))
  	inform (input_location, "remove the %qs", "< >");
--- 33709,33717 ----
        && cp_lexer_peek_token (parser->lexer)->type == CPP_TEMPLATE_ID)
      {
        auto_diagnostic_group d;
!       if (emit_diagnostic ((cxx_dialect >= cxx20
! 			    ? diagnostics::kind::pedwarn
! 			    : diagnostics::kind::warning),
  			   input_location, OPT_Wtemplate_id_cdtor,
  			   "template-id not allowed for constructor in C++20"))
  	inform (input_location, "remove the %qs", "< >");
*************** cp_parser_omp_error (cp_parser *parser,
*** 53048,53058 ****
        if (msg == NULL)
  	msg = _("<message unknown at compile time>");
      }
    if (msg)
!     emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
  		     "%<pragma omp error%> encountered: %s", msg);
    else
!     emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
  		     "%<pragma omp error%> encountered");
    return false;
  }
--- 53053,53066 ----
        if (msg == NULL)
  	msg = _("<message unknown at compile time>");
      }
+   const enum diagnostics::kind diag_kind = (severity_fatal
+ 					    ? diagnostics::kind::error
+ 					    : diagnostics::kind::warning);
    if (msg)
!     emit_diagnostic (diag_kind, loc, 0,
  		     "%<pragma omp error%> encountered: %s", msg);
    else
!     emit_diagnostic (diag_kind, loc, 0,
  		     "%<pragma omp error%> encountered");
    return false;
  }
diff -Nrcpad gcc-16-20250720/gcc/cp/pt.cc gcc-16-20250727/gcc/cp/pt.cc
*** gcc-16-20250720/gcc/cp/pt.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/pt.cc	Sun Jul 27 22:32:08 2025
*************** tsubst_function_decl (tree t, tree args,
*** 14916,14921 ****
--- 14916,14924 ----
        argvec = NULL_TREE;
      }
  
+   /* Make sure tsubst_decl substitutes all the parameters.  */
+   cp_evaluated ev;
+ 
    tree closure = (lambda_fntype ? TYPE_METHOD_BASETYPE (lambda_fntype)
  		  : NULL_TREE);
    tree ctx = closure ? closure : DECL_CONTEXT (t);
*************** tsubst_lambda_expr (tree t, tree args, t
*** 20494,20504 ****
      r = error_mark_node;
    else
      {
-       /* The body of a lambda-expression is not a subexpression of the
- 	 enclosing expression.  Parms are to have DECL_CHAIN tsubsted,
- 	 which would be skipped if cp_unevaluated_operand.  */
-       cp_evaluated ev;
- 
        /* Fix the type of 'this'.
  	 For static and xobj member functions we use this to transport the
  	 lambda's closure type.  It appears that in the regular case the
--- 20497,20502 ----
*************** tsubst_lambda_expr (tree t, tree args, t
*** 20524,20529 ****
--- 20522,20531 ----
        /* Let finish_function set this.  */
        DECL_DECLARED_CONSTEXPR_P (fn) = false;
  
+       /* The body of a lambda-expression is not a subexpression of the
+ 	 enclosing expression.  */
+       cp_evaluated ev;
+ 
        bool nested = cfun;
        if (nested)
  	push_function_context ();
*************** alias_ctad_tweaks (tree tmpl, tree uguid
*** 31214,31227 ****
  	  /* Substitute the deduced arguments plus the rewritten template
  	     parameters into f to get g.  This covers the type, copyness,
  	     guideness, and explicit-specifier.  */
! 	  tree g;
! 	    {
! 	      /* Parms are to have DECL_CHAIN tsubsted, which would be skipped
! 		 if cp_unevaluated_operand.  */
! 	      cp_evaluated ev;
! 	      g = tsubst_decl (DECL_TEMPLATE_RESULT (f), targs, complain,
  			       /*use_spec_table=*/false);
- 	    }
  	  if (g == error_mark_node)
  	    continue;
  	  DECL_NAME (g) = name;
--- 31216,31223 ----
  	  /* Substitute the deduced arguments plus the rewritten template
  	     parameters into f to get g.  This covers the type, copyness,
  	     guideness, and explicit-specifier.  */
! 	  tree g = tsubst_decl (DECL_TEMPLATE_RESULT (f), targs, complain,
  			       /*use_spec_table=*/false);
  	  if (g == error_mark_node)
  	    continue;
  	  DECL_NAME (g) = name;
*************** do_class_deduction (tree ptype, tree tmp
*** 31651,31657 ****
  	  /* Be permissive with equivalent alias templates.  */
  	  tree u = get_underlying_template (tmpl);
  	  auto_diagnostic_group d;
! 	  diagnostic_t dk = (u == tmpl) ? DK_ERROR : DK_PEDWARN;
  	  bool complained
  	    = emit_diagnostic (dk, input_location, 0,
  			       "alias template deduction only available "
--- 31647,31655 ----
  	  /* Be permissive with equivalent alias templates.  */
  	  tree u = get_underlying_template (tmpl);
  	  auto_diagnostic_group d;
! 	  const enum diagnostics::kind dk = ((u == tmpl)
! 					     ? diagnostics::kind::error
! 					     : diagnostics::kind::pedwarn);
  	  bool complained
  	    = emit_diagnostic (dk, input_location, 0,
  			       "alias template deduction only available "
diff -Nrcpad gcc-16-20250720/gcc/cp/semantics.cc gcc-16-20250727/gcc/cp/semantics.cc
*** gcc-16-20250720/gcc/cp/semantics.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/semantics.cc	Sun Jul 27 22:32:08 2025
*************** finish_asm_stmt (location_t loc, int vol
*** 2338,2344 ****
  	  oconstraints[i] = constraint;
  
  	  if (parse_output_constraint (&constraint, i, ninputs, noutputs,
! 				       &allows_mem, &allows_reg, &is_inout))
  	    {
  	      /* If the operand is going to end up in memory,
  		 mark it addressable.  */
--- 2338,2345 ----
  	  oconstraints[i] = constraint;
  
  	  if (parse_output_constraint (&constraint, i, ninputs, noutputs,
! 				       &allows_mem, &allows_reg, &is_inout,
! 				       nullptr))
  	    {
  	      /* If the operand is going to end up in memory,
  		 mark it addressable.  */
*************** finish_asm_stmt (location_t loc, int vol
*** 2397,2403 ****
  	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
  	  bool constraint_parsed
  	    = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 				      oconstraints, &allows_mem, &allows_reg);
  	  /* If the operand is going to end up in memory, don't call
  	     decay_conversion.  */
  	  if (constraint_parsed && !allows_reg && allows_mem)
--- 2398,2405 ----
  	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
  	  bool constraint_parsed
  	    = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 				      oconstraints, &allows_mem, &allows_reg,
! 				      nullptr);
  	  /* If the operand is going to end up in memory, don't call
  	     decay_conversion.  */
  	  if (constraint_parsed && !allows_reg && allows_mem)
*************** check_trait_type (tree type, int kind =
*** 13689,13695 ****
  
    type = complete_type (strip_array_types (type));
    if (!COMPLETE_TYPE_P (type)
!       && cxx_incomplete_type_diagnostic (NULL_TREE, type, DK_PERMERROR)
        && !flag_permissive)
      return false;
    return true;
--- 13691,13698 ----
  
    type = complete_type (strip_array_types (type));
    if (!COMPLETE_TYPE_P (type)
!       && cxx_incomplete_type_diagnostic (NULL_TREE, type,
! 					 diagnostics::kind::permerror)
        && !flag_permissive)
      return false;
    return true;
diff -Nrcpad gcc-16-20250720/gcc/cp/tree.cc gcc-16-20250727/gcc/cp/tree.cc
*** gcc-16-20250720/gcc/cp/tree.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/tree.cc	Sun Jul 27 22:32:08 2025
*************** build_min_non_dep_op_overload (enum tree
*** 3696,3701 ****
--- 3696,3753 ----
    int nargs, expected_nargs;
    tree fn, call, obj = NULL_TREE;
  
+   releasing_vec args;
+   va_start (p, overload);
+ 
+   bool negated = false, rewritten = false, reversed = false;
+   if (cxx_dialect >= cxx20 && TREE_CODE (overload) == TREE_LIST)
+     {
+       /* Handle rebuilding a C++20 rewritten comparison operator expression,
+ 	 e.g. !(x == y), y <=> x, (x <=> y) @ 0 etc, that resolved to a call
+ 	 to a user-defined operator<=>/==.  */
+       gcc_checking_assert (TREE_CODE_CLASS (op) == tcc_comparison
+ 			   || op == SPACESHIP_EXPR);
+       int flags = TREE_INT_CST_LOW (TREE_PURPOSE (overload));
+       if (TREE_CODE (non_dep) == TRUTH_NOT_EXPR)
+ 	{
+ 	  negated = true;
+ 	  non_dep = TREE_OPERAND (non_dep, 0);
+ 	}
+       if (flags & LOOKUP_REWRITTEN)
+ 	rewritten = true;
+       if (flags & LOOKUP_REVERSED)
+ 	reversed = true;
+       if (rewritten
+ 	  && DECL_OVERLOADED_OPERATOR_IS (TREE_VALUE (overload),
+ 					  SPACESHIP_EXPR))
+ 	{
+ 	  /* Handle (x <=> y) @ 0 and 0 @ (y <=> x) by recursing to first
+ 	     rebuild the <=>.  Note that both OVERLOAD and the provided arguments
+ 	     in this case already correspond to the selected operator<=>.  */
+ 
+ 	  tree spaceship_non_dep = CALL_EXPR_ARG (non_dep, reversed ? 1 : 0);
+ 	  gcc_checking_assert (TREE_CODE (spaceship_non_dep) == CALL_EXPR);
+ 	  tree spaceship_op0 = va_arg (p, tree);
+ 	  tree spaceship_op1 = va_arg (p, tree);
+ 	  if (reversed)
+ 	    std::swap (spaceship_op0, spaceship_op1);
+ 
+ 	  /* Push the correct arguments for the operator OP expression, and
+ 	     set OVERLOAD appropriately.  */
+ 	  tree op0 = build_min_non_dep_op_overload (SPACESHIP_EXPR,
+ 						    spaceship_non_dep,
+ 						    TREE_VALUE (overload),
+ 						    spaceship_op0,
+ 						    spaceship_op1);
+ 	  tree op1 = CALL_EXPR_ARG (non_dep, reversed ? 0 : 1);
+ 	  gcc_checking_assert (integer_zerop (op1));
+ 	  vec_safe_push (args, op0);
+ 	  vec_safe_push (args, op1);
+ 	  overload = CALL_EXPR_FN (non_dep);
+ 	}
+       else
+ 	overload = TREE_VALUE (overload);
+     }
    non_dep = extract_call_expr (non_dep);
  
    nargs = call_expr_nargs (non_dep);
*************** build_min_non_dep_op_overload (enum tree
*** 3716,3747 ****
      expected_nargs += 1;
    gcc_assert (nargs == expected_nargs);
  
-   releasing_vec args;
-   va_start (p, overload);
- 
    if (!DECL_OBJECT_MEMBER_FUNCTION_P (overload))
      {
        fn = overload;
!       if (op == ARRAY_REF)
! 	obj = va_arg (p, tree);
!       for (int i = 0; i < nargs; i++)
  	{
! 	  tree arg = va_arg (p, tree);
! 	  vec_safe_push (args, arg);
  	}
      }
    else
      {
        tree object = va_arg (p, tree);
-       tree binfo = TYPE_BINFO (TREE_TYPE (object));
-       tree method = build_baselink (binfo, binfo, overload, NULL_TREE);
-       fn = build_min (COMPONENT_REF, TREE_TYPE (overload),
- 		      object, method, NULL_TREE);
        for (int i = 0; i < nargs; i++)
  	{
  	  tree arg = va_arg (p, tree);
  	  vec_safe_push (args, arg);
  	}
      }
  
    va_end (p);
--- 3768,3807 ----
      expected_nargs += 1;
    gcc_assert (nargs == expected_nargs);
  
    if (!DECL_OBJECT_MEMBER_FUNCTION_P (overload))
      {
        fn = overload;
!       if (vec_safe_length (args) != 0)
! 	/* The correct arguments were already pushed above.  */
! 	gcc_checking_assert (rewritten);
!       else
  	{
! 	  if (op == ARRAY_REF)
! 	    obj = va_arg (p, tree);
! 	  for (int i = 0; i < nargs; i++)
! 	    {
! 	      tree arg = va_arg (p, tree);
! 	      vec_safe_push (args, arg);
! 	    }
  	}
+       if (reversed)
+ 	std::swap ((*args)[0], (*args)[1]);
      }
    else
      {
+       gcc_checking_assert (vec_safe_length (args) == 0);
        tree object = va_arg (p, tree);
        for (int i = 0; i < nargs; i++)
  	{
  	  tree arg = va_arg (p, tree);
  	  vec_safe_push (args, arg);
  	}
+       if (reversed)
+ 	std::swap (object, (*args)[0]);
+       tree binfo = TYPE_BINFO (TREE_TYPE (object));
+       tree method = build_baselink (binfo, binfo, overload, NULL_TREE);
+       fn = build_min (COMPONENT_REF, TREE_TYPE (overload),
+ 		      object, method, NULL_TREE);
      }
  
    va_end (p);
*************** build_min_non_dep_op_overload (enum tree
*** 3753,3758 ****
--- 3813,3820 ----
    CALL_EXPR_ORDERED_ARGS (call_expr) = CALL_EXPR_ORDERED_ARGS (non_dep);
    CALL_EXPR_REVERSE_ARGS (call_expr) = CALL_EXPR_REVERSE_ARGS (non_dep);
  
+   if (negated)
+     call = build_min (TRUTH_NOT_EXPR, boolean_type_node, call);
    if (obj)
      return keep_unused_object_arg (call, obj, overload);
    return call;
diff -Nrcpad gcc-16-20250720/gcc/cp/typeck.cc gcc-16-20250727/gcc/cp/typeck.cc
*** gcc-16-20250720/gcc/cp/typeck.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/typeck.cc	Sun Jul 27 22:32:08 2025
*************** complete_type_or_maybe_complain (tree ty
*** 155,161 ****
    else if (!COMPLETE_TYPE_P (type))
      {
        if (complain & tf_error)
! 	cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
        note_failed_type_completion (type, complain);
        return NULL_TREE;
      }
--- 155,161 ----
    else if (!COMPLETE_TYPE_P (type))
      {
        if (complain & tf_error)
! 	cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error);
        note_failed_type_completion (type, complain);
        return NULL_TREE;
      }
*************** type_after_usual_arithmetic_conversions
*** 618,624 ****
  
  static void
  composite_pointer_error (const op_location_t &location,
! 			 diagnostic_t kind, tree t1, tree t2,
  			 composite_pointer_operation operation)
  {
    switch (operation)
--- 618,624 ----
  
  static void
  composite_pointer_error (const op_location_t &location,
! 			 enum diagnostics::kind kind, tree t1, tree t2,
  			 composite_pointer_operation operation)
  {
    switch (operation)
*************** composite_pointer_type_r (const op_locat
*** 690,696 ****
    else
      {
        if (complain & tf_error)
! 	composite_pointer_error (location, DK_PERMERROR,
  				 t1, t2, operation);
        else
  	return error_mark_node;
--- 690,696 ----
    else
      {
        if (complain & tf_error)
! 	composite_pointer_error (location, diagnostics::kind::permerror,
  				 t1, t2, operation);
        else
  	return error_mark_node;
*************** composite_pointer_type_r (const op_locat
*** 716,722 ****
  			TYPE_PTRMEM_CLASS_TYPE (t2)))
  	{
  	  if (complain & tf_error)
! 	    composite_pointer_error (location, DK_PERMERROR,
  				     t1, t2, operation);
  	  else
  	    return error_mark_node;
--- 716,722 ----
  			TYPE_PTRMEM_CLASS_TYPE (t2)))
  	{
  	  if (complain & tf_error)
! 	    composite_pointer_error (location, diagnostics::kind::permerror,
  				     t1, t2, operation);
  	  else
  	    return error_mark_node;
*************** composite_pointer_type (const op_locatio
*** 851,857 ****
        else
          {
            if (complain & tf_error)
! 	    composite_pointer_error (location, DK_ERROR, t1, t2, operation);
            return error_mark_node;
          }
      }
--- 851,858 ----
        else
          {
            if (complain & tf_error)
! 	    composite_pointer_error (location, diagnostics::kind::error,
! 				     t1, t2, operation);
            return error_mark_node;
          }
      }
*************** cp_build_function_call_vec (tree functio
*** 4530,4536 ****
      {
        if (complain & tf_error)
  	{
! 	  if (!flag_diagnostics_show_caret)
  	    error_at (input_location,
  		      "%qE cannot be used as a function", original);
  	  else if (DECL_P (original))
--- 4531,4541 ----
      {
        if (complain & tf_error)
  	{
! 	  if (is_stub_object (original))
! 	    error_at (input_location,
! 		      "%qT cannot be used as a function",
! 		      TREE_TYPE (original));
! 	  else if (!flag_diagnostics_show_caret)
  	    error_at (input_location,
  		      "%qE cannot be used as a function", original);
  	  else if (DECL_P (original))
*************** convert_arguments (tree typelist, vec<tr
*** 4672,4683 ****
        if (type == void_type_node)
  	{
            if (complain & tf_error)
!             {
! 	      error_args_num (input_location, fndecl, /*too_many_p=*/true);
!               return i;
!             }
!           else
!             return -1;
  	}
  
        /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
--- 4677,4684 ----
        if (type == void_type_node)
  	{
            if (complain & tf_error)
! 	    error_args_num (input_location, fndecl, /*too_many_p=*/true);
! 	  return -1;
  	}
  
        /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
*************** maybe_warn_about_returning_address_of_lo
*** 10805,10811 ****
      {
        if (TYPE_REF_P (valtype))
  	/* P2748 made this an error in C++26.  */
! 	emit_diagnostic (cxx_dialect >= cxx26 ? DK_PERMERROR : DK_WARNING,
  			 loc, OPT_Wreturn_local_addr,
  			 "returning reference to temporary");
        else if (TYPE_PTR_P (valtype))
--- 10806,10814 ----
      {
        if (TYPE_REF_P (valtype))
  	/* P2748 made this an error in C++26.  */
! 	emit_diagnostic ((cxx_dialect >= cxx26
! 			  ? diagnostics::kind::permerror
! 			  : diagnostics::kind::warning),
  			 loc, OPT_Wreturn_local_addr,
  			 "returning reference to temporary");
        else if (TYPE_PTR_P (valtype))
diff -Nrcpad gcc-16-20250720/gcc/cp/typeck2.cc gcc-16-20250727/gcc/cp/typeck2.cc
*** gcc-16-20250720/gcc/cp/typeck2.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/cp/typeck2.cc	Sun Jul 27 22:32:08 2025
*************** cxx_readonly_error (location_t loc, tree
*** 119,124 ****
--- 119,129 ----
  			  G_("increment of read-only reference %qD"),
  			  G_("decrement of read-only reference %qD"),
  			  TREE_OPERAND (arg, 0));
+   else if (is_stub_object (arg))
+     {
+       gcc_assert (errstring == lv_assign);
+       error_at (loc, "assignment to read-only type %qT", TREE_TYPE (arg));
+     }
    else
      readonly_error (loc, arg, errstring);
  }
*************** cxx_incomplete_type_inform (const_tree t
*** 290,300 ****
  /* Print an error message for invalid use of an incomplete type.
     VALUE is the expression that was used (or 0 if that isn't known)
     and TYPE is the type that was invalid.  DIAG_KIND indicates the
!    type of diagnostic (see diagnostic.def).  */
  
  bool
  cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
! 				const_tree type, diagnostic_t diag_kind)
  {
    bool is_decl = false, complained = false;
  
--- 295,306 ----
  /* Print an error message for invalid use of an incomplete type.
     VALUE is the expression that was used (or 0 if that isn't known)
     and TYPE is the type that was invalid.  DIAG_KIND indicates the
!    type of diagnostic (see diagnostics/kinds.def).  */
  
  bool
  cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
! 				const_tree type,
! 				enum diagnostics::kind diag_kind)
  {
    bool is_decl = false, complained = false;
  
*************** cxx_incomplete_type_diagnostic (location
*** 440,446 ****
  void
  cxx_incomplete_type_error (location_t loc, const_tree value, const_tree type)
  {
!   cxx_incomplete_type_diagnostic (loc, value, type, DK_ERROR);
  }
  
  
--- 446,452 ----
  void
  cxx_incomplete_type_error (location_t loc, const_tree value, const_tree type)
  {
!   cxx_incomplete_type_diagnostic (loc, value, type, diagnostics::kind::error);
  }
  
  
*************** add_exception_specifier (tree list, tree
*** 2627,2633 ****
    bool ok;
    tree core = spec;
    bool is_ptr;
!   diagnostic_t diag_type = DK_UNSPECIFIED; /* none */
  
    if (spec == error_mark_node)
      return list;
--- 2633,2639 ----
    bool ok;
    tree core = spec;
    bool is_ptr;
!   enum diagnostics::kind diag_type = diagnostics::kind::unspecified; /* none */
  
    if (spec == error_mark_node)
      return list;
*************** add_exception_specifier (tree list, tree
*** 2659,2665 ****
  	 and calls.  So just give a pedwarn at this point; we will give an
  	 error later if we hit one of those two cases.  */
        if (!COMPLETE_TYPE_P (complete_type (core)))
! 	diag_type = DK_PEDWARN; /* pedwarn */
      }
  
    if (ok)
--- 2665,2671 ----
  	 and calls.  So just give a pedwarn at this point; we will give an
  	 error later if we hit one of those two cases.  */
        if (!COMPLETE_TYPE_P (complete_type (core)))
! 	diag_type = diagnostics::kind::pedwarn; /* pedwarn */
      }
  
    if (ok)
*************** add_exception_specifier (tree list, tree
*** 2673,2681 ****
  	list = tree_cons (NULL_TREE, spec, list);
      }
    else
!     diag_type = DK_ERROR; /* error */
  
!   if (diag_type != DK_UNSPECIFIED
        && (complain & tf_warning_or_error))
      cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
  
--- 2679,2687 ----
  	list = tree_cons (NULL_TREE, spec, list);
      }
    else
!     diag_type = diagnostics::kind::error; /* error */
  
!   if (diag_type != diagnostics::kind::unspecified
        && (complain & tf_warning_or_error))
      cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
  
diff -Nrcpad gcc-16-20250720/gcc/d/ChangeLog gcc-16-20250727/gcc/d/ChangeLog
*** gcc-16-20250720/gcc/d/ChangeLog	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/d/ChangeLog	Sun Jul 27 22:32:08 2025
***************
*** 1,3 ****
--- 1,22 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* d-diagnostic.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* d-diagnostic.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* d-diagnostic.cc (d_diagnostic_report_diagnostic): Update to add
+ 	"m_" prefix to fields of diagnostic_info throughout.
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* toir.cc: Pass null pointer to
+ 	parse_{input,output}_constraint().
+ 
  2025-04-29  Iain Buclaw  <ibuclaw@gdcproject.org>
  
  	PR d/103044
diff -Nrcpad gcc-16-20250720/gcc/d/d-diagnostic.cc gcc-16-20250727/gcc/d/d-diagnostic.cc
*** gcc-16-20250720/gcc/d/d-diagnostic.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/d/d-diagnostic.cc	Sun Jul 27 22:32:08 2025
*************** escape_d_format (const char *format)
*** 185,191 ****
  static void ATTRIBUTE_GCC_DIAG(3,0)
  d_diagnostic_report_diagnostic (const SourceLoc &loc, int opt,
  				const char *format, va_list ap,
! 				diagnostic_t kind, bool verbatim)
  {
    va_list argp;
    va_copy (argp, ap);
--- 185,191 ----
  static void ATTRIBUTE_GCC_DIAG(3,0)
  d_diagnostic_report_diagnostic (const SourceLoc &loc, int opt,
  				const char *format, va_list ap,
! 				enum diagnostics::kind kind, bool verbatim)
  {
    va_list argp;
    va_copy (argp, ap);
*************** d_diagnostic_report_diagnostic (const So
*** 193,205 ****
    if (loc.filename.length != 0 || !verbatim)
      {
        rich_location rich_loc (line_table, make_location_t (loc));
!       diagnostic_info diagnostic;
        char *xformat = expand_d_format (format);
  
        diagnostic_set_info_translated (&diagnostic, xformat, &argp,
  				      &rich_loc, kind);
        if (opt != 0)
! 	diagnostic.option_id = opt;
  
        diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
--- 193,205 ----
    if (loc.filename.length != 0 || !verbatim)
      {
        rich_location rich_loc (line_table, make_location_t (loc));
!       diagnostics::diagnostic_info diagnostic;
        char *xformat = expand_d_format (format);
  
        diagnostic_set_info_translated (&diagnostic, xformat, &argp,
  				      &rich_loc, kind);
        if (opt != 0)
! 	diagnostic.m_option_id = opt;
  
        diagnostic_report_diagnostic (global_dc, &diagnostic);
      }
*************** void D_ATTRIBUTE_FORMAT(2,0) ATTRIBUTE_G
*** 224,230 ****
  verrorReport (const SourceLoc loc, const char *format, va_list ap,
  	      ErrorKind kind, const char *prefix1, const char *prefix2)
  {
!   diagnostic_t diag_kind = DK_UNSPECIFIED;
    int opt = 0;
    bool verbatim = false;
    char *xformat;
--- 224,230 ----
  verrorReport (const SourceLoc loc, const char *format, va_list ap,
  	      ErrorKind kind, const char *prefix1, const char *prefix2)
  {
!   enum diagnostics::kind diag_kind = diagnostics::kind::unspecified;
    int opt = 0;
    bool verbatim = false;
    char *xformat;
*************** verrorReport (const SourceLoc loc, const
*** 238,244 ****
        if (global.gag && !global.params.v.showGaggedErrors)
  	return;
  
!       diag_kind = global.gag ? DK_ANACHRONISM : DK_ERROR;
      }
    else if (kind == ErrorKind::warning)
      {
--- 238,246 ----
        if (global.gag && !global.params.v.showGaggedErrors)
  	return;
  
!       diag_kind = (global.gag
! 		   ? diagnostics::kind::anachronism
! 		   : diagnostics::kind::error);
      }
    else if (kind == ErrorKind::warning)
      {
*************** verrorReport (const SourceLoc loc, const
*** 254,260 ****
        if (global.params.useWarnings == DIAGNOSTICerror)
  	global.warnings++;
  
!       diag_kind = DK_WARNING;
      }
    else if (kind == ErrorKind::deprecation)
      {
--- 256,262 ----
        if (global.params.useWarnings == DIAGNOSTICerror)
  	global.warnings++;
  
!       diag_kind = diagnostics::kind::warning;
      }
    else if (kind == ErrorKind::deprecation)
      {
*************** verrorReport (const SourceLoc loc, const
*** 270,280 ****
  	}
  
        opt = OPT_Wdeprecated;
!       diag_kind = DK_WARNING;
      }
    else if (kind == ErrorKind::message)
      {
!       diag_kind = DK_NOTE;
        verbatim = true;
      }
    else if (kind == ErrorKind::tip)
--- 272,282 ----
  	}
  
        opt = OPT_Wdeprecated;
!       diag_kind = diagnostics::kind::warning;
      }
    else if (kind == ErrorKind::message)
      {
!       diag_kind = diagnostics::kind::note;
        verbatim = true;
      }
    else if (kind == ErrorKind::tip)
*************** verrorReport (const SourceLoc loc, const
*** 282,288 ****
        if (global.gag)
  	return;
  
!       diag_kind = DK_DEBUG;
        verbatim = true;
      }
    else
--- 284,290 ----
        if (global.gag)
  	return;
  
!       diag_kind = diagnostics::kind::debug;
        verbatim = true;
      }
    else
*************** verrorReportSupplemental (const SourceLo
*** 328,334 ****
    else
      gcc_unreachable ();
  
!   d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
  }
  
  /* Call this after printing out fatal error messages to clean up and
--- 330,337 ----
    else
      gcc_unreachable ();
  
!   d_diagnostic_report_diagnostic (loc, 0, format, ap, diagnostics::kind::note,
! 				  false);
  }
  
  /* Call this after printing out fatal error messages to clean up and
diff -Nrcpad gcc-16-20250720/gcc/d/toir.cc gcc-16-20250727/gcc/d/toir.cc
*** gcc-16-20250720/gcc/d/toir.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/d/toir.cc	Sun Jul 27 22:32:08 2025
*************** public:
*** 1450,1456 ****
  	    oconstraints[i] = constraint;
  
  	    if (parse_output_constraint (&constraint, i, ninputs, noutputs,
! 					 &allows_mem, &allows_reg, &is_inout))
  	      {
  		/* If the output argument is going to end up in memory.  */
  		if (!allows_reg)
--- 1450,1457 ----
  	    oconstraints[i] = constraint;
  
  	    if (parse_output_constraint (&constraint, i, ninputs, noutputs,
! 					 &allows_mem, &allows_reg, &is_inout,
! 					 nullptr))
  	      {
  		/* If the output argument is going to end up in memory.  */
  		if (!allows_reg)
*************** public:
*** 1469,1475 ****
  	      = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
  
  	    if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 					oconstraints, &allows_mem, &allows_reg))
  	      {
  		/* If the input argument is going to end up in memory.  */
  		if (!allows_reg && allows_mem)
--- 1470,1477 ----
  	      = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
  
  	    if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
! 					oconstraints, &allows_mem, &allows_reg,
! 					nullptr))
  	      {
  		/* If the input argument is going to end up in memory.  */
  		if (!allows_reg && allows_mem)
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-buffer.h gcc-16-20250727/gcc/diagnostic-buffer.h
*** gcc-16-20250720/gcc/diagnostic-buffer.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-buffer.h	Thu Jan  1 00:00:00 1970
***************
*** 1,109 ****
- /* Support for buffering diagnostics before flushing them to output format.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_BUFFER_H
- #define GCC_DIAGNOSTIC_BUFFER_H
- 
- #include "diagnostic.h"
- 
- class diagnostic_per_format_buffer;
- class diagnostic_output_format;
-   class diagnostic_text_output_format;
- 
- /* Class representing a buffer of zero or more diagnostics that
-    have been reported to a diagnostic_context, but which haven't
-    yet been flushed.
- 
-    A diagnostic_buffer can be:
- 
-    * flushed to the diagnostic_context, which issues
-    the diagnostics within the buffer to the output format
-    and checks for limits such as -fmax-errors=, or
- 
-    * moved to another diagnostic_buffer, which moves the diagnostics
-    within the first buffer to the other buffer, appending them after any
-    existing diagnostics within the destination buffer, emptying the
-    source buffer, or
- 
-    * cleared, which discards any diagnostics within the buffer
-    without issuing them to the output format.
- 
-    Since a buffer needs to contain output-format-specific data,
-    it's not possible to change the output format of the
-    diagnostic_context once any buffers are non-empty.
- 
-    To simplify implementing output formats, it's not possible
-    to change buffering on a diagnostic_context whilst within a
-    diagnostic group.  */
- 
- class diagnostic_buffer
- {
-  public:
-   friend class diagnostic_context;
- 
-   diagnostic_buffer (diagnostic_context &ctxt);
-   ~diagnostic_buffer ();
- 
-   void dump (FILE *out, int indent) const;
-   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
- 
-   int diagnostic_count (diagnostic_t kind) const
-   {
-     return m_diagnostic_counters.get_count (kind);
-   }
- 
-   bool empty_p () const;
- 
-   void move_to (diagnostic_buffer &dest);
- 
-  private:
-   void ensure_per_format_buffers ();
- 
-   diagnostic_context &m_ctxt;
-   auto_vec<diagnostic_per_format_buffer *> *m_per_format_buffers;
- 
-   /* The number of buffered diagnostics of each kind.  */
-   diagnostic_counters m_diagnostic_counters;
- };
- 
- /* Implementation detail of diagnostic_buffer.
- 
-    Abstract base class describing how to represent zero of more
-    buffered diagnostics for a particular diagnostic_output_format
-    (e.g. text vs SARIF).
- 
-    Each diagnostic_output_format subclass should implement its own
-    subclass for handling diagnostic_buffer.  */
- 
- class diagnostic_per_format_buffer
- {
- public:
-   virtual ~diagnostic_per_format_buffer () {}
- 
-   virtual void dump (FILE *out, int indent) const = 0;
-   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
- 
-   virtual bool empty_p () const = 0;
-   virtual void move_to (diagnostic_per_format_buffer &dest) = 0;
-   virtual void clear () = 0;
-   virtual void flush () = 0;
- };
- 
- #endif /* ! GCC_DIAGNOSTIC_BUFFER_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-client-data-hooks.h gcc-16-20250727/gcc/diagnostic-client-data-hooks.h
*** gcc-16-20250720/gcc/diagnostic-client-data-hooks.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-client-data-hooks.h	Thu Jan  1 00:00:00 1970
***************
*** 1,118 ****
- /* Additional metadata about a client for a diagnostic context.
-    Copyright (C) 2022-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_CLIENT_DATA_HOOKS_H
- #define GCC_DIAGNOSTIC_CLIENT_DATA_HOOKS_H
- 
- #include "logical-location.h"
- 
- class sarif_object;
- class client_version_info;
- 
- /* A bundle of additional metadata, owned by the diagnostic_context,
-    for querying things about the client, like version data.  */
- 
- class diagnostic_client_data_hooks
- {
-  public:
-   virtual ~diagnostic_client_data_hooks () {}
- 
-   /* Get version info for this client, or NULL.  */
-   virtual const client_version_info *get_any_version_info () const = 0;
- 
-   /* Get the current logical_location_manager for this client, or NULL.  */
-   virtual const logical_location_manager *get_logical_location_manager () const = 0;
- 
-   /* Get the current logical_location, or null.
-      If this returns a non-null logical_location, then
-      get_logical_location_manager must return non-NULL.  */
-   virtual logical_location get_current_logical_location () const = 0;
- 
-   /* Get a sourceLanguage value for FILENAME, or return NULL.
-      See SARIF v2.1.0 Appendix J for suggested values.  */
-   virtual const char *
-   maybe_get_sarif_source_language (const char *filename) const = 0;
- 
-   /* Hook to allow client to populate a SARIF "invocation" object with
-      a custom property bag (see SARIF v2.1.0 section 3.8).  */
-   virtual void
-   add_sarif_invocation_properties (sarif_object &invocation_obj) const = 0;
- };
- 
- /* Factory function for making an instance of diagnostic_client_data_hooks
-    for use in the compiler (i.e. with knowledge of "tree", access to
-    langhooks, etc).  */
- 
- extern std::unique_ptr<diagnostic_client_data_hooks> make_compiler_data_hooks ();
- 
- class diagnostic_client_plugin_info;
- 
- /* Abstract base class for a diagnostic_context to get at
-    version information about the client.  */
- 
- class client_version_info
- {
- public:
-   class plugin_visitor
-   {
-   public:
-     virtual void on_plugin (const diagnostic_client_plugin_info &) = 0;
-   };
- 
-   virtual ~client_version_info () {}
- 
-   /* Get a string suitable for use as the value of the "name" property
-      (SARIF v2.1.0 section 3.19.8).  */
-   virtual const char *get_tool_name () const = 0;
- 
-   /* Create a string suitable for use as the value of the "fullName" property
-      (SARIF v2.1.0 section 3.19.9).  */
-   virtual char *maybe_make_full_name () const = 0;
- 
-   /* Get a string suitable for use as the value of the "version" property
-      (SARIF v2.1.0 section 3.19.13).  */
-   virtual const char *get_version_string () const = 0;
- 
-   /* Create a string suitable for use as the value of the "informationUri"
-      property (SARIF v2.1.0 section 3.19.17).  */
-   virtual char *maybe_make_version_url () const = 0;
- 
-   virtual void for_each_plugin (plugin_visitor &v) const = 0;
- };
- 
- /* Abstract base class for a diagnostic_context to get at
-    information about a specific plugin within a client.  */
- 
- class diagnostic_client_plugin_info
- {
- public:
-   /* For use e.g. by SARIF "name" property (SARIF v2.1.0 section 3.19.8).  */
-   virtual const char *get_short_name () const = 0;
- 
-   /* For use e.g. by SARIF "fullName" property
-      (SARIF v2.1.0 section 3.19.9).  */
-   virtual const char *get_full_name () const = 0;
- 
-   /* For use e.g. by SARIF "version" property
-      (SARIF v2.1.0 section 3.19.13).  */
-   virtual const char *get_version () const = 0;
- };
- 
- #endif /* ! GCC_DIAGNOSTIC_CLIENT_DATA_HOOKS_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-color.cc gcc-16-20250727/gcc/diagnostic-color.cc
*** gcc-16-20250720/gcc/diagnostic-color.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-color.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,534 ****
- /* Output colorization.
-    Copyright (C) 2011-2025 Free Software Foundation, Inc.
- 
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3, or (at your option)
-    any later version.
- 
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
- 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-    02110-1301, USA.  */
- 
- #include "config.h"
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "diagnostic-color.h"
- #include "diagnostic-url.h"
- #include "label-text.h"
- 
- #ifdef __MINGW32__
- #  define WIN32_LEAN_AND_MEAN
- #  include <windows.h>
- #endif
- 
- #include "color-macros.h"
- #include "selftest.h"
- 
- /* The context and logic for choosing default --color screen attributes
-    (foreground and background colors, etc.) are the following.
-       -- There are eight basic colors available, each with its own
- 	 nominal luminosity to the human eye and foreground/background
- 	 codes (black [0 %, 30/40], blue [11 %, 34/44], red [30 %, 31/41],
- 	 magenta [41 %, 35/45], green [59 %, 32/42], cyan [70 %, 36/46],
- 	 yellow [89 %, 33/43], and white [100 %, 37/47]).
-       -- Sometimes, white as a background is actually implemented using
- 	 a shade of light gray, so that a foreground white can be visible
- 	 on top of it (but most often not).
-       -- Sometimes, black as a foreground is actually implemented using
- 	 a shade of dark gray, so that it can be visible on top of a
- 	 background black (but most often not).
-       -- Sometimes, more colors are available, as extensions.
-       -- Other attributes can be selected/deselected (bold [1/22],
- 	 underline [4/24], standout/inverse [7/27], blink [5/25], and
- 	 invisible/hidden [8/28]).  They are sometimes implemented by
- 	 using colors instead of what their names imply; e.g., bold is
- 	 often achieved by using brighter colors.  In practice, only bold
- 	 is really available to us, underline sometimes being mapped by
- 	 the terminal to some strange color choice, and standout best
- 	 being left for use by downstream programs such as less(1).
-       -- We cannot assume that any of the extensions or special features
- 	 are available for the purpose of choosing defaults for everyone.
-       -- The most prevalent default terminal backgrounds are pure black
- 	 and pure white, and are not necessarily the same shades of
- 	 those as if they were selected explicitly with SGR sequences.
- 	 Some terminals use dark or light pictures as default background,
- 	 but those are covered over by an explicit selection of background
- 	 color with an SGR sequence; their users will appreciate their
- 	 background pictures not be covered like this, if possible.
-       -- Some uses of colors attributes is to make some output items
- 	 more understated (e.g., context lines); this cannot be achieved
- 	 by changing the background color.
-       -- For these reasons, the GCC color defaults should strive not
- 	 to change the background color from its default, unless it's
- 	 for a short item that should be highlighted, not understated.
-       -- The GCC foreground color defaults (without an explicitly set
- 	 background) should provide enough contrast to be readable on any
- 	 terminal with either a black (dark) or white (light) background.
- 	 This only leaves red, magenta, green, and cyan (and their bold
- 	 counterparts) and possibly bold blue.  */
- /* Default colors. The user can overwrite them using environment
-    variable GCC_COLORS.  */
- struct color_default
- {
-   const char *m_name;
-   const char *m_val;
- };
- 
- /* For GCC_COLORS.  */
- static const color_default gcc_color_defaults[] =
- {
-   { "error", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED) },
-   { "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA) },
-   { "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN) },
-   { "range1", SGR_SEQ (COLOR_FG_GREEN) },
-   { "range2", SGR_SEQ (COLOR_FG_BLUE) },
-   { "locus", SGR_SEQ (COLOR_BOLD) },
-   { "quote", SGR_SEQ (COLOR_BOLD) },
-   { "path", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN) },
-   { "fnname", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN) },
-   { "targs", SGR_SEQ (COLOR_FG_MAGENTA) },
-   { "fixit-insert", SGR_SEQ (COLOR_FG_GREEN) },
-   { "fixit-delete", SGR_SEQ (COLOR_FG_RED) },
-   { "diff-filename", SGR_SEQ (COLOR_BOLD) },
-   { "diff-hunk", SGR_SEQ (COLOR_FG_CYAN) },
-   { "diff-delete", SGR_SEQ (COLOR_FG_RED) },
-   { "diff-insert", SGR_SEQ (COLOR_FG_GREEN) },
-   { "type-diff", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN) },
-   { "valid", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN) },
-   { "invalid", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED) },
-   { "highlight-a", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN) },
-   { "highlight-b", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_BLUE) }
- };
- 
- class diagnostic_color_dict
- {
- public:
-   diagnostic_color_dict (const color_default *default_values,
- 			 size_t num_default_values);
- 
-   bool parse_envvar_value (const char *const envvar_value);
- 
-   const char *get_start_by_name (const char *name, size_t name_len) const;
-   const char *get_start_by_name (const char *name) const
-   {
-     return get_start_by_name (name, strlen (name));
-   }
- 
- private:
-   struct entry
-   {
-     entry (const color_default &d)
-     : m_name (d.m_name),
-       m_name_len (strlen (d.m_name)),
-       m_val (label_text::borrow (d.m_val))
-     {
-     }
- 
-     const char *m_name;
-     size_t m_name_len;
-     label_text m_val;
-   };
- 
-   const entry *get_entry_by_name (const char *name, size_t name_len) const;
-   entry *get_entry_by_name (const char *name, size_t name_len);
- 
-   std::vector<entry> m_entries;
- };
- 
- static diagnostic_color_dict *g_color_dict;
- 
- const char *
- colorize_start (bool show_color, const char *name, size_t name_len)
- {
-   if (!show_color)
-     return "";
- 
-   if (!g_color_dict)
-     return "";
- 
-   return g_color_dict->get_start_by_name (name, name_len);
- }
- 
- /* Look for an entry named NAME of length NAME_LEN within this
-    diagnostic_color_dict, or nullptr if there isn't one.  */
- 
- const diagnostic_color_dict::entry *
- diagnostic_color_dict::get_entry_by_name (const char *name,
- 					  size_t name_len) const
- {
-   for (auto &iter : m_entries)
-     if (iter.m_name_len == name_len
- 	&& memcmp (iter.m_name, name, name_len) == 0)
-       return &iter;
-   return nullptr;
- }
- 
- /* Non-const version of the above.  */
- 
- diagnostic_color_dict::entry *
- diagnostic_color_dict::get_entry_by_name (const char *name,
- 					  size_t name_len)
- {
-   for (auto &iter : m_entries)
-     if (iter.m_name_len == name_len
- 	&& memcmp (iter.m_name, name, name_len) == 0)
-       return &iter;
-   return nullptr;
- }
- 
- /* Return the SGR codes to start a color entry named NAME of length
-    NAME_LEN within this diagnostic_color_dict, or the empty string if
-    there isn't one.  */
- 
- const char *
- diagnostic_color_dict::get_start_by_name (const char *name,
- 					  size_t name_len) const
- {
-   if (const entry *e = get_entry_by_name (name, name_len))
-     return e->m_val.get ();
- 
-   return "";
- }
- 
- const char *
- colorize_stop (bool show_color)
- {
-   return show_color ? SGR_RESET : "";
- }
- 
- /* diagnostic_color_dict's ctor.  Initialize it from the given array
-    of color_default values.  */
- 
- diagnostic_color_dict::
- diagnostic_color_dict (const color_default *default_values,
- 		       size_t num_default_values)
- {
-   m_entries.reserve (num_default_values);
-   for (size_t idx = 0; idx < num_default_values; idx++)
-     m_entries.push_back (entry (default_values[idx]));
- }
- 
- /* Parse a list of color definitions from an environment variable
-    value (such as that of GCC_COLORS).
-    No character escaping is needed or supported.  */
- 
- bool
- diagnostic_color_dict::parse_envvar_value (const char *const envvar_value)
- {
-   /* envvar not set: use the default colors.  */
-   if (envvar_value == nullptr)
-     return true;
- 
-   /* envvar set to empty string: disable colorization.  */
-   if (*envvar_value == '\0')
-     return false;
- 
-   const char *q, *name, *val;
-   size_t name_len = 0, val_len = 0;
- 
-   name = q = envvar_value;
-   val = nullptr;
-   /* From now on, be well-formed or you're gone.  */
-   for (;;)
-     if (*q == ':' || *q == '\0')
-       {
- 	if (val)
- 	  val_len = q - val;
- 	else
- 	  name_len = q - name;
- 	/* Empty name without val (empty cap)
- 	   won't match and will be ignored.  */
- 	entry *e = get_entry_by_name (name, name_len);
- 	/* If name unknown, go on for forward compatibility.  */
- 	if (e && val)
- 	  {
- 	    char *b = XNEWVEC (char, val_len + sizeof (SGR_SEQ ("")));
- 	    memcpy (b, SGR_START, strlen (SGR_START));
- 	    memcpy (b + strlen (SGR_START), val, val_len);
- 	    memcpy (b + strlen (SGR_START) + val_len, SGR_END,
- 		    sizeof (SGR_END));
- 	    e->m_val = label_text::take (b);
- 	  }
- 	if (*q == '\0')
- 	  return true;
- 	name = ++q;
- 	val = nullptr;
-       }
-     else if (*q == '=')
-       {
- 	if (q == name || val)
- 	  return true;
- 
- 	name_len = q - name;
- 	val = ++q; /* Can be the empty string.  */
-       }
-     else if (val == nullptr)
-       q++; /* Accumulate name.  */
-     else if (*q == ';' || (*q >= '0' && *q <= '9'))
-       q++; /* Accumulate val.  Protect the terminal from being sent
- 	      garbage.  */
-     else
-       return true;
- }
- 
- /* Parse GCC_COLORS.  The default would look like:
-    GCC_COLORS='error=01;31:warning=01;35:note=01;36:\
-    range1=32:range2=34:locus=01:quote=01:path=01;36:\
-    fixit-insert=32:fixit-delete=31:'\
-    diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\
-    type-diff=01;32'.  */
- static bool
- parse_gcc_colors ()
- {
-   if (!g_color_dict)
-     return false;
-   return g_color_dict->parse_envvar_value (getenv ("GCC_COLORS")); /* Plural! */
- }
- 
- /* Return true if we should use color when in auto mode, false otherwise. */
- static bool
- should_colorize (void)
- {
- #ifdef __MINGW32__
-   /* For consistency reasons, one should check the handle returned by
-      _get_osfhandle(_fileno(stderr)) because the function
-      pp_write_text_to_stream() in pretty-print.cc calls fputs() on
-      that stream.  However, the code below for non-Windows doesn't seem
-      to care about it either...  */
-   HANDLE handle;
-   DWORD mode;
-   BOOL isconsole = false;
- 
-   handle = GetStdHandle (STD_ERROR_HANDLE);
- 
-   if ((handle != INVALID_HANDLE_VALUE) && (handle != nullptr))
-     isconsole = GetConsoleMode (handle, &mode);
- 
- #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
-   if (isconsole)
-     {
-       /* Try to enable processing of VT100 escape sequences */
-       mode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
-       SetConsoleMode (handle, mode);
-     }
- #endif
- 
-   return isconsole;
- #else
-   char const *t = getenv ("TERM");
-   /* emacs M-x shell sets TERM="dumb".  */
-   return t && strcmp (t, "dumb") != 0 && isatty (STDERR_FILENO);
- #endif
- }
- 
- bool
- colorize_init (diagnostic_color_rule_t rule)
- {
-   if (!g_color_dict)
-     g_color_dict = new diagnostic_color_dict (gcc_color_defaults,
- 					      ARRAY_SIZE (gcc_color_defaults));
- 
-   switch (rule)
-     {
-     case DIAGNOSTICS_COLOR_NO:
-       return false;
-     case DIAGNOSTICS_COLOR_YES:
-       return parse_gcc_colors ();
-     case DIAGNOSTICS_COLOR_AUTO:
-       if (should_colorize ())
- 	return parse_gcc_colors ();
-       else
- 	return false;
-     default:
-       gcc_unreachable ();
-     }
- }
- 
- /* Return URL_FORMAT_XXX which tells how we should emit urls
-    when in always mode.
-    We use GCC_URLS and if that is not defined TERM_URLS.
-    If neither is defined the feature is enabled by default.  */
- 
- static diagnostic_url_format
- parse_env_vars_for_urls ()
- {
-   const char *p;
- 
-   p = getenv ("GCC_URLS"); /* Plural! */
-   if (p == nullptr)
-     p = getenv ("TERM_URLS");
- 
-   if (p == nullptr)
-     return URL_FORMAT_DEFAULT;
- 
-   if (*p == '\0')
-     return URL_FORMAT_NONE;
- 
-   if (!strcmp (p, "no"))
-     return URL_FORMAT_NONE;
- 
-   if (!strcmp (p, "st"))
-     return URL_FORMAT_ST;
- 
-   if (!strcmp (p, "bel"))
-     return URL_FORMAT_BEL;
- 
-   return URL_FORMAT_DEFAULT;
- }
- 
- /* Return true if we should use urls when in auto mode, false otherwise.  */
- 
- static bool
- auto_enable_urls ()
- {
-   const char *term, *colorterm;
- 
-   /* First check the terminal is capable of printing color escapes,
-      if not URLs won't work either.  */
-   if (!should_colorize ())
-     return false;
- 
- #ifdef __MINGW32__
-   HANDLE handle;
-   DWORD mode;
- 
-   handle = GetStdHandle (STD_ERROR_HANDLE);
-   if ((handle == INVALID_HANDLE_VALUE) || (handle == nullptr))
-     return false;
- 
-   /* If ansi escape sequences aren't supported by the console, then URLs will
-      print mangled from mingw_ansi_fputs's console API translation. It wouldn't
-      be useful even if this weren't the case.  */
-   if (GetConsoleMode (handle, &mode)
- #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
-       && !(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)
- #endif
-       )
-     return false;
- #endif
- 
-   /* xfce4-terminal is known to not implement URLs at this time.
-      Recently new installations (0.8) will safely ignore the URL escape
-      sequences, but a large number of legacy installations (0.6.3) print
-      garbage when URLs are printed.  Therefore we lose nothing by
-      disabling this feature for that specific terminal type.  */
-   colorterm = getenv ("COLORTERM");
-   if (colorterm && !strcmp (colorterm, "xfce4-terminal"))
-     return false;
- 
-   /* Old versions of gnome-terminal where URL escapes cause screen
-      corruptions set COLORTERM="gnome-terminal", recent versions
-      with working URL support set this to "truecolor".  */
-   if (colorterm && !strcmp (colorterm, "gnome-terminal"))
-     return false;
- 
-   /* Since the following checks are less specific than the ones
-      above, let GCC_URLS and TERM_URLS override the decision.  */
-   if (getenv ("GCC_URLS") || getenv ("TERM_URLS"))
-     return true;
- 
-   /* In an ssh session the COLORTERM is not there, but TERM=xterm
-      can be used as an indication of a incompatible terminal while
-      TERM=xterm-256color appears to be a working terminal.  */
-   term = getenv ("TERM");
-   if (!colorterm && term && !strcmp (term, "xterm"))
-     return false;
- 
-   /* When logging in a linux over serial line, we see TERM=linux
-      and no COLORTERM, it is unlikely that the URL escapes will
-      work in that environmen either.  */
-   if (!colorterm && term && !strcmp (term, "linux"))
-     return false;
- 
-   return true;
- }
- 
- /* Determine if URLs should be enabled, based on RULE,
-    and, if so, which format to use.
-    This reuses the logic for colorization.  */
- 
- diagnostic_url_format
- determine_url_format (diagnostic_url_rule_t rule)
- {
-   switch (rule)
-     {
-     case DIAGNOSTICS_URL_NO:
-       return URL_FORMAT_NONE;
-     case DIAGNOSTICS_URL_YES:
-       return parse_env_vars_for_urls ();
-     case DIAGNOSTICS_URL_AUTO:
-       if (auto_enable_urls ())
- 	return parse_env_vars_for_urls ();
-       else
- 	return URL_FORMAT_NONE;
-     default:
-       gcc_unreachable ();
-     }
- }
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* Test of an empty diagnostic_color_dict.  */
- 
- static void
- test_empty_color_dict ()
- {
-   diagnostic_color_dict d (nullptr, 0);
-   ASSERT_STREQ (d.get_start_by_name ("warning"), "");
-   ASSERT_STREQ (d.get_start_by_name ("should-not-be-found"), "");
- }
- 
- /* Test of a diagnostic_color_dict with GCC's defaults.  */
- 
- static void
- test_default_color_dict ()
- {
-   diagnostic_color_dict d (gcc_color_defaults,
- 			   ARRAY_SIZE (gcc_color_defaults));
-   ASSERT_STREQ (d.get_start_by_name ("warning"),
- 		SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA));
-   ASSERT_STREQ (d.get_start_by_name ("should-not-be-found"), "");
- }
- 
- /* Test of a diagnostic_color_dict with GCC's defaults plus overrides from
-    an environment variable.  */
- 
- static void
- test_color_dict_envvar_parsing ()
- {
-   diagnostic_color_dict d (gcc_color_defaults,
- 			   ARRAY_SIZE (gcc_color_defaults));
- 
-   d.parse_envvar_value ("error=01;37:warning=01;42:unknown-value=01;36");
- 
-   ASSERT_STREQ (d.get_start_by_name ("error"),
- 		SGR_SEQ ("01;37"));
-   ASSERT_STREQ (d.get_start_by_name ("warning"),
- 		SGR_SEQ ("01;42"));
-   ASSERT_STREQ (d.get_start_by_name ("unknown-value"), "");
-   ASSERT_STREQ (d.get_start_by_name ("should-not-be-found"), "");
- }
- 
- 
- /* Run all of the selftests within this file.  */
- 
- void
- diagnostic_color_cc_tests ()
- {
-   test_empty_color_dict ();
-   test_default_color_dict ();
-   test_color_dict_envvar_parsing ();
- }
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-color.h gcc-16-20250727/gcc/diagnostic-color.h
*** gcc-16-20250720/gcc/diagnostic-color.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-color.h	Thu Jan  1 00:00:00 1970
***************
*** 1,65 ****
- /* Copyright (C) 2013-2025 Free Software Foundation, Inc.
-    Contributed by Manuel Lopez-Ibanez <manu@gcc.gnu.org>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- /* Based on code from: */
- /* grep.c - main driver file for grep.
-    Copyright (C) 1992-2025 Free Software Foundation, Inc.
- 
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3, or (at your option)
-    any later version.
- 
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
- 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-    02110-1301, USA.
- 
-    Written July 1992 by Mike Haertel.  */
- 
- #ifndef GCC_DIAGNOSTIC_COLOR_H
- #define GCC_DIAGNOSTIC_COLOR_H
- 
- /* Whether to add color to diagnostics:
-    o DIAGNOSTICS_COLOR_NO: never
-    o DIAGNOSTICS_COLOR_YES: always
-    o DIAGNOSTICS_COLOR_AUTO: depending on the output stream.  */
- typedef enum
- {
-   DIAGNOSTICS_COLOR_NO       = 0,
-   DIAGNOSTICS_COLOR_YES      = 1,
-   DIAGNOSTICS_COLOR_AUTO     = 2
- } diagnostic_color_rule_t;
- 
- const char *colorize_start (bool, const char *, size_t);
- const char *colorize_stop (bool);
- bool colorize_init (diagnostic_color_rule_t);
- 
- inline const char *
- colorize_start (bool show_color, const char *name)
- {
-   return colorize_start (show_color, name, strlen (name));
- }
- 
- #endif /* ! GCC_DIAGNOSTIC_COLOR_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-core.h gcc-16-20250727/gcc/diagnostic-core.h
*** gcc-16-20250720/gcc/diagnostic-core.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-core.h	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 23,43 ****
  #define GCC_DIAGNOSTIC_CORE_H
  
  #include "bversion.h"
! 
! /* Constants used to discriminate diagnostics.  */
! typedef enum
! {
! #define DEFINE_DIAGNOSTIC_KIND(K, msgid, C) K,
! #include "diagnostic.def"
! #undef DEFINE_DIAGNOSTIC_KIND
!   DK_LAST_DIAGNOSTIC_KIND,
!   /* This is used for tagging pragma pops in the diagnostic
!      classification history chain.  */
!   DK_POP,
!   /* This is used internally to note that a diagnostic is enabled
!      without mandating any specific type.  */
!   DK_ANY,
! } diagnostic_t;
  
  /* RAII-style class for grouping related diagnostics within global_dc.  */
  
--- 23,30 ----
  #define GCC_DIAGNOSTIC_CORE_H
  
  #include "bversion.h"
! #include "diagnostics/kinds.h"
! #include "diagnostics/option-id.h"
  
  /* RAII-style class for grouping related diagnostics within global_dc.  */
  
*************** class auto_diagnostic_nesting_level
*** 61,88 ****
  };
  
  /* Forward decl.  */
! class diagnostic_metadata; /* See diagnostic-metadata.h.  */
! 
! /* A class to use for the ID of an option that controls
!    a particular diagnostic.
!    This is just a wrapper around "int", but better documents
!    the intent of the code.  */
! 
! struct diagnostic_option_id
! {
!   diagnostic_option_id () : m_idx (0) {}
! 
!   diagnostic_option_id (int idx) : m_idx (idx) {}
!   /* Ideally we'd take an enum opt_code here, but we don't
!      want to depend on its decl.  */
! 
!   bool operator== (diagnostic_option_id other) const
!   {
!     return m_idx == other.m_idx;
!   }
! 
!   int m_idx;
! };
  
  extern const char *progname;
  
--- 48,56 ----
  };
  
  /* Forward decl.  */
! namespace diagnostics {
!    class metadata; /* See diagnostics/metadata.h.  */
! } // namespace diagnostics
  
  extern const char *progname;
  
*************** extern void internal_error (const char *
*** 109,137 ****
  extern void internal_error_no_backtrace (const char *, ...)
       ATTRIBUTE_GCC_DIAG(1,2) ATTRIBUTE_NORETURN;
  /* Pass one of the OPT_W* from options.h as the first parameter.  */
! extern bool warning (diagnostic_option_id,
  		     const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
  extern bool warning_n (location_t,
! 		       diagnostic_option_id,
  		       unsigned HOST_WIDE_INT,
  		       const char *, const char *, ...)
      ATTRIBUTE_GCC_DIAG(4,6) ATTRIBUTE_GCC_DIAG(5,6);
  extern bool warning_n (rich_location *,
! 		       diagnostic_option_id,
  		       unsigned HOST_WIDE_INT,
  		       const char *, const char *, ...)
      ATTRIBUTE_GCC_DIAG(4, 6) ATTRIBUTE_GCC_DIAG(5, 6);
  extern bool warning_at (location_t,
! 			diagnostic_option_id,
  			const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
  extern bool warning_at (rich_location *,
! 			diagnostic_option_id,
  			const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
  extern bool warning_meta (rich_location *,
! 			  const diagnostic_metadata &,
! 			  diagnostic_option_id,
  			  const char *, ...)
      ATTRIBUTE_GCC_DIAG(4,5);
  extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
--- 77,105 ----
  extern void internal_error_no_backtrace (const char *, ...)
       ATTRIBUTE_GCC_DIAG(1,2) ATTRIBUTE_NORETURN;
  /* Pass one of the OPT_W* from options.h as the first parameter.  */
! extern bool warning (diagnostics::option_id,
  		     const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
  extern bool warning_n (location_t,
! 		       diagnostics::option_id,
  		       unsigned HOST_WIDE_INT,
  		       const char *, const char *, ...)
      ATTRIBUTE_GCC_DIAG(4,6) ATTRIBUTE_GCC_DIAG(5,6);
  extern bool warning_n (rich_location *,
! 		       diagnostics::option_id,
  		       unsigned HOST_WIDE_INT,
  		       const char *, const char *, ...)
      ATTRIBUTE_GCC_DIAG(4, 6) ATTRIBUTE_GCC_DIAG(5, 6);
  extern bool warning_at (location_t,
! 			diagnostics::option_id,
  			const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
  extern bool warning_at (rich_location *,
! 			diagnostics::option_id,
  			const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,4);
  extern bool warning_meta (rich_location *,
! 			  const diagnostics::metadata &,
! 			  diagnostics::option_id,
  			  const char *, ...)
      ATTRIBUTE_GCC_DIAG(4,5);
  extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
*************** extern void error_n (location_t, unsigne
*** 141,169 ****
  extern void error_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
  extern void error_at (rich_location *, const char *, ...)
    ATTRIBUTE_GCC_DIAG(2,3);
! extern void error_meta (rich_location *, const diagnostic_metadata &,
  			const char *, ...)
    ATTRIBUTE_GCC_DIAG(3,4);
  extern void fatal_error (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3)
       ATTRIBUTE_NORETURN;
  /* Pass one of the OPT_W* from options.h as the second parameter.  */
  extern bool pedwarn (location_t,
! 		     diagnostic_option_id,
  		     const char *, ...)
       ATTRIBUTE_GCC_DIAG(3,4);
  extern bool pedwarn (rich_location *,
! 		     diagnostic_option_id,
  		     const char *, ...)
       ATTRIBUTE_GCC_DIAG(3,4);
  extern bool permerror (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
  extern bool permerror (rich_location *, const char *,
  				   ...) ATTRIBUTE_GCC_DIAG(2,3);
  extern bool permerror_opt (location_t,
! 			   diagnostic_option_id,
  			   const char *, ...)
    ATTRIBUTE_GCC_DIAG(3,4);
  extern bool permerror_opt (rich_location *,
! 			   diagnostic_option_id,
  			   const char *, ...)
    ATTRIBUTE_GCC_DIAG(3,4);
  extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
--- 109,137 ----
  extern void error_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
  extern void error_at (rich_location *, const char *, ...)
    ATTRIBUTE_GCC_DIAG(2,3);
! extern void error_meta (rich_location *, const diagnostics::metadata &,
  			const char *, ...)
    ATTRIBUTE_GCC_DIAG(3,4);
  extern void fatal_error (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3)
       ATTRIBUTE_NORETURN;
  /* Pass one of the OPT_W* from options.h as the second parameter.  */
  extern bool pedwarn (location_t,
! 		     diagnostics::option_id,
  		     const char *, ...)
       ATTRIBUTE_GCC_DIAG(3,4);
  extern bool pedwarn (rich_location *,
! 		     diagnostics::option_id,
  		     const char *, ...)
       ATTRIBUTE_GCC_DIAG(3,4);
  extern bool permerror (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
  extern bool permerror (rich_location *, const char *,
  				   ...) ATTRIBUTE_GCC_DIAG(2,3);
  extern bool permerror_opt (location_t,
! 			   diagnostics::option_id,
  			   const char *, ...)
    ATTRIBUTE_GCC_DIAG(3,4);
  extern bool permerror_opt (rich_location *,
! 			   diagnostics::option_id,
  			   const char *, ...)
    ATTRIBUTE_GCC_DIAG(3,4);
  extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
*************** extern void inform_n (location_t, unsign
*** 174,196 ****
  		      const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5);
  extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
! extern bool emit_diagnostic (diagnostic_t,
  			     location_t,
! 			     diagnostic_option_id,
  			     const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
! extern bool emit_diagnostic (diagnostic_t,
  			     rich_location *,
! 			     diagnostic_option_id,
  			     const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
! extern bool emit_diagnostic_valist (diagnostic_t,
  				    location_t,
! 				    diagnostic_option_id,
  				    const char *, va_list *)
    ATTRIBUTE_GCC_DIAG (4,0);
! extern bool emit_diagnostic_valist_meta (diagnostic_t,
  					 rich_location *,
! 					 const diagnostic_metadata *,
! 					 diagnostic_option_id,
  					 const char *,
  					 va_list *) ATTRIBUTE_GCC_DIAG (5,0);
  extern bool seen_error (void);
--- 142,164 ----
  		      const char *, ...)
      ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5);
  extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
! extern bool emit_diagnostic (enum diagnostics::kind,
  			     location_t,
! 			     diagnostics::option_id,
  			     const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
! extern bool emit_diagnostic (enum diagnostics::kind,
  			     rich_location *,
! 			     diagnostics::option_id,
  			     const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
! extern bool emit_diagnostic_valist (enum diagnostics::kind,
  				    location_t,
! 				    diagnostics::option_id,
  				    const char *, va_list *)
    ATTRIBUTE_GCC_DIAG (4,0);
! extern bool emit_diagnostic_valist_meta (enum diagnostics::kind,
  					 rich_location *,
! 					 const diagnostics::metadata *,
! 					 diagnostics::option_id,
  					 const char *,
  					 va_list *) ATTRIBUTE_GCC_DIAG (5,0);
  extern bool seen_error (void);
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-diagram.h gcc-16-20250727/gcc/diagnostic-diagram.h
*** gcc-16-20250720/gcc/diagnostic-diagram.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-diagram.h	Thu Jan  1 00:00:00 1970
***************
*** 1,51 ****
- /* Support for diagrams within diagnostics.
-    Copyright (C) 2023-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_DIAGRAM_H
- #define GCC_DIAGNOSTIC_DIAGRAM_H
- 
- namespace text_art
- {
-   class canvas;
- } // namespace text_art
- 
- /* A text art diagram, along with an "alternative text" string
-    describing it.  */
- 
- class diagnostic_diagram
- {
-  public:
-   diagnostic_diagram (const text_art::canvas &canvas,
- 		      const char *alt_text)
-   : m_canvas (canvas),
-     m_alt_text (alt_text)
-   {
-     gcc_assert (alt_text);
-   }
- 
-   const text_art::canvas &get_canvas () const { return m_canvas; }
-   const char *get_alt_text () const { return m_alt_text; }
- 
-  private:
-   const text_art::canvas &m_canvas;
-   const char *const m_alt_text;
- };
- 
- #endif /* ! GCC_DIAGNOSTIC_DIAGRAM_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-digraphs.cc gcc-16-20250727/gcc/diagnostic-digraphs.cc
*** gcc-16-20250720/gcc/diagnostic-digraphs.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-digraphs.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,484 ****
- /* Directed graphs associated with a diagnostic.
-    Copyright (C) 2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- 
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #define INCLUDE_ALGORITHM
- #define INCLUDE_MAP
- #define INCLUDE_SET
- #define INCLUDE_STRING
- #define INCLUDE_VECTOR
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- 
- #include "graphviz.h"
- #include "diagnostic-digraphs.h"
- #include "diagnostic-format-sarif.h"
- 
- #include "selftest.h"
- 
- using digraph = diagnostics::digraphs::digraph;
- using digraph_node = diagnostics::digraphs::node;
- using digraph_edge = diagnostics::digraphs::edge;
- 
- namespace {
- 
- class conversion_to_dot
- {
- public:
-   std::unique_ptr<dot::graph>
-   make_dot_graph_from_diagnostic_graph (const digraph &);
- 
-   std::unique_ptr<dot::stmt>
-   make_dot_node_from_digraph_node (const digraph_node &);
- 
-   std::unique_ptr<dot::edge_stmt>
-   make_dot_edge_from_digraph_edge (const digraph_edge &);
- 
-   dot::id
-   get_dot_id_for_node (const digraph_node &);
- 
-   bool
-   has_edges_p (const digraph_node &);
- 
- private:
-   std::set<const digraph_node *> m_nodes_with_edges;
-   std::map<const digraph_node *, dot::stmt *> m_node_map;
- };
- 
- } // anonymous namespace
- 
- // class conversion_to_dot
- 
- std::unique_ptr<dot::graph>
- conversion_to_dot::
- make_dot_graph_from_diagnostic_graph (const diagnostics::digraphs::digraph &input_graph)
- {
-   auto output_graph = std::make_unique<dot::graph> ();
- 
-   if (const char *description = input_graph.get_description ())
-     output_graph->m_stmt_list.add_attr (dot::id ("label"),
- 					dot::id (description));
- 
-   const int num_nodes = input_graph.get_num_nodes ();
-   const int num_edges = input_graph.get_num_edges ();
- 
-   /* Determine which nodes have in-edges and out-edges.  */
-   for (int i = 0; i < num_edges; ++i)
-     {
-       const digraph_edge &input_edge = input_graph.get_edge (i);
-       m_nodes_with_edges.insert (&input_edge.get_src_node ());
-       m_nodes_with_edges.insert (&input_edge.get_dst_node ());
-     }
- 
-   for (int i = 0; i < num_nodes; ++i)
-     {
-       const digraph_node &input_node = input_graph.get_node (i);
-       auto dot_node_stmt = make_dot_node_from_digraph_node (input_node);
-       output_graph->m_stmt_list.add_stmt (std::move (dot_node_stmt));
-     }
- 
-   for (int i = 0; i < num_edges; ++i)
-     {
-       const digraph_edge &input_edge = input_graph.get_edge (i);
-       auto dot_edge_stmt = make_dot_edge_from_digraph_edge (input_edge);
-       output_graph->m_stmt_list.add_stmt (std::move (dot_edge_stmt));
-     }
- 
-   return output_graph;
- }
- 
- std::unique_ptr<dot::stmt>
- conversion_to_dot::
- make_dot_node_from_digraph_node (const diagnostics::digraphs::node &input_node)
- {
-   dot::id dot_id (get_dot_id_for_node (input_node));
- 
-   /* For now, we can only do either edges or children, not both
-      ...but see https://graphviz.org/docs/attrs/compound/  */
- 
-   if (has_edges_p (input_node))
-     {
-       auto output_node
- 	= std::make_unique<dot::node_stmt> (std::move (dot_id));
-       m_node_map[&input_node] = output_node.get ();
-       if (const char *label = input_node.get_label ())
- 	output_node->set_label (dot::id (label));
-       return output_node;
-     }
-   else
-     {
-       auto output_node = std::make_unique<dot::subgraph> (std::move (dot_id));
-       m_node_map[&input_node] = output_node.get ();
-       if (const char *label = input_node.get_label ())
- 	output_node->add_attr (dot::id ("label"), dot::id (label));
-       const int num_children = input_node.get_num_children ();
-       for (int i = 0; i < num_children; ++i)
- 	{
- 	  const digraph_node &input_child = input_node.get_child (i);
- 	  auto dot_child_stmt = make_dot_node_from_digraph_node (input_child);
- 	  output_node->m_stmt_list.add_stmt (std::move (dot_child_stmt));
- 	}
-       return output_node;
-     }
- }
- 
- std::unique_ptr<dot::edge_stmt>
- conversion_to_dot::
- make_dot_edge_from_digraph_edge (const digraph_edge &input_edge)
- {
-   const digraph_node &src_dnode = input_edge.get_src_node ();
-   const digraph_node &dst_dnode = input_edge.get_dst_node ();
-   auto output_edge
-     = std::make_unique<dot::edge_stmt>
-     (get_dot_id_for_node (src_dnode),
-      get_dot_id_for_node (dst_dnode));
-   if (const char *label = input_edge.get_label ())
-     output_edge->set_label (dot::id (label));
-   return output_edge;
- }
- 
- dot::id
- conversion_to_dot::get_dot_id_for_node (const digraph_node &input_node)
- {
-   if (has_edges_p (input_node))
-     return input_node.get_id ();
-   else
-     return std::string ("cluster_") + input_node.get_id ();
- }
- 
- bool
- conversion_to_dot::has_edges_p (const digraph_node &input_node)
- {
-   return m_nodes_with_edges.find (&input_node) != m_nodes_with_edges.end ();
- }
- 
- // class object
- 
- const char *
- diagnostics::digraphs::object::
- get_attr (const char *key_prefix, const char *key) const
- {
-   if (!m_property_bag)
-     return nullptr;
-   std::string prefixed_key = std::string (key_prefix) + key;
-   if (json::value *jv = m_property_bag->get (prefixed_key.c_str ()))
-     if (json::string *jstr = jv->dyn_cast_string ())
-       return jstr->get_string ();
-   return nullptr;
- }
- 
- void
- diagnostics::digraphs::object::
- set_attr (const char *key_prefix, const char *key, const char *value)
- {
-   set_json_attr (key_prefix, key, std::make_unique<json::string> (value));
- }
- 
- void
- diagnostics::digraphs::object::
- set_json_attr (const char *key_prefix, const char *key, std::unique_ptr<json::value> value)
- {
-   std::string prefixed_key = std::string (key_prefix) + key;
-   if (!m_property_bag)
-     m_property_bag = std::make_unique<json::object> ();
-   m_property_bag->set (prefixed_key.c_str (), std::move (value));
- }
- 
- // class digraph
- 
- DEBUG_FUNCTION void
- diagnostics::digraphs::digraph::dump () const
- {
-   make_json_sarif_graph ()->dump ();
- }
- 
- std::unique_ptr<json::object>
- diagnostics::digraphs::digraph::make_json_sarif_graph () const
- {
-   return make_sarif_graph (*this, nullptr, nullptr);
- }
- 
- std::unique_ptr<dot::graph>
- diagnostics::digraphs::digraph::make_dot_graph () const
- {
-   conversion_to_dot to_dot;
-   return to_dot.make_dot_graph_from_diagnostic_graph (*this);
- }
- 
- std::unique_ptr<diagnostics::digraphs::digraph>
- diagnostics::digraphs::digraph::clone () const
- {
-   auto result = std::make_unique<diagnostics::digraphs::digraph> ();
- 
-   if (get_property_bag ())
-     result->set_property_bag (get_property_bag ()->clone_as_object ());
- 
-   std::map<diagnostics::digraphs::node *, diagnostics::digraphs::node *> node_mapping;
- 
-   for (auto &iter : m_nodes)
-     result->add_node (iter->clone (*result, node_mapping));
-   for (auto &iter : m_edges)
-     result->add_edge (iter->clone (*result, node_mapping));
- 
-   return result;
- }
- 
- void
- diagnostics::digraphs::digraph::add_edge (const char *id,
- 					  node &src_node,
- 					  node &dst_node,
- 					  const char *label)
- {
-   auto e = std::make_unique<digraph_edge> (*this,
- 					   id,
- 					   src_node,
- 					   dst_node);
-   if (label)
-     e->set_label (label);
-   add_edge (std::move (e));
- }
- 
- /* Utility function for edge ids: either use EDGE_ID, or
-    generate a unique one for when we don't care about the name.
- 
-    Edges in SARIF "SHALL" have an id that's unique within the graph
-    (SARIF 2.1.0 §3.41.2).  This is so that graph traversals can refer
-    to edges by id (SARIF 2.1.0's §3.43.2 edgeId property).  */
- 
- std::string
- diagnostics::digraphs::digraph::make_edge_id (const char *edge_id)
- {
-   /* If we have an id, use it.  */
-   if (edge_id)
-     return edge_id;
- 
-   /* Otherwise, generate a unique one of the form "edgeN".  */
-   while (true)
-     {
-       auto candidate (std::string ("edge")
- 		      + std::to_string (m_next_edge_id_index++));
-       auto iter = m_id_to_edge_map.find (candidate);
-       if (iter != m_id_to_edge_map.end ())
- 	{
- 	  // Try again with the next index...
- 	  continue;
- 	}
-       return candidate;
-     }
- }
- 
- // class node
- 
- DEBUG_FUNCTION void
- diagnostics::digraphs::node::dump () const
- {
-   to_json_sarif_node ()->dump ();
- }
- 
- std::unique_ptr<json::object>
- diagnostics::digraphs::node::to_json_sarif_node () const
- {
-   return make_sarif_node (*this, nullptr, nullptr);
- }
- 
- std::unique_ptr<diagnostics::digraphs::node>
- diagnostics::digraphs::node::clone (digraph &new_graph,
- 				    std::map<node *, node *> &node_mapping) const
- {
-   auto result
-     = std::make_unique<diagnostics::digraphs::node> (new_graph,
- 						     get_id ());
-   node_mapping.insert ({const_cast <node *> (this), result.get ()});
- 
-   result->set_logical_loc (m_logical_loc);
- 
-   if (get_property_bag ())
-     result->set_property_bag (get_property_bag ()->clone_as_object ());
- 
-   for (auto &iter : m_children)
-     result->add_child (iter->clone (new_graph, node_mapping));
- 
-   return result;
- }
- 
- // class edge
- 
- std::unique_ptr<digraph_edge>
- digraph_edge::clone (digraph &new_graph,
- 		     const std::map<node *, node *> &node_mapping) const
- {
-   auto iter_new_src = node_mapping.find (&m_src_node);
-   gcc_assert (iter_new_src != node_mapping.end ());
-   auto iter_new_dst = node_mapping.find (&m_dst_node);
-   gcc_assert (iter_new_dst != node_mapping.end ());
-   auto result
-     = std::make_unique<digraph_edge> (new_graph,
- 				      m_id.c_str (),
- 				      *iter_new_src->second,
- 				      *iter_new_dst->second);
-   if (get_property_bag ())
-     result->set_property_bag (get_property_bag ()->clone_as_object ());
- 
-   return result;
- }
- 
- DEBUG_FUNCTION void
- diagnostics::digraphs::edge::dump () const
- {
-   to_json_sarif_edge ()->dump ();
- }
- 
- std::unique_ptr<json::object>
- diagnostics::digraphs::edge::to_json_sarif_edge () const
- {
-   return make_sarif_edge (*this, nullptr);
- }
- 
- // class lazy_digraph
- 
- const diagnostics::digraphs::digraph &
- diagnostics::digraphs::lazy_digraph::get_or_create_digraph () const
- {
-   if (!m_digraph)
-     m_digraph = create_digraph ();
-   gcc_assert (m_digraph);
-   return *m_digraph;
- }
- 
- // class lazy_digraphs
- 
- const std::vector<std::unique_ptr<diagnostics::digraphs::digraph>> &
- diagnostics::digraphs::lazy_digraphs::get_or_create_digraphs () const
- {
-   if (!m_digraphs)
-     m_digraphs = create_digraphs ();
-   gcc_assert (m_digraphs);
-   return *m_digraphs;
- }
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- static void
- test_empty_graph ()
- {
-   digraph g;
- 
-   {
-     auto sarif = g.make_json_sarif_graph ();
- 
-     pretty_printer pp;
-     sarif->print (&pp, true);
-     ASSERT_STREQ
-       (pp_formatted_text (&pp),
-        ("{\"nodes\": [],\n"
- 	" \"edges\": []}"));
-   }
- 
-   {
-     auto dg = g.make_dot_graph ();
- 
-     pretty_printer pp;
-     dot::writer w (pp);
-     dg->print (w);
-     ASSERT_STREQ
-       (pp_formatted_text (&pp),
-        ("digraph {\n"
- 	"}\n"));
-   }
- }
- 
- static void
- test_simple_graph ()
- {
- #define KEY_PREFIX "/placeholder/"
-   auto g = std::make_unique<digraph> ();
-   g->set_description ("test graph");
-   g->set_attr (KEY_PREFIX, "date", "1066");
- 
-   auto a = std::make_unique<digraph_node> (*g, "a");
-   auto b = std::make_unique<digraph_node> (*g, "b");
-   b->set_attr (KEY_PREFIX, "color", "red");
-   auto c = std::make_unique<digraph_node> (*g, "c");
-   c->set_label ("I am a node label");
- 
-   auto e = std::make_unique<digraph_edge> (*g, nullptr, *a, *c);
-   e->set_attr (KEY_PREFIX, "status", "copacetic");
-   e->set_label ("I am an edge label");
-   g->add_edge (std::move (e));
- 
-   g->add_node (std::move (a));
- 
-   b->add_child (std::move (c));
-   g->add_node (std::move (b));
- #undef KEY_PREFIX
- 
-   {
-     auto sarif = g->make_json_sarif_graph ();
- 
-     pretty_printer pp;
-     sarif->print (&pp, true);
-     ASSERT_STREQ
-       (pp_formatted_text (&pp),
-        ("{\"properties\": {\"/placeholder/date\": \"1066\"},\n"
- 	" \"nodes\": [{\"id\": \"a\"},\n"
- 	"           {\"id\": \"b\",\n"
- 	"            \"properties\": {\"/placeholder/color\": \"red\"},\n"
- 	"            \"children\": [{\"id\": \"c\"}]}],\n"
- 	" \"edges\": [{\"id\": \"edge0\",\n"
- 	"            \"properties\": {\"/placeholder/status\": \"copacetic\"},\n"
- 	"            \"sourceNodeId\": \"a\",\n"
- 	"            \"targetNodeId\": \"c\"}]}"));
-   }
- 
-   {
-     auto dg = g->make_dot_graph ();
- 
-     pretty_printer pp;
-     dot::writer w (pp);
-     dg->print (w);
-     ASSERT_STREQ
-       (pp_formatted_text (&pp),
-        ("digraph {\n"
- 	"    label=\"test graph\";\n"
- 	"    a;\n"
- 	"    \n"
- 	"    subgraph cluster_b {\n"
- 	"        c [label=\"I am a node label\"];\n"
- 	"\n"
- 	"    };\n"
- 	"    a -> c [label=\"I am an edge label\"];\n"
- 	"}\n"));
-   }
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- diagnostic_digraphs_cc_tests ()
- {
-   test_empty_graph ();
-   test_simple_graph ();
- }
- 
- } // namespace selftest
- 
- #endif /* CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-digraphs.h gcc-16-20250727/gcc/diagnostic-digraphs.h
*** gcc-16-20250720/gcc/diagnostic-digraphs.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-digraphs.h	Thu Jan  1 00:00:00 1970
***************
*** 1,421 ****
- /* Directed graphs associated with a diagnostic.
-    Copyright (C) 2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_DIGRAPHS_H
- #define GCC_DIAGNOSTIC_DIGRAPHS_H
- 
- #include "json.h"
- #include "logical-location.h"
- 
- class graphviz_out;
- 
- class sarif_graph;
- class sarif_node;
- class sarif_edge;
- 
- namespace dot { class graph; }
- 
- namespace diagnostics {
- namespace digraphs {
- 
- /* A family of classes: digraph, node, and edge, closely related to
-    SARIF's graph, node, and edge types (SARIF v2.1.0 sections 3.39-3.41).
- 
-    Nodes can have child nodes, allowing for arbitrarily deep nesting.
-    Edges can be between any pair of nodes (potentially at different
-    nesting levels).
- 
-    Digraphs, nodes, and edges also optionally have a JSON property bag,
-    allowing round-tripping of arbitrary key/value pairs through SARIF.  */
- 
- class digraph;
- class node;
- class edge;
- 
- /* A base class for digraph, node, and edge to allow them to have
-    an optional JSON property bag.  */
- 
- class object
- {
- public:
-   const char *
-   get_attr (const char *key_prefix,
- 	    const char *key) const;
- 
-   void
-   set_attr (const char *key_prefix,
- 	    const char *key,
- 	    const char *value);
- 
-   void
-   set_json_attr (const char *key_prefix,
- 		 const char *key,
- 		 std::unique_ptr<json::value> value);
- 
-   json::object *
-   get_property_bag () const { return m_property_bag.get (); }
- 
-   void
-   set_property_bag (std::unique_ptr<json::object> property_bag)
-   {
-     m_property_bag = std::move (property_bag);
-   }
- 
- private:
-   std::unique_ptr<json::object> m_property_bag;
- };
- 
- // A directed graph, corresponding to SARIF v2.1.0 section 3.39.
- 
- class digraph : public object
- {
-  public:
-   friend class node;
-   friend class edge;
- 
-   digraph () : m_next_edge_id_index (0) {}
-   virtual ~digraph () {}
- 
-   const char *
-   get_description () const
-   {
-     if (!m_description)
-       return nullptr;
-     return m_description->c_str ();
-   }
- 
-   void
-   set_description (const char *desc)
-   {
-     if (desc)
-       m_description = std::make_unique<std::string> (desc);
-     else
-       m_description = nullptr;
-   }
-   void
-   set_description (std::string desc)
-   {
-     m_description = std::make_unique<std::string> (std::move (desc));
-   }
- 
-   node *
-   get_node_by_id (const char *id) const
-   {
-     auto iter = m_id_to_node_map.find (id);
-     if (iter == m_id_to_node_map.end ())
-       return nullptr;
-     return iter->second;
-   }
- 
-   edge *
-   get_edge_by_id (const char *id) const
-   {
-     auto iter = m_id_to_edge_map.find (id);
-     if (iter == m_id_to_edge_map.end ())
-       return nullptr;
-     return iter->second;
-   }
- 
-   size_t
-   get_num_nodes () const
-   {
-     return m_nodes.size ();
-   }
- 
-   node &
-   get_node (size_t idx) const
-   {
-     return *m_nodes[idx].get ();
-   }
- 
-   size_t
-   get_num_edges () const
-   {
-     return m_edges.size ();
-   }
- 
-   edge &
-   get_edge (size_t idx) const
-   {
-     return *m_edges[idx].get ();
-   }
- 
-   void
-   dump () const;
- 
-   std::unique_ptr<json::object>
-   make_json_sarif_graph () const;
- 
-   std::unique_ptr<dot::graph>
-   make_dot_graph () const;
- 
-   void
-   add_node (std::unique_ptr<node> n)
-   {
-     gcc_assert (n);
-     m_nodes.push_back (std::move (n));
-   }
- 
-   void
-   add_edge (std::unique_ptr<edge> e)
-   {
-     gcc_assert (e);
-     m_edges.push_back (std::move (e));
-   }
- 
-   void
-   add_edge (const char *id,
- 	    node &src_node,
- 	    node &dst_node,
- 	    const char *label = nullptr);
- 
-   std::unique_ptr<digraph> clone () const;
- 
-  private:
-   void
-   add_node_id (std::string node_id, node &new_node)
-   {
-     m_id_to_node_map.insert ({std::move (node_id), &new_node});
-   }
-   void
-   add_edge_id (std::string edge_id, edge &new_edge)
-   {
-     m_id_to_edge_map.insert ({std::move (edge_id), &new_edge});
-   }
- 
-   std::string
-   make_edge_id (const char *edge_id);
- 
-   std::unique_ptr<std::string> m_description;
-   std::map<std::string, node *> m_id_to_node_map;
-   std::map<std::string, edge *> m_id_to_edge_map;
-   std::vector<std::unique_ptr<node>> m_nodes;
-   std::vector<std::unique_ptr<edge>> m_edges;
-   size_t m_next_edge_id_index;
- };
- 
- // A node in a directed graph, corresponding to SARIF v2.1.0 section 3.40.
- 
- class node : public object
- {
-  public:
-   virtual ~node () {}
- 
-   node (digraph &g, std::string id)
-   : m_id (id),
-     m_physical_loc (UNKNOWN_LOCATION)
-   {
-     g.add_node_id (std::move (id), *this);
-   }
-   node (const node &) = delete;
- 
-   std::string
-   get_id () const { return m_id; }
- 
-   const char *
-   get_label () const
-   {
-     if (!m_label)
-       return nullptr;
-     return m_label->c_str ();
-   }
- 
-   void
-   set_label (const char *label)
-   {
-     if (label)
-       m_label = std::make_unique<std::string> (label);
-     else
-       m_label = nullptr;
-   }
-   void
-   set_label (std::string label)
-   {
-     m_label = std::make_unique<std::string> (std::move (label));
-   }
- 
-   size_t
-   get_num_children () const { return m_children.size (); }
- 
-   node &
-   get_child (size_t idx) const { return *m_children[idx].get (); }
- 
-   void
-   add_child (std::unique_ptr<node> child)
-   {
-     gcc_assert (child);
-     m_children.push_back (std::move (child));
-   }
- 
-   location_t
-   get_physical_loc () const
-   {
-     return m_physical_loc;
-   }
- 
-   void
-   set_physical_loc (location_t physical_loc)
-   {
-     m_physical_loc = physical_loc;
-   }
- 
-   logical_location
-   get_logical_loc () const
-   {
-     return m_logical_loc;
-   }
- 
-   void
-   set_logical_loc (logical_location logical_loc)
-   {
-     m_logical_loc = logical_loc;
-   }
- 
-   void print (graphviz_out &gv) const;
- 
-   void
-   dump () const;
- 
-   std::unique_ptr<json::object>
-   to_json_sarif_node () const;
- 
-   std::unique_ptr<node>
-   clone (digraph &new_graph,
- 	 std::map<node *, node *> &node_mapping) const;
- 
-  private:
-   std::string m_id;
-   std::unique_ptr<std::string> m_label;
-   std::vector<std::unique_ptr<node>> m_children;
-   location_t m_physical_loc;
-   logical_location m_logical_loc;
- };
- 
- // An edge in a directed graph, corresponding to SARIF v2.1.0 section 3.41.
- 
- class edge : public object
- {
-  public:
-   virtual ~edge () {}
- 
-   /* SARIF requires us to provide unique edge IDs within a graph,
-      but otherwise we don't need them.
-      Pass in nullptr for the id to get the graph to generate a unique
-      edge id for us.  */
-   edge (digraph &g,
- 	const char *id,
- 	node &src_node,
- 	node &dst_node)
-   : m_id (g.make_edge_id (id)),
-     m_src_node (src_node),
-     m_dst_node (dst_node)
-   {
-     g.add_edge_id (m_id, *this);
-   }
- 
-   std::string
-   get_id () const { return m_id; }
- 
-   const char *
-   get_label () const
-   {
-     if (!m_label)
-       return nullptr;
-     return m_label->c_str ();
-   }
- 
-   void
-   set_label (const char *label)
-   {
-     if (label)
-       m_label = std::make_unique<std::string> (label);
-     else
-       m_label = nullptr;
-   }
- 
-   node &
-   get_src_node () const { return m_src_node; }
- 
-   node &
-   get_dst_node () const { return m_dst_node; }
- 
-   void
-   dump () const;
- 
-   std::unique_ptr<json::object>
-   to_json_sarif_edge () const;
- 
-   std::unique_ptr<edge>
-   clone (digraph &new_graph,
- 	 const std::map<diagnostics::digraphs::node *, diagnostics::digraphs::node *> &node_mapping) const;
- 
- private:
-   std::string m_id;
-   std::unique_ptr<std::string> m_label;
-   node &m_src_node;
-   node &m_dst_node;
- };
- 
- /* Abstract base class for lazily creating
-    a digraph on demand.
- 
-    This allows us to avoid the work of creating the digraph for
-    the common case where we just have a text sink.  */
- 
- class lazy_digraph
- {
- public:
-   virtual ~lazy_digraph () {}
- 
-   const digraph &
-   get_or_create_digraph () const;
- 
- private:
-   virtual std::unique_ptr<digraph>
-   create_digraph () const = 0;
- 
-   mutable std::unique_ptr<digraph> m_digraph;
- };
- 
- /* Abstract base class for lazily creating a collection of
-    digraphs on demand.
- 
-    This allows us to avoid the work of creating the digraphs for
-    the common case where we just have a text sink.  */
- 
- class lazy_digraphs
- {
- public:
-   virtual ~lazy_digraphs () {}
- 
-   const std::vector<std::unique_ptr<digraph>> &
-   get_or_create_digraphs () const;
- 
- private:
-   virtual std::unique_ptr<std::vector<std::unique_ptr<digraph>>>
-   create_digraphs () const = 0;
- 
-   mutable std::unique_ptr<std::vector<std::unique_ptr<digraph>>> m_digraphs;
- };
- 
- } // namespace digraphs
- } // namespace diagnostics
- 
- #endif /* ! GCC_DIAGNOSTIC_DIGRAPHS_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-event-id.h gcc-16-20250727/gcc/diagnostic-event-id.h
*** gcc-16-20250720/gcc/diagnostic-event-id.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-event-id.h	Thu Jan  1 00:00:00 1970
***************
*** 1,72 ****
- /* A class for referring to events within a diagnostic_path.
-    Copyright (C) 2019-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_EVENT_ID_H
- #define GCC_DIAGNOSTIC_EVENT_ID_H
- 
- /* A class for referring to events within a diagnostic_path.
- 
-    They are stored as 0-based offsets into the events, but
-    printed (e.g. via %@) as 1-based numbers.
- 
-    For example, a 3-event path has event offsets 0, 1, and 2,
-    which would be shown to the user as "(1)", "(2)" and "(3)".
- 
-    This has its own header so that pretty-print.cc can use this
-    to implement "%@" without bringing in all of diagnostic_path
-    (which e.g. refers to "tree").  */
- 
- class diagnostic_event_id_t
- {
-  public:
-   diagnostic_event_id_t () : m_index (UNKNOWN_EVENT_IDX) {}
-   diagnostic_event_id_t (int zero_based_idx) : m_index (zero_based_idx) {}
- 
-   bool known_p () const { return m_index != UNKNOWN_EVENT_IDX; }
- 
-   int zero_based () const
-   {
-     gcc_assert (known_p ());
-     return m_index;
-   }
- 
-   int one_based () const
-   {
-     gcc_assert (known_p ());
-     return m_index + 1;
-   }
- 
-  private:
-   static const int UNKNOWN_EVENT_IDX = -1;
-   int m_index; // zero-based
- };
- 
- /* A pointer to a diagnostic_event_id_t, for use with the "%@" format
-    code, which will print a 1-based representation for it, with suitable
-    colorization, e.g. "(1)".
-    The %@ format code requires that known_p be true for the event ID. */
- typedef diagnostic_event_id_t *diagnostic_event_id_ptr;
- 
- /* A type for compactly referring to a particular thread within a
-    diagnostic_path.  Typically there is just one thread per path,
-    with id 0.  */
- typedef int diagnostic_thread_id_t;
- 
- #endif /* ! GCC_DIAGNOSTIC_EVENT_ID_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-format-html.cc gcc-16-20250727/gcc/diagnostic-format-html.cc
*** gcc-16-20250720/gcc/diagnostic-format-html.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-format-html.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,1703 ****
- /* HTML output for diagnostics.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #include "config.h"
- #define INCLUDE_MAP
- #define INCLUDE_STRING
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "diagnostic.h"
- #include "diagnostic-metadata.h"
- #include "diagnostic-format.h"
- #include "diagnostic-format-html.h"
- #include "diagnostic-format-text.h"
- #include "diagnostic-format-sarif.h"
- #include "diagnostic-output-file.h"
- #include "diagnostic-buffer.h"
- #include "diagnostic-path.h"
- #include "diagnostic-client-data-hooks.h"
- #include "selftest.h"
- #include "selftest-diagnostic.h"
- #include "pretty-print-format-impl.h"
- #include "pretty-print-urlifier.h"
- #include "edit-context.h"
- #include "intl.h"
- #include "xml.h"
- #include "xml-printer.h"
- #include "diagnostic-digraphs.h"
- #include "diagnostic-state-graphs.h"
- #include "graphviz.h"
- #include "json.h"
- #include "selftest-xml.h"
- 
- // struct html_generation_options
- 
- html_generation_options::html_generation_options ()
- : m_css (true),
-   m_javascript (true),
-   m_show_state_diagrams (false),
-   m_show_state_diagrams_sarif (false),
-   m_show_state_diagrams_dot_src (false)
- {
- }
- 
- class html_builder;
- 
- /* Concrete buffering implementation subclass for HTML output.  */
- 
- class diagnostic_html_format_buffer : public diagnostic_per_format_buffer
- {
- public:
-   friend class html_builder;
-   friend class html_output_format;
- 
-   diagnostic_html_format_buffer (html_builder &builder)
-   : m_builder (builder)
-   {}
- 
-   void dump (FILE *out, int indent) const final override;
-   bool empty_p () const final override;
-   void move_to (diagnostic_per_format_buffer &dest) final override;
-   void clear () final override;
-   void flush () final override;
- 
-   void add_result (std::unique_ptr<xml::element> result)
-   {
-     m_results.push_back (std::move (result));
-   }
- 
- private:
-   html_builder &m_builder;
-   std::vector<std::unique_ptr<xml::element>> m_results;
- };
- 
- /* A class for managing HTML output of diagnostics.
- 
-    Implemented:
-    - message text
- 
-    Known limitations/missing functionality:
-    - title for page
-    - file/line/column
-    - error vs warning
-    - CWEs
-    - rules
-    - fix-it hints
-    - paths
- */
- 
- class html_builder
- {
- public:
-   friend class diagnostic_html_format_buffer;
- 
-   html_builder (diagnostic_context &context,
- 		pretty_printer &pp,
- 		const line_maps *line_maps,
- 		const html_generation_options &html_gen_opts);
- 
-   void
-   set_main_input_filename (const char *name);
- 
-   void on_report_diagnostic (const diagnostic_info &diagnostic,
- 			     diagnostic_t orig_diag_kind,
- 			     diagnostic_html_format_buffer *buffer);
-   void emit_diagram (const diagnostic_diagram &diagram);
-   void emit_global_graph (const diagnostics::digraphs::lazy_digraph &);
- 
-   void end_group ();
- 
-   std::unique_ptr<xml::element> take_current_diagnostic ()
-   {
-     return std::move (m_cur_diagnostic_element);
-   }
- 
-   void flush_to_file (FILE *outf);
- 
-   const xml::document &get_document () const { return *m_document; }
- 
-   void set_printer (pretty_printer &pp)
-   {
-     m_printer = &pp;
-   }
- 
-   std::unique_ptr<xml::element>
-   make_element_for_metadata (const diagnostic_metadata &metadata);
- 
-   std::unique_ptr<xml::element>
-   make_element_for_patch (const diagnostic_info &diagnostic);
- 
-   void add_focus_id (std::string focus_id)
-   {
-     m_ui_focus_ids.append_string (focus_id.c_str ());
-   }
- 
-   std::unique_ptr<xml::node>
-   maybe_make_state_diagram (const diagnostic_event &event);
- 
- private:
-   void
-   add_stylesheet (std::string url);
- 
-   std::unique_ptr<xml::element>
-   make_element_for_diagnostic (const diagnostic_info &diagnostic,
- 			       diagnostic_t orig_diag_kind,
- 			       bool alert);
- 
-   std::unique_ptr<xml::element>
-   make_metadata_element (label_text label,
- 			 label_text url);
- 
-   void
-   add_at_nesting_level (size_t nesting_level,
- 			std::unique_ptr<xml::element> child_diag_element);
- 
-   void
-   push_nesting_level ();
- 
-   void
-   pop_nesting_level ();
- 
-   void
-   add_graph (const diagnostics::digraphs::digraph &dg,
- 	     xml::element &parent_element);
- 
-   diagnostic_context &m_context;
-   pretty_printer *m_printer;
-   const line_maps *m_line_maps;
-   html_generation_options m_html_gen_opts;
-   const logical_location_manager *m_logical_loc_mgr;
- 
-   std::unique_ptr<xml::document> m_document;
-   xml::element *m_head_element;
-   xml::element *m_title_element;
-   xml::element *m_body_element;
-   xml::element *m_diagnostics_element;
-   std::unique_ptr<xml::element> m_cur_diagnostic_element;
-   std::vector<xml::element *> m_cur_nesting_levels;
-   int m_next_diag_id; // for handing out unique IDs
-   json::array m_ui_focus_ids;
-   logical_location m_last_logical_location;
-   location_t m_last_location;
-   expanded_location m_last_expanded_location;
- };
- 
- static std::unique_ptr<xml::element>
- make_div (std::string class_)
- {
-   auto div = std::make_unique<xml::element> ("div", false);
-   div->set_attr ("class", std::move (class_));
-   return div;
- }
- 
- static std::unique_ptr<xml::element>
- make_span (std::string class_)
- {
-   auto span = std::make_unique<xml::element> ("span", true);
-   span->set_attr ("class", std::move (class_));
-   return span;
- }
- 
- /* class diagnostic_html_format_buffer : public diagnostic_per_format_buffer.  */
- 
- void
- diagnostic_html_format_buffer::dump (FILE *out, int indent) const
- {
-   fprintf (out, "%*sdiagnostic_html_format_buffer:\n", indent, "");
-   int idx = 0;
-   for (auto &result : m_results)
-     {
-       fprintf (out, "%*sresult[%i]:\n", indent + 2, "", idx);
-       result->dump (out);
-       fprintf (out, "\n");
-       ++idx;
-     }
- }
- 
- bool
- diagnostic_html_format_buffer::empty_p () const
- {
-   return m_results.empty ();
- }
- 
- void
- diagnostic_html_format_buffer::move_to (diagnostic_per_format_buffer &base)
- {
-   diagnostic_html_format_buffer &dest
-     = static_cast<diagnostic_html_format_buffer &> (base);
-   for (auto &&result : m_results)
-     dest.m_results.push_back (std::move (result));
-   m_results.clear ();
- }
- 
- void
- diagnostic_html_format_buffer::clear ()
- {
-   m_results.clear ();
- }
- 
- void
- diagnostic_html_format_buffer::flush ()
- {
-   for (auto &&result : m_results)
-     m_builder.m_diagnostics_element->add_child (std::move (result));
-   m_results.clear ();
- }
- 
- /* class html_builder.  */
- 
- /* Style information for writing out HTML paths.
-    Colors taken from https://pf3.patternfly.org/v3/styles/color-palette/ */
- 
- static const char * const HTML_STYLE
-   = ("  <style>\n"
-      "    .linenum { color: white;\n"
-      "               background-color: #0088ce;\n"
-      "               white-space: pre;\n"
-      "               border-right: 1px solid black; }\n"
-      "    .ruler { color: red;\n"
-      "              white-space: pre; }\n"
-      "    .source { color: blue;\n"
-      "              background-color: white;\n"
-      "              white-space: pre; }\n"
-      "    .annotation { color: green;\n"
-      "                  background-color: white;\n"
-      "                  white-space: pre; }\n"
-      "    .linenum-gap { text-align: center;\n"
-      "                   border-top: 1px solid black;\n"
-      "                   border-right: 1px solid black;\n"
-      "                   background-color: #ededed; }\n"
-      "    .source-gap { border-bottom: 1px dashed black;\n"
-      "                  border-top: 1px dashed black;\n"
-      "                  background-color: #ededed; }\n"
-      "    .no-locus-event { font-family: monospace;\n"
-      "                      color: green;\n"
-      "                      white-space: pre; }\n"
-      "    .funcname { font-weight: bold; }\n"
-      "    .events-hdr { color: white;\n"
-      "                  background-color: #030303; }\n"
-      "    .event-range {  border: 1px solid black;\n"
-      "                    padding: 0px; }\n"
-      "    .event-range-with-margin { border-spacing: 0; }\n"
-      "    .locus { font-family: monospace;\n"
-      "             border-spacing: 0px; }\n"
-      "    .selected { color: white;\n"
-      "                background-color: #0088ce; }\n"
-      "    .stack-frame-with-margin { border-spacing: 0; }\n"
-      "    .stack-frame {  padding: 5px;\n"
-      "                    box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.5); }\n"
-      "    .frame-funcname { text-align: right;\n"
-      "                      font-style: italic; } \n"
-      "    .highlight-a { color: #703fec;\n" // pf-purple-400
-      "                   font-weight: bold; }\n"
-      "    .highlight-b { color: #3f9c35;\n" // pf-green-400
-      "                   font-weight: bold; }\n"
-      "    .gcc-quoted-text { font-weight: bold;\n"
-      "                       font-family: mono; }\n"
-      "  </style>\n");
- 
- /* A little JavaScript for ease of navigation.
-    Keys j/k move forward and backward cyclically through a list
-    of focus ids (written out in another <script> tag as the HTML
-    is flushed).  */
- 
- const char * const HTML_SCRIPT
-   = ("  var current_focus_idx = 0;\n"
-      "\n"
-      "  function get_focus_span (focus_idx)\n"
-      "  {\n"
-      "      const element_id = focus_ids[focus_idx];\n"
-      "      return document.getElementById(element_id);\n"
-      "  }\n"
-      "  function get_any_state_diagram (focus_idx)\n"
-      "  {\n"
-      "      const element_id = focus_ids[focus_idx];\n"
-      "      return document.getElementById(element_id + \"-state-diagram\");\n"
-      "  }\n"
-      "  function unhighlight_current_focus_idx ()\n"
-      "  {\n"
-      "      get_focus_span (current_focus_idx).classList.remove ('selected');\n"
-      "      state_diagram = get_any_state_diagram (current_focus_idx);\n"
-      "      if (state_diagram) {\n"
-      "          state_diagram.style.visibility = \"hidden\";\n"
-      "      }\n"
-      "  }\n"
-      "  function highlight_current_focus_idx ()\n"
-      "  {\n"
-      "      const el = get_focus_span (current_focus_idx);\n"
-      "      el.classList.add ('selected');\n"
-      "      state_diagram = get_any_state_diagram (current_focus_idx);\n"
-      "      if (state_diagram) {\n"
-      "          state_diagram.style.visibility = \"visible\";\n"
-      "      }\n"
-      "      // Center the element on the screen\n"
-      "      const top_y = el.getBoundingClientRect ().top + window.pageYOffset;\n"
-      "      const middle = top_y - (window.innerHeight / 2);\n"
-      "      window.scrollTo (0, middle);\n"
-      "  }\n"
-      "  function select_prev_focus_idx ()\n"
-      "  {\n"
-      "      unhighlight_current_focus_idx ();\n"
-      "      if (current_focus_idx > 0)\n"
-      "          current_focus_idx -= 1;\n"
-      "      else\n"
-      "          current_focus_idx = focus_ids.length - 1;\n"
-      "      highlight_current_focus_idx ();\n"
-      "  }\n"
-      "  function select_next_focus_idx ()\n"
-      "  {\n"
-      "      unhighlight_current_focus_idx ();\n"
-      "      if (current_focus_idx < focus_ids.length - 1)\n"
-      "          current_focus_idx += 1;\n"
-      "      else\n"
-      "          current_focus_idx = 0;\n"
-      "      highlight_current_focus_idx ();\n"
-      "  }\n"
-      "  document.addEventListener('keydown', function (ev) {\n"
-      "      if (ev.key == 'j')\n"
-      "          select_next_focus_idx ();\n"
-      "      else if (ev.key == 'k')\n"
-      "          select_prev_focus_idx ();\n"
-      "  });\n"
-      "  highlight_current_focus_idx ();\n");
- 
- struct html_doctypedecl : public xml::doctypedecl
- {
-   void write_as_xml (pretty_printer *pp,
- 		     int depth, bool indent) const final override
-   {
-     if (indent)
-       {
- 	for (int i = 0; i < depth; ++i)
- 	  pp_string (pp, "  ");
-       }
-     pp_string (pp, "<!DOCTYPE html\n"
- 	       "     PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
- 	       "     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
-     if (indent)
-       pp_newline (pp);
-   }
- };
- 
- /* html_builder's ctor.  */
- 
- html_builder::html_builder (diagnostic_context &context,
- 			    pretty_printer &pp,
- 			    const line_maps *line_maps,
- 			    const html_generation_options &html_gen_opts)
- : m_context (context),
-   m_printer (&pp),
-   m_line_maps (line_maps),
-   m_html_gen_opts (html_gen_opts),
-   m_logical_loc_mgr (nullptr),
-   m_head_element (nullptr),
-   m_title_element (nullptr),
-   m_body_element (nullptr),
-   m_diagnostics_element (nullptr),
-   m_next_diag_id (0),
-   m_last_location (UNKNOWN_LOCATION),
-   m_last_expanded_location ({})
- {
-   gcc_assert (m_line_maps);
- 
-   if (auto client_data_hooks = context.get_client_data_hooks ())
-     m_logical_loc_mgr = client_data_hooks->get_logical_location_manager ();
- 
-   m_document = std::make_unique<xml::document> ();
-   m_document->m_doctypedecl = std::make_unique<html_doctypedecl> ();
-   {
-     auto html_element = std::make_unique<xml::element> ("html", false);
-     html_element->set_attr ("xmlns",
- 			    "http://www.w3.org/1999/xhtml");
-     xml::printer xp (*html_element.get ());
-     m_document->add_child (std::move (html_element));
- 
-     {
-       xml::auto_print_element head (xp, "head");
-       m_head_element = xp.get_insertion_point ();
-       {
- 	xml::auto_print_element title (xp, "title", true);
- 	m_title_element = xp.get_insertion_point ();
- 	m_title_element->add_text (" ");
-       }
- 
-       if (m_html_gen_opts.m_css)
- 	{
- 	  add_stylesheet ("https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly.min.css");
- 	  add_stylesheet ("https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly-additions.min.css");
- 	  xp.add_raw (HTML_STYLE);
- 	}
-       if (m_html_gen_opts.m_javascript)
- 	{
- 	  xp.push_tag ("script");
- 	  /* Escaping rules are different for HTML <script> elements,
- 	     so add the script "raw" for now.  */
- 	  xp.add_raw (HTML_SCRIPT);
- 	  xp.pop_tag ("script");
- 	}
-     }
- 
-     {
-       xml::auto_print_element body (xp, "body");
-       m_body_element = xp.get_insertion_point ();
-       {
- 	auto diagnostics_element = make_div ("gcc-diagnostic-list");
- 	m_diagnostics_element = diagnostics_element.get ();
- 	xp.append (std::move (diagnostics_element));
-       }
-     }
-   }
- }
- 
- void
- html_builder::set_main_input_filename (const char *name)
- {
-   gcc_assert (m_title_element);
-   if (name)
-     {
-       m_title_element->m_children.clear ();
-       m_title_element->add_text (name);
-     }
- }
- 
- void
- html_builder::add_stylesheet (std::string url)
- {
-   gcc_assert (m_head_element);
- 
-   xml::printer xp (*m_head_element);
-   xp.push_tag ("link", false);
-   xp.set_attr ("rel", "stylesheet");
-   xp.set_attr ("type", "text/css");
-   xp.set_attr ("href", std::move (url));
- }
- 
- /* Implementation of "on_report_diagnostic" for HTML output.  */
- 
- void
- html_builder::on_report_diagnostic (const diagnostic_info &diagnostic,
- 				    diagnostic_t orig_diag_kind,
- 				    diagnostic_html_format_buffer *buffer)
- {
-   if (diagnostic.kind == DK_ICE || diagnostic.kind == DK_ICE_NOBT)
-     {
-       /* Print a header for the remaining output to stderr, and
- 	 return, attempting to print the usual ICE messages to
- 	 stderr.  Hopefully this will be helpful to the user in
- 	 indicating what's gone wrong (also for DejaGnu, for pruning
- 	 those messages).   */
-       fnotice (stderr, "Internal compiler error:\n");
-     }
- 
-   const int nesting_level = m_context.get_diagnostic_nesting_level ();
-   bool alert = true;
-   if (m_cur_diagnostic_element && nesting_level > 0)
-     alert = false;
-   if (!m_cur_diagnostic_element)
-     m_last_logical_location = logical_location ();
-   auto diag_element
-     = make_element_for_diagnostic (diagnostic, orig_diag_kind, alert);
-   if (buffer)
-     {
-       gcc_assert (!m_cur_diagnostic_element);
-       buffer->m_results.push_back (std::move (diag_element));
-     }
-   else
-     {
-       if (m_cur_diagnostic_element)
- 	{
- 	  /* Nested diagnostic.  */
- 	  gcc_assert (nesting_level >= 0);
- 	  add_at_nesting_level (nesting_level, std::move (diag_element));
- 	}
-       else
- 	/* Top-level diagnostic.  */
- 	{
- 	  m_cur_diagnostic_element = std::move (diag_element);
- 	  m_cur_nesting_levels.clear ();
- 	}
-     }
- }
- 
- // For ease of comparison with experimental-nesting-show-levels=yes
- 
- static void
- add_nesting_level_attr (xml::element &element,
- 			int nesting_level)
- {
-   element.set_attr ("nesting-level", std::to_string (nesting_level));
- }
- 
- void
- html_builder::
- add_at_nesting_level (size_t nesting_level,
- 		      std::unique_ptr<xml::element> child_diag_element)
- {
-   gcc_assert (m_cur_diagnostic_element);
-   while (nesting_level > m_cur_nesting_levels.size ())
-     push_nesting_level ();
-   while (nesting_level < m_cur_nesting_levels.size ())
-     pop_nesting_level ();
- 
-   if (nesting_level > 0)
-     {
-       gcc_assert (!m_cur_nesting_levels.empty ());
-       auto current_nesting_level = m_cur_nesting_levels.back ();
-       xml::printer xp (*current_nesting_level);
-       xp.push_tag ("li");
-       add_nesting_level_attr (*xp.get_insertion_point (),
- 			      m_cur_nesting_levels.size ());
-       xp.append (std::move (child_diag_element));
-       xp.pop_tag ("li");
-     }
-   else
-     m_cur_diagnostic_element->add_child (std::move (child_diag_element));
- }
- 
- void
- html_builder::push_nesting_level ()
- {
-   gcc_assert (m_cur_diagnostic_element);
-   auto new_nesting_level = std::make_unique<xml::element> ("ul", false);
-   add_nesting_level_attr (*new_nesting_level,
- 			  m_cur_nesting_levels.size () + 1);
-   xml::element *current_nesting_level = nullptr;
-   if (!m_cur_nesting_levels.empty ())
-     current_nesting_level = m_cur_nesting_levels.back ();
-   m_cur_nesting_levels.push_back (new_nesting_level.get ());
-   if (current_nesting_level)
-     current_nesting_level->add_child (std::move (new_nesting_level));
-   else
-     m_cur_diagnostic_element->add_child (std::move (new_nesting_level));
- }
- 
- void
- html_builder::pop_nesting_level ()
- {
-   gcc_assert (m_cur_diagnostic_element);
-   m_cur_nesting_levels.pop_back ();
- }
- 
- static void
- print_pre_source (xml::printer &xp, const char *text)
- {
-   xp.push_tag_with_class ("pre", "source", true);
-   xp.add_text (text);
-   xp.pop_tag ("pre");
- }
- 
- std::unique_ptr<xml::node>
- html_builder::maybe_make_state_diagram (const diagnostic_event &event)
- {
-   if (!m_html_gen_opts.m_show_state_diagrams)
-     return nullptr;
- 
-   if (!m_logical_loc_mgr)
-     return nullptr;
- 
-   /* Get state graph; if we're going to print it later, also request
-      the debug version.  */
-   auto state_graph
-     = event.maybe_make_diagnostic_state_graph
- 	(m_html_gen_opts.m_show_state_diagrams_sarif);
-   if (!state_graph)
-     return nullptr;
- 
-   // Convert it to .dot AST
-   auto dot_graph
-     = diagnostics::state_graphs::make_dot_graph (*state_graph,
- 						 *m_logical_loc_mgr);
-   gcc_assert (dot_graph);
- 
-   auto wrapper = std::make_unique<xml::element> ("div", false);
-   xml::printer xp (*wrapper);
- 
-   if (m_html_gen_opts.m_show_state_diagrams_sarif)
-     {
-       // For debugging, show the SARIF src inline:
-       pretty_printer pp;
-       state_graph->make_json_sarif_graph ()->print (&pp, true);
-       print_pre_source (xp, pp_formatted_text (&pp));
-     }
- 
-   if (m_html_gen_opts.m_show_state_diagrams_dot_src)
-     {
-       // For debugging, show the dot src inline:
-       pretty_printer pp;
-       dot::writer w (pp);
-       dot_graph->print (w);
-       print_pre_source (xp, pp_formatted_text (&pp));
-     }
- 
-   // Turn the .dot into SVG and splice into place
-   auto svg = dot::make_svg_from_graph (*dot_graph);
-   if (svg)
-     xp.append (std::move (svg));
- 
-   return wrapper;
- }
- 
- /* Custom subclass of html_label_writer.
-    Wrap labels within a <span> element, supplying them with event IDs.
-    Add the IDs to the list of focus IDs.  */
- 
- class html_path_label_writer : public html_label_writer
- {
- public:
-   html_path_label_writer (xml::printer &xp,
- 			  html_builder &builder,
- 			  const diagnostic_path &path,
- 			  const std::string &event_id_prefix)
-   : m_xp (xp),
-     m_html_builder (builder),
-     m_path (path),
-     m_event_id_prefix (event_id_prefix),
-     m_next_event_idx (0),
-     m_curr_event_id ()
-   {
-   }
- 
-   void begin_label () final override
-   {
-     m_curr_event_id = m_next_event_idx++;
-     m_xp.push_tag_with_class ("span", "event", true);
-     m_xp.set_attr ("id", get_element_id ());
-     m_html_builder.add_focus_id (get_element_id ());
-   }
- 
-   void end_label () final override
-   {
-     const diagnostic_event &event
-       = m_path.get_event (m_curr_event_id.zero_based ());
-     if (auto state_doc = m_html_builder.maybe_make_state_diagram (event))
-     {
-       m_xp.push_tag_with_class ("div", "state-diagram", false);
-       m_xp.set_attr ("id", get_element_id () + "-state-diagram");
-       m_xp.set_attr ("style",
- 		     ("position: absolute;"
- 		      " z-index: 1;"
- 		      " visibility: hidden;"));
-       m_xp.append (std::move (state_doc));
-       m_xp.pop_tag ("div");
-     }
- 
-     m_xp.pop_tag ("span"); // from begin_label
-   }
- 
- private:
-   std::string
-   get_element_id () const
-   {
-     gcc_assert (m_curr_event_id.known_p ());
-     return (m_event_id_prefix
- 	    + std::to_string (m_curr_event_id.zero_based ()));
-   }
- 
-   xml::printer &m_xp;
-   html_builder &m_html_builder;
-   const diagnostic_path &m_path;
-   const std::string &m_event_id_prefix;
-   int m_next_event_idx;
-   diagnostic_event_id_t m_curr_event_id;
- };
- 
- /* See https://pf3.patternfly.org/v3/pattern-library/widgets/#alerts */
- static const char *
- get_pf_class_for_alert_div (diagnostic_t diag_kind)
- {
-   switch (diag_kind)
-     {
-     case DK_DEBUG:
-     case DK_NOTE:
-       return "alert alert-info";
- 
-     case DK_ANACHRONISM:
-     case DK_WARNING:
-       return "alert alert-warning";
- 
-     case DK_ERROR:
-     case DK_SORRY:
-     case DK_ICE:
-     case DK_ICE_NOBT:
-     case DK_FATAL:
-       return "alert alert-danger";
- 
-     default:
-       gcc_unreachable ();
-     }
- }
- 
- static const char *
- get_pf_class_for_alert_icon (diagnostic_t diag_kind)
- {
-   switch (diag_kind)
-     {
-     case DK_DEBUG:
-     case DK_NOTE:
-       return "pficon pficon-info";
- 
-     case DK_ANACHRONISM:
-     case DK_WARNING:
-       return "pficon pficon-warning-triangle-o";
- 
-     case DK_ERROR:
-     case DK_SORRY:
-     case DK_ICE:
-     case DK_ICE_NOBT:
-     case DK_FATAL:
-       return "pficon pficon-error-circle-o";
- 
-     default:
-       gcc_unreachable ();
-     }
- }
- 
- static const char *
- get_label_for_logical_location_kind (enum logical_location_kind kind)
- {
-   switch (kind)
-     {
-     default:
-       gcc_unreachable ();
-     case logical_location_kind::unknown:
-       return nullptr;
- 
-     /* Kinds within executable code.  */
-     case logical_location_kind::function:
-       return "Function";
-     case logical_location_kind::member:
-       return "Member";
-     case logical_location_kind::module_:
-       return "Module";
-     case logical_location_kind::namespace_:
-       return "Namespace";
-     case logical_location_kind::type:
-       return "Type";
-     case logical_location_kind::return_type:
-       return "Return type";
-     case logical_location_kind::parameter:
-       return "Parameter";
-     case logical_location_kind::variable:
-       return "Variable";
- 
-     /* Kinds within XML or HTML documents.  */
-     case logical_location_kind::element:
-       return "Element";
-     case logical_location_kind::attribute:
-       return "Attribute";
-     case logical_location_kind::text:
-       return "Text";
-     case logical_location_kind::comment:
-       return "Comment";
-     case logical_location_kind::processing_instruction:
-       return "Processing Instruction";
-     case logical_location_kind::dtd:
-       return "DTD";
-     case logical_location_kind::declaration:
-       return "Declaration";
- 
-   /* Kinds within JSON documents.  */
-     case logical_location_kind::object:
-       return "Object";
-     case logical_location_kind::array:
-       return "Array";
-     case logical_location_kind::property:
-       return "Property";
-     case logical_location_kind::value:
-       return "Value";
-     }
- }
- 
- static void
- add_labelled_value (xml::printer &xp,
- 		    std::string id,
- 		    std::string label,
- 		    std::string value,
- 		    bool quote_value)
- {
-   xp.push_tag ("div", true);
-   xp.set_attr ("id", id);
-   xp.push_tag ("span");
-   xp.add_text (label);
-   xp.add_text (" ");
-   xp.pop_tag ("span");
-   xp.push_tag ("span");
-   if (quote_value)
-     xp.set_attr ("class", "gcc-quoted-text");
-   xp.add_text (std::move (value));
-   xp.pop_tag ("span");
-   xp.pop_tag ("div");
- }
- 
- class html_token_printer : public token_printer
- {
- public:
-   html_token_printer (xml::element &parent_element)
-     /* Ideally pp_token_lists that reach a token_printer should be
-        "balanced", but for now they can have mismatching pp_tokens
-        e.g. a begin_color without an end_color (PR other/120610).
-        Give html_token_printer its own xml::printer as a firewall to
-        limit the scope of the mismatches in the HTML.  */
-     : m_xp (parent_element,
- 	    /* Similarly we don't check that the popped tags match.  */
- 	    false)
-   {
-   }
-   void print_tokens (pretty_printer */*pp*/,
- 		     const pp_token_list &tokens) final override
-   {
-     /* Implement print_tokens by adding child elements to
-        m_parent_element.  */
-     for (auto iter = tokens.m_first; iter; iter = iter->m_next)
-       switch (iter->m_kind)
- 	{
- 	default:
- 	  gcc_unreachable ();
- 
- 	case pp_token::kind::text:
- 	  {
- 	    pp_token_text *sub = as_a <pp_token_text *> (iter);
- 	    /* The value might be in the obstack, so we may need to
- 	       copy it.  */
- 	    m_xp.add_text (sub->m_value.get ());
- 	    }
- 	  break;
- 
- 	case pp_token::kind::begin_color:
- 	  {
- 	    pp_token_begin_color *sub = as_a <pp_token_begin_color *> (iter);
- 	    gcc_assert (sub->m_value.get ());
- 	    m_xp.push_tag_with_class ("span", sub->m_value.get ());
- 	  }
- 	  break;
- 
- 	case pp_token::kind::end_color:
- 	  m_xp.pop_tag ("span");
- 	  break;
- 
- 	case pp_token::kind::begin_quote:
- 	  {
- 	    m_xp.add_text (open_quote);
- 	    m_xp.push_tag_with_class ("span", "gcc-quoted-text");
- 	  }
- 	  break;
- 	case pp_token::kind::end_quote:
- 	  {
- 	    m_xp.pop_tag ("span");
- 	    m_xp.add_text (close_quote);
- 	  }
- 	  break;
- 
- 	case pp_token::kind::begin_url:
- 	  {
- 	    pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter);
- 	    m_xp.push_tag ("a", true);
- 	    m_xp.set_attr ("href", sub->m_value.get ());
- 	  }
- 	  break;
- 	case pp_token::kind::end_url:
- 	  m_xp.pop_tag ("a");
- 	  break;
- 
- 	case pp_token::kind::event_id:
- 	  {
- 	    pp_token_event_id *sub = as_a <pp_token_event_id *> (iter);
- 	    gcc_assert (sub->m_event_id.known_p ());
- 	    m_xp.add_text ("(");
- 	    m_xp.add_text (std::to_string (sub->m_event_id.one_based ()));
- 	    m_xp.add_text (")");
- 	  }
- 	  break;
- 	}
-   }
- 
- private:
-   xml::printer m_xp;
- };
- 
- /* Make a <div class="gcc-diagnostic"> for DIAGNOSTIC.
- 
-    If ALERT is true, make it be a PatternFly alert (see
-    https://pf3.patternfly.org/v3/pattern-library/widgets/#alerts) and
-    show severity text (e.g. "error: ").
- 
-    If ALERT is false, don't show the severity text and don't show
-    the filename if it's the same as the previous diagnostic within the
-    diagnostic group.  */
- 
- std::unique_ptr<xml::element>
- html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic,
- 					   diagnostic_t orig_diag_kind,
- 					   bool alert)
- {
-   const int diag_idx = m_next_diag_id++;
-   std::string diag_id;
-   {
-     pretty_printer pp;
-     pp_printf (&pp, "gcc-diag-%i", diag_idx);
-     diag_id = pp_formatted_text (&pp);
-   }
- 
-   // TODO: might be nice to emulate the text output format, but colorize it
- 
-   /* See https://pf3.patternfly.org/v3/pattern-library/widgets/#alerts
-      which has this example:
- <div class="alert alert-danger">
-   <span class="pficon pficon-error-circle-o"></span>
-   <strong>Hey there is a problem!</strong> Yeah this is really messed up and you should <a href="#" class="alert-link">know about it</a>.
- </div>
-   */
-   auto diag_element = make_div ("gcc-diagnostic");
-   diag_element->set_attr ("id", diag_id);
-   if (alert)
-     diag_element->set_attr ("class",
- 			    get_pf_class_for_alert_div (diagnostic.kind));
- 
-   xml::printer xp (*diag_element.get ());
-   const size_t depth_within_alert_div = 1;
- 
-   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
- 
-   if (alert)
-     {
-       xp.push_tag_with_class ("span",
- 			      get_pf_class_for_alert_icon (diagnostic.kind),
- 			      true);
-       xp.add_text (" ");
-       xp.pop_tag ("span");
-     }
- 
-   // The rest goes in the <div>...
-   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
- 
-   xp.push_tag_with_class ("div", "gcc-message", true);
-   std::string message_alert_id (diag_id + "-message");
-   xp.set_attr ("id", message_alert_id);
-   add_focus_id (message_alert_id);
- 
-   const size_t depth_within_message_div = depth_within_alert_div + 1;
-   gcc_assert (xp.get_num_open_tags () == depth_within_message_div);
- 
-   // Severity e.g. "warning: "
-   bool show_severity = true;
-   if (!alert)
-     show_severity = false;
-   if (show_severity)
-   {
-     xp.push_tag ("strong");
-     xp.add_text (_(get_diagnostic_kind_text (diagnostic.kind)));
-     xp.pop_tag ("strong");
-     xp.add_text (" ");
-   }
- 
-   // Add the message itself:
-   html_token_printer tok_printer (*xp.get_insertion_point ());
-   m_printer->set_token_printer (&tok_printer);
-   pp_output_formatted_text (m_printer, m_context.get_urlifier ());
-   m_printer->set_token_printer (nullptr);
-   pp_clear_output_area (m_printer);
- 
-   // Add any metadata as a suffix to the message
-   if (diagnostic.metadata)
-     {
-       xp.add_text (" ");
-       xp.append (make_element_for_metadata (*diagnostic.metadata));
-     }
- 
-   // Add any option as a suffix to the message
- 
-   label_text option_text = label_text::take
-     (m_context.make_option_name (diagnostic.option_id,
- 				 orig_diag_kind, diagnostic.kind));
-   if (option_text.get ())
-     {
-       label_text option_url = label_text::take
- 	(m_context.make_option_url (diagnostic.option_id));
- 
-       xp.add_text (" ");
-       auto option_span = make_span ("gcc-option");
-       option_span->add_text ("[");
-       {
- 	if (option_url.get ())
- 	  {
- 	    auto anchor = std::make_unique<xml::element> ("a", true);
- 	    anchor->set_attr ("href", option_url.get ());
- 	    anchor->add_text (option_text.get ());
- 	    option_span->add_child (std::move (anchor));
- 	  }
- 	else
- 	  option_span->add_text (option_text.get ());
- 	option_span->add_text ("]");
-       }
-       xp.append (std::move (option_span));
-     }
- 
-   gcc_assert (xp.get_num_open_tags () == depth_within_message_div);
- 
-   xp.pop_tag ("div");
- 
-   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
- 
-   /* Show any logical location.  */
-   if (m_logical_loc_mgr)
-     if (auto client_data_hooks = m_context.get_client_data_hooks ())
-       if (auto logical_loc = client_data_hooks->get_current_logical_location ())
- 	if (logical_loc != m_last_logical_location)
- 	  {
- 	    enum logical_location_kind kind
- 	      = m_logical_loc_mgr->get_kind (logical_loc);;
- 	    if (const char *label = get_label_for_logical_location_kind (kind))
- 	      if (const char *name_with_scope
- 		  = m_logical_loc_mgr->get_name_with_scope (logical_loc))
- 		add_labelled_value (xp, "logical-location",
- 				    label, name_with_scope, true);
- 	    m_last_logical_location = logical_loc;
- 	  }
- 
-   /* Show any physical location.  */
-   const expanded_location s
-     = diagnostic_expand_location (&diagnostic);
-   if (s != m_last_expanded_location
-       || alert)
-     {
-       if (s.file
- 	  && (s.file != m_last_expanded_location.file
- 	      || alert))
- 	add_labelled_value (xp, "file", "File", s.file, false);
-       if (s.line)
- 	{
- 	  add_labelled_value (xp, "line", "Line", std::to_string (s.line), false);
- 	  diagnostic_column_policy column_policy (m_context);
- 	  int converted_column = column_policy.converted_column (s);
- 	  if (converted_column >= 0)
- 	    add_labelled_value (xp, "column", "Column",
- 				std::to_string (converted_column),
- 				false);
- 	}
-       if (s.file)
- 	m_last_expanded_location = s;
-     }
- 
-   /* Source (and fix-it hints).  */
-   {
-     // TODO: m_context.m_last_location should be moved into the sink
-     location_t saved = m_context.m_last_location;
-     m_context.m_last_location = m_last_location;
-     m_context.maybe_show_locus_as_html (*diagnostic.richloc,
- 					m_context.m_source_printing,
- 					diagnostic.kind,
- 					xp,
- 					nullptr,
- 					nullptr);
-     m_context.m_last_location = saved;
-     m_last_location = m_context.m_last_location;
-   }
- 
-   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
- 
-   /* Execution path.  */
-   if (auto path = diagnostic.richloc->get_path ())
-     {
-       xp.push_tag ("div");
-       xp.set_attr ("id", "execution-path");
- 
-       xp.push_tag ("label", true);
-       const int num_events = path->num_events ();
-       pretty_printer pp;
-       pp_printf_n (&pp, num_events,
- 		   "Execution path with %i event",
- 		   "Execution path with %i events",
- 		   num_events);
-       xp.add_text_from_pp (pp);
-       xp.pop_tag ("label");
- 
-       std::string event_id_prefix (diag_id + "-event-");
-       html_path_label_writer event_label_writer (xp, *this, *path,
- 						 event_id_prefix);
- 
-       diagnostic_source_print_policy dspp (m_context);
-       print_path_as_html (xp, *path, m_context, &event_label_writer,
- 			  dspp);
- 
-       xp.pop_tag ("div");
-     }
- 
-   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
- 
-   // Try to display any per-diagnostic graphs
-   if (diagnostic.metadata)
-     if (auto ldg = diagnostic.metadata->get_lazy_digraphs ())
-       {
- 	auto &digraphs = ldg->get_or_create_digraphs ();
- 	for (auto &dg : digraphs)
- 	  add_graph (*dg, *xp.get_insertion_point ());
-       }
- 
-   if (auto patch_element = make_element_for_patch (diagnostic))
-     {
-       xp.push_tag ("div");
-       xp.set_attr ("id", "suggested-fix");
-       xp.push_tag ("label", true);
-       xp.add_text ("Suggested fix");
-       xp.pop_tag ("label");
-       xp.append (std::move (patch_element));
-       xp.pop_tag ("div");
-     }
- 
-   return diag_element;
- }
- 
- std::unique_ptr<xml::element>
- html_builder::make_element_for_patch (const diagnostic_info &diagnostic)
- {
-   edit_context ec (m_context.get_file_cache ());
-   ec.add_fixits (diagnostic.richloc);
-   if (char *diff = ec.generate_diff (true))
-     {
-       if (strlen (diff) > 0)
- 	{
- 	  auto element = std::make_unique<xml::element> ("pre", true);
- 	  element->set_attr ("class", "gcc-generated-patch");
- 	  element->add_text (diff);
- 	  free (diff);
- 	  return element;
- 	}
-       else
- 	free (diff);
-     }
-   return nullptr;
- }
- 
- std::unique_ptr<xml::element>
- html_builder::make_metadata_element (label_text label,
- 				     label_text url)
- {
-   auto item = make_span ("gcc-metadata-item");
-   xml::printer xp (*item.get ());
-   xp.add_text ("[");
-   {
-     if (url.get ())
-       {
- 	xp.push_tag ("a", true);
- 	xp.set_attr ("href", url.get ());
-       }
-     xp.add_text (label.get ());
-     if (url.get ())
-       xp.pop_tag ("a");
-   }
-   xp.add_text ("]");
-   return item;
- }
- 
- std::unique_ptr<xml::element>
- html_builder::make_element_for_metadata (const diagnostic_metadata &metadata)
- {
-   auto span_metadata = make_span ("gcc-metadata");
- 
-   int cwe = metadata.get_cwe ();
-   if (cwe)
-     {
-       pretty_printer pp;
-       pp_printf (&pp, "CWE-%i", cwe);
-       label_text label = label_text::take (xstrdup (pp_formatted_text (&pp)));
-       label_text url = label_text::take (get_cwe_url (cwe));
-       span_metadata->add_child
- 	(make_metadata_element (std::move (label), std::move (url)));
-     }
- 
-   for (unsigned idx = 0; idx < metadata.get_num_rules (); ++idx)
-     {
-       auto &rule = metadata.get_rule (idx);
-       label_text label = label_text::take (rule.make_description ());
-       label_text url = label_text::take (rule.make_url ());
-       span_metadata->add_child
- 	(make_metadata_element (std::move (label), std::move (url)));
-     }
- 
-   return span_metadata;
- }
- 
- /* Implementation of diagnostic_context::m_diagrams.m_emission_cb
-    for HTML output.  */
- 
- void
- html_builder::emit_diagram (const diagnostic_diagram &/*diagram*/)
- {
-   /* We must be within the emission of a top-level diagnostic.  */
-   gcc_assert (m_cur_diagnostic_element);
- 
-   // TODO: currently a no-op
- }
- 
- void
- html_builder::add_graph (const diagnostics::digraphs::digraph &dg,
- 			 xml::element &parent_element)
- {
-   if (auto dot_graph = dg.make_dot_graph ())
-     if (auto svg_element = dot::make_svg_from_graph (*dot_graph))
-       {
- 	auto div = std::make_unique<xml::element> ("div", false);
- 	div->set_attr ("class", "gcc-directed-graph");
- 	xml::printer xp (*div);
- 	if (const char *description = dg.get_description ())
- 	  {
- 	    xp.push_tag ("h2", true);
- 	    xp.add_text (description);
- 	    xp.pop_tag ("h2");
- 	  }
- 	xp.append (std::move (svg_element));
- 	parent_element.add_child (std::move (div));
-       }
- }
- 
- void
- html_builder::emit_global_graph (const diagnostics::digraphs::lazy_digraph &ldg)
- {
-   auto &dg = ldg.get_or_create_digraph ();
-   gcc_assert (m_body_element);
-   add_graph (dg, *m_body_element);
- }
- 
- /* Implementation of "end_group_cb" for HTML output.  */
- 
- void
- html_builder::end_group ()
- {
-   if (m_cur_diagnostic_element)
-     m_diagnostics_element->add_child (std::move (m_cur_diagnostic_element));
- }
- 
- /* Create a top-level object, and add it to all the results
-    (and other entities) we've seen so far.
- 
-    Flush it all to OUTF.  */
- 
- void
- html_builder::flush_to_file (FILE *outf)
- {
-   if (m_html_gen_opts.m_javascript)
-     {
-       gcc_assert (m_head_element);
-       xml::printer xp (*m_head_element);
-       /* Add an initialization of the global js variable "focus_ids"
- 	 using the array of IDs we saved as we went.  */
-       xp.push_tag ("script");
-       pretty_printer pp;
-       pp_string (&pp, "focus_ids = ");
-       m_ui_focus_ids.print (&pp, true);
-       pp_string (&pp, ";\n");
-       xp.add_raw (pp_formatted_text (&pp));
-       xp.pop_tag ("script");
-     }
-   auto top = m_document.get ();
-   top->dump (outf);
-   fprintf (outf, "\n");
- }
- 
- class html_output_format : public diagnostic_output_format
- {
- public:
-   ~html_output_format ()
-   {
-     /* Any diagnostics should have been handled by now.
-        If not, then something's gone wrong with diagnostic
-        groupings.  */
-     std::unique_ptr<xml::element> pending_diag
-       = m_builder.take_current_diagnostic ();
-     gcc_assert (!pending_diag);
-   }
- 
-   void dump (FILE *out, int indent) const override
-   {
-     fprintf (out, "%*shtml_output_format\n", indent, "");
-     diagnostic_output_format::dump (out, indent);
-   }
- 
-   void
-   set_main_input_filename (const char *name) final override
-   {
-     m_builder.set_main_input_filename (name);
-   }
- 
-   std::unique_ptr<diagnostic_per_format_buffer>
-   make_per_format_buffer () final override
-   {
-     return std::make_unique<diagnostic_html_format_buffer> (m_builder);
-   }
-   void set_buffer (diagnostic_per_format_buffer *base_buffer) final override
-   {
-     diagnostic_html_format_buffer *buffer
-       = static_cast<diagnostic_html_format_buffer *> (base_buffer);
-     m_buffer = buffer;
-   }
- 
-   void on_begin_group () final override
-   {
-     /* No-op,  */
-   }
-   void on_end_group () final override
-   {
-     m_builder.end_group ();
-   }
-   void
-   on_report_diagnostic (const diagnostic_info &diagnostic,
- 			diagnostic_t orig_diag_kind) final override
-   {
-     m_builder.on_report_diagnostic (diagnostic, orig_diag_kind, m_buffer);
-   }
-   void on_diagram (const diagnostic_diagram &diagram) final override
-   {
-     m_builder.emit_diagram (diagram);
-   }
-   void after_diagnostic (const diagnostic_info &) final override
-   {
-     /* No-op, but perhaps could show paths here.  */
-   }
-   bool follows_reference_printer_p () const final override
-   {
-     return false;
-   }
-   void update_printer () final override
-   {
-     m_printer = m_context.clone_printer ();
- 
-     /* Don't colorize the text.  */
-     pp_show_color (m_printer.get ()) = false;
- 
-     /* No textual URLs.  */
-     m_printer->set_url_format (URL_FORMAT_NONE);
- 
-     /* Update the builder to use the new printer.  */
-     m_builder.set_printer (*get_printer ());
-   }
- 
-   void
-   report_global_digraph (const diagnostics::digraphs::lazy_digraph &ldg) final override
-   {
-     m_builder.emit_global_graph (ldg);
-   }
- 
-   const xml::document &get_document () const
-   {
-     return m_builder.get_document ();
-   }
- 
-   html_builder &get_builder () { return m_builder; }
- 
- protected:
-   html_output_format (diagnostic_context &context,
- 		      const line_maps *line_maps,
- 		      const html_generation_options &html_gen_opts)
-   : diagnostic_output_format (context),
-     m_builder (context, *get_printer (), line_maps, html_gen_opts),
-     m_buffer (nullptr)
-   {}
- 
-   html_builder m_builder;
-   diagnostic_html_format_buffer *m_buffer;
- };
- 
- class html_file_output_format : public html_output_format
- {
- public:
-   html_file_output_format (diagnostic_context &context,
- 			   const line_maps *line_maps,
- 			   const html_generation_options &html_gen_opts,
- 			   diagnostic_output_file output_file)
-   : html_output_format (context, line_maps, html_gen_opts),
-     m_output_file (std::move (output_file))
-   {
-     gcc_assert (m_output_file.get_open_file ());
-     gcc_assert (m_output_file.get_filename ());
-   }
-   ~html_file_output_format ()
-   {
-     m_builder.flush_to_file (m_output_file.get_open_file ());
-   }
-   void dump (FILE *out, int indent) const override
-   {
-     fprintf (out, "%*shtml_file_output_format: %s\n",
- 	     indent, "",
- 	     m_output_file.get_filename ());
-     diagnostic_output_format::dump (out, indent);
-   }
-   bool machine_readable_stderr_p () const final override
-   {
-     return false;
-   }
- 
- private:
-   diagnostic_output_file m_output_file;
- };
- 
- /* Attempt to open BASE_FILE_NAME.html for writing.
-    Return a non-null diagnostic_output_file,
-    or return a null diagnostic_output_file and complain to CONTEXT
-    using LINE_MAPS.  */
- 
- diagnostic_output_file
- diagnostic_output_format_open_html_file (diagnostic_context &context,
- 					 line_maps *line_maps,
- 					 const char *base_file_name)
- {
-   if (!base_file_name)
-     {
-       rich_location richloc (line_maps, UNKNOWN_LOCATION);
-       context.emit_diagnostic_with_group
- 	(DK_ERROR, richloc, nullptr, 0,
- 	 "unable to determine filename for HTML output");
-       return diagnostic_output_file ();
-     }
- 
-   label_text filename = label_text::take (concat (base_file_name,
- 						  ".html",
- 						  nullptr));
-   FILE *outf = fopen (filename.get (), "w");
-   if (!outf)
-     {
-       rich_location richloc (line_maps, UNKNOWN_LOCATION);
-       context.emit_diagnostic_with_group
- 	(DK_ERROR, richloc, nullptr, 0,
- 	 "unable to open %qs for HTML output: %m",
- 	 filename.get ());
-       return diagnostic_output_file ();
-     }
-   return diagnostic_output_file (outf, true, std::move (filename));
- }
- 
- std::unique_ptr<diagnostic_output_format>
- make_html_sink (diagnostic_context &context,
- 		const line_maps &line_maps,
- 		const html_generation_options &html_gen_opts,
- 		diagnostic_output_file output_file)
- {
-   auto sink
-     = std::make_unique<html_file_output_format> (context,
- 						 &line_maps,
- 						 html_gen_opts,
- 						 std::move (output_file));
-   sink->update_printer ();
-   return sink;
- }
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* Helper for writing tests of html_token_printer.
-    Printing to m_pp will appear as HTML within m_top_element, a <div>.  */
- 
- struct token_printer_test
- {
-   token_printer_test ()
-   : m_top_element ("div", true),
-     m_tok_printer (m_top_element)
-   {
-     m_pp.set_token_printer (&m_tok_printer);
-   }
- 
-   xml::element m_top_element;
-   html_token_printer m_tok_printer;
-   pretty_printer m_pp;
- };
- 
- static void
- test_token_printer ()
- {
-   {
-     token_printer_test t;
-     pp_printf (&t.m_pp, "hello world");
-     ASSERT_XML_PRINT_EQ
-       (t.m_top_element,
-        "<div>hello world</div>\n");
-   }
- 
-   {
-     token_printer_test t;
-     pp_printf (&t.m_pp, "%qs: %qs", "foo", "bar");
-     ASSERT_XML_PRINT_EQ
-       (t.m_top_element,
-        "<div>"
-        "`"
-        "<span class=\"gcc-quoted-text\">"
-        "foo"
-        "</span>"
-        "&apos;: `"
-        "<span class=\"gcc-quoted-text\">"
-        "bar"
-        "</span>"
-        "&apos;"
-        "</div>\n");
-   }
- 
-   {
-     token_printer_test t;
-     diagnostic_event_id_t event_id (0);
-     pp_printf (&t.m_pp, "foo %@ bar", &event_id);
-     ASSERT_XML_PRINT_EQ
-       (t.m_top_element,
-        "<div>foo (1) bar</div>\n");
-   }
- }
- 
- /* A subclass of html_output_format for writing selftests.
-    The XML output is cached internally, rather than written
-    out to a file.  */
- 
- class test_html_diagnostic_context : public test_diagnostic_context
- {
- public:
-   test_html_diagnostic_context ()
-   {
-     html_generation_options html_gen_opts;
-     html_gen_opts.m_css = false;
-     html_gen_opts.m_javascript = false;
-     auto sink = std::make_unique<html_buffered_output_format> (*this,
- 							       line_table,
- 							       html_gen_opts);
-     sink->update_printer ();
-     sink->set_main_input_filename ("(main input filename)");
-     m_format = sink.get (); // borrowed
- 
-     set_output_format (std::move (sink));
-   }
- 
-   const xml::document &get_document () const
-   {
-     return m_format->get_document ();
-   }
- 
-   html_builder &get_builder () const
-   {
-     return m_format->get_builder ();
-   }
- 
- private:
-   class html_buffered_output_format : public html_output_format
-   {
-   public:
-     html_buffered_output_format (diagnostic_context &context,
- 				 const line_maps *line_maps,
- 				 const html_generation_options &html_gen_opts)
-     : html_output_format (context, line_maps, html_gen_opts)
-     {
-     }
-     bool machine_readable_stderr_p () const final override
-     {
-       return true;
-     }
-   };
- 
-   html_output_format *m_format; // borrowed
- };
- 
- /* Test of reporting a diagnostic at UNKNOWN_LOCATION to a
-    diagnostic_context and examining the generated XML document.
-    Verify various basic properties. */
- 
- static void
- test_simple_log ()
- {
-   test_html_diagnostic_context dc;
- 
-   rich_location richloc (line_table, UNKNOWN_LOCATION);
-   dc.report (DK_ERROR, richloc, nullptr, 0, "this is a test: %qs", "foo");
- 
-   const xml::document &doc  = dc.get_document ();
- 
-   ASSERT_XML_PRINT_EQ
-     (doc,
-      ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-       "<!DOCTYPE html\n"
-       "     PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
-       "     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
-       "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
-       "  <head>\n"
-       "    <title>(main input filename)</title>\n"
-       "  </head>\n"
-       "  <body>\n"
-       "    <div class=\"gcc-diagnostic-list\">\n"
-       "      <div class=\"alert alert-danger\" id=\"gcc-diag-0\">\n"
-       "        <span class=\"pficon pficon-error-circle-o\"> </span>\n"
-       "        <div class=\"gcc-message\" id=\"gcc-diag-0-message\"><strong>error: </strong> this is a test: `<span class=\"gcc-quoted-text\">foo</span>&apos;</div>\n"
-       "      </div>\n"
-       "    </div>\n"
-       "  </body>\n"
-       "</html>\n"));
- }
- 
- static void
- test_metadata ()
- {
-   test_html_diagnostic_context dc;
-   html_builder &b = dc.get_builder ();
- 
-   {
-     diagnostic_metadata metadata;
-     metadata.add_cwe (415);
-     auto element = b.make_element_for_metadata (metadata);
-     ASSERT_XML_PRINT_EQ
-       (*element,
-        "<span class=\"gcc-metadata\">"
-        "<span class=\"gcc-metadata-item\">"
-        "["
-        "<a href=\"https://cwe.mitre.org/data/definitions/415.html\">"
-        "CWE-415"
-        "</a>"
-        "]"
-        "</span>"
-        "</span>\n");
-   }
- 
-   {
-     diagnostic_metadata metadata;
-     diagnostic_metadata::precanned_rule rule ("MISC-42",
- 					      "http://example.com");
-     metadata.add_rule (rule);
-     auto element = b.make_element_for_metadata (metadata);
-     ASSERT_XML_PRINT_EQ
-       (*element,
-        "<span class=\"gcc-metadata\">"
-        "<span class=\"gcc-metadata-item\">"
-        "["
-        "<a href=\"http://example.com\">"
-        "MISC-42"
-        "</a>"
-        "]"
-        "</span>"
-        "</span>\n");
-   }
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- diagnostic_format_html_cc_tests ()
- {
-   auto_fix_quotes fix_quotes;
-   test_token_printer ();
-   test_simple_log ();
-   test_metadata ();
- }
- 
- } // namespace selftest
- 
- #endif /* CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-format-html.h gcc-16-20250727/gcc/diagnostic-format-html.h
*** gcc-16-20250720/gcc/diagnostic-format-html.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-format-html.h	Thu Jan  1 00:00:00 1970
***************
*** 1,64 ****
- /* HTML output for diagnostics.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_FORMAT_HTML_H
- #define GCC_DIAGNOSTIC_FORMAT_HTML_H
- 
- #include "diagnostic-format.h"
- #include "diagnostic-output-file.h"
- 
- struct html_generation_options
- {
-   html_generation_options ();
- 
-   bool m_css;
-   bool m_javascript;
- 
-   // Debugging options:
- 
-   // If true, attempt to show state diagrams at events
-   bool m_show_state_diagrams;
- 
-   // If true, show the SARIF form of the state with such diagrams
-   bool m_show_state_diagrams_sarif;
- 
-   // If true, show the .dot source used for the diagram
-   bool m_show_state_diagrams_dot_src;
- };
- 
- extern diagnostic_output_file
- diagnostic_output_format_open_html_file (diagnostic_context &context,
- 					 line_maps *line_maps,
- 					 const char *base_file_name);
- 
- extern std::unique_ptr<diagnostic_output_format>
- make_html_sink (diagnostic_context &context,
- 		const line_maps &line_maps,
- 		const html_generation_options &html_gen_opts,
- 		diagnostic_output_file output_file);
- 
- extern void
- print_path_as_html (xml::printer &xp,
- 		    const diagnostic_path &path,
- 		    diagnostic_context &dc,
- 		    html_label_writer *event_label_writer,
- 		    const diagnostic_source_print_policy &dspp);
- 
- #endif /* ! GCC_DIAGNOSTIC_FORMAT_HTML_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-format-sarif.cc gcc-16-20250727/gcc/diagnostic-format-sarif.cc
*** gcc-16-20250720/gcc/diagnostic-format-sarif.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-format-sarif.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,5063 ****
- /* SARIF output for diagnostics
-    Copyright (C) 2018-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- 
- #include "config.h"
- #define INCLUDE_LIST
- #define INCLUDE_MAP
- #define INCLUDE_STRING
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "diagnostic.h"
- #include "diagnostic-metadata.h"
- #include "diagnostic-digraphs.h"
- #include "diagnostic-state-graphs.h"
- #include "diagnostic-path.h"
- #include "diagnostic-format.h"
- #include "diagnostic-buffer.h"
- #include "json.h"
- #include "cpplib.h"
- #include "logical-location.h"
- #include "diagnostic-client-data-hooks.h"
- #include "diagnostic-diagram.h"
- #include "text-art/canvas.h"
- #include "diagnostic-format-sarif.h"
- #include "diagnostic-format-text.h"
- #include "ordered-hash-map.h"
- #include "sbitmap.h"
- #include "selftest.h"
- #include "selftest-diagnostic.h"
- #include "selftest-diagnostic-show-locus.h"
- #include "selftest-json.h"
- #include "text-range-label.h"
- #include "pretty-print-format-impl.h"
- #include "pretty-print-urlifier.h"
- #include "demangle.h"
- #include "backtrace.h"
- #include "xml.h"
- 
- /* A json::array where the values are "unique" as per
-    SARIF v2.1.0 section 3.7.3 ("Array properties with unique values").  */
- 
- template <typename JsonElementType>
- class sarif_array_of_unique : public json::array
- {
-  public:
-   size_t append_uniquely (std::unique_ptr<JsonElementType> val)
-   {
-     /* This should be O(log(n)) due to the std::map.  */
-     auto search = m_index_by_value.find (val.get ());
-     if (search != m_index_by_value.end())
-       return (*search).second;
- 
-     const size_t insertion_idx = size ();
-     m_index_by_value.insert ({val.get (), insertion_idx});
-     append (std::move (val));
-     return insertion_idx;
-   }
- 
-   /* For ease of reading output, add "index": idx to all
-      objects in the array.
-      We don't do this until we've added everything, since
-      the "index" property would otherwise confuse the
-      comparison against new elements.  */
-   void add_explicit_index_values ()
-   {
-     for (size_t idx = 0; idx < length (); ++idx)
-       if (json::object *obj = get (idx)->dyn_cast_object ())
- 	obj->set_integer ("index", idx);
-   }
- 
- private:
-   struct comparator_t {
-     bool operator () (const json::value *a, const json::value *b) const
-     {
-       gcc_assert (a);
-       gcc_assert (b);
-       return json::value::compare (*a, *b) < 0;
-     }
-   };
- 
-   // json::value * here is borrowed from m_elements
-   std::map<json::value *, int, comparator_t> m_index_by_value;
- };
- 
- /* Forward decls.  */
- class sarif_builder;
- class content_renderer;
-   class escape_nonascii_renderer;
- 
- /* Subclasses of sarif_object.
-    Keep these in order of their descriptions in the specification.  */
- class sarif_artifact_content; // 3.3
- class sarif_artifact_location; // 3.4
- class sarif_message; // 3.11
- class sarif_multiformat_message_string; // 3.12
- class sarif_log; // 3.13
- class sarif_run; // 3.14
- class sarif_tool; // 3.18
- class sarif_tool_component; // 3.19
- class sarif_invocation; // 3.20
- class sarif_artifact; // 3.24
- class sarif_location_manager; // not in the spec
- class sarif_result; // 3.27
- class sarif_location; // 3.28
- class sarif_physical_location; // 3.29
- class sarif_region; // 3.30
- class sarif_logical_location; // 3.33
- class sarif_location_relationship; // 3.34
- class sarif_code_flow; // 3.36
- class sarif_thread_flow; // 3.37
- class sarif_thread_flow_location; // 3.38
- class sarif_reporting_descriptor; // 3.49
- class sarif_reporting_descriptor_reference; // 3.53
- class sarif_tool_component_reference; // 3.54
- class sarif_fix; // 3.55
- class sarif_artifact_change; // 3.56
- class sarif_replacement; // 3.57
- class sarif_ice_notification; // 3.58
- 
- // Valid values for locationRelationship's "kinds" property (3.34.3)
- 
- enum class location_relationship_kind
- {
-   includes,
-   is_included_by,
-   relevant,
- 
-   NUM_KINDS
- };
- 
- /* Declarations of subclasses of sarif_object.
-    Keep these in order of their descriptions in the specification.  */
- 
- /* Subclass of sarif_object for SARIF "artifactContent" objects
-    (SARIF v2.1.0 section 3.3).  */
- 
- class sarif_artifact_content : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "artifactLocation" objects
-    (SARIF v2.1.0 section 3.4).  */
- 
- class sarif_artifact_location : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "message" objects
-    (SARIF v2.1.0 section 3.11).  */
- 
- class sarif_message : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "multiformatMessageString" objects
-    (SARIF v2.1.0 section 3.12).  */
- 
- class sarif_multiformat_message_string : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "log" objects
-    (SARIF v2.1.0 section 3.13).  */
- 
- class sarif_log : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "run" objects
-    (SARIF v2.1.0 section 3.14).  */
- 
- class sarif_run : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "tool" objects
-    (SARIF v2.1.0 section 3.18).  */
- 
- class sarif_tool : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "toolComponent" objects
-    (SARIF v2.1.0 section 3.19).  */
- 
- class sarif_tool_component : public sarif_object {};
- 
- /* Make a JSON string for the current date and time.
-    See SARIF v2.1.0 section 3.9 "Date/time properties".
-    Given that we don't run at the very beginning/end of the
-    process, it doesn't make sense to be more accurate than
-    the current second.  */
- 
- static std::unique_ptr<json::string>
- make_date_time_string_for_current_time ()
- {
-   time_t t = time (nullptr);
-   struct tm *tm = gmtime (&t);
-   char buf[256];
-   snprintf (buf, sizeof (buf) - 1,
- 	    ("%04i-%02i-%02iT"
- 	     "%02i:%02i:%02iZ"),
- 	    tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- 	    tm->tm_hour, tm->tm_min, tm->tm_sec);
-   return std::make_unique<json::string> (buf);
- }
- 
- /* Subclass of sarif_object for SARIF "invocation" objects
-    (SARIF v2.1.0 section 3.20).  */
- 
- class sarif_invocation : public sarif_object
- {
- public:
-   sarif_invocation (sarif_builder &builder,
- 		    const char * const *original_argv);
- 
-   void add_notification_for_ice (const diagnostic_info &diagnostic,
- 				 sarif_builder &builder,
- 				 std::unique_ptr<json::object> backtrace);
-   void prepare_to_flush (sarif_builder &builder);
- 
- private:
-   std::unique_ptr<json::array> m_notifications_arr;
-   bool m_success;
- };
- 
- /* Corresponds to values for the SARIF artifact objects "roles" property.
-    (SARIF v2.1.0 section 3.24.6).  */
- 
- enum class diagnostic_artifact_role
- {
-   analysis_target, /* "analysisTarget".  */
-   debug_output_file, /* "debugOutputFile".  */
-   result_file, /* "resultFile".  */
- 
-   /* "scannedFile" added in 2.2;
-      see https://github.com/oasis-tcs/sarif-spec/issues/459 */
-   scanned_file,
- 
-   traced_file, /* "tracedFile".  */
- 
-   NUM_ROLES
- };
- 
- /* Subclass of sarif_object for SARIF artifact objects
-    (SARIF v2.1.0 section 3.24).  */
- 
- class sarif_artifact : public sarif_object
- {
- public:
-   sarif_artifact (const char *filename)
-   : m_filename (filename),
-     m_roles ((unsigned)diagnostic_artifact_role::NUM_ROLES),
-     m_embed_contents (false)
-   {
-     bitmap_clear (m_roles);
-   }
- 
-   void add_role (enum diagnostic_artifact_role role,
- 		 bool embed_contents);
- 
-   bool embed_contents_p () const { return m_embed_contents; }
-   void populate_contents (sarif_builder &builder);
-   void populate_roles ();
- 
- private:
-   const char *m_filename;
-   auto_sbitmap m_roles;
- 
-   /* Flag to track whether this artifact should have a "contents" property
-      (SARIF v2.1.0 section 3.24.8).
-      We only add the contents for those artifacts that have a location
-      referencing them (so that a consumer might want to quote the source).   */
-   bool m_embed_contents;
- };
- 
- /* A class for sarif_objects that own a "namespace" of numeric IDs for
-    managing location objects within them.  Currently (SARIF v2.1.0)
-    this is just for sarif_result (section 3.28.2), but it will likely
-    eventually also be for notification objects; see
-    https://github.com/oasis-tcs/sarif-spec/issues/540
- 
-    Consider locations with chains of include information e.g.
- 
-    > include-chain-1.c:
-    >   #include "include-chain-1.h"
- 
-    include-chain-1.h:
-      | // First set of decls, which will be referenced in notes
-      | #include "include-chain-1-1.h"
-      |
-      | // Second set of decls, which will trigger the errors
-      | #include "include-chain-1-2.h"
- 
-    include-chain-1-1.h:
-      | int p;
-      | int q;
- 
-    include-chain-1-1.h:
-      | char p;
-      | char q;
- 
-    GCC's textual output emits:
-      |   In file included from PATH/include-chain-1.h:5,
-      |                    from PATH/include-chain-1.c:30:
-      |   PATH/include-chain-1-2.h:1:6: error: conflicting types for 'p'; have 'char'
-      |       1 | char p;
-      |         |      ^
-      |   In file included from PATH/include-chain-1.h:2:
-      |   PATH/include-chain-1-1.h:1:5: note: previous declaration of 'p' with type 'int'
-      |       1 | int p;
-      |         |     ^
-      |   PATH/include-chain-1-2.h:2:6: error: conflicting types for 'q'; have 'char'
-      |       2 | char q;
-      |         |      ^
-      |   PATH/include-chain-1-1.h:2:5: note: previous declaration of 'q' with type 'int'
-      |       2 | int q;
-      |         |     ^
- 
-    Whenever a SARIF location is added for a location_t that
-    was #included from somewhere, we queue up the creation of a SARIF
-    location for the location of the #include.  The worklist of queued
-    locations is flushed when the result is finished, which lazily creates
-    any additional related locations for the include chain, and the
-    relationships between the locations.  Doing so can lead to further
-    include locations being processed.  The worklist approach allows us
-    to lazily explore the relevant part of the directed graph of location_t
-    values implicit in our line_maps structure, replicating it as a directed
-    graph of SARIF locations within the SARIF result object, like this:
- 
-    [0]: error in include-chain-1-2.h ("conflicting types for 'p'; have 'char'")
-    [1]: #include "include-chain-1-2.h" in include-chain-1.h
-    [2]: note in include-chain-1-2.h ("previous declaration of 'p' with type 'int'")
-    [3]: #include "include-chain-1-1.h" in include-chain-1.h
-    [4]: #include "include-chain-1.h" in include-chain-1.c
- 
-    where we want to capture this "includes" graph in SARIF form:
-    . +-----------------------------------+ +----------------------------------+
-    . |"id": 0                            | |"id": 2                           |
-    . | error: "conflicting types for 'p';| | note: previous declaration of 'p'|
-    . |  have 'char'"|                    | | with type 'int'")                |
-    . | in include-chain-1-2.h            | | in include-chain-1-1.h           |
-    . +-----------------------------------+ +----------------------------------+
-    .            ^         |                            ^         |
-    .   includes |         | included-by       includes |         | included-by
-    .            |         V                            |         V
-    .  +--------------------------------+    +--------------------------------+
-    .  |"id": 1                         |    |"id": 3                         |
-    .  | #include "include-chain-1-2.h" |    | #include "include-chain-1-1.h" |
-    .  | in include-chain-1.h           |    | in include-chain-1.h           |
-    .  +--------------------------------+    +--------------------------------+
-    .                   ^     |                       ^    |
-    .          includes |     | included-by  includes |    | included-by
-    .                   |     V                       |    V
-    .                  +------------------------------------+
-    .                  |"id": 4                             |
-    .                  | The  #include "include-chain-1.h"  |
-    .                  | in include-chain-1.c               |
-    .                  +------------------------------------+
-  */
- 
- class sarif_location_manager : public sarif_object
- {
- public:
-   /* A worklist of pending actions needed to fully process this object.
- 
-      This lets us lazily walk our data structures to build the
-      directed graph of locations, whilst keeping "notes" at the top
-      of the "relatedLocations" array, and avoiding the need for
-      recursion.  */
-   struct worklist_item
-   {
-     enum class kind
-     {
-      /* Process a #include relationship where m_location_obj
- 	was #included-d at m_where.  */
-      included_from,
- 
-      /* Process a location_t that was added as a secondary location
- 	to a rich_location without a label.  */
-      unlabelled_secondary_location
-     };
- 
-     worklist_item (sarif_location &location_obj,
- 		   enum kind kind,
- 		   location_t where)
-       : m_location_obj (location_obj),
- 	m_kind (kind),
- 	m_where (where)
-     {
-     }
- 
-     sarif_location &m_location_obj;
-     enum kind m_kind;
-     location_t m_where;
-   };
- 
-   sarif_location_manager ()
-   : m_related_locations_arr (nullptr),
-     m_next_location_id (0)
-   {
-   }
- 
-   unsigned allocate_location_id ()
-   {
-     return m_next_location_id++;
-   }
- 
-   virtual void
-   add_related_location (std::unique_ptr<sarif_location> location_obj,
- 			sarif_builder &builder);
- 
-   void
-   add_relationship_to_worklist (sarif_location &location_obj,
- 				enum worklist_item::kind kind,
- 				location_t where);
- 
-   void
-   process_worklist (sarif_builder &builder);
- 
-   void
-   process_worklist_item (sarif_builder &builder,
- 			 const worklist_item &item);
- private:
-   json::array *m_related_locations_arr; // borrowed
-   unsigned m_next_location_id;
- 
-   std::list<worklist_item> m_worklist;
-   std::map<location_t, sarif_location *> m_included_from_locations;
-   std::map<location_t, sarif_location *> m_unlabelled_secondary_locations;
- };
- 
- /* Subclass of sarif_object for SARIF "result" objects
-    (SARIF v2.1.0 section 3.27).
-    Each SARIF result object has its own "namespace" of numeric IDs for
-    managing location objects (SARIF v2.1.0 section 3.28.2). */
- 
- class sarif_result : public sarif_location_manager
- {
- public:
-   sarif_result (unsigned idx_within_parent)
-   : m_idx_within_parent (idx_within_parent)
-   {}
- 
-   unsigned get_index_within_parent () const { return m_idx_within_parent; }
- 
-   void
-   on_nested_diagnostic (const diagnostic_info &diagnostic,
- 			diagnostic_t orig_diag_kind,
- 			sarif_builder &builder);
-   void on_diagram (const diagnostic_diagram &diagram,
- 		   sarif_builder &builder);
- 
- private:
-   const unsigned m_idx_within_parent;
- };
- 
- /* Subclass of sarif_object for SARIF "location" objects
-    (SARIF v2.1.0 section 3.28).
-    A location object can have an "id" which must be unique within
-    the enclosing result, if any (see SARIF v2.1.0 section 3.28.2).  */
- 
- class sarif_location : public sarif_object
- {
- public:
-   long lazily_add_id (sarif_location_manager &loc_mgr);
-   long get_id () const;
- 
-   void lazily_add_relationship (sarif_location &target,
- 				enum location_relationship_kind kind,
- 				sarif_location_manager &loc_mgr);
- 
- private:
-   sarif_location_relationship &
-   lazily_add_relationship_object (sarif_location &target,
- 				  sarif_location_manager &loc_mgr);
- 
-   json::array &lazily_add_relationships_array ();
- 
-   std::map<sarif_location *,
- 	   sarif_location_relationship *> m_relationships_map;
- };
- 
- /* Subclass of sarif_object for SARIF "physicalLocation" objects
-    (SARIF v2.1.0 section 3.29).  */
- 
- class sarif_physical_location : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "region" objects
-    (SARIF v2.1.0 section 3.30).  */
- 
- class sarif_region : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "logicalLocation" objects
-    (SARIF v2.1.0 section 3.33).  */
- 
- class sarif_logical_location : public sarif_object
- {
- };
- 
- /* Subclass of sarif_object for SARIF "locationRelationship" objects
-    (SARIF v2.1.0 section 3.34).  */
- 
- class sarif_location_relationship : public sarif_object
- {
- public:
-   sarif_location_relationship (sarif_location &target,
- 			       sarif_location_manager &loc_mgr);
- 
-   long get_target_id () const;
- 
-   void lazily_add_kind (enum location_relationship_kind kind);
- 
- private:
-   auto_sbitmap m_kinds;
- };
- 
- /* Subclass of sarif_object for SARIF "codeFlow" objects
-    (SARIF v2.1.0 section 3.36).  */
- 
- class sarif_code_flow : public sarif_object
- {
- public:
-   sarif_code_flow (sarif_result &parent,
- 		   unsigned idx_within_parent);
- 
-   sarif_result &get_parent () const { return m_parent; }
-   unsigned get_index_within_parent () const { return m_idx_within_parent; }
- 
-   sarif_thread_flow &
-   get_or_append_thread_flow (const diagnostic_thread &thread,
- 			     diagnostic_thread_id_t thread_id);
- 
-   sarif_thread_flow &
-   get_thread_flow (diagnostic_thread_id_t thread_id);
- 
-   void add_location (sarif_thread_flow_location &);
- 
-   sarif_thread_flow_location &
-   get_thread_flow_loc_obj (diagnostic_event_id_t event_id) const;
- 
- private:
-   sarif_result &m_parent;
-   const unsigned m_idx_within_parent;
- 
-   hash_map<int_hash<diagnostic_thread_id_t, -1, -2>,
- 	   sarif_thread_flow *> m_thread_id_map; // borrowed ptr
-   json::array *m_thread_flows_arr; // borrowed
- 
-   /* Vec of borrowed ptr, allowing for going easily from
-      an event_id to the corresponding threadFlowLocation object.  */
-   std::vector<sarif_thread_flow_location *> m_all_tfl_objs;
- };
- 
- /* Subclass of sarif_object for SARIF "threadFlow" objects
-    (SARIF v2.1.0 section 3.37).  */
- 
- class sarif_thread_flow : public sarif_object
- {
- public:
-   sarif_thread_flow (sarif_code_flow &parent,
- 		     const diagnostic_thread &thread,
- 		     unsigned idx_within_parent);
- 
-   sarif_code_flow &get_parent () const { return m_parent; }
-   unsigned get_index_within_parent () const { return m_idx_within_parent; }
- 
-   sarif_thread_flow_location &add_location ();
- 
- private:
-   sarif_code_flow &m_parent;
-   json::array *m_locations_arr; // borrowed
-   const unsigned m_idx_within_parent;
- };
- 
- /* Subclass of sarif_object for SARIF "threadFlowLocation" objects
-    (SARIF v2.1.0 section 3.38).  */
- 
- class sarif_thread_flow_location : public sarif_object
- {
- public:
-   sarif_thread_flow_location (sarif_thread_flow &parent,
- 			      unsigned idx_within_parent)
-   : m_parent (parent),
-     m_idx_within_parent (idx_within_parent)
-   {
-   }
- 
-   sarif_thread_flow &get_parent () const { return m_parent; }
-   unsigned get_index_within_parent () const { return m_idx_within_parent; }
- 
- private:
-   sarif_thread_flow &m_parent;
-   const unsigned m_idx_within_parent;
- };
- 
- /* Subclass of sarif_object for SARIF "reportingDescriptor" objects
-    (SARIF v2.1.0 section 3.49).  */
- 
- class sarif_reporting_descriptor : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "reportingDescriptorReference" objects
-    (SARIF v2.1.0 section 3.53).  */
- 
- class sarif_reporting_descriptor_reference : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "toolComponentReference" objects
-    (SARIF v2.1.0 section 3.54).  */
- 
- class sarif_tool_component_reference : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "fix" objects
-    (SARIF v2.1.0 section 3.55).  */
- 
- class sarif_fix : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "artifactChange" objects
-    (SARIF v2.1.0 section 3.56).  */
- 
- class sarif_artifact_change : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "replacement" objects
-    (SARIF v2.1.0 section 3.57).  */
- 
- class sarif_replacement : public sarif_object {};
- 
- /* Subclass of sarif_object for SARIF "notification" objects
-    (SARIF v2.1.0 section 3.58).
- 
-    This subclass is specifically for notifying when an
-    internal compiler error occurs.  */
- 
- class sarif_ice_notification : public sarif_location_manager
- {
- public:
-   sarif_ice_notification (const diagnostic_info &diagnostic,
- 			  sarif_builder &builder,
- 			  std::unique_ptr<json::object> backtrace);
- 
-   void
-   add_related_location (std::unique_ptr<sarif_location> location_obj,
- 			sarif_builder &builder) final override;
- };
- 
- /* Abstract base class for use when making an  "artifactContent"
-    object (SARIF v2.1.0 section 3.3): generate a value for the
-    3.3.4 "rendered" property.
-    Can return nullptr, for "no property".  */
- 
- class content_renderer
- {
- public:
-   virtual ~content_renderer () {}
- 
-   virtual std::unique_ptr<sarif_multiformat_message_string>
-   render (const sarif_builder &builder) const = 0;
- };
- 
- /* Concrete buffering implementation subclass for JSON output.  */
- 
- class diagnostic_sarif_format_buffer : public diagnostic_per_format_buffer
- {
- public:
-   friend class sarif_output_format;
- 
-   diagnostic_sarif_format_buffer (sarif_builder &builder)
-   : m_builder (builder)
-   {}
- 
-   void dump (FILE *out, int indent) const final override;
-   bool empty_p () const final override;
-   void move_to (diagnostic_per_format_buffer &dest) final override;
-   void clear () final override;
-   void flush () final override;
- 
-   void add_result (std::unique_ptr<sarif_result> result)
-   {
-     m_results.push_back (std::move (result));
-   }
- 
-   size_t num_results () const { return m_results.size (); }
-   sarif_result &get_result (size_t idx) { return *m_results[idx]; }
- 
- private:
-   sarif_builder &m_builder;
-   std::vector<std::unique_ptr<sarif_result>> m_results;
- };
- 
- /* Classes for abstracting away JSON vs other serialization formats.  */
- 
- // class sarif_serialization_format_json : public sarif_serialization_format
- 
- void
- sarif_serialization_format_json::write_to_file (FILE *outf,
- 						const json::value &top)
- {
-   top.dump (outf, m_formatted);
-   fprintf (outf, "\n");
- }
- 
- /* A class for managing SARIF output (for -fdiagnostics-format=sarif-stderr
-    and -fdiagnostics-format=sarif-file).
- 
-    As diagnostics occur, we build "result" JSON objects, and
-    accumulate state:
-    - which source files are referenced
-    - which warnings are emitted
-    - which CWEs are used
- 
-    At the end of the compile, we use the above to build the full SARIF
-    object tree, adding the result objects to the correct place, and
-    creating objects for the various source files, warnings and CWEs
-    referenced.
- 
-    Implemented:
-    - fix-it hints
-    - CWE metadata
-    - diagnostic groups (see limitations below)
-    - logical locations (e.g. cfun)
-    - labelled ranges (as annotations)
-    - secondary ranges without labels (as related locations)
- 
-    Known limitations:
-    - GCC supports nesting of diagnostics (one-deep nesting via
-      auto_diagnostic_group, and arbitrary nesting via
-      auto_diagnostic_nesting_level).  These are captured in the SARIF
-      as related locations, and so we only capture location and message
-      information from such nested diagnostics (e.g. we ignore fix-it
-      hints on them).  Diagnostics within an auto_diagnostic_nesting_level
-      have their nesting level captured as a property.
-    - although we capture command-line arguments (section 3.20.2), we don't
-      yet capture response files.
-    - doesn't capture "artifact.encoding" property
-      (SARIF v2.1.0 section 3.24.9).
-    - doesn't capture hashes of the source files
-      ("artifact.hashes" property (SARIF v2.1.0 section 3.24.11).
-    - doesn't capture the "analysisTarget" property
-      (SARIF v2.1.0 section 3.27.13).
-    - doesn't capture -Werror cleanly
-    - doesn't capture inlining information (can SARIF handle this?)
-    - doesn't capture macro expansion information (can SARIF handle this?).
-    - doesn't capture any diagnostic_metadata::rules associated with
-      a diagnostic.  */
- 
- class sarif_builder
- {
- public:
-   friend class diagnostic_sarif_format_buffer;
- 
-   sarif_builder (diagnostic_context &context,
- 		 pretty_printer &printer,
- 		 const line_maps *line_maps,
- 		 std::unique_ptr<sarif_serialization_format> serialization_format,
- 		 const sarif_generation_options &sarif_gen_opts);
-   ~sarif_builder ();
- 
-   void set_printer (pretty_printer &printer)
-   {
-     m_printer = &printer;
-   }
- 
-   const logical_location_manager *
-   get_logical_location_manager () const
-   {
-     return m_logical_loc_mgr;
-   }
- 
-   void
-   set_main_input_filename (const char *name);
- 
-   void on_report_diagnostic (const diagnostic_info &diagnostic,
- 			     diagnostic_t orig_diag_kind,
- 			     diagnostic_sarif_format_buffer *buffer);
-   void emit_diagram (const diagnostic_diagram &diagram);
-   void end_group ();
- 
-   void
-   report_global_digraph (const diagnostics::digraphs::lazy_digraph &);
- 
-   std::unique_ptr<sarif_result> take_current_result ()
-   {
-     return std::move (m_cur_group_result);
-   }
- 
-   std::unique_ptr<sarif_log> flush_to_object ();
-   void flush_to_file (FILE *outf);
- 
-   std::unique_ptr<json::array>
-   make_locations_arr (sarif_location_manager &loc_mgr,
- 		      const diagnostic_info &diagnostic,
- 		      enum diagnostic_artifact_role role);
-   std::unique_ptr<sarif_location>
-   make_location_object (sarif_location_manager *loc_mgr,
- 			const rich_location &rich_loc,
- 			logical_location logical_loc,
- 			enum diagnostic_artifact_role role);
-   std::unique_ptr<sarif_location>
-   make_location_object (sarif_location_manager &loc_mgr,
- 			location_t where,
- 			enum diagnostic_artifact_role role);
-   std::unique_ptr<sarif_message>
-   make_message_object (const char *msg) const;
-   std::unique_ptr<sarif_message>
-   make_message_object_for_diagram (const diagnostic_diagram &diagram);
-   std::unique_ptr<sarif_artifact_content>
-   maybe_make_artifact_content_object (const char *filename) const;
- 
-   std::unique_ptr<sarif_artifact_location>
-   make_artifact_location_object (const char *filename);
- 
-   const sarif_code_flow *
-   get_code_flow_for_event_ids () const
-   {
-     return m_current_code_flow;
-   }
- 
-   diagnostic_context &get_context () const { return m_context; }
-   pretty_printer *get_printer () const { return m_printer; }
-   token_printer &get_token_printer () { return m_token_printer; }
-   enum sarif_version get_version () const { return m_sarif_gen_opts.m_version; }
- 
-   size_t num_results () const { return m_results_array->size (); }
-   sarif_result &get_result (size_t idx)
-   {
-     auto element = (*m_results_array)[idx];
-     gcc_assert (element);
-     return *static_cast<sarif_result *> (element);
-   }
- 
-   const sarif_generation_options &get_opts () const { return m_sarif_gen_opts; }
- 
-   std::unique_ptr<sarif_logical_location>
-   make_minimal_sarif_logical_location (logical_location);
- 
- private:
-   class sarif_token_printer : public token_printer
-   {
-   public:
-     sarif_token_printer (sarif_builder &builder)
-       : m_builder (builder)
-     {
-     }
-     void print_tokens (pretty_printer *pp,
- 		       const pp_token_list &tokens) final override;
-   private:
-     sarif_builder &m_builder;
-   };
- 
-   std::unique_ptr<sarif_result>
-   make_result_object (const diagnostic_info &diagnostic,
- 		      diagnostic_t orig_diag_kind,
- 		      unsigned idx_within_parent);
-   void
-   add_any_include_chain (sarif_location_manager &loc_mgr,
- 			 sarif_location &location_obj,
- 			 location_t where);
-   void
-   set_any_logical_locs_arr (sarif_location &location_obj,
- 			    logical_location logical_loc);
-   std::unique_ptr<sarif_location>
-   make_location_object (sarif_location_manager &loc_mgr,
- 			const diagnostic_event &event,
- 			enum diagnostic_artifact_role role);
-   std::unique_ptr<sarif_code_flow>
-   make_code_flow_object (sarif_result &result,
- 			 unsigned idx_within_parent,
- 			 const diagnostic_path &path);
-   void
-   populate_thread_flow_location_object (sarif_result &result,
- 					sarif_thread_flow_location &thread_flow_loc_obj,
- 					const diagnostic_event &event,
- 					int event_execution_idx);
-   std::unique_ptr<json::array>
-   maybe_make_kinds_array (diagnostic_event::meaning m) const;
-   std::unique_ptr<sarif_physical_location>
-   maybe_make_physical_location_object (location_t loc,
- 				       enum diagnostic_artifact_role role,
- 				       int column_override,
- 				       const content_renderer *snippet_renderer);
-   std::unique_ptr<sarif_artifact_location>
-   make_artifact_location_object (location_t loc);
-   std::unique_ptr<sarif_artifact_location>
-   make_artifact_location_object_for_pwd () const;
-   std::unique_ptr<sarif_region>
-   maybe_make_region_object (location_t loc,
- 			    int column_override) const;
-   std::unique_ptr<sarif_region>
-   maybe_make_region_object_for_context (location_t loc,
- 					const content_renderer *snippet_renderer) const;
-   std::unique_ptr<sarif_region>
-   make_region_object_for_hint (const fixit_hint &hint) const;
- 
-   int
-   ensure_sarif_logical_location_for (logical_location k);
- 
-   std::unique_ptr<sarif_multiformat_message_string>
-   make_multiformat_message_string (const char *msg) const;
-   std::unique_ptr<sarif_log>
-   make_top_level_object (std::unique_ptr<sarif_invocation> invocation_obj,
- 			 std::unique_ptr<json::array> results);
-   std::unique_ptr<sarif_run>
-   make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
- 		   std::unique_ptr<json::array> results);
-   std::unique_ptr<sarif_tool>
-   make_tool_object ();
-   std::unique_ptr<sarif_tool_component>
-   make_driver_tool_component_object ();
-   std::unique_ptr<json::array> maybe_make_taxonomies_array () const;
-   std::unique_ptr<sarif_tool_component>
-   maybe_make_cwe_taxonomy_object () const;
-   std::unique_ptr<sarif_tool_component_reference>
-   make_tool_component_reference_object_for_cwe () const;
-   std::unique_ptr<sarif_reporting_descriptor>
-   make_reporting_descriptor_object_for_warning (const diagnostic_info &diagnostic,
- 						diagnostic_t orig_diag_kind,
- 						const char *option_text);
-   std::unique_ptr<sarif_reporting_descriptor>
-   make_reporting_descriptor_object_for_cwe_id (int cwe_id) const;
-   std::unique_ptr<sarif_reporting_descriptor_reference>
-   make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id);
-   sarif_artifact &
-   get_or_create_artifact (const char *filename,
- 			  enum diagnostic_artifact_role role,
- 			  bool embed_contents);
-   char *
-   get_source_lines (const char *filename,
- 		    int start_line,
- 		    int end_line) const;
-   std::unique_ptr<sarif_artifact_content>
-   maybe_make_artifact_content_object (const char *filename,
- 				      int start_line,
- 				      int end_line,
- 				      const content_renderer *r) const;
-   std::unique_ptr<sarif_fix>
-   make_fix_object (const rich_location &rich_loc);
-   std::unique_ptr<sarif_artifact_change>
-   make_artifact_change_object (const rich_location &richloc);
-   std::unique_ptr<sarif_replacement>
-   make_replacement_object (const fixit_hint &hint) const;
-   std::unique_ptr<sarif_artifact_content>
-   make_artifact_content_object (const char *text) const;
-   int get_sarif_column (expanded_location exploc) const;
- 
-   std::unique_ptr<json::object>
-   make_stack_from_backtrace ();
- 
-   diagnostic_context &m_context;
-   pretty_printer *m_printer;
-   const line_maps *m_line_maps;
-   sarif_token_printer m_token_printer;
- 
-   const logical_location_manager *m_logical_loc_mgr;
- 
-   /* The JSON object for the invocation object.  */
-   std::unique_ptr<sarif_invocation> m_invocation_obj;
- 
-   /* The JSON array of pending diagnostics.  */
-   std::unique_ptr<json::array> m_results_array;
- 
-   /* The JSON object for the result object (if any) in the current
-      diagnostic group.  */
-   std::unique_ptr<sarif_result> m_cur_group_result;
- 
-   /* Ideally we'd use std::unique_ptr<sarif_artifact> here, but I had
-      trouble getting this to work when building with GCC 4.8.  */
-   ordered_hash_map <nofree_string_hash,
- 		    sarif_artifact *> m_filename_to_artifact_map;
- 
-   bool m_seen_any_relative_paths;
-   hash_set <free_string_hash> m_rule_id_set;
-   std::unique_ptr<json::array> m_rules_arr;
- 
-   /* The set of all CWE IDs we've seen, if any.  */
-   hash_set <int_hash <int, 0, 1> > m_cwe_id_set;
- 
-   std::unique_ptr<sarif_array_of_unique<sarif_logical_location>> m_cached_logical_locs;
- 
-   std::unique_ptr<sarif_array_of_unique<sarif_graph>> m_run_graphs;
- 
-   int m_tabstop;
- 
-   std::unique_ptr<sarif_serialization_format> m_serialization_format;
-   const sarif_generation_options m_sarif_gen_opts;
- 
-   unsigned m_next_result_idx;
-   sarif_code_flow *m_current_code_flow;
- };
- 
- /* class sarif_object : public json::object.  */
- 
- sarif_property_bag &
- sarif_object::get_or_create_properties ()
- {
-   json::value *properties_val = get ("properties");
-   if (properties_val)
-     {
-       if (properties_val->get_kind () == json::JSON_OBJECT)
- 	return *static_cast <sarif_property_bag *> (properties_val);
-     }
- 
-   sarif_property_bag *bag = new sarif_property_bag ();
-   set ("properties", bag);
-   return *bag;
- }
- 
- /* class sarif_invocation : public sarif_object.  */
- 
- sarif_invocation::sarif_invocation (sarif_builder &builder,
- 				    const char * const *original_argv)
- : m_notifications_arr (std::make_unique<json::array> ()),
-   m_success (true)
- {
-   // "arguments" property (SARIF v2.1.0 section 3.20.2)
-   if (original_argv)
-     {
-       auto arguments_arr = std::make_unique<json::array> ();
-       for (size_t i = 0; original_argv[i]; ++i)
- 	arguments_arr->append_string (original_argv[i]);
-       set<json::array> ("arguments", std::move (arguments_arr));
-     }
- 
-   // "workingDirectory" property (SARIF v2.1.0 section 3.20.19)
-   if (const char *pwd = getpwd ())
-     set<sarif_artifact_location> ("workingDirectory",
- 				  builder.make_artifact_location_object (pwd));
- 
-   // "startTimeUtc" property (SARIF v2.1.0 section 3.20.7)
-   set<json::string> ("startTimeUtc",
- 		     make_date_time_string_for_current_time ());
- }
- 
- /* Handle an internal compiler error DIAGNOSTIC.
-    Add an object representing the ICE to the notifications array.  */
- 
- void
- sarif_invocation::add_notification_for_ice (const diagnostic_info &diagnostic,
- 					    sarif_builder &builder,
- 					    std::unique_ptr<json::object> backtrace)
- {
-   m_success = false;
- 
-   auto notification
-     = std::make_unique<sarif_ice_notification> (diagnostic,
- 						builder,
- 						std::move (backtrace));
- 
-   /* Support for related locations within a notification was added
-      in SARIF 2.2; see https://github.com/oasis-tcs/sarif-spec/issues/540  */
-   if (builder.get_version () >= sarif_version::v2_2_prerelease_2024_08_08)
-     notification->process_worklist (builder);
- 
-   m_notifications_arr->append<sarif_ice_notification>
-     (std::move (notification));
- }
- 
- void
- sarif_invocation::prepare_to_flush (sarif_builder &builder)
- {
-   const diagnostic_context &context = builder.get_context ();
- 
-   /* "executionSuccessful" property (SARIF v2.1.0 section 3.20.14).  */
-   if (context.execution_failed_p ())
-     m_success = false;
-   set_bool ("executionSuccessful", m_success);
- 
-   /* "toolExecutionNotifications" property (SARIF v2.1.0 section 3.20.21).  */
-   set ("toolExecutionNotifications", std::move (m_notifications_arr));
- 
-   /* Call client hook, allowing it to create a custom property bag for
-      this object (SARIF v2.1.0 section 3.8) e.g. for recording time vars.  */
-   if (auto client_data_hooks = context.get_client_data_hooks ())
-     client_data_hooks->add_sarif_invocation_properties (*this);
- 
-   // "endTimeUtc" property (SARIF v2.1.0 section 3.20.8);
-   set<json::string> ("endTimeUtc",
- 		     make_date_time_string_for_current_time ());
- }
- 
- /* class sarif_artifact : public sarif_object.  */
- 
- /* Add ROLE to this artifact's roles.
-    If EMBED_CONTENTS is true, then flag that we will attempt to embed the
-    contents of this artifact when writing it out.  */
- 
- void
- sarif_artifact::add_role (enum diagnostic_artifact_role role,
- 			  bool embed_contents)
- {
-   /* TODO(SARIF 2.2): "scannedFile" is to be added as a role in SARIF 2.2;
-      see https://github.com/oasis-tcs/sarif-spec/issues/459
- 
-      For now, skip them.
-      Ultimately, we probably shouldn't bother embedding the contents
-      of such artifacts, just the snippets.  */
-   if (role == diagnostic_artifact_role::scanned_file)
-     return;
- 
-   if (embed_contents)
-     m_embed_contents = true;
- 
-   /* In SARIF v2.1.0 section 3.24.6 "roles" property:
-      "resultFile" is for an artifact
-      "which the analysis tool was not explicitly instructed to scan",
-      whereas "analysisTarget" is for one where the
-      "analysis tool was instructed to scan this artifact".
-      Hence the latter excludes the former.  */
-   if (role == diagnostic_artifact_role::result_file)
-     if (bitmap_bit_p (m_roles, (int)diagnostic_artifact_role::analysis_target))
- 	return;
- 
-   bitmap_set_bit (m_roles, (int)role);
- }
- 
- /* Populate the "contents" property (SARIF v2.1.0 section 3.24.8).
-    We do this after initialization to
-    (a) ensure that any charset options have been set
-    (b) only populate it for artifacts that are referenced by a location.  */
- 
- void
- sarif_artifact::populate_contents (sarif_builder &builder)
- {
-   if (auto artifact_content_obj
- 	= builder.maybe_make_artifact_content_object (m_filename))
-     set<sarif_artifact_content> ("contents", std::move (artifact_content_obj));
- }
- 
- /* Get a string for ROLE corresponding to the
-    SARIF v2.1.0 section 3.24.6 "roles" property.  */
- 
- static const char *
- get_artifact_role_string (enum diagnostic_artifact_role role)
- {
-   switch (role)
-     {
-     default:
-       gcc_unreachable ();
-     case diagnostic_artifact_role::analysis_target:
-       return "analysisTarget";
-     case diagnostic_artifact_role::debug_output_file:
-       return "debugOutputFile";
-     case diagnostic_artifact_role::result_file:
-       return "resultFile";
-     case diagnostic_artifact_role::scanned_file:
-       return "scannedFile";
-     case diagnostic_artifact_role::traced_file:
-       return "tracedFile";
-     }
- }
- 
- /* Populate the "roles" property of this sarif_artifact with a new
-    json::array for the artifact.roles property (SARIF v2.1.0 section 3.24.6)
-    containing strings such as "analysisTarget", "resultFile"
-    and/or "tracedFile".  */
- 
- void
- sarif_artifact::populate_roles ()
- {
-   if (bitmap_empty_p (m_roles))
-     return;
-   auto roles_arr (std::make_unique<json::array> ());
-   for (int i = 0; i < (int)diagnostic_artifact_role::NUM_ROLES; i++)
-     if (bitmap_bit_p (m_roles, i))
-       {
- 	enum diagnostic_artifact_role role = (enum diagnostic_artifact_role)i;
- 	roles_arr->append_string (get_artifact_role_string (role));
-       }
-   set<json::array> ("roles", std::move (roles_arr));
- }
- 
- /* class sarif_location_manager : public sarif_object.  */
- 
- /* Base implementation of sarif_location_manager::add_related_location vfunc.
- 
-    Add LOCATION_OBJ to this object's "relatedLocations" array,
-    creating it if it doesn't yet exist.  */
- 
- void
- sarif_location_manager::
- add_related_location (std::unique_ptr<sarif_location> location_obj,
- 		      sarif_builder &)
- {
-   if (!m_related_locations_arr)
-     {
-       m_related_locations_arr = new json::array ();
-       /* Give ownership of m_related_locations_arr to json::object;
- 	 keep a borrowed ptr.  */
-       set ("relatedLocations", m_related_locations_arr);
-     }
-   m_related_locations_arr->append (std::move (location_obj));
- }
- 
- void
- sarif_location_manager::
- add_relationship_to_worklist (sarif_location &location_obj,
- 			      enum worklist_item::kind kind,
- 			      location_t where)
- {
-   m_worklist.push_back (worklist_item (location_obj,
- 				       kind,
- 				       where));
- }
- 
- /* Process all items in this result's worklist.
-    Doing so may temporarily add new items to the end
-    of the worklist.
-    Handling any item should be "lazy", and thus we should
-    eventually drain the queue and terminate.  */
- 
- void
- sarif_location_manager::process_worklist (sarif_builder &builder)
- {
-   while (!m_worklist.empty ())
-     {
-       const worklist_item &item = m_worklist.front ();
-       process_worklist_item (builder, item);
-       m_worklist.pop_front ();
-     }
- }
- 
- /* Process one item in this result's worklist, potentially
-    adding new items to the end of the worklist.  */
- 
- void
- sarif_location_manager::process_worklist_item (sarif_builder &builder,
- 					       const worklist_item &item)
- {
-   switch (item.m_kind)
-     {
-     default:
-       gcc_unreachable ();
-     case worklist_item::kind::included_from:
-       {
- 	sarif_location &included_loc_obj = item.m_location_obj;
- 	sarif_location *includer_loc_obj = nullptr;
- 	auto iter = m_included_from_locations.find (item.m_where);
- 	if (iter != m_included_from_locations.end ())
- 	  includer_loc_obj = iter->second;
- 	else
- 	  {
- 	    std::unique_ptr<sarif_location> new_loc_obj
- 	      = builder.make_location_object
- 		  (*this,
- 		   item.m_where,
- 		   diagnostic_artifact_role::scanned_file);
- 	    includer_loc_obj = new_loc_obj.get ();
- 	    add_related_location (std::move (new_loc_obj), builder);
- 	    auto kv
- 	      = std::pair<location_t, sarif_location *> (item.m_where,
- 							 includer_loc_obj);
- 	    m_included_from_locations.insert (kv);
- 	  }
- 
- 	includer_loc_obj->lazily_add_relationship
- 	  (included_loc_obj,
- 	   location_relationship_kind::includes,
- 	   *this);
- 	included_loc_obj.lazily_add_relationship
- 	  (*includer_loc_obj,
- 	   location_relationship_kind::is_included_by,
- 	   *this);
-       }
-       break;
-     case worklist_item::kind::unlabelled_secondary_location:
-       {
- 	sarif_location &primary_loc_obj = item.m_location_obj;
- 	sarif_location *secondary_loc_obj = nullptr;
- 	auto iter = m_unlabelled_secondary_locations.find (item.m_where);
- 	if (iter != m_unlabelled_secondary_locations.end ())
- 	  secondary_loc_obj = iter->second;
- 	else
- 	  {
- 	    std::unique_ptr<sarif_location> new_loc_obj
- 	      = builder.make_location_object
- 		  (*this,
- 		   item.m_where,
- 		   diagnostic_artifact_role::scanned_file);
- 	    secondary_loc_obj = new_loc_obj.get ();
- 	    add_related_location (std::move (new_loc_obj), builder);
- 	    auto kv
- 	      = std::pair<location_t, sarif_location *> (item.m_where,
- 							 secondary_loc_obj);
- 	    m_unlabelled_secondary_locations.insert (kv);
- 	  }
- 	gcc_assert (secondary_loc_obj);
- 	primary_loc_obj.lazily_add_relationship
- 	  (*secondary_loc_obj,
- 	   location_relationship_kind::relevant,
- 	   *this);
-       }
-       break;
-     }
- }
- 
- /* class sarif_result : public sarif_location_manager.  */
- 
- /* Handle secondary diagnostics that occur within a diagnostic group.
-    The closest SARIF seems to have to nested diagnostics is the
-    "relatedLocations" property of result objects (SARIF v2.1.0 section 3.27.22),
-    so we lazily set this property and populate the array if and when
-    secondary diagnostics occur (such as notes to a warning).  */
- 
- void
- sarif_result::on_nested_diagnostic (const diagnostic_info &diagnostic,
- 				    diagnostic_t /*orig_diag_kind*/,
- 				    sarif_builder &builder)
- {
-   /* We don't yet generate meaningful logical locations for notes;
-      sometimes these will related to current_function_decl, but
-      often they won't.  */
-   auto location_obj
-     = builder.make_location_object (this, *diagnostic.richloc,
- 				    logical_location (),
- 				    diagnostic_artifact_role::result_file);
-   auto message_obj
-     = builder.make_message_object (pp_formatted_text (builder.get_printer ()));
-   pp_clear_output_area (builder.get_printer ());
-   location_obj->set<sarif_message> ("message", std::move (message_obj));
- 
-   /* Add nesting level, as per "P3358R0 SARIF for Structured Diagnostics"
-      https://wg21.link/P3358R0  */
-   sarif_property_bag &bag = location_obj->get_or_create_properties ();
-   bag.set_integer ("nestingLevel",
- 		   builder.get_context ().get_diagnostic_nesting_level ());
- 
-   add_related_location (std::move (location_obj), builder);
- }
- 
- /* Handle diagrams that occur within a diagnostic group.
-    The closest thing in SARIF seems to be to add a location to the
-    "releatedLocations" property  (SARIF v2.1.0 section 3.27.22),
-    and to put the diagram into the "message" property of that location
-    (SARIF v2.1.0 section 3.28.5).  */
- 
- void
- sarif_result::on_diagram (const diagnostic_diagram &diagram,
- 			  sarif_builder &builder)
- {
-   auto location_obj = std::make_unique<sarif_location> ();
-   auto message_obj = builder.make_message_object_for_diagram (diagram);
-   location_obj->set<sarif_message> ("message", std::move (message_obj));
- 
-   add_related_location (std::move (location_obj), builder);
- }
- 
- /* class sarif_location : public sarif_object.  */
- 
- /* Ensure this location has an "id" and return it.
-    Use LOC_MGR if an id needs to be allocated.
- 
-    See the "id" property (3.28.2).
- 
-    We use this to only assign ids to locations that are
-    referenced by another sarif object; others have no "id".   */
- 
- long
- sarif_location::lazily_add_id (sarif_location_manager &loc_mgr)
- {
-   long id = get_id ();
-   if (id != -1)
-     return id;
-   id = loc_mgr.allocate_location_id ();
-   set_integer ("id", id);
-   gcc_assert (id != -1);
-   return id;
- }
- 
- /* Get the id of this location, or -1 if it doesn't have one.  */
- 
- long
- sarif_location::get_id () const
- {
-   json::value *id = get ("id");
-   if (!id)
-     return -1;
-   gcc_assert (id->get_kind () == json::JSON_INTEGER);
-   return static_cast <json::integer_number *> (id)->get ();
- }
- 
- // 3.34.3 kinds property
- static const char *
- get_string_for_location_relationship_kind (enum location_relationship_kind kind)
- {
-   switch (kind)
-     {
-     default:
-       gcc_unreachable ();
-     case location_relationship_kind::includes:
-       return "includes";
-     case location_relationship_kind::is_included_by:
-       return "isIncludedBy";
-     case location_relationship_kind::relevant:
-       return "relevant";
-     }
- }
- 
- /* Lazily populate this location's "relationships" property (3.28.7)
-    with the relationship of KIND to TARGET, creating objects
-    as necessary.
-    Use LOC_MGR for any locations that need "id" values.  */
- 
- void
- sarif_location::lazily_add_relationship (sarif_location &target,
- 					 enum location_relationship_kind kind,
- 					 sarif_location_manager &loc_mgr)
- {
-   sarif_location_relationship &relationship_obj
-     = lazily_add_relationship_object (target, loc_mgr);
- 
-   relationship_obj.lazily_add_kind (kind);
- }
- 
- /* Lazily populate this location's "relationships" property (3.28.7)
-    with a location_relationship to TARGET, creating objects
-    as necessary.
-    Use LOC_MGR for any locations that need "id" values.  */
- 
- sarif_location_relationship &
- sarif_location::lazily_add_relationship_object (sarif_location &target,
- 						sarif_location_manager &loc_mgr)
- {
-   /* See if THIS already has a locationRelationship referencing TARGET.  */
-   auto iter = m_relationships_map.find (&target);
-   if (iter != m_relationships_map.end ())
-     {
-       /* We already have a locationRelationship from THIS to TARGET.  */
-       sarif_location_relationship *relationship = iter->second;
-       gcc_assert (relationship->get_target_id() == target.get_id ());
-       return *relationship;
-     }
- 
-   // Ensure that THIS has a "relationships" property (3.28.7).
-   json::array &relationships_arr = lazily_add_relationships_array ();
- 
-   /* No existing locationRelationship from THIS to TARGET; make one,
-      record it, and add it to the "relationships" array.  */
-   auto relationship_obj
-     = std::make_unique<sarif_location_relationship> (target, loc_mgr);
-   sarif_location_relationship *relationship = relationship_obj.get ();
-   auto kv
-     = std::pair<sarif_location *,
- 		sarif_location_relationship *> (&target, relationship);
-   m_relationships_map.insert (kv);
- 
-   relationships_arr.append (std::move (relationship_obj));
- 
-   return *relationship;
- }
- 
- /* Ensure this location has a "relationships" array (3.28.7).  */
- 
- json::array &
- sarif_location::lazily_add_relationships_array ()
- {
-   const char *const property_name = "relationships";
-   if (json::value *relationships = get (property_name))
-     {
-       gcc_assert (relationships->get_kind () == json::JSON_ARRAY);
-       return *static_cast <json::array *> (relationships);
-     }
-   json::array *relationships_arr = new json::array ();
-   set (property_name, relationships_arr);
-   return *relationships_arr;
- }
- 
- /* class sarif_ice_notification : public sarif_location_manager.  */
- 
- /* sarif_ice_notification's ctor.
-    DIAGNOSTIC is an internal compiler error.  */
- 
- sarif_ice_notification::
- sarif_ice_notification (const diagnostic_info &diagnostic,
- 			sarif_builder &builder,
- 			std::unique_ptr<json::object> backtrace)
- {
-   /* "locations" property (SARIF v2.1.0 section 3.58.4).  */
-   auto locations_arr
-     = builder.make_locations_arr (*this,
- 				  diagnostic,
- 				  diagnostic_artifact_role::result_file);
-   set<json::array> ("locations", std::move (locations_arr));
- 
-   /* "message" property (SARIF v2.1.0 section 3.85.5).  */
-   auto message_obj
-     = builder.make_message_object (pp_formatted_text (builder.get_printer ()));
-   pp_clear_output_area (builder.get_printer ());
-   set<sarif_message> ("message", std::move (message_obj));
- 
-   /* "level" property (SARIF v2.1.0 section 3.58.6).  */
-   set_string ("level", "error");
- 
-   /* If we have backtrace information, add it as part of a property bag.  */
-   if (backtrace)
-     {
-       sarif_property_bag &bag = get_or_create_properties ();
-       bag.set ("gcc/backtrace", std::move (backtrace));
-     }
- }
- 
- /* Implementation of sarif_location_manager::add_related_location vfunc
-    for notifications.  */
- 
- void
- sarif_ice_notification::
- add_related_location (std::unique_ptr<sarif_location> location_obj,
- 		      sarif_builder &builder)
- {
-   /* Support for related locations within a notification was added
-      in SARIF 2.2; see https://github.com/oasis-tcs/sarif-spec/issues/540  */
-   if (builder.get_version () >= sarif_version::v2_2_prerelease_2024_08_08)
-     sarif_location_manager::add_related_location (std::move (location_obj),
- 						  builder);
-   /* Otherwise implicitly discard LOCATION_OBJ.  */
- }
- 
- /* class sarif_location_relationship : public sarif_object.  */
- 
- sarif_location_relationship::
- sarif_location_relationship (sarif_location &target,
- 			     sarif_location_manager &loc_mgr)
- : m_kinds ((unsigned)location_relationship_kind::NUM_KINDS)
- {
-   bitmap_clear (m_kinds);
-   set_integer ("target", target.lazily_add_id (loc_mgr));
- }
- 
- long
- sarif_location_relationship::get_target_id () const
- {
-   json::value *id = get ("id");
-   gcc_assert (id);
-   return static_cast <json::integer_number *> (id)->get ();
- }
- 
- void
- sarif_location_relationship::
- lazily_add_kind (enum location_relationship_kind kind)
- {
-   if (bitmap_bit_p (m_kinds, (int)kind))
-     return; // already have this kind
-   bitmap_set_bit (m_kinds, (int)kind);
- 
-   // 3.34.3 kinds property
-   json::array *kinds_arr = nullptr;
-   if (json::value *kinds_val = get ("kinds"))
-     {
-       gcc_assert (kinds_val->get_kind () == json::JSON_ARRAY);
-     }
-   else
-     {
-       kinds_arr = new json::array ();
-       set ("kinds", kinds_arr);
-     }
-   const char *kind_str = get_string_for_location_relationship_kind (kind);
-   kinds_arr->append_string (kind_str);
- }
- 
- /* class sarif_code_flow : public sarif_object.  */
- 
- sarif_code_flow::sarif_code_flow (sarif_result &parent,
- 				  unsigned idx_within_parent)
- : m_parent (parent),
-   m_idx_within_parent (idx_within_parent)
- {
-   /* "threadFlows" property (SARIF v2.1.0 section 3.36.3).  */
-   auto thread_flows_arr = std::make_unique<json::array> ();
-   m_thread_flows_arr = thread_flows_arr.get (); // borrowed
-   set<json::array> ("threadFlows", std::move (thread_flows_arr));
- }
- 
- sarif_thread_flow &
- sarif_code_flow::get_or_append_thread_flow (const diagnostic_thread &thread,
- 					    diagnostic_thread_id_t thread_id)
- {
-   sarif_thread_flow **slot = m_thread_id_map.get (thread_id);
-   if (slot)
-     return **slot;
- 
-   unsigned next_thread_flow_idx = m_thread_flows_arr->size ();
-   auto thread_flow_obj
-     = std::make_unique<sarif_thread_flow> (*this, thread, next_thread_flow_idx);
-   m_thread_id_map.put (thread_id, thread_flow_obj.get ()); // borrowed
-   sarif_thread_flow *result = thread_flow_obj.get ();
-   m_thread_flows_arr->append<sarif_thread_flow> (std::move (thread_flow_obj));
-   return *result;
- }
- 
- sarif_thread_flow &
- sarif_code_flow::get_thread_flow (diagnostic_thread_id_t thread_id)
- {
-   sarif_thread_flow **slot = m_thread_id_map.get (thread_id);
-   gcc_assert (slot); // it must already have one
-   return **slot;
- }
- 
- void
- sarif_code_flow::add_location (sarif_thread_flow_location &tfl_obj)
- {
-   m_all_tfl_objs.push_back (&tfl_obj);
- }
- 
- sarif_thread_flow_location &
- sarif_code_flow::get_thread_flow_loc_obj (diagnostic_event_id_t event_id) const
- {
-   gcc_assert (event_id.known_p ());
-   gcc_assert ((size_t)event_id.zero_based () < m_all_tfl_objs.size ());
-   sarif_thread_flow_location *tfl_obj = m_all_tfl_objs[event_id.zero_based ()];
-   gcc_assert (tfl_obj);
-   return *tfl_obj;
- }
- 
- /* class sarif_thread_flow : public sarif_object.  */
- 
- sarif_thread_flow::sarif_thread_flow (sarif_code_flow &parent,
- 				      const diagnostic_thread &thread,
- 				      unsigned idx_within_parent)
- : m_parent (parent),
-   m_idx_within_parent (idx_within_parent)
- {
-   /* "id" property (SARIF v2.1.0 section 3.37.2).  */
-   label_text name (thread.get_name (false));
-   set_string ("id", name.get ());
- 
-   /* "locations" property (SARIF v2.1.0 section 3.37.6).  */
-   m_locations_arr = new json::array ();
- 
-   /* Give ownership of m_locations_arr to json::object;
-      keep a borrowed ptr.  */
-   set ("locations", m_locations_arr);
- }
- 
- /* Add a sarif_thread_flow_location to this threadFlow object, but
-    don't populate it yet.  */
- 
- sarif_thread_flow_location &
- sarif_thread_flow::add_location ()
- {
-   const unsigned thread_flow_location_idx = m_locations_arr->size ();
-   sarif_thread_flow_location *thread_flow_loc_obj
-     = new sarif_thread_flow_location (*this, thread_flow_location_idx);
-   m_locations_arr->append (thread_flow_loc_obj);
-   m_parent.add_location (*thread_flow_loc_obj);
-   return *thread_flow_loc_obj;
- }
- 
- /* class sarif_builder.  */
- 
- /* sarif_builder's ctor.  */
- 
- sarif_builder::sarif_builder (diagnostic_context &context,
- 			      pretty_printer &printer,
- 			      const line_maps *line_maps,
- 			      std::unique_ptr<sarif_serialization_format> serialization_format,
- 			      const sarif_generation_options &sarif_gen_opts)
- : m_context (context),
-   m_printer (&printer),
-   m_line_maps (line_maps),
-   m_token_printer (*this),
-   m_logical_loc_mgr (nullptr),
-   m_invocation_obj
-     (std::make_unique<sarif_invocation> (*this,
- 					 context.get_original_argv ())),
-   m_results_array (new json::array ()),
-   m_cur_group_result (nullptr),
-   m_seen_any_relative_paths (false),
-   m_rule_id_set (),
-   m_rules_arr (new json::array ()),
-   m_cached_logical_locs
-     (std::make_unique<sarif_array_of_unique<sarif_logical_location>> ()),
-   m_run_graphs
-     (std::make_unique<sarif_array_of_unique<sarif_graph>> ()),
-   m_tabstop (context.m_tabstop),
-   m_serialization_format (std::move (serialization_format)),
-   m_sarif_gen_opts (sarif_gen_opts),
-   m_next_result_idx (0),
-   m_current_code_flow (nullptr)
- {
-   gcc_assert (m_line_maps);
-   gcc_assert (m_serialization_format);
- 
-   if (auto client_data_hooks = context.get_client_data_hooks ())
-     m_logical_loc_mgr = client_data_hooks->get_logical_location_manager ();
- }
- 
- sarif_builder::~sarif_builder ()
- {
-   /* Normally m_filename_to_artifact_map will have been emptied as part
-      of make_run_object, but this isn't run by all the selftests.
-      Ensure the artifact objects are cleaned up for such cases.  */
-   for (auto iter : m_filename_to_artifact_map)
-     {
-       sarif_artifact *artifact_obj = iter.second;
-       delete artifact_obj;
-     }
- }
- 
- /* Functions at which to stop the backtrace print.  It's not
-    particularly helpful to print the callers of these functions.  */
- 
- static const char * const bt_stop[] =
- {
-   "main",
-   "toplev::main",
-   "execute_one_pass",
-   "compile_file",
- };
- 
- struct bt_closure
- {
-   bt_closure (sarif_builder &builder,
- 	      json::array *frames_arr)
-   : m_builder (builder),
-     m_frames_arr (frames_arr)
-   {
-   }
- 
-   sarif_builder &m_builder;
-   json::array *m_frames_arr;
- };
- 
- /* A callback function passed to the backtrace_full function.  */
- 
- static int
- bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
- 	     const char *function)
- {
-   bt_closure *closure = (bt_closure *)data;
- 
-   /* If we don't have any useful information, don't print
-      anything.  */
-   if (filename == nullptr && function == nullptr)
-     return 0;
- 
-   /* Skip functions in diagnostic.cc or diagnostic-global-context.cc.  */
-   if (closure->m_frames_arr->size () == 0
-       && filename != nullptr
-       && (strcmp (lbasename (filename), "diagnostic.cc") == 0
- 	  || strcmp (lbasename (filename),
- 		     "diagnostic-global-context.cc") == 0))
-     return 0;
- 
-   /* Print up to 20 functions.  We could make this a --param, but
-      since this is only for debugging just use a constant for now.  */
-   if (closure->m_frames_arr->size () >= 20)
-     {
-       /* Returning a non-zero value stops the backtrace.  */
-       return 1;
-     }
- 
-   char *alc = nullptr;
-   if (function != nullptr)
-     {
-       char *str = cplus_demangle_v3 (function,
- 				     (DMGL_VERBOSE | DMGL_ANSI
- 				      | DMGL_GNU_V3 | DMGL_PARAMS));
-       if (str != nullptr)
- 	{
- 	  alc = str;
- 	  function = str;
- 	}
- 
-       for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
- 	{
- 	  size_t len = strlen (bt_stop[i]);
- 	  if (strncmp (function, bt_stop[i], len) == 0
- 	      && (function[len] == '\0' || function[len] == '('))
- 	    {
- 	      if (alc != nullptr)
- 		free (alc);
- 	      /* Returning a non-zero value stops the backtrace.  */
- 	      return 1;
- 	    }
- 	}
-     }
- 
-   auto frame_obj = std::make_unique<json::object> ();
- 
-   /* I tried using sarifStack and sarifStackFrame for this
-      but it's not a good fit e.g. PC information.  */
-   char buf[128];
-   snprintf (buf, sizeof (buf) - 1, "0x%lx", (unsigned long)pc);
-   frame_obj->set_string ("pc", buf);
-   if (function)
-     frame_obj->set_string ("function", function);
-   if (filename)
-     frame_obj->set_string ("filename", filename);
-   frame_obj->set_integer ("lineno", lineno);
-   closure->m_frames_arr->append (std::move (frame_obj));
- 
-   if (alc != nullptr)
-     free (alc);
- 
-   return 0;
- }
- 
- /* Attempt to generate a JSON object representing a backtrace,
-    for adding to ICE notifications.  */
- 
- std::unique_ptr<json::object>
- sarif_builder::make_stack_from_backtrace ()
- {
-   auto frames_arr = std::make_unique<json::array> ();
- 
-   backtrace_state *state = nullptr;
-   state = backtrace_create_state (nullptr, 0, nullptr, nullptr);
-   bt_closure closure (*this, frames_arr.get ());
-   const int frames_to_skip = 5;
-   if (state != nullptr)
-     backtrace_full (state, frames_to_skip, bt_callback, nullptr,
- 		    (void *) &closure);
- 
-   if (frames_arr->size () == 0)
-     return nullptr;
- 
-   auto stack = std::make_unique<json::object> ();
-   stack->set ("frames", std::move (frames_arr));
-   return stack;
- }
- 
- void
- sarif_builder::set_main_input_filename (const char *name)
- {
-   /* Mark NAME as the artifact that the tool was instructed to scan.
-      Only quote the contents if it gets referenced by physical locations,
-      since otherwise the "no diagnostics" case would quote the main input
-      file, and doing so noticeably bloated the output seen in analyzer
-      integration testing (build directory went from 20G -> 21G).  */
-   if (name)
-     get_or_create_artifact (name,
- 			    diagnostic_artifact_role::analysis_target,
- 			    false);
- }
- 
- /* Implementation of "on_report_diagnostic" for SARIF output.  */
- 
- void
- sarif_builder::on_report_diagnostic (const diagnostic_info &diagnostic,
- 				     diagnostic_t orig_diag_kind,
- 				     diagnostic_sarif_format_buffer *buffer)
- {
-   pp_output_formatted_text (m_printer, m_context.get_urlifier ());
- 
-   if (diagnostic.kind == DK_ICE || diagnostic.kind == DK_ICE_NOBT)
-     {
-       std::unique_ptr<json::object> stack = make_stack_from_backtrace ();
-       m_invocation_obj->add_notification_for_ice (diagnostic, *this,
- 						  std::move (stack));
- 
-       /* Print a header for the remaining output to stderr, and
- 	 return, attempting to print the usual ICE messages to
- 	 stderr.  Hopefully this will be helpful to the user in
- 	 indicating what's gone wrong (also for DejaGnu, for pruning
- 	 those messages).   */
-       fnotice (stderr, "Internal compiler error:\n");
- 
-       return;
-     }
- 
-   if (buffer)
-     {
-       /* When buffering, we can only handle top-level results.  */
-       gcc_assert (!m_cur_group_result);
-       buffer->add_result (make_result_object (diagnostic, orig_diag_kind,
- 					      m_next_result_idx++));
-       return;
-     }
- 
-   if (m_cur_group_result)
-     /* Nested diagnostic.  */
-     m_cur_group_result->on_nested_diagnostic (diagnostic,
- 					      orig_diag_kind,
- 					      *this);
-   else
-     {
-       /* Top-level diagnostic.  */
-       m_cur_group_result = make_result_object (diagnostic, orig_diag_kind,
- 					       m_next_result_idx++);
-     }
- }
- 
- /* Implementation of diagnostic_context::m_diagrams.m_emission_cb
-    for SARIF output.  */
- 
- void
- sarif_builder::emit_diagram (const diagnostic_diagram &diagram)
- {
-   /* We must be within the emission of a top-level diagnostic.  */
-   gcc_assert (m_cur_group_result);
-   m_cur_group_result->on_diagram (diagram, *this);
- }
- 
- /* Implementation of "end_group_cb" for SARIF output.  */
- 
- void
- sarif_builder::end_group ()
- {
-   if (m_cur_group_result)
-     {
-       m_cur_group_result->process_worklist (*this);
-       m_results_array->append<sarif_result> (std::move (m_cur_group_result));
-     }
- }
- 
- void
- sarif_builder::
- report_global_digraph (const diagnostics::digraphs::lazy_digraph &ldg)
- {
-   auto &dg = ldg.get_or_create_digraph ();
- 
-   /* Presumably the location manager must be nullptr; see
-      https://github.com/oasis-tcs/sarif-spec/issues/712  */
-   m_run_graphs->append (make_sarif_graph (dg, this, nullptr));
- }
- 
- /* Create a top-level object, and add it to all the results
-    (and other entities) we've seen so far, moving ownership
-    to the object.  */
- 
- std::unique_ptr<sarif_log>
- sarif_builder::flush_to_object ()
- {
-   m_invocation_obj->prepare_to_flush (*this);
-   std::unique_ptr<sarif_log> top
-     = make_top_level_object (std::move (m_invocation_obj),
- 			     std::move (m_results_array));
-   return top;
- }
- 
- /* Create a top-level object, and add it to all the results
-    (and other entities) we've seen so far.
- 
-    Flush it all to OUTF.  */
- 
- void
- sarif_builder::flush_to_file (FILE *outf)
- {
-   std::unique_ptr<sarif_log> top = flush_to_object ();
-   m_serialization_format->write_to_file (outf, *top);
- }
- 
- /* Attempt to convert DIAG_KIND to a suitable value for the "level"
-    property (SARIF v2.1.0 section 3.27.10).
- 
-    Return nullptr if there isn't one.  */
- 
- static const char *
- maybe_get_sarif_level (diagnostic_t diag_kind)
- {
-   switch (diag_kind)
-     {
-     case DK_WARNING:
-       return "warning";
-     case DK_ERROR:
-       return "error";
-     case DK_NOTE:
-     case DK_ANACHRONISM:
-       return "note";
-     default:
-       return nullptr;
-     }
- }
- 
- /* Make a string for DIAG_KIND suitable for use a ruleId
-    (SARIF v2.1.0 section 3.27.5) as a fallback for when we don't
-    have anything better to use.  */
- 
- static char *
- make_rule_id_for_diagnostic_kind (diagnostic_t diag_kind)
- {
-   /* Lose the trailing ": ".  */
-   const char *kind_text = get_diagnostic_kind_text (diag_kind);
-   size_t len = strlen (kind_text);
-   gcc_assert (len > 2);
-   gcc_assert (kind_text[len - 2] == ':');
-   gcc_assert (kind_text[len - 1] == ' ');
-   char *rstrip = xstrdup (kind_text);
-   rstrip[len - 2] = '\0';
-   return rstrip;
- }
- 
- /* Make a "result" object (SARIF v2.1.0 section 3.27) for DIAGNOSTIC.  */
- 
- std::unique_ptr<sarif_result>
- sarif_builder::make_result_object (const diagnostic_info &diagnostic,
- 				   diagnostic_t orig_diag_kind,
- 				   unsigned idx_within_parent)
- {
-   auto result_obj = std::make_unique<sarif_result> (idx_within_parent);
- 
-   /* "ruleId" property (SARIF v2.1.0 section 3.27.5).  */
-   /* Ideally we'd have an option_name for these.  */
-   if (char *option_text
- 	= m_context.make_option_name (diagnostic.option_id,
- 				      orig_diag_kind, diagnostic.kind))
-     {
-       /* Lazily create reportingDescriptor objects for and add to m_rules_arr.
- 	 Set ruleId referencing them.  */
-       result_obj->set_string ("ruleId", option_text);
-       if (m_rule_id_set.contains (option_text))
- 	free (option_text);
-       else
- 	{
- 	  /* This is the first time we've seen this ruleId.  */
- 	  /* Add to set, taking ownership.  */
- 	  m_rule_id_set.add (option_text);
- 
- 	  m_rules_arr->append<sarif_reporting_descriptor>
- 	    (make_reporting_descriptor_object_for_warning (diagnostic,
- 							   orig_diag_kind,
- 							   option_text));
- 	}
-     }
-   else
-     {
-       /* Otherwise, we have an "error" or a stray "note"; use the
- 	 diagnostic kind as the ruleId, so that the result object at least
- 	 has a ruleId.
- 	 We don't bother creating reportingDescriptor objects for these.  */
-       char *rule_id = make_rule_id_for_diagnostic_kind (orig_diag_kind);
-       result_obj->set_string ("ruleId", rule_id);
-       free (rule_id);
-     }
- 
-   if (diagnostic.metadata)
-     {
-       /* "taxa" property (SARIF v2.1.0 section 3.27.8).  */
-       if (int cwe_id = diagnostic.metadata->get_cwe ())
- 	{
- 	  auto taxa_arr = std::make_unique<json::array> ();
- 	  taxa_arr->append<sarif_reporting_descriptor_reference>
- 	    (make_reporting_descriptor_reference_object_for_cwe_id (cwe_id));
- 	  result_obj->set<json::array> ("taxa", std::move (taxa_arr));
- 	}
- 
-       diagnostic.metadata->maybe_add_sarif_properties (*result_obj);
- 
-       /* We don't yet support diagnostic_metadata::rule.  */
-     }
- 
-   /* "level" property (SARIF v2.1.0 section 3.27.10).  */
-   if (const char *sarif_level = maybe_get_sarif_level (diagnostic.kind))
-     result_obj->set_string ("level", sarif_level);
- 
-   /* "message" property (SARIF v2.1.0 section 3.27.11).  */
-   auto message_obj
-     = make_message_object (pp_formatted_text (m_printer));
-   pp_clear_output_area (m_printer);
-   result_obj->set<sarif_message> ("message", std::move (message_obj));
- 
-   /* "locations" property (SARIF v2.1.0 section 3.27.12).  */
-   result_obj->set<json::array>
-     ("locations",
-      make_locations_arr (*result_obj.get (),
- 			 diagnostic,
- 			 diagnostic_artifact_role::result_file));
- 
-   /* "codeFlows" property (SARIF v2.1.0 section 3.27.18).  */
-   if (const diagnostic_path *path = diagnostic.richloc->get_path ())
-     {
-       auto code_flows_arr = std::make_unique<json::array> ();
-       const unsigned code_flow_index = 0;
-       code_flows_arr->append<sarif_code_flow>
- 	(make_code_flow_object (*result_obj.get (),
- 				code_flow_index,
- 				*path));
-       result_obj->set<json::array> ("codeFlows", std::move (code_flows_arr));
-     }
- 
-   // "graphs" property (SARIF v2.1.0 section 3.27.19).  */
-   if (diagnostic.metadata)
-     if (auto ldg = diagnostic.metadata->get_lazy_digraphs ())
-       {
- 	auto &digraphs = ldg->get_or_create_digraphs ();
- 	auto graphs_arr = std::make_unique<json::array> ();
- 	for (auto &iter : digraphs)
- 	  graphs_arr->append (make_sarif_graph (*iter, this,
- 						result_obj.get ()));
- 	if (graphs_arr->size () > 0)
- 	  result_obj->set<json::array> ("graphs", std::move (graphs_arr));
-       }
- 
-   /* The "relatedLocations" property (SARIF v2.1.0 section 3.27.22) is
-      set up later, if any nested diagnostics occur within this diagnostic
-      group.  */
- 
-   /* "fixes" property (SARIF v2.1.0 section 3.27.30).  */
-   const rich_location *richloc = diagnostic.richloc;
-   if (richloc->get_num_fixit_hints ())
-     {
-       auto fix_arr = std::make_unique<json::array> ();
-       fix_arr->append<sarif_fix> (make_fix_object (*richloc));
-       result_obj->set<json::array> ("fixes", std::move (fix_arr));
-     }
- 
-   return result_obj;
- }
- 
- /* Make a "reportingDescriptor" object (SARIF v2.1.0 section 3.49)
-    for a GCC warning.  */
- 
- std::unique_ptr<sarif_reporting_descriptor>
- sarif_builder::
- make_reporting_descriptor_object_for_warning (const diagnostic_info &diagnostic,
- 					      diagnostic_t /*orig_diag_kind*/,
- 					      const char *option_text)
- {
-   auto reporting_desc = std::make_unique<sarif_reporting_descriptor> ();
- 
-   /* "id" property (SARIF v2.1.0 section 3.49.3).  */
-   reporting_desc->set_string ("id", option_text);
- 
-   /* We don't implement "name" property (SARIF v2.1.0 section 3.49.7), since
-      it seems redundant compared to "id".  */
- 
-   /* "helpUri" property (SARIF v2.1.0 section 3.49.12).  */
-   if (char *option_url = m_context.make_option_url (diagnostic.option_id))
-     {
-       reporting_desc->set_string ("helpUri", option_url);
-       free (option_url);
-     }
- 
-   return reporting_desc;
- }
- 
- /* Make a "reportingDescriptor" object (SARIF v2.1.0 section 3.49)
-    for CWE_ID, for use within the CWE taxa array.  */
- 
- std::unique_ptr<sarif_reporting_descriptor>
- sarif_builder::make_reporting_descriptor_object_for_cwe_id (int cwe_id) const
- {
-   auto reporting_desc = std::make_unique<sarif_reporting_descriptor> ();
- 
-   /* "id" property (SARIF v2.1.0 section 3.49.3).  */
-   {
-     pretty_printer pp;
-     pp_printf (&pp, "%i", cwe_id);
-     reporting_desc->set_string ("id", pp_formatted_text (&pp));
-   }
- 
-   /* "helpUri" property (SARIF v2.1.0 section 3.49.12).  */
-   {
-     char *url = get_cwe_url (cwe_id);
-     reporting_desc->set_string ("helpUri", url);
-     free (url);
-   }
- 
-   return reporting_desc;
- }
- 
- /* Make a "reportingDescriptorReference" object (SARIF v2.1.0 section 3.52)
-    referencing CWE_ID, for use within a result object.
-    Also, add CWE_ID to m_cwe_id_set.  */
- 
- std::unique_ptr<sarif_reporting_descriptor_reference>
- sarif_builder::
- make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id)
- {
-   auto desc_ref_obj = std::make_unique<sarif_reporting_descriptor_reference> ();
- 
-   /* "id" property (SARIF v2.1.0 section 3.52.4).  */
-   {
-     pretty_printer pp;
-     pp_printf (&pp, "%i", cwe_id);
-     desc_ref_obj->set_string ("id", pp_formatted_text (&pp));
-   }
- 
-   /* "toolComponent" property (SARIF v2.1.0 section 3.52.7).  */
-   desc_ref_obj->set<sarif_tool_component_reference>
-     ("toolComponent", make_tool_component_reference_object_for_cwe ());
- 
-   /* Add CWE_ID to our set.  */
-   gcc_assert (cwe_id > 0);
-   m_cwe_id_set.add (cwe_id);
- 
-   return desc_ref_obj;
- }
- 
- /* Make a "toolComponentReference" object (SARIF v2.1.0 section 3.54) that
-    references the CWE taxonomy.  */
- 
- std::unique_ptr<sarif_tool_component_reference>
- sarif_builder::
- make_tool_component_reference_object_for_cwe () const
- {
-   auto comp_ref_obj = std::make_unique<sarif_tool_component_reference> ();
- 
-   /* "name" property  (SARIF v2.1.0 section 3.54.3).  */
-   comp_ref_obj->set_string ("name", "cwe");
- 
-   return comp_ref_obj;
- }
- 
- /* Make an array suitable for use as the "locations" property of:
-    - a "result" object (SARIF v2.1.0 section 3.27.12), or
-    - a "notification" object (SARIF v2.1.0 section 3.58.4).
-    Use LOC_MGR for any locations that need "id" values.  */
- 
- std::unique_ptr<json::array>
- sarif_builder::make_locations_arr (sarif_location_manager &loc_mgr,
- 				   const diagnostic_info &diagnostic,
- 				   enum diagnostic_artifact_role role)
- {
-   auto locations_arr = std::make_unique<json::array> ();
-   logical_location logical_loc;
-   if (auto client_data_hooks = m_context.get_client_data_hooks ())
-     logical_loc = client_data_hooks->get_current_logical_location ();
- 
-   auto location_obj
-     = make_location_object (&loc_mgr, *diagnostic.richloc, logical_loc, role);
-   /* Don't add entirely empty location objects to the array.  */
-   if (!location_obj->is_empty ())
-     locations_arr->append<sarif_location> (std::move (location_obj));
- 
-   return locations_arr;
- }
- 
- /* If LOGICAL_LOC is non-null, use it to create a "logicalLocations" property
-    within LOCATION_OBJ (SARIF v2.1.0 section 3.28.4) with a minimal logical
-    location object referencing theRuns.logicalLocations (3.33.3).  */
- 
- void
- sarif_builder::
- set_any_logical_locs_arr (sarif_location &location_obj,
- 			  logical_location logical_loc)
- {
-   if (!logical_loc)
-     return;
-   gcc_assert (m_logical_loc_mgr);
-   auto location_locs_arr = std::make_unique<json::array> ();
- 
-   auto logical_loc_obj = make_minimal_sarif_logical_location (logical_loc);
- 
-   location_locs_arr->append<sarif_logical_location>
-     (std::move (logical_loc_obj));
- 
-   location_obj.set<json::array> ("logicalLocations",
- 				 std::move (location_locs_arr));
- }
- 
- /* Make a "location" object (SARIF v2.1.0 section 3.28) for RICH_LOC
-    and LOGICAL_LOC.
-    Use LOC_MGR for any locations that need "id" values, and for
-    any worklist items.
-    Note that we might not always have a LOC_MGR; see
-    https://github.com/oasis-tcs/sarif-spec/issues/712  */
- 
- std::unique_ptr<sarif_location>
- sarif_builder::make_location_object (sarif_location_manager *loc_mgr,
- 				     const rich_location &rich_loc,
- 				     logical_location logical_loc,
- 				     enum diagnostic_artifact_role role)
- {
-   class escape_nonascii_renderer : public content_renderer
-   {
-   public:
-     escape_nonascii_renderer (const rich_location &richloc,
- 			      enum diagnostics_escape_format escape_format)
-     : m_richloc (richloc),
-       m_escape_format (escape_format)
-     {}
- 
-     std::unique_ptr<sarif_multiformat_message_string>
-     render (const sarif_builder &builder) const final override
-     {
-       diagnostic_context dc;
-       diagnostic_initialize (&dc, 0);
-       dc.m_source_printing.enabled = true;
-       dc.m_source_printing.colorize_source_p = false;
-       dc.m_source_printing.show_labels_p = true;
-       dc.m_source_printing.show_line_numbers_p = true;
- 
-       rich_location my_rich_loc (m_richloc);
-       my_rich_loc.set_escape_on_output (true);
- 
-       diagnostic_source_print_policy source_policy (dc);
-       dc.set_escape_format (m_escape_format);
-       diagnostic_text_output_format text_output (dc);
-       source_policy.print (*text_output.get_printer (),
- 			   my_rich_loc, DK_ERROR, nullptr);
- 
-       const char *buf = pp_formatted_text (text_output.get_printer ());
-       std::unique_ptr<sarif_multiformat_message_string> result
- 	= builder.make_multiformat_message_string (buf);
- 
-       diagnostic_finish (&dc);
- 
-       return result;
-     }
-   private:
-     const rich_location &m_richloc;
-     enum diagnostics_escape_format m_escape_format;
-   } the_renderer (rich_loc,
- 		  m_context.get_escape_format ());
- 
-   auto location_obj = std::make_unique<sarif_location> ();
- 
-   /* Get primary loc from RICH_LOC.  */
-   location_t loc = rich_loc.get_loc ();
- 
-   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
-   const content_renderer *snippet_renderer
-     = rich_loc.escape_on_output_p () ? &the_renderer : nullptr;
-   if (auto phs_loc_obj
- 	= maybe_make_physical_location_object (loc, role,
- 					       rich_loc.get_column_override (),
- 					       snippet_renderer))
-     location_obj->set<sarif_physical_location> ("physicalLocation",
- 						std::move (phs_loc_obj));
- 
-   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
-   set_any_logical_locs_arr (*location_obj, logical_loc);
- 
-   /* Handle labelled ranges and/or secondary locations.  */
-   {
-     std::unique_ptr<json::array> annotations_arr = nullptr;
-     for (unsigned int i = 0; i < rich_loc.get_num_locations (); i++)
-       {
- 	const location_range *range = rich_loc.get_range (i);
- 	bool handled = false;
- 	if (const range_label *label = range->m_label)
- 	  {
- 	    label_text text = label->get_text (i);
- 	    if (text.get ())
- 	      {
- 		/* Create annotations for any labelled ranges.  */
- 		location_t range_loc = rich_loc.get_loc (i);
- 		auto region
- 		  = maybe_make_region_object (range_loc,
- 					      rich_loc.get_column_override ());
- 		if (region)
- 		  {
- 		    if (!annotations_arr)
- 		      annotations_arr = std::make_unique<json::array> ();
- 		    region->set<sarif_message>
- 		      ("message", make_message_object (text.get ()));
- 		    annotations_arr->append<sarif_region> (std::move (region));
- 		    handled = true;
- 		  }
- 	      }
- 	  }
- 
- 	/* Add related locations for any secondary locations in RICH_LOC
- 	   that don't have labels (and thus aren't added to "annotations"). */
- 	if (loc_mgr && i > 0 && !handled)
- 	  loc_mgr->add_relationship_to_worklist
- 	    (*location_obj.get (),
- 	     sarif_location_manager::worklist_item::kind::unlabelled_secondary_location,
- 	     range->m_loc);
-       }
-     if (annotations_arr)
-       /* "annotations" property (SARIF v2.1.0 section 3.28.6).  */
-       location_obj->set<json::array> ("annotations",
- 				      std::move (annotations_arr));
-   }
- 
-   if (loc_mgr)
-     add_any_include_chain (*loc_mgr, *location_obj.get (), loc);
- 
-   /* A flag for hinting that the diagnostic involves issues at the
-      level of character encodings (such as homoglyphs, or misleading
-      bidirectional control codes), and thus that it will be helpful
-      to the user if we show some representation of
-      how the characters in the pertinent source lines are encoded.  */
-   if (rich_loc.escape_on_output_p ())
-     {
-       sarif_property_bag &bag = location_obj->get_or_create_properties ();
-       bag.set_bool ("gcc/escapeNonAscii", rich_loc.escape_on_output_p ());
-     }
- 
-   return location_obj;
- }
- 
- /* If WHERE was #included from somewhere, add a worklist item
-    to LOC_MGR to lazily add a location for the #include location,
-    and relationships between it and the LOCATION_OBJ.
-    Compare with diagnostic_context::report_current_module, but rather
-    than iterating the current chain, we add the next edge and iterate
-    in the worklist, so that edges are only added once.  */
- 
- void
- sarif_builder::add_any_include_chain (sarif_location_manager &loc_mgr,
- 				      sarif_location &location_obj,
- 				      location_t where)
- {
-   if (where <= BUILTINS_LOCATION)
-     return;
- 
-   const line_map_ordinary *map = nullptr;
-   linemap_resolve_location (m_line_maps, where,
- 			    LRK_MACRO_DEFINITION_LOCATION,
- 			    &map);
- 
-   if (!map)
-     return;
- 
-   location_t include_loc = linemap_included_from (map);
-   map = linemap_included_from_linemap (m_line_maps, map);
-   if (!map)
-     return;
-   loc_mgr.add_relationship_to_worklist
-     (location_obj,
-      sarif_result::worklist_item::kind::included_from,
-      include_loc);
- }
- 
- /* Make a "location" object (SARIF v2.1.0 section 3.28) for WHERE
-    within an include chain.  */
- 
- std::unique_ptr<sarif_location>
- sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
- 				     location_t loc,
- 				     enum diagnostic_artifact_role role)
- {
-   auto location_obj = std::make_unique<sarif_location> ();
- 
-   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
-   if (auto phs_loc_obj
-       = maybe_make_physical_location_object (loc, role, 0, nullptr))
-     location_obj->set<sarif_physical_location> ("physicalLocation",
- 						std::move (phs_loc_obj));
- 
-   add_any_include_chain (loc_mgr, *location_obj.get (), loc);
- 
-   return location_obj;
- }
- 
- /* Make a "location" object (SARIF v2.1.0 section 3.28) for EVENT
-    within a diagnostic_path.  */
- 
- std::unique_ptr<sarif_location>
- sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
- 				     const diagnostic_event &event,
- 				     enum diagnostic_artifact_role role)
- {
-   auto location_obj = std::make_unique<sarif_location> ();
- 
-   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
-   location_t loc = event.get_location ();
-   if (auto phs_loc_obj
- 	= maybe_make_physical_location_object (loc, role, 0, nullptr))
-     location_obj->set<sarif_physical_location> ("physicalLocation",
- 						std::move (phs_loc_obj));
- 
-   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
-   logical_location logical_loc = event.get_logical_location ();
-   set_any_logical_locs_arr (*location_obj, logical_loc);
- 
-   /* "message" property (SARIF v2.1.0 section 3.28.5).  */
-   std::unique_ptr<pretty_printer> pp = get_printer ()->clone ();
-   event.print_desc (*pp);
-   location_obj->set<sarif_message>
-     ("message",
-      make_message_object (pp_formatted_text (pp.get ())));
- 
-   add_any_include_chain (loc_mgr, *location_obj.get (), loc);
- 
-   return location_obj;
- }
- 
- /* Make a "physicalLocation" object (SARIF v2.1.0 section 3.29) for LOC.
- 
-    If COLUMN_OVERRIDE is non-zero, then use it as the column number
-    if LOC has no column information.
- 
-    Ensure that we have an artifact object for the file, adding ROLE to it,
-    and flagging that we will attempt to embed the contents of the artifact
-    when writing it out.  */
- 
- std::unique_ptr<sarif_physical_location>
- sarif_builder::
- maybe_make_physical_location_object (location_t loc,
- 				     enum diagnostic_artifact_role role,
- 				     int column_override,
- 				     const content_renderer *snippet_renderer)
- {
-   if (loc <= BUILTINS_LOCATION || LOCATION_FILE (loc) == nullptr)
-     return nullptr;
- 
-   auto phys_loc_obj = std::make_unique<sarif_physical_location> ();
- 
-   /* "artifactLocation" property (SARIF v2.1.0 section 3.29.3).  */
-   phys_loc_obj->set<sarif_artifact_location>
-     ("artifactLocation", make_artifact_location_object (loc));
-   get_or_create_artifact (LOCATION_FILE (loc), role, true);
- 
-   /* "region" property (SARIF v2.1.0 section 3.29.4).  */
-   if (auto region_obj = maybe_make_region_object (loc, column_override))
-     phys_loc_obj->set<sarif_region> ("region", std::move (region_obj));
- 
-   /* "contextRegion" property (SARIF v2.1.0 section 3.29.5).  */
-   if (auto context_region_obj
- 	= maybe_make_region_object_for_context (loc, snippet_renderer))
-     phys_loc_obj->set<sarif_region> ("contextRegion",
- 				     std::move (context_region_obj));
- 
-   /* Instead, we add artifacts to the run as a whole,
-      with artifact.contents.
-      Could do both, though.  */
- 
-   return phys_loc_obj;
- }
- 
- /* Make an "artifactLocation" object (SARIF v2.1.0 section 3.4) for LOC,
-    or return nullptr.  */
- 
- std::unique_ptr<sarif_artifact_location>
- sarif_builder::make_artifact_location_object (location_t loc)
- {
-   return make_artifact_location_object (LOCATION_FILE (loc));
- }
- 
- /* The ID value for use in "uriBaseId" properties (SARIF v2.1.0 section 3.4.4)
-    for when we need to express paths relative to PWD.  */
- 
- #define PWD_PROPERTY_NAME ("PWD")
- 
- /* Make an "artifactLocation" object (SARIF v2.1.0 section 3.4) for FILENAME,
-    or return nullptr.  */
- 
- std::unique_ptr<sarif_artifact_location>
- sarif_builder::make_artifact_location_object (const char *filename)
- {
-   auto artifact_loc_obj = std::make_unique<sarif_artifact_location> ();
- 
-   /* "uri" property (SARIF v2.1.0 section 3.4.3).  */
-   artifact_loc_obj->set_string ("uri", filename);
- 
-   if (filename[0] != '/')
-     {
-       /* If we have a relative path, set the "uriBaseId" property
- 	 (SARIF v2.1.0 section 3.4.4).  */
-       artifact_loc_obj->set_string ("uriBaseId", PWD_PROPERTY_NAME);
-       m_seen_any_relative_paths = true;
-     }
- 
-   return artifact_loc_obj;
- }
- 
- /* Get the PWD, or nullptr, as an absolute file-based URI,
-    adding a trailing forward slash (as required by SARIF v2.1.0
-    section 3.14.14).  */
- 
- static char *
- make_pwd_uri_str ()
- {
-   /* The prefix of a file-based URI, up to, but not including the path. */
- #define FILE_PREFIX ("file://")
- 
-   const char *pwd = getpwd ();
-   if (!pwd)
-     return nullptr;
-   size_t len = strlen (pwd);
-   if (len == 0 || pwd[len - 1] != '/')
-     return concat (FILE_PREFIX, pwd, "/", nullptr);
-   else
-     {
-       gcc_assert (pwd[len - 1] == '/');
-       return concat (FILE_PREFIX, pwd, nullptr);
-     }
- }
- 
- /* Make an "artifactLocation" object (SARIF v2.1.0 section 3.4) for the pwd,
-    for use in the "run.originalUriBaseIds" property (SARIF v2.1.0
-    section 3.14.14) when we have any relative paths.  */
- 
- std::unique_ptr<sarif_artifact_location>
- sarif_builder::make_artifact_location_object_for_pwd () const
- {
-   auto artifact_loc_obj = std::make_unique<sarif_artifact_location> ();
- 
-   /* "uri" property (SARIF v2.1.0 section 3.4.3).  */
-   if (char *pwd = make_pwd_uri_str ())
-     {
-       gcc_assert (strlen (pwd) > 0);
-       gcc_assert (pwd[strlen (pwd) - 1] == '/');
-       artifact_loc_obj->set_string ("uri", pwd);
-       free (pwd);
-     }
- 
-   return artifact_loc_obj;
- }
- 
- /* Get the column number within EXPLOC.  */
- 
- int
- sarif_builder::get_sarif_column (expanded_location exploc) const
- {
-   cpp_char_column_policy policy (m_tabstop, cpp_wcwidth);
-   return location_compute_display_column (m_context.get_file_cache (),
- 					  exploc, policy);
- }
- 
- /* Make a "region" object (SARIF v2.1.0 section 3.30) for LOC,
-    or return nullptr.
- 
-    If COLUMN_OVERRIDE is non-zero, then use it as the column number
-    if LOC has no column information.
- 
-    We only support text properties of regions ("text regions"),
-    not binary properties ("binary regions"); see 3.30.1.  */
- 
- std::unique_ptr<sarif_region>
- sarif_builder::maybe_make_region_object (location_t loc,
- 					 int column_override) const
- {
-   location_t caret_loc = get_pure_location (loc);
- 
-   if (caret_loc <= BUILTINS_LOCATION)
-     return nullptr;
- 
-   location_t start_loc = get_start (loc);
-   location_t finish_loc = get_finish (loc);
- 
-   expanded_location exploc_caret = expand_location (caret_loc);
-   expanded_location exploc_start = expand_location (start_loc);
-   expanded_location exploc_finish = expand_location (finish_loc);
- 
-   if (exploc_start.file !=exploc_caret.file)
-     return nullptr;
-   if (exploc_finish.file !=exploc_caret.file)
-     return nullptr;
- 
-   /* We can have line == 0 in the presence of "#" lines.
-      SARIF requires lines > 0, so if we hit this case we don't have a
-      way of validly representing the region as SARIF; bail out.  */
-   if (exploc_start.line <= 0)
-     return nullptr;
- 
-   auto region_obj = std::make_unique<sarif_region> ();
- 
-   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
-   region_obj->set_integer ("startLine", exploc_start.line);
- 
-   /* "startColumn" property (SARIF v2.1.0 section 3.30.6).
- 
-      We use column == 0 to mean the whole line, so omit the column
-      information for this case, unless COLUMN_OVERRIDE is non-zero,
-      (for handling certain awkward lexer diagnostics)  */
- 
-   if (exploc_start.column == 0 && column_override)
-     /* Use the provided column number.  */
-     exploc_start.column = column_override;
- 
-   if (exploc_start.column > 0)
-     {
-       int start_column = get_sarif_column (exploc_start);
-       region_obj->set_integer ("startColumn", start_column);
-     }
- 
-   /* "endLine" property (SARIF v2.1.0 section 3.30.7) */
-   if (exploc_finish.line != exploc_start.line
-       && exploc_finish.line > 0)
-     region_obj->set_integer ("endLine", exploc_finish.line);
- 
-   /* "endColumn" property (SARIF v2.1.0 section 3.30.8).
-      This expresses the column immediately beyond the range.
- 
-      We use column == 0 to mean the whole line, so omit the column
-      information for this case.  */
-   if (exploc_finish.column > 0)
-     {
-       int next_column = get_sarif_column (exploc_finish) + 1;
-       region_obj->set_integer ("endColumn", next_column);
-     }
- 
-   return region_obj;
- }
- 
- /* Make a "region" object (SARIF v2.1.0 section 3.30) for the "contextRegion"
-    property (SARIF v2.1.0 section 3.29.5) of a "physicalLocation".
- 
-    This is similar to maybe_make_region_object, but ignores column numbers,
-    covering the line(s) as a whole, and including a "snippet" property
-    embedding those source lines, making it easier for consumers to show
-    the pertinent source.  */
- 
- std::unique_ptr<sarif_region>
- sarif_builder::
- maybe_make_region_object_for_context (location_t loc,
- 				      const content_renderer *snippet_renderer)
-   const
- {
-   location_t caret_loc = get_pure_location (loc);
- 
-   if (caret_loc <= BUILTINS_LOCATION)
-     return nullptr;
- 
-   location_t start_loc = get_start (loc);
-   location_t finish_loc = get_finish (loc);
- 
-   expanded_location exploc_caret = expand_location (caret_loc);
-   expanded_location exploc_start = expand_location (start_loc);
-   expanded_location exploc_finish = expand_location (finish_loc);
- 
-   if (exploc_start.file !=exploc_caret.file)
-     return nullptr;
-   if (exploc_finish.file !=exploc_caret.file)
-     return nullptr;
- 
-   /* We can have line == 0 in the presence of "#" lines.
-      SARIF requires lines > 0, so if we hit this case we don't have a
-      way of validly representing the region as SARIF; bail out.  */
-   if (exploc_start.line <= 0)
-     return nullptr;
- 
-   auto region_obj = std::make_unique<sarif_region> ();
- 
-   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
-   region_obj->set_integer ("startLine", exploc_start.line);
- 
-   /* "endLine" property (SARIF v2.1.0 section 3.30.7) */
-   if (exploc_finish.line != exploc_start.line
-       && exploc_finish.line > 0)
-     region_obj->set_integer ("endLine", exploc_finish.line);
- 
-   /* "snippet" property (SARIF v2.1.0 section 3.30.13).  */
-   if (auto artifact_content_obj
- 	= maybe_make_artifact_content_object (exploc_start.file,
- 					      exploc_start.line,
- 					      exploc_finish.line,
- 					      snippet_renderer))
-     region_obj->set<sarif_artifact_content> ("snippet",
- 					     std::move (artifact_content_obj));
- 
-   return region_obj;
- }
- 
- /* Make a "region" object (SARIF v2.1.0 section 3.30) for the deletion region
-    of HINT (as per SARIF v2.1.0 section 3.57.3).  */
- 
- std::unique_ptr<sarif_region>
- sarif_builder::make_region_object_for_hint (const fixit_hint &hint) const
- {
-   location_t start_loc = hint.get_start_loc ();
-   location_t next_loc = hint.get_next_loc ();
- 
-   expanded_location exploc_start = expand_location (start_loc);
-   expanded_location exploc_next = expand_location (next_loc);
- 
-   auto region_obj = std::make_unique<sarif_region> ();
- 
-   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
-   region_obj->set_integer ("startLine", exploc_start.line);
- 
-   /* "startColumn" property (SARIF v2.1.0 section 3.30.6) */
-   int start_col = get_sarif_column (exploc_start);
-   region_obj->set_integer ("startColumn", start_col);
- 
-   /* "endLine" property (SARIF v2.1.0 section 3.30.7) */
-   if (exploc_next.line != exploc_start.line)
-     region_obj->set_integer ("endLine", exploc_next.line);
- 
-   /* "endColumn" property (SARIF v2.1.0 section 3.30.8).
-      This expresses the column immediately beyond the range.  */
-   int next_col =  get_sarif_column (exploc_next);
-   region_obj->set_integer ("endColumn", next_col);
- 
-   return region_obj;
- }
- 
- /* Attempt to get a string for a logicalLocation's "kind" property
-    (SARIF v2.1.0 section 3.33.7).
-    Return nullptr if unknown.  */
- 
- static const char *
- maybe_get_sarif_kind (enum logical_location_kind kind)
- {
-   switch (kind)
-     {
-     default:
-       gcc_unreachable ();
-     case logical_location_kind::unknown:
-       return nullptr;
- 
-     /* Kinds within executable code.  */
-     case logical_location_kind::function:
-       return "function";
-     case logical_location_kind::member:
-       return "member";
-     case logical_location_kind::module_:
-       return "module";
-     case logical_location_kind::namespace_:
-       return "namespace";
-     case logical_location_kind::type:
-       return "type";
-     case logical_location_kind::return_type:
-       return "returnType";
-     case logical_location_kind::parameter:
-       return "parameter";
-     case logical_location_kind::variable:
-       return "variable";
- 
-     /* Kinds within XML or HTML documents.  */
-     case logical_location_kind::element:
-       return "element";
-     case logical_location_kind::attribute:
-       return "attribute";
-     case logical_location_kind::text:
-       return "text";
-     case logical_location_kind::comment:
-       return "comment";
-     case logical_location_kind::processing_instruction:
-       return "processingInstruction";
-     case logical_location_kind::dtd:
-       return "dtd";
-     case logical_location_kind::declaration:
-       return "declaration";
- 
-     /* Kinds within JSON documents.  */
-     case logical_location_kind::object:
-       return "object";
-     case logical_location_kind::array:
-       return "array";
-     case logical_location_kind::property:
-       return "property";
-     case logical_location_kind::value:
-       return "value";
-     }
- }
- 
- /* Set PROPERTY_NAME within this bag to a "logicalLocation" object (SARIF v2.1.0
-    section 3.33) for LOGICAL_LOC.  The object has an "index" property to refer to
-    theRuns.logicalLocations (3.33.3).  */
- 
- void
- sarif_property_bag::set_logical_location (const char *property_name,
- 					  sarif_builder &builder,
- 					  logical_location logical_loc)
- {
-   set<sarif_logical_location>
-     (property_name,
-      builder.make_minimal_sarif_logical_location (logical_loc));
- }
- 
- static void
- copy_any_property_bag (const diagnostics::digraphs::object &input_obj,
- 		       sarif_object &output_obj)
- {
-   if (input_obj.get_property_bag ())
-     {
-       const json::object &old_bag = *input_obj.get_property_bag ();
-       sarif_property_bag &new_bag = output_obj.get_or_create_properties ();
-       for (size_t i = 0; i < old_bag.get_num_keys (); ++i)
- 	{
- 	  const char *key = old_bag.get_key (i);
- 	  json::value *val = old_bag.get (key);
- 	  new_bag.set (key, val->clone ());
- 	}
-     }
- }
- 
- std::unique_ptr<sarif_graph>
- make_sarif_graph (const diagnostics::digraphs::digraph &g,
- 		  sarif_builder *builder,
- 		  sarif_location_manager *sarif_location_mgr)
- {
-   auto result = std::make_unique<sarif_graph> ();
- 
-   // 3.39.2 description property
-   if (const char *desc = g.get_description ())
-     if (builder)
-       result->set<sarif_message> ("description",
- 				  builder->make_message_object (desc));
- 
-   copy_any_property_bag (g, *result);
- 
-   // 3.39.3 nodes property
-   auto nodes_arr = std::make_unique<json::array> ();
-   const int num_nodes = g.get_num_nodes ();
-   for (int i = 0; i < num_nodes; ++i)
-     nodes_arr->append (make_sarif_node (g.get_node (i),
- 					builder,
- 					sarif_location_mgr));
-   result->set ("nodes", std::move (nodes_arr));
- 
-   // 3.39.4 edges property
-   auto edges_arr = std::make_unique<json::array> ();
-   const int num_edges = g.get_num_edges ();
-   for (int i = 0; i < num_edges; ++i)
-     edges_arr->append (make_sarif_edge (g.get_edge (i), builder));
-   result->set ("edges", std::move (edges_arr));
- 
-   return result;
- }
- 
- std::unique_ptr<sarif_node>
- make_sarif_node (const diagnostics::digraphs::node &n,
- 		 sarif_builder *builder,
- 		 sarif_location_manager *sarif_location_mgr)
- {
-   auto result = std::make_unique<sarif_node> ();
- 
-   // 3.40.2 id property
-   result->set_string ("id", n.get_id ().c_str ());
- 
-   copy_any_property_bag (n, *result);
- 
-   // 3.40.3 label property
-   if (const char *label = n.get_label ())
-     if (builder)
-       result->set<sarif_message> ("label",
- 				  builder->make_message_object (label));
- 
-   // 3.40.4 location property
-   if (n.get_logical_loc ()
-       || n.get_physical_loc () != UNKNOWN_LOCATION)
-     if (builder)
-       {
- 	rich_location rich_loc
- 	  (line_table, n.get_physical_loc ());
- 	auto loc_obj
- 	  = builder->make_location_object
- 	      (sarif_location_mgr,
- 	       rich_loc,
- 	       n.get_logical_loc (),
- 	       diagnostic_artifact_role::scanned_file);
- 	result->set<sarif_location> ("location",
- 				     std::move (loc_obj));
-     }
- 
-   // 3.40.5 children property
-   if (const int num_children = n.get_num_children ())
-     {
-       auto children_arr = std::make_unique<json::array> ();
-       for (int i = 0; i < num_children; ++i)
- 	children_arr->append (make_sarif_node (n.get_child (i),
- 					       builder,
- 					       sarif_location_mgr));
-       result->set ("children", std::move (children_arr));
-     }
- 
-   return result;
- }
- 
- std::unique_ptr<sarif_edge>
- make_sarif_edge (const diagnostics::digraphs::edge &e,
- 		 sarif_builder *builder)
- {
-   auto result = std::make_unique<sarif_edge> ();
- 
-   // 3.41.2 id property
-   result->set_string ("id", e.get_id ().c_str ());
- 
-   copy_any_property_bag (e, *result);
- 
-   // 3.41.3 label property
-   if (const char *label = e.get_label ())
-     if (builder)
-       result->set<sarif_message> ("label",
- 				  builder->make_message_object (label));
- 
-   // 3.41.4 sourceNodeId property
-   result->set_string ("sourceNodeId", e.get_src_node ().get_id ().c_str ());
- 
-   // 3.41.5 targetNodeId property
-   result->set_string ("targetNodeId", e.get_dst_node ().get_id ().c_str ());
- 
-   return result;
- }
- 
- void
- sarif_property_bag::set_graph (const char *property_name,
- 			       sarif_builder &builder,
- 			       sarif_location_manager *sarif_location_mgr,
- 			       const diagnostics::digraphs::digraph &g)
- {
-   set<sarif_graph> (property_name,
- 		    make_sarif_graph (g, &builder, sarif_location_mgr));
- }
- 
- /* Ensure that m_cached_logical_locs has a "logicalLocation" object
-    (SARIF v2.1.0 section 3.33) for K, and return its index within the
-    array.  */
- 
- int
- sarif_builder::
- ensure_sarif_logical_location_for (logical_location k)
- {
-   gcc_assert (m_logical_loc_mgr);
- 
-   auto sarif_logical_loc = std::make_unique<sarif_logical_location> ();
- 
-   if (const char *short_name = m_logical_loc_mgr->get_short_name (k))
-     sarif_logical_loc->set_string ("name", short_name);
- 
-   /* "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
-   if (const char *name_with_scope = m_logical_loc_mgr->get_name_with_scope (k))
-     sarif_logical_loc->set_string ("fullyQualifiedName", name_with_scope);
- 
-   /* "decoratedName" property (SARIF v2.1.0 section 3.33.6).  */
-   if (const char *internal_name = m_logical_loc_mgr->get_internal_name (k))
-     sarif_logical_loc->set_string ("decoratedName", internal_name);
- 
-   /* "kind" property (SARIF v2.1.0 section 3.33.7).  */
-   enum logical_location_kind kind = m_logical_loc_mgr->get_kind (k);
-   if (const char *sarif_kind_str = maybe_get_sarif_kind (kind))
-     sarif_logical_loc->set_string ("kind", sarif_kind_str);
- 
-   /* "parentIndex" property (SARIF v2.1.0 section 3.33.8).  */
-   if (auto parent_key = m_logical_loc_mgr->get_parent (k))
-     {
-       /* Recurse upwards.  */
-       int parent_index = ensure_sarif_logical_location_for (parent_key);
-       sarif_logical_loc->set_integer ("parentIndex", parent_index);
-     }
- 
-   /* Consolidate if this logical location already exists.  */
-   int index
-     = m_cached_logical_locs->append_uniquely (std::move (sarif_logical_loc));
- 
-   return index;
- }
- 
- /* Ensure that theRuns.logicalLocations (3.14.17) has a "logicalLocation" object
-    (SARIF v2.1.0 section 3.33) for LOGICAL_LOC.
-    Create and return a minimal logicalLocation object referring to the
-    full object by index.  */
- 
- std::unique_ptr<sarif_logical_location>
- sarif_builder::
- make_minimal_sarif_logical_location (logical_location logical_loc)
- {
-   gcc_assert (m_logical_loc_mgr);
- 
-   /* Ensure that m_cached_logical_locs has a "logicalLocation" object
-      (SARIF v2.1.0 section 3.33) for LOGICAL_LOC, and return its index within
-      the array.  */
- 
-   auto sarif_logical_loc = std::make_unique <sarif_logical_location> ();
- 
-   int index = ensure_sarif_logical_location_for (logical_loc);
- 
-   // 3.33.3 index property
-   sarif_logical_loc->set_integer ("index", index);
- 
-   /* "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
-   if (const char *name_with_scope
-         = m_logical_loc_mgr->get_name_with_scope (logical_loc))
-     sarif_logical_loc->set_string ("fullyQualifiedName", name_with_scope);
- 
-   return sarif_logical_loc;
- }
- 
- label_text
- make_sarif_url_for_event (const sarif_code_flow *code_flow,
- 			  diagnostic_event_id_t event_id)
- {
-   gcc_assert (event_id.known_p ());
- 
-   if (!code_flow)
-     return label_text ();
- 
-   const sarif_thread_flow_location &tfl_obj
-     = code_flow->get_thread_flow_loc_obj (event_id);
-   const int location_idx = tfl_obj.get_index_within_parent ();
- 
-   const sarif_thread_flow &thread_flow_obj = tfl_obj.get_parent ();
-   const int thread_flow_idx = thread_flow_obj.get_index_within_parent ();
- 
-   const sarif_code_flow &code_flow_obj = thread_flow_obj.get_parent ();
-   const int code_flow_idx = code_flow_obj.get_index_within_parent ();
- 
-   const sarif_result &result_obj = code_flow_obj.get_parent ();
-   const int result_idx = result_obj.get_index_within_parent ();
- 
-   /* We only support a single run object in the log.  */
-   const int run_idx = 0;
- 
-   char *buf = xasprintf
-     ("sarif:/runs/%i/results/%i/codeFlows/%i/threadFlows/%i/locations/%i",
-      run_idx, result_idx, code_flow_idx, thread_flow_idx, location_idx);
-   return label_text::take (buf);
- }
- 
- /* Make a "codeFlow" object (SARIF v2.1.0 section 3.36) for PATH.  */
- 
- std::unique_ptr<sarif_code_flow>
- sarif_builder::make_code_flow_object (sarif_result &result,
- 				      unsigned idx_within_parent,
- 				      const diagnostic_path &path)
- {
-   auto code_flow_obj
-     = std::make_unique <sarif_code_flow> (result, idx_within_parent);
- 
-   /* First pass:
-      Create threadFlows and threadFlowLocation objects within them,
-      effectively recording a mapping from event_id to threadFlowLocation
-      so that we can later go from an event_id to a URI within the
-      SARIF file.  */
-   for (unsigned i = 0; i < path.num_events (); i++)
-     {
-       const diagnostic_event &event = path.get_event (i);
-       const diagnostic_thread_id_t thread_id = event.get_thread_id ();
- 
-       sarif_thread_flow &thread_flow_obj
- 	= code_flow_obj->get_or_append_thread_flow (path.get_thread (thread_id),
- 						    thread_id);
-       thread_flow_obj.add_location ();
-     }
- 
-   /* Second pass: walk the events, populating the tfl objs.  */
-   m_current_code_flow = code_flow_obj.get ();
-   for (unsigned i = 0; i < path.num_events (); i++)
-     {
-       const diagnostic_event &event = path.get_event (i);
-       sarif_thread_flow_location &thread_flow_loc_obj
- 	= code_flow_obj->get_thread_flow_loc_obj (i);
-       populate_thread_flow_location_object (result,
- 					    thread_flow_loc_obj,
- 					    event,
- 					    i);
-     }
-   m_current_code_flow = nullptr;
- 
-   return code_flow_obj;
- }
- 
- /* Populate TFL_OBJ, a "threadFlowLocation" object (SARIF v2.1.0 section 3.38)
-    based on EVENT.  */
- 
- void
- sarif_builder::
- populate_thread_flow_location_object (sarif_result &result,
- 				      sarif_thread_flow_location &tfl_obj,
- 				      const diagnostic_event &ev,
- 				      int event_execution_idx)
- {
-   /* Give diagnostic_event subclasses a chance to add custom properties
-      via a property bag.  */
-   ev.maybe_add_sarif_properties (*this, tfl_obj);
- 
-   if (get_opts ().m_state_graph)
-     if (auto state_graph = ev.maybe_make_diagnostic_state_graph (true))
-       {
- 	sarif_property_bag &props = tfl_obj.get_or_create_properties ();
- 
- #define PROPERTY_PREFIX "gcc/diagnostic_event/"
- 	props.set_graph (PROPERTY_PREFIX "state_graph",
- 			 *this,
- 			 /* Use RESULT for any related locations in the graph's
- 			    nodes.
- 			    It's not clear if this is correct; see:
- 			    https://github.com/oasis-tcs/sarif-spec/issues/712
- 			 */
- 			 &result,
- 			 *state_graph);
- #undef PROPERTY_PREFIX
-       }
- 
-   /* "location" property (SARIF v2.1.0 section 3.38.3).  */
-   tfl_obj.set<sarif_location>
-     ("location",
-      make_location_object (result, ev, diagnostic_artifact_role::traced_file));
- 
-   /* "kinds" property (SARIF v2.1.0 section 3.38.8).  */
-   diagnostic_event::meaning m = ev.get_meaning ();
-   if (auto kinds_arr = maybe_make_kinds_array (m))
-     tfl_obj.set<json::array> ("kinds", std::move (kinds_arr));
- 
-   /* "nestingLevel" property (SARIF v2.1.0 section 3.38.10).  */
-   tfl_obj.set_integer ("nestingLevel", ev.get_stack_depth ());
- 
-   /* "executionOrder" property (SARIF v2.1.0 3.38.11).
-      Offset by 1 to match the human-readable values emitted by %@.  */
-   tfl_obj.set_integer ("executionOrder", event_execution_idx + 1);
- 
-   /* It might be nice to eventually implement the following for -fanalyzer:
-      - the "stack" property (SARIF v2.1.0 section 3.38.5)
-      - the "state" property (SARIF v2.1.0 section 3.38.9)
-      - the "importance" property (SARIF v2.1.0 section 3.38.13).  */
- }
- 
- /* If M has any known meaning, make a json array suitable for the "kinds"
-    property of a "threadFlowLocation" object (SARIF v2.1.0 section 3.38.8).
- 
-    Otherwise, return nullptr.  */
- 
- std::unique_ptr<json::array>
- sarif_builder::maybe_make_kinds_array (diagnostic_event::meaning m) const
- {
-   if (m.m_verb == diagnostic_event::verb::unknown
-       && m.m_noun == diagnostic_event::noun::unknown
-       && m.m_property == diagnostic_event::property::unknown)
-     return nullptr;
- 
-   auto kinds_arr = std::make_unique<json::array> ();
-   if (const char *verb_str
- 	= diagnostic_event::meaning::maybe_get_verb_str (m.m_verb))
-     kinds_arr->append_string (verb_str);
-   if (const char *noun_str
- 	= diagnostic_event::meaning::maybe_get_noun_str (m.m_noun))
-     kinds_arr->append_string (noun_str);
-   if (const char *property_str
- 	= diagnostic_event::meaning::maybe_get_property_str (m.m_property))
-     kinds_arr->append_string (property_str);
-   return kinds_arr;
- }
- 
- /* In "3.11.5 Messages with placeholders":
-    "Within both plain text and formatted message strings, the characters
-    "{" and "}" SHALL be represented by the character sequences
-    "{{" and "}}" respectively."  */
- 
- static std::string
- escape_braces (const char *text)
- {
-   std::string result;
-   while (char ch = *text++)
-     switch (ch)
-       {
-       case '{':
-       case '}':
- 	result += ch;
- 	/* Fall through.  */
-       default:
- 	result += ch;
- 	break;
-       }
-   return result;
- }
- 
- static void
- set_string_property_escaping_braces (json::object &obj,
- 				     const char *property_name,
- 				     const char *value)
- {
-   std::string escaped (escape_braces (value));
-   obj.set_string (property_name, escaped.c_str ());
- }
- 
- /* Make a "message" object (SARIF v2.1.0 section 3.11) for MSG.  */
- 
- std::unique_ptr<sarif_message>
- sarif_builder::make_message_object (const char *msg) const
- {
-   auto message_obj = std::make_unique<sarif_message> ();
- 
-   /* "text" property (SARIF v2.1.0 section 3.11.8).  */
-   set_string_property_escaping_braces (*message_obj,
- 				       "text", msg);
- 
-   return message_obj;
- }
- 
- /* Make a "message" object (SARIF v2.1.0 section 3.11) for DIAGRAM.
-    We emit the diagram as a code block within the Markdown part
-    of the message.  */
- 
- std::unique_ptr<sarif_message>
- sarif_builder::make_message_object_for_diagram (const diagnostic_diagram &diagram)
- {
-   auto message_obj = std::make_unique<sarif_message> ();
- 
-   /* "text" property (SARIF v2.1.0 section 3.11.8).  */
-   set_string_property_escaping_braces (*message_obj,
- 				       "text", diagram.get_alt_text ());
- 
-   pretty_printer *const pp = m_printer;
-   char *saved_prefix = pp_take_prefix (pp);
-   pp_set_prefix (pp, nullptr);
- 
-   /* "To produce a code block in Markdown, simply indent every line of
-      the block by at least 4 spaces or 1 tab."
-      Here we use 4 spaces.  */
-   diagram.get_canvas ().print_to_pp (pp, "    ");
-   pp_set_prefix (pp, saved_prefix);
- 
-   /* "markdown" property (SARIF v2.1.0 section 3.11.9).  */
-   set_string_property_escaping_braces (*message_obj,
- 				       "markdown", pp_formatted_text (pp));
- 
-   pp_clear_output_area (pp);
- 
-   return message_obj;
- }
- 
- /* Make a "multiformatMessageString object" (SARIF v2.1.0 section 3.12)
-    for MSG.  */
- 
- std::unique_ptr<sarif_multiformat_message_string>
- sarif_builder::make_multiformat_message_string (const char *msg) const
- {
-   auto message_obj = std::make_unique<sarif_multiformat_message_string> ();
- 
-   /* "text" property (SARIF v2.1.0 section 3.12.3).  */
-   set_string_property_escaping_braces (*message_obj,
- 				       "text", msg);
- 
-   return message_obj;
- }
- 
- /* Convert VERSION to a value for the "$schema" property
-    of a "sarifLog" object (SARIF v2.1.0 section 3.13.3).  */
- 
- static const char *
- sarif_version_to_url (enum sarif_version version)
- {
-   switch (version)
-     {
-     default:
-       gcc_unreachable ();
-     case sarif_version::v2_1_0:
-       return "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json";
-     case sarif_version::v2_2_prerelease_2024_08_08:
-       return "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/refs/tags/2.2-prerelease-2024-08-08/sarif-2.2/schema/sarif-2-2.schema.json";
-     }
- }
- 
- /* Convert VERSION to a value for the "version" property
-    of a "sarifLog" object (SARIF v2.1.0 section 3.13.2).  */
- 
- static const char *
- sarif_version_to_property (enum sarif_version version)
- {
-   switch (version)
-     {
-     default:
-       gcc_unreachable ();
-     case sarif_version::v2_1_0:
-       return "2.1.0";
-     case sarif_version::v2_2_prerelease_2024_08_08:
-       /* I would have used "2.2-prerelease-2024-08-08",
- 	 but the schema only accepts "2.2".  */
-       return "2.2";
-     }
- }
- 
- /* Make a top-level "sarifLog" object (SARIF v2.1.0 section 3.13).  */
- 
- std::unique_ptr<sarif_log>
- sarif_builder::
- make_top_level_object (std::unique_ptr<sarif_invocation> invocation_obj,
- 		       std::unique_ptr<json::array> results)
- {
-   auto log_obj = std::make_unique<sarif_log> ();
- 
-   /* "$schema" property (SARIF v2.1.0 section 3.13.3) .  */
-   log_obj->set_string ("$schema", sarif_version_to_url (get_version ()));
- 
-   /* "version" property (SARIF v2.1.0 section 3.13.2).  */
-   log_obj->set_string ("version", sarif_version_to_property (get_version ()));
- 
-   /* "runs" property (SARIF v2.1.0 section 3.13.4).  */
-   auto run_arr = std::make_unique<json::array> ();
-   auto run_obj = make_run_object (std::move (invocation_obj),
- 				  std::move (results));
-   run_arr->append<sarif_run> (std::move (run_obj));
-   log_obj->set<json::array> ("runs", std::move (run_arr));
- 
-   return log_obj;
- }
- 
- /* Make a "run" object (SARIF v2.1.0 section 3.14).  */
- 
- std::unique_ptr<sarif_run>
- sarif_builder::
- make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
- 		 std::unique_ptr<json::array> results)
- {
-   auto run_obj = std::make_unique<sarif_run> ();
- 
-   /* "tool" property (SARIF v2.1.0 section 3.14.6).  */
-   run_obj->set<sarif_tool> ("tool", make_tool_object ());
- 
-   /* "taxonomies" property (SARIF v2.1.0 section 3.14.8).  */
-   if (auto taxonomies_arr = maybe_make_taxonomies_array ())
-     run_obj->set<json::array> ("taxonomies", std::move (taxonomies_arr));
- 
-   /* "invocations" property (SARIF v2.1.0 section 3.14.11).  */
-   {
-     auto invocations_arr = std::make_unique<json::array> ();
-     invocations_arr->append (std::move (invocation_obj));
-     run_obj->set<json::array> ("invocations", std::move (invocations_arr));
-   }
- 
-   /* "originalUriBaseIds (SARIF v2.1.0 section 3.14.14).  */
-   if (m_seen_any_relative_paths)
-     {
-       auto orig_uri_base_ids = std::make_unique<json::object> ();
-       orig_uri_base_ids->set<sarif_artifact_location>
- 	(PWD_PROPERTY_NAME, make_artifact_location_object_for_pwd ());
-       run_obj->set<json::object> ("originalUriBaseIds",
- 				  std::move (orig_uri_base_ids));
-     }
- 
-   /* "artifacts" property (SARIF v2.1.0 section 3.14.15).  */
-   auto artifacts_arr = std::make_unique<json::array> ();
-   for (auto iter : m_filename_to_artifact_map)
-     {
-       sarif_artifact *artifact_obj = iter.second;
-       if (artifact_obj->embed_contents_p ())
- 	artifact_obj->populate_contents (*this);
-       artifact_obj->populate_roles ();
-       artifacts_arr->append (artifact_obj);
-     }
-   run_obj->set<json::array> ("artifacts", std::move (artifacts_arr));
-   m_filename_to_artifact_map.empty ();
- 
-   /* "results" property (SARIF v2.1.0 section 3.14.23).  */
-   run_obj->set<json::array> ("results", std::move (results));
- 
-   /* "logicalLocations" property (SARIF v2.1.0 3.14.17). */
-   if (m_cached_logical_locs->size () > 0)
-     {
-       m_cached_logical_locs->add_explicit_index_values ();
-       run_obj->set<json::array> ("logicalLocations",
- 				 std::move (m_cached_logical_locs));
-     }
- 
-   // "graphs" property (SARIF v2.1.0 3.14.20)
-   if (m_run_graphs->size () > 0)
-     run_obj->set<json::array> ("graphs",
- 			       std::move (m_run_graphs));
- 
-   return run_obj;
- }
- 
- /* Make a "tool" object (SARIF v2.1.0 section 3.18).  */
- 
- std::unique_ptr<sarif_tool>
- sarif_builder::make_tool_object ()
- {
-   auto tool_obj = std::make_unique<sarif_tool> ();
- 
-   /* "driver" property (SARIF v2.1.0 section 3.18.2).  */
-   tool_obj->set<sarif_tool_component> ("driver",
- 				       make_driver_tool_component_object ());
- 
-   /* Report plugins via the "extensions" property
-      (SARIF v2.1.0 section 3.18.3).  */
-   if (auto client_data_hooks = m_context.get_client_data_hooks ())
-     if (const client_version_info *vinfo
- 	  = client_data_hooks->get_any_version_info ())
-       {
- 	class my_plugin_visitor : public client_version_info :: plugin_visitor
- 	{
- 	public:
- 	  void on_plugin (const diagnostic_client_plugin_info &p) final override
- 	  {
- 	    /* Create a "toolComponent" object (SARIF v2.1.0 section 3.19)
- 	       for the plugin.  */
- 	    auto plugin_obj = std::make_unique<sarif_tool_component> ();
- 
- 	    /* "name" property (SARIF v2.1.0 section 3.19.8).  */
- 	    if (const char *short_name = p.get_short_name ())
- 	      plugin_obj->set_string ("name", short_name);
- 
- 	    /* "fullName" property (SARIF v2.1.0 section 3.19.9).  */
- 	    if (const char *full_name = p.get_full_name ())
- 	      plugin_obj->set_string ("fullName", full_name);
- 
- 	    /* "version" property (SARIF v2.1.0 section 3.19.13).  */
- 	    if (const char *version = p.get_version ())
- 	      plugin_obj->set_string ("version", version);
- 
- 	    m_plugin_objs.push_back (std::move (plugin_obj));
- 	  }
- 	  std::vector<std::unique_ptr<sarif_tool_component>> m_plugin_objs;
- 	};
- 	my_plugin_visitor v;
- 	vinfo->for_each_plugin (v);
- 	if (v.m_plugin_objs.size () > 0)
- 	  {
- 	    auto extensions_arr = std::make_unique<json::array> ();
- 	    for (auto &iter : v.m_plugin_objs)
- 	      extensions_arr->append<sarif_tool_component> (std::move (iter));
- 	    tool_obj->set<json::array> ("extensions",
- 					std::move (extensions_arr));
- 	  }
-       }
- 
-   /* Perhaps we could also show GMP, MPFR, MPC, isl versions as other
-      "extensions" (see toplev.cc: print_version).  */
- 
-   return tool_obj;
- }
- 
- /* Make a "toolComponent" object (SARIF v2.1.0 section 3.19) for what SARIF
-    calls the "driver" (see SARIF v2.1.0 section 3.18.1).  */
- 
- std::unique_ptr<sarif_tool_component>
- sarif_builder::make_driver_tool_component_object ()
- {
-   auto driver_obj = std::make_unique<sarif_tool_component> ();
- 
-   if (auto client_data_hooks = m_context.get_client_data_hooks ())
-     if (const client_version_info *vinfo
- 	  = client_data_hooks->get_any_version_info ())
-       {
- 	/* "name" property (SARIF v2.1.0 section 3.19.8).  */
- 	if (const char *name = vinfo->get_tool_name ())
- 	  driver_obj->set_string ("name", name);
- 
- 	/* "fullName" property (SARIF v2.1.0 section 3.19.9).  */
- 	if (char *full_name = vinfo->maybe_make_full_name ())
- 	  {
- 	    driver_obj->set_string ("fullName", full_name);
- 	    free (full_name);
- 	  }
- 
- 	/* "version" property (SARIF v2.1.0 section 3.19.13).  */
- 	if (const char *version = vinfo->get_version_string ())
- 	  driver_obj->set_string ("version", version);
- 
- 	/* "informationUri" property (SARIF v2.1.0 section 3.19.17).  */
- 	if (char *version_url =  vinfo->maybe_make_version_url ())
- 	  {
- 	    driver_obj->set_string ("informationUri", version_url);
- 	    free (version_url);
- 	  }
-       }
- 
-   /* "rules" property (SARIF v2.1.0 section 3.19.23).  */
-   driver_obj->set<json::array> ("rules", std::move (m_rules_arr));
- 
-   return driver_obj;
- }
- 
- /* If we've seen any CWE IDs, make an array for the "taxonomies" property
-    (SARIF v2.1.0 section 3.14.8) of a run object, containing a single
-    "toolComponent" (3.19) as per 3.19.3, representing the CWE.
- 
-    Otherwise return nullptr.  */
- 
- std::unique_ptr<json::array>
- sarif_builder::maybe_make_taxonomies_array () const
- {
-   auto cwe_obj = maybe_make_cwe_taxonomy_object ();
-   if (!cwe_obj)
-     return nullptr;
- 
-   /* "taxonomies" property (SARIF v2.1.0 section 3.14.8).  */
-   auto taxonomies_arr = std::make_unique<json::array> ();
-   taxonomies_arr->append<sarif_tool_component> (std::move (cwe_obj));
-   return taxonomies_arr;
- }
- 
- /* If we've seen any CWE IDs, make a "toolComponent" object
-    (SARIF v2.1.0 section 3.19) representing the CWE taxonomy, as per 3.19.3.
-    Populate the "taxa" property with all of the CWE IDs in m_cwe_id_set.
- 
-    Otherwise return nullptr.  */
- 
- std::unique_ptr<sarif_tool_component>
- sarif_builder::maybe_make_cwe_taxonomy_object () const
- {
-   if (m_cwe_id_set.is_empty ())
-     return nullptr;
- 
-   auto taxonomy_obj = std::make_unique<sarif_tool_component> ();
- 
-   /* "name" property (SARIF v2.1.0 section 3.19.8).  */
-   taxonomy_obj->set_string ("name", "CWE");
- 
-   /* "version" property (SARIF v2.1.0 section 3.19.13).  */
-   taxonomy_obj->set_string ("version", "4.7");
- 
-   /* "organization" property (SARIF v2.1.0 section 3.19.18).  */
-   taxonomy_obj->set_string ("organization", "MITRE");
- 
-   /* "shortDescription" property (SARIF v2.1.0 section 3.19.19).  */
-   taxonomy_obj->set<sarif_multiformat_message_string>
-     ("shortDescription",
-      make_multiformat_message_string ("The MITRE"
- 				      " Common Weakness Enumeration"));
- 
-   /* "taxa" property (SARIF v2.1.0 3.section 3.19.25).  */
-   auto taxa_arr = std::make_unique<json::array> ();
-   for (auto cwe_id : m_cwe_id_set)
-     taxa_arr->append<sarif_reporting_descriptor>
-       (make_reporting_descriptor_object_for_cwe_id (cwe_id));
-   taxonomy_obj->set<json::array> ("taxa", std::move (taxa_arr));
- 
-   return taxonomy_obj;
- }
- 
- /* Ensure that we have an "artifact" object (SARIF v2.1.0 section 3.24)
-    for FILENAME, adding it to m_filename_to_artifact_map if not already
-    found, and adding ROLE to it.
-    If EMBED_CONTENTS is true, then flag that we will attempt to embed the
-    contents of this artifact when writing it out.  */
- 
- sarif_artifact &
- sarif_builder::get_or_create_artifact (const char *filename,
- 				       enum diagnostic_artifact_role role,
- 				       bool embed_contents)
- {
-   if (auto *slot = m_filename_to_artifact_map.get (filename))
-     {
-       (*slot)->add_role (role, embed_contents);
-       return **slot;
-     }
- 
-   sarif_artifact *artifact_obj = new sarif_artifact (filename);
-   artifact_obj->add_role (role, embed_contents);
-   m_filename_to_artifact_map.put (filename, artifact_obj);
- 
-   /* "location" property (SARIF v2.1.0 section 3.24.2).  */
-   artifact_obj->set<sarif_artifact_location>
-     ("location", make_artifact_location_object (filename));
- 
-   /* "sourceLanguage" property (SARIF v2.1.0 section 3.24.10).  */
-   switch (role)
-     {
-     default:
-       gcc_unreachable ();
-     case diagnostic_artifact_role::analysis_target:
-     case diagnostic_artifact_role::result_file:
-     case diagnostic_artifact_role::scanned_file:
-     case diagnostic_artifact_role::traced_file:
-       /* Assume that these are in the source language.  */
-       if (auto client_data_hooks = m_context.get_client_data_hooks ())
- 	if (const char *source_lang
- 	    = client_data_hooks->maybe_get_sarif_source_language (filename))
- 	  artifact_obj->set_string ("sourceLanguage", source_lang);
-       break;
- 
-     case diagnostic_artifact_role::debug_output_file:
-       /* Assume that these are not in the source language.  */
-       break;
-     }
- 
-   return *artifact_obj;
- }
- 
- /* Make an "artifactContent" object (SARIF v2.1.0 section 3.3) for the
-    full contents of FILENAME.  */
- 
- std::unique_ptr<sarif_artifact_content>
- sarif_builder::maybe_make_artifact_content_object (const char *filename) const
- {
-   /* Let input.cc handle any charset conversion.  */
-   char_span utf8_content
-     = m_context.get_file_cache ().get_source_file_content (filename);
-   if (!utf8_content)
-     return nullptr;
- 
-   /* Don't add it if it's not valid UTF-8.  */
-   if (!cpp_valid_utf8_p(utf8_content.get_buffer (), utf8_content.length ()))
-     return nullptr;
- 
-   auto artifact_content_obj = std::make_unique<sarif_artifact_content> ();
-   artifact_content_obj->set<json::string>
-     ("text",
-      std::make_unique <json::string> (utf8_content.get_buffer (),
- 				   utf8_content.length ()));
-   return artifact_content_obj;
- }
- 
- /* Attempt to read the given range of lines from FILENAME; return
-    a freshly-allocated 0-terminated buffer containing them, or nullptr.  */
- 
- char *
- sarif_builder::get_source_lines (const char *filename,
- 				 int start_line,
- 				 int end_line) const
- {
-   auto_vec<char> result;
- 
-   for (int line = start_line; line <= end_line; line++)
-     {
-       char_span line_content
- 	= m_context.get_file_cache ().get_source_line (filename, line);
-       if (!line_content.get_buffer ())
- 	return nullptr;
-       result.reserve (line_content.length () + 1);
-       for (size_t i = 0; i < line_content.length (); i++)
- 	result.quick_push (line_content[i]);
-       result.quick_push ('\n');
-     }
-   result.safe_push ('\0');
- 
-   return xstrdup (result.address ());
- }
- 
- /* Make an "artifactContent" object (SARIF v2.1.0 section 3.3) for the given
-    run of lines within FILENAME (including the endpoints).
-    If R is non-NULL, use it to potentially set the "rendered"
-    property (3.3.4).  */
- 
- std::unique_ptr<sarif_artifact_content>
- sarif_builder::
- maybe_make_artifact_content_object (const char *filename,
- 				    int start_line,
- 				    int end_line,
- 				    const content_renderer *r) const
- {
-   char *text_utf8 = get_source_lines (filename, start_line, end_line);
- 
-   if (!text_utf8)
-     return nullptr;
- 
-   /* Don't add it if it's not valid UTF-8.  */
-   if (!cpp_valid_utf8_p(text_utf8, strlen(text_utf8)))
-     {
-       free (text_utf8);
-       return nullptr;
-     }
- 
-   auto artifact_content_obj = std::make_unique<sarif_artifact_content> ();
-   artifact_content_obj->set_string ("text", text_utf8);
-   free (text_utf8);
- 
-   /* 3.3.4 "rendered" property.  */
-   if (r)
-     if (std::unique_ptr<sarif_multiformat_message_string> rendered
- 	  = r->render (*this))
-       artifact_content_obj->set ("rendered", std::move (rendered));
- 
-   return artifact_content_obj;
- }
- 
- /* Make a "fix" object (SARIF v2.1.0 section 3.55) for RICHLOC.  */
- 
- std::unique_ptr<sarif_fix>
- sarif_builder::make_fix_object (const rich_location &richloc)
- {
-   auto fix_obj = std::make_unique<sarif_fix> ();
- 
-   /* "artifactChanges" property (SARIF v2.1.0 section 3.55.3).  */
-   /* We assume that all fix-it hints in RICHLOC affect the same file.  */
-   auto artifact_change_arr = std::make_unique<json::array> ();
-   artifact_change_arr->append<sarif_artifact_change>
-     (make_artifact_change_object (richloc));
-   fix_obj->set<json::array> ("artifactChanges",
- 			     std::move (artifact_change_arr));
- 
-   return fix_obj;
- }
- 
- /* Make an "artifactChange" object (SARIF v2.1.0 section 3.56) for RICHLOC.  */
- 
- std::unique_ptr<sarif_artifact_change>
- sarif_builder::make_artifact_change_object (const rich_location &richloc)
- {
-   auto artifact_change_obj = std::make_unique<sarif_artifact_change> ();
- 
-   /* "artifactLocation" property (SARIF v2.1.0 section 3.56.2).  */
-   artifact_change_obj->set<sarif_artifact_location>
-     ("artifactLocation",
-      make_artifact_location_object (richloc.get_loc ()));
- 
-   /* "replacements" property (SARIF v2.1.0 section 3.56.3).  */
-   auto replacement_arr = std::make_unique<json::array> ();
-   for (unsigned int i = 0; i < richloc.get_num_fixit_hints (); i++)
-     {
-       const fixit_hint *hint = richloc.get_fixit_hint (i);
-       replacement_arr->append<sarif_replacement>
- 	(make_replacement_object (*hint));
-     }
-   artifact_change_obj->set<json::array> ("replacements",
- 					 std::move (replacement_arr));
- 
-   return artifact_change_obj;
- }
- 
- /* Make a "replacement" object (SARIF v2.1.0 section 3.57) for HINT.  */
- 
- std::unique_ptr<sarif_replacement>
- sarif_builder::make_replacement_object (const fixit_hint &hint) const
- {
-   auto replacement_obj = std::make_unique<sarif_replacement> ();
- 
-   /* "deletedRegion" property (SARIF v2.1.0 section 3.57.3).  */
-   replacement_obj->set<sarif_region> ("deletedRegion",
- 				      make_region_object_for_hint (hint));
- 
-   /* "insertedContent" property (SARIF v2.1.0 section 3.57.4).  */
-   replacement_obj->set<sarif_artifact_content>
-     ("insertedContent",
-      make_artifact_content_object (hint.get_string ()));
- 
-   return replacement_obj;
- }
- 
- /* Make an "artifactContent" object (SARIF v2.1.0 section 3.3) for TEXT.  */
- 
- std::unique_ptr<sarif_artifact_content>
- sarif_builder::make_artifact_content_object (const char *text) const
- {
-   auto content_obj = std::make_unique<sarif_artifact_content> ();
- 
-   /* "text" property (SARIF v2.1.0 section 3.3.2).  */
-   content_obj->set_string ("text", text);
- 
-   return content_obj;
- }
- 
- /* class diagnostic_sarif_format_buffer : public diagnostic_per_format_buffer.  */
- 
- void
- diagnostic_sarif_format_buffer::dump (FILE *out, int indent) const
- {
-   fprintf (out, "%*sdiagnostic_sarif_format_buffer:\n", indent, "");
-   int idx = 0;
-   for (auto &result : m_results)
-     {
-       fprintf (out, "%*sresult[%i]:\n", indent + 2, "", idx);
-       result->dump (out, true);
-       fprintf (out, "\n");
-       ++idx;
-     }
- }
- 
- bool
- diagnostic_sarif_format_buffer::empty_p () const
- {
-   return m_results.empty ();
- }
- 
- void
- diagnostic_sarif_format_buffer::move_to (diagnostic_per_format_buffer &base)
- {
-   diagnostic_sarif_format_buffer &dest
-     = static_cast<diagnostic_sarif_format_buffer &> (base);
-   for (auto &&result : m_results)
-     dest.m_results.push_back (std::move (result));
-   m_results.clear ();
- }
- 
- void
- diagnostic_sarif_format_buffer::clear ()
- {
-   m_results.clear ();
- }
- 
- void
- diagnostic_sarif_format_buffer::flush ()
- {
-   for (auto &&result : m_results)
-     {
-       result->process_worklist (m_builder);
-       m_builder.m_results_array->append<sarif_result> (std::move (result));
-     }
-   m_results.clear ();
- }
- 
- class sarif_output_format : public diagnostic_output_format
- {
- public:
-   ~sarif_output_format ()
-   {
-     /* Any sarifResult objects should have been handled by now.
-        If not, then something's gone wrong with diagnostic
-        groupings.  */
-     std::unique_ptr<sarif_result> pending_result
-       = m_builder.take_current_result ();
-     gcc_assert (!pending_result);
-   }
- 
-   void dump (FILE *out, int indent) const override
-   {
-     fprintf (out, "%*ssarif_output_format\n", indent, "");
-     diagnostic_output_format::dump (out, indent);
-   }
- 
-   void
-   set_main_input_filename (const char *name) final override
-   {
-     m_builder.set_main_input_filename (name);
-   }
- 
-   std::unique_ptr<diagnostic_per_format_buffer>
-   make_per_format_buffer () final override
-   {
-     return std::make_unique<diagnostic_sarif_format_buffer> (m_builder);
-   }
-   void set_buffer (diagnostic_per_format_buffer *base_buffer) final override
-   {
-     diagnostic_sarif_format_buffer *buffer
-       = static_cast<diagnostic_sarif_format_buffer *> (base_buffer);
-     m_buffer = buffer;
-   }
- 
-   bool follows_reference_printer_p () const final override
-   {
-     return false;
-   }
- 
-   void update_printer () final override
-   {
-     m_printer = m_context.clone_printer ();
- 
-     /* Don't colorize the text.  */
-     pp_show_color (m_printer.get ()) = false;
- 
-     /* No textual URLs.  */
-     m_printer->set_url_format (URL_FORMAT_NONE);
- 
-     /* Use builder's token printer.  */
-     get_printer ()->set_token_printer (&m_builder.get_token_printer ());
- 
-     /* Update the builder to use the new printer.  */
-     m_builder.set_printer (*get_printer ());
-   }
- 
-   void on_begin_group () final override
-   {
-     /* No-op,  */
-   }
-   void on_end_group () final override
-   {
-     m_builder.end_group ();
-   }
-   void
-   on_report_diagnostic (const diagnostic_info &diagnostic,
- 			diagnostic_t orig_diag_kind) final override
-   {
-     m_builder.on_report_diagnostic (diagnostic, orig_diag_kind, m_buffer);
-   }
-   void on_diagram (const diagnostic_diagram &diagram) final override
-   {
-     m_builder.emit_diagram (diagram);
-   }
-   void after_diagnostic (const diagnostic_info &) final override
-   {
-     /* No-op.  */
-   }
- 
-   void
-   report_global_digraph (const diagnostics::digraphs::lazy_digraph &lazy_digraph) final override
-   {
-     m_builder.report_global_digraph (lazy_digraph);
-   }
- 
-   sarif_builder &get_builder () { return m_builder; }
- 
-   size_t num_results () const { return m_builder.num_results (); }
-   sarif_result &get_result (size_t idx) { return m_builder.get_result (idx); }
- 
- protected:
-   sarif_output_format (diagnostic_context &context,
- 		       const line_maps *line_maps,
- 		       std::unique_ptr<sarif_serialization_format> serialization_format,
- 		       const sarif_generation_options &sarif_gen_opts)
-   : diagnostic_output_format (context),
-     m_builder (context, *get_printer (), line_maps,
- 	       std::move (serialization_format), sarif_gen_opts),
-     m_buffer (nullptr)
-   {}
- 
-   sarif_builder m_builder;
-   diagnostic_sarif_format_buffer *m_buffer;
- };
- 
- class sarif_stream_output_format : public sarif_output_format
- {
- public:
-   sarif_stream_output_format (diagnostic_context &context,
- 			      const line_maps *line_maps,
- 			      std::unique_ptr<sarif_serialization_format> serialization_format,
- 			      const sarif_generation_options &sarif_gen_opts,
- 			      FILE *stream)
-   : sarif_output_format (context, line_maps,
- 			 std::move (serialization_format), sarif_gen_opts),
-     m_stream (stream)
-   {
-   }
-   ~sarif_stream_output_format ()
-   {
-     m_builder.flush_to_file (m_stream);
-   }
-   bool machine_readable_stderr_p () const final override
-   {
-     return m_stream == stderr;
-   }
- private:
-   FILE *m_stream;
- };
- 
- class sarif_file_output_format : public sarif_output_format
- {
- public:
-   sarif_file_output_format (diagnostic_context &context,
- 			    const line_maps *line_maps,
- 			    std::unique_ptr<sarif_serialization_format> serialization_format,
- 			    const sarif_generation_options &sarif_gen_opts,
- 			    diagnostic_output_file output_file)
-   : sarif_output_format (context, line_maps,
- 			 std::move (serialization_format), sarif_gen_opts),
-     m_output_file (std::move (output_file))
-   {
-     gcc_assert (m_output_file.get_open_file ());
-     gcc_assert (m_output_file.get_filename ());
-   }
-   ~sarif_file_output_format ()
-   {
-     m_builder.flush_to_file (m_output_file.get_open_file ());
-   }
-   void dump (FILE *out, int indent) const override
-   {
-     fprintf (out, "%*ssarif_file_output_format: %s\n",
- 	     indent, "",
- 	     m_output_file.get_filename ());
-     diagnostic_output_format::dump (out, indent);
-   }
-   bool machine_readable_stderr_p () const final override
-   {
-     return false;
-   }
- 
- private:
-   diagnostic_output_file m_output_file;
- };
- 
- /* Print the start of an embedded link to PP, as per 3.11.6.  */
- 
- static void
- sarif_begin_embedded_link (pretty_printer *pp)
- {
-   pp_character (pp, '[');
- }
- 
- /* Print the end of an embedded link to PP, as per 3.11.6.  */
- 
- static void
- sarif_end_embedded_link (pretty_printer *pp,
- 			 const char *url)
- {
-   pp_string (pp, "](");
-   /* TODO: does the URI need escaping?
-      See https://github.com/oasis-tcs/sarif-spec/issues/657 */
-   pp_string (pp, url);
-   pp_character (pp, ')');
- }
- 
- /* class sarif_token_printer : public token_printer.  */
- 
- /* Implementation of pretty_printer::token_printer for SARIF output.
-    Emit URLs as per 3.11.6 ("Messages with embedded links").  */
- 
- void
- sarif_builder::sarif_token_printer::print_tokens (pretty_printer *pp,
- 						  const pp_token_list &tokens)
- {
-   /* Convert to text, possibly with colorization, URLs, etc.  */
-   label_text current_url;
-   for (auto iter = tokens.m_first; iter; iter = iter->m_next)
-     switch (iter->m_kind)
-       {
-       default:
- 	gcc_unreachable ();
- 
-       case pp_token::kind::text:
- 	{
- 	  const pp_token_text *sub = as_a <const pp_token_text *> (iter);
- 	  const char * const str = sub->m_value.get ();
- 	  if (current_url.get ())
- 	    {
- 	      /* Write iter->m_value, but escaping any
- 		 escaped link characters as per 3.11.6.  */
- 	      for (const char *ptr = str; *ptr; ptr++)
- 		{
- 		  const char ch = *ptr;
- 		  switch (ch)
- 		    {
- 		    default:
- 		      pp_character (pp, ch);
- 		      break;
- 		    case '\\':
- 		    case '[':
- 		    case ']':
- 		      pp_character (pp, '\\');
- 		      pp_character (pp, ch);
- 		      break;
- 		    }
- 		}
- 	    }
- 	  else
- 	    /* TODO: is other escaping needed? (e.g. of '[')
- 	       See https://github.com/oasis-tcs/sarif-spec/issues/658 */
- 	    pp_string (pp, str);
- 	}
- 	break;
- 
-       case pp_token::kind::begin_color:
-       case pp_token::kind::end_color:
- 	/* These are no-ops.  */
- 	break;
- 
-       case pp_token::kind::begin_quote:
- 	pp_begin_quote (pp, pp_show_color (pp));
- 	break;
-       case pp_token::kind::end_quote:
- 	pp_end_quote (pp, pp_show_color (pp));
- 	break;
- 
-       /* Emit URLs as per 3.11.6 ("Messages with embedded links").  */
-       case pp_token::kind::begin_url:
- 	{
- 	  pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter);
- 	  sarif_begin_embedded_link (pp);
- 	  current_url = std::move (sub->m_value);
- 	}
- 	break;
-       case pp_token::kind::end_url:
- 	gcc_assert (current_url.get ());
- 	sarif_end_embedded_link (pp, current_url.get ());
- 	current_url = label_text::borrow (nullptr);
- 	break;
- 
-       case pp_token::kind::event_id:
- 	{
- 	  pp_token_event_id *sub = as_a <pp_token_event_id *> (iter);
- 	  gcc_assert (sub->m_event_id.known_p ());
- 	  const sarif_code_flow *code_flow
- 	    = m_builder.get_code_flow_for_event_ids ();
- 	  label_text url = make_sarif_url_for_event (code_flow,
- 						     sub->m_event_id);
- 	  if (url.get ())
- 	    sarif_begin_embedded_link (pp);
- 	  pp_character (pp, '(');
- 	  pp_decimal_int (pp, sub->m_event_id.one_based ());
- 	  pp_character (pp, ')');
- 	  if (url.get ())
- 	    sarif_end_embedded_link (pp, url.get ());
- 	}
- 	break;
-       }
- }
- 
- /* Populate CONTEXT in preparation for SARIF output (either to stderr, or
-    to a file).
-    Return a reference to *FMT.  */
- 
- static diagnostic_output_format &
- diagnostic_output_format_init_sarif (diagnostic_context &context,
- 				     std::unique_ptr<sarif_output_format> fmt)
- {
-   gcc_assert (fmt);
-   diagnostic_output_format &out = *fmt;
- 
-   fmt->update_printer ();
- 
-   context.set_output_format (std::move (fmt));
- 
-   return out;
- }
- 
- /* Populate CONTEXT in preparation for SARIF output to stderr.
-    Return a reference to the new sink.  */
- 
- diagnostic_output_format &
- diagnostic_output_format_init_sarif_stderr (diagnostic_context &context,
- 					    const line_maps *line_maps,
- 					    bool formatted)
- {
-   gcc_assert (line_maps);
-   const sarif_generation_options sarif_gen_opts;
-   auto serialization
-     = std::make_unique<sarif_serialization_format_json> (formatted);
-   return diagnostic_output_format_init_sarif
-     (context,
-      std::make_unique<sarif_stream_output_format> (context,
- 						   line_maps,
- 						   std::move (serialization),
- 						   sarif_gen_opts,
- 						   stderr));
- }
- 
- /* Attempt to open "BASE_FILE_NAME""EXTENSION" for writing.
-    Return a non-null diagnostic_output_file,
-    or return a null diagnostic_output_file and complain to CONTEXT
-    using LINE_MAPS.  */
- 
- diagnostic_output_file
- diagnostic_output_file::try_to_open (diagnostic_context &context,
- 				     line_maps *line_maps,
- 				     const char *base_file_name,
- 				     const char *extension,
- 				     bool is_binary)
- {
-   gcc_assert (extension);
-   gcc_assert (extension[0] == '.');
- 
-   if (!base_file_name)
-     {
-       rich_location richloc (line_maps, UNKNOWN_LOCATION);
-       context.emit_diagnostic_with_group
- 	(DK_ERROR, richloc, nullptr, 0,
- 	 "unable to determine filename for SARIF output");
-       return diagnostic_output_file ();
-     }
- 
-   label_text filename = label_text::take (concat (base_file_name,
- 						  extension,
- 						  nullptr));
-   FILE *outf = fopen (filename.get (), is_binary ? "wb" : "w");
-   if (!outf)
-     {
-       rich_location richloc (line_maps, UNKNOWN_LOCATION);
-       context.emit_diagnostic_with_group
- 	(DK_ERROR, richloc, nullptr, 0,
- 	 "unable to open %qs for diagnostic output: %m",
- 	 filename.get ());
-       return diagnostic_output_file ();
-     }
-   return diagnostic_output_file (outf, true, std::move (filename));
- }
- 
- /* Attempt to open BASE_FILE_NAME.sarif for writing JSON.
-    Return a non-null diagnostic_output_file,
-    or return a null diagnostic_output_file and complain to CONTEXT
-    using LINE_MAPS.  */
- 
- diagnostic_output_file
- diagnostic_output_format_open_sarif_file (diagnostic_context &context,
- 					  line_maps *line_maps,
- 					  const char *base_file_name,
- 					  enum sarif_serialization_kind serialization_kind)
- {
-   const char *suffix;
-   bool is_binary;
-   switch (serialization_kind)
-     {
-     default:
-       gcc_unreachable ();
-     case sarif_serialization_kind::json:
-       suffix = ".sarif";
-       is_binary = false;
-       break;
-     }
- 
-   return diagnostic_output_file::try_to_open (context,
- 					      line_maps,
- 					      base_file_name,
- 					      suffix,
- 					      is_binary);
- }
- 
- /* Populate CONTEXT in preparation for SARIF output to a file named
-    BASE_FILE_NAME.sarif.
-    Return a reference to the new sink.  */
- 
- diagnostic_output_format &
- diagnostic_output_format_init_sarif_file (diagnostic_context &context,
- 					  line_maps *line_maps,
- 					  bool formatted,
- 					  const char *base_file_name)
- {
-   gcc_assert (line_maps);
- 
-   diagnostic_output_file output_file
-     = diagnostic_output_format_open_sarif_file (context,
- 						line_maps,
- 						base_file_name,
- 						sarif_serialization_kind::json);
-   auto serialization
-     = std::make_unique<sarif_serialization_format_json> (formatted);
- 
-   const sarif_generation_options sarif_gen_opts;
-   return diagnostic_output_format_init_sarif
-     (context,
-      std::make_unique<sarif_file_output_format> (context,
- 						 line_maps,
- 						 std::move (serialization),
- 						 sarif_gen_opts,
- 						 std::move (output_file)));
- }
- 
- /* Populate CONTEXT in preparation for SARIF output to STREAM.
-    Return a reference to the new sink.  */
- 
- diagnostic_output_format &
- diagnostic_output_format_init_sarif_stream (diagnostic_context &context,
- 					    const line_maps *line_maps,
- 					    bool formatted,
- 					    FILE *stream)
- {
-   gcc_assert (line_maps);
-   const sarif_generation_options sarif_gen_opts;
-   auto serialization
-     = std::make_unique<sarif_serialization_format_json> (formatted);
-   return diagnostic_output_format_init_sarif
-     (context,
-      std::make_unique<sarif_stream_output_format> (context,
- 						   line_maps,
- 						   std::move (serialization),
- 						   sarif_gen_opts,
- 						   stream));
- }
- 
- std::unique_ptr<diagnostic_output_format>
- make_sarif_sink (diagnostic_context &context,
- 		 const line_maps &line_maps,
- 		 std::unique_ptr<sarif_serialization_format> serialization,
- 		 const sarif_generation_options &sarif_gen_opts,
- 		 diagnostic_output_file output_file)
- {
-   auto sink
-     = std::make_unique<sarif_file_output_format> (context,
- 						  &line_maps,
- 						  std::move (serialization),
- 						  sarif_gen_opts,
- 						  std::move (output_file));
-   sink->update_printer ();
-   return sink;
- }
- 
- // struct sarif_generation_options
- 
- sarif_generation_options::sarif_generation_options ()
- : m_version (sarif_version::v2_1_0),
-   m_state_graph (false)
- {
- }
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- static void
- test_sarif_array_of_unique_1 ()
- {
-   sarif_array_of_unique<json::string> arr;
- 
-   ASSERT_EQ (arr.length (), 0);
- 
-   {
-     size_t idx = arr.append_uniquely (std::make_unique<json::string> ("foo"));
-     ASSERT_EQ (idx, 0);
-     ASSERT_EQ (arr.length (), 1);
-   }
-   {
-     size_t idx = arr.append_uniquely (std::make_unique<json::string> ("bar"));
-     ASSERT_EQ (idx, 1);
-     ASSERT_EQ (arr.length (), 2);
-   }
- 
-   /* Try adding them again, should be idempotent.  */
-   {
-     size_t idx = arr.append_uniquely (std::make_unique<json::string> ("foo"));
-     ASSERT_EQ (idx, 0);
-     ASSERT_EQ (arr.length (), 2);
-   }
-   {
-     size_t idx = arr.append_uniquely (std::make_unique<json::string> ("bar"));
-     ASSERT_EQ (idx, 1);
-     ASSERT_EQ (arr.length (), 2);
-   }
- }
- 
- static void
- test_sarif_array_of_unique_2 ()
- {
-   sarif_array_of_unique<json::object> arr;
- 
-   ASSERT_EQ (arr.length (), 0);
- 
-   {
-     auto obj0 = std::make_unique<json::object> ();
-     size_t idx = arr.append_uniquely (std::move (obj0));
-     ASSERT_EQ (idx, 0);
-     ASSERT_EQ (arr.length (), 1);
- 
-     // Attempting to add another empty objects should be idempotent.
-     idx = arr.append_uniquely (std::make_unique<json::object> ());
-     ASSERT_EQ (idx, 0);
-     ASSERT_EQ (arr.length (), 1);
-   }
-   {
-     auto obj1 = std::make_unique<json::object> ();
-     obj1->set_string ("foo", "bar");
-     size_t idx = arr.append_uniquely (std::move (obj1));
-     ASSERT_EQ (idx, 1);
-     ASSERT_EQ (arr.length (), 2);
- 
-     // Attempting to add an equivalent object should be idempotent.
-     auto other = std::make_unique<json::object> ();
-     other->set_string ("foo", "bar");
-     idx = arr.append_uniquely (std::move (other));
-     ASSERT_EQ (idx, 1);
-     ASSERT_EQ (arr.length (), 2);
-   }
- 
-   // Verify behavior of add_explicit_index_values.
-   arr.add_explicit_index_values ();
-   ASSERT_JSON_INT_PROPERTY_EQ (arr[0], "index", 0);
-   ASSERT_JSON_INT_PROPERTY_EQ (arr[1], "index", 1);
- }
- 
- /* A subclass of sarif_output_format for writing selftests.
-    The JSON output is cached internally, rather than written
-    out to a file.  */
- 
- class test_sarif_diagnostic_context : public test_diagnostic_context
- {
- public:
-   test_sarif_diagnostic_context (const char *main_input_filename,
- 				 const sarif_generation_options &sarif_gen_opts)
-   {
-     auto format = std::make_unique<buffered_output_format> (*this,
- 							    line_table,
- 							    true,
- 							    sarif_gen_opts);
-     m_format = format.get (); // borrowed
-     diagnostic_output_format_init_sarif (*this, std::move (format));
-     m_format->set_main_input_filename (main_input_filename);
-   }
- 
-   std::unique_ptr<sarif_log> flush_to_object ()
-   {
-     return m_format->flush_to_object ();
-   }
- 
-   size_t num_results () const { return m_format->num_results (); }
-   sarif_result &get_result (size_t idx) { return m_format->get_result (idx); }
- 
- private:
-   class buffered_output_format : public sarif_output_format
-   {
-   public:
-     buffered_output_format (diagnostic_context &context,
- 			    const line_maps *line_maps,
- 			    bool formatted,
- 			    const sarif_generation_options &sarif_gen_opts)
-     : sarif_output_format (context, line_maps,
- 			   std::make_unique<sarif_serialization_format_json>
- 			     (formatted),
- 			   sarif_gen_opts)
-     {
-     }
-     bool machine_readable_stderr_p () const final override
-     {
-       return false;
-     }
-     std::unique_ptr<sarif_log> flush_to_object ()
-     {
-       return m_builder.flush_to_object ();
-     }
-   };
- 
-   buffered_output_format *m_format; // borrowed
- };
- 
- /* Test making a sarif_location for a complex rich_location
-    with labels and escape-on-output.  */
- 
- static void
- test_make_location_object (const sarif_generation_options &sarif_gen_opts,
- 			   const line_table_case &case_)
- {
-   diagnostic_show_locus_fixture_one_liner_utf8 f (case_);
-   location_t line_end = linemap_position_for_column (line_table, 31);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   test_diagnostic_context dc;
-   pretty_printer pp;
-   sarif_builder builder
-     (dc, pp, line_table,
-      std::make_unique<sarif_serialization_format_json> (true),
-      sarif_gen_opts);
- 
-   /* These "columns" are byte offsets, whereas later on the columns
-      in the generated SARIF use sarif_builder::get_sarif_column and
-      thus respect tabs, encoding.  */
-   const location_t foo
-     = make_location (linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 8));
-   const location_t bar
-     = make_location (linemap_position_for_column (line_table, 12),
- 		     linemap_position_for_column (line_table, 12),
- 		     linemap_position_for_column (line_table, 17));
-   const location_t field
-     = make_location (linemap_position_for_column (line_table, 19),
- 		     linemap_position_for_column (line_table, 19),
- 		     linemap_position_for_column (line_table, 30));
- 
-   text_range_label label0 ("label0");
-   text_range_label label1 ("label1");
-   text_range_label label2 ("label2");
- 
-   rich_location richloc (line_table, foo, &label0, nullptr);
-   richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-   richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
-   richloc.set_escape_on_output (true);
- 
-   sarif_result result (0);
- 
-   std::unique_ptr<sarif_location> location_obj
-     = builder.make_location_object
- 	(&result, richloc, logical_location (),
- 	 diagnostic_artifact_role::analysis_target);
-   ASSERT_NE (location_obj, nullptr);
- 
-   auto physical_location
-     = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (location_obj.get (),
- 					       "physicalLocation");
-   {
-     auto region
-       = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (physical_location, "region");
-     ASSERT_JSON_INT_PROPERTY_EQ (region, "startLine", 1);
-     ASSERT_JSON_INT_PROPERTY_EQ (region, "startColumn", 1);
-     ASSERT_JSON_INT_PROPERTY_EQ (region, "endColumn", 7);
-   }
-   {
-     auto context_region
-       = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (physical_location,
- 						 "contextRegion");
-     ASSERT_JSON_INT_PROPERTY_EQ (context_region, "startLine", 1);
- 
-     {
-       auto snippet
- 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (context_region, "snippet");
- 
-       /* We expect the snippet's "text" to be a copy of the content.  */
-       ASSERT_JSON_STRING_PROPERTY_EQ (snippet, "text",  f.m_content);
- 
-       /* We expect the snippet to have a "rendered" whose "text" has a
- 	 pure ASCII escaped copy of the line (with labels, etc).  */
-       {
- 	auto rendered
- 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (snippet, "rendered");
- 	ASSERT_JSON_STRING_PROPERTY_EQ
- 	  (rendered, "text",
- 	   "1 | <U+1F602>_foo = <U+03C0>_bar.<U+1F602>_field<U+03C0>;\n"
- 	   "  | ^~~~~~~~~~~~~   ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~\n"
- 	   "  | |               |            |\n"
- 	   "  | label0          label1       label2\n");
-       }
-     }
-   }
-   auto annotations
-     = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (location_obj.get (),
- 					      "annotations");
-   ASSERT_EQ (annotations->size (), 3);
-   {
-     {
-       auto a0 = (*annotations)[0];
-       ASSERT_JSON_INT_PROPERTY_EQ (a0, "startLine", 1);
-       ASSERT_JSON_INT_PROPERTY_EQ (a0, "startColumn", 1);
-       ASSERT_JSON_INT_PROPERTY_EQ (a0, "endColumn", 7);
-       auto message
- 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (a0, "message");
-       ASSERT_JSON_STRING_PROPERTY_EQ (message, "text", "label0");
-     }
-     {
-       auto a1 = (*annotations)[1];
-       ASSERT_JSON_INT_PROPERTY_EQ (a1, "startLine", 1);
-       ASSERT_JSON_INT_PROPERTY_EQ (a1, "startColumn", 10);
-       ASSERT_JSON_INT_PROPERTY_EQ (a1, "endColumn", 15);
-       auto message
- 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (a1, "message");
-       ASSERT_JSON_STRING_PROPERTY_EQ (message, "text", "label1");
-     }
-     {
-       auto a2 = (*annotations)[2];
-       ASSERT_JSON_INT_PROPERTY_EQ (a2, "startLine", 1);
-       ASSERT_JSON_INT_PROPERTY_EQ (a2, "startColumn", 16);
-       ASSERT_JSON_INT_PROPERTY_EQ (a2, "endColumn", 25);
-       auto message
- 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (a2, "message");
-       ASSERT_JSON_STRING_PROPERTY_EQ (message, "text", "label2");
-     }
-   }
- }
- 
- /* Test of reporting a diagnostic at UNKNOWN_LOCATION to a
-    diagnostic_context and examining the generated sarif_log.
-    Verify various basic properties. */
- 
- static void
- test_simple_log (const sarif_generation_options &sarif_gen_opts)
- {
-   test_sarif_diagnostic_context dc ("MAIN_INPUT_FILENAME", sarif_gen_opts);
- 
-   rich_location richloc (line_table, UNKNOWN_LOCATION);
-   dc.report (DK_ERROR, richloc, nullptr, 0, "this is a test: %i", 42);
- 
-   auto log_ptr = dc.flush_to_object ();
- 
-   // 3.13 sarifLog:
-   auto log = log_ptr.get ();
-   const enum sarif_version version = sarif_gen_opts.m_version;
-   ASSERT_JSON_STRING_PROPERTY_EQ (log, "$schema",
- 				  sarif_version_to_url (version));
-   ASSERT_JSON_STRING_PROPERTY_EQ (log, "version",
- 				  sarif_version_to_property (version));
- 
-   auto runs = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (log, "runs"); // 3.13.4
-   ASSERT_EQ (runs->size (), 1);
- 
-   // 3.14 "run" object:
-   auto run = (*runs)[0];
- 
-   {
-     // 3.14.6:
-     auto tool = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (run, "tool");
- 
-     EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (tool, "driver"); // 3.18.2
-   }
- 
-   {
-     // 3.14.11
-     auto invocations
-       = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "invocations");
-     ASSERT_EQ (invocations->size (), 1);
- 
-     {
-       // 3.20 "invocation" object:
-       auto invocation = (*invocations)[0];
- 
-       // 3.20.3 arguments property
- 
-       // 3.20.7 startTimeUtc property
-       EXPECT_JSON_OBJECT_WITH_STRING_PROPERTY (invocation, "startTimeUtc");
- 
-       // 3.20.8 endTimeUtc property
-       EXPECT_JSON_OBJECT_WITH_STRING_PROPERTY (invocation, "endTimeUtc");
- 
-       // 3.20.19 workingDirectory property
-       {
- 	auto wd_obj
- 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (invocation,
- 						     "workingDirectory");
- 	EXPECT_JSON_OBJECT_WITH_STRING_PROPERTY (wd_obj, "uri");
-       }
- 
-       // 3.20.21 toolExecutionNotifications property
-       auto notifications
- 	= EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY
- 	    (invocation, "toolExecutionNotifications");
-       ASSERT_EQ (notifications->size (), 0);
-     }
-   }
- 
-   {
-     // 3.14.15:
-     auto artifacts = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "artifacts");
-     ASSERT_EQ (artifacts->size (), 1);
- 
-     {
-       // 3.24 "artifact" object:
-       auto artifact = (*artifacts)[0];
- 
-       // 3.24.2:
-       auto location
- 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (artifact, "location");
-       ASSERT_JSON_STRING_PROPERTY_EQ (location, "uri", "MAIN_INPUT_FILENAME");
- 
-       // 3.24.6:
-       auto roles = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (artifact, "roles");
-       ASSERT_EQ (roles->size (), 1);
-       {
- 	auto role = (*roles)[0];
- 	ASSERT_JSON_STRING_EQ (role, "analysisTarget");
-       }
-     }
-   }
- 
-   {
-     // 3.14.23:
-     auto results = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "results");
-     ASSERT_EQ (results->size (), 1);
- 
-     {
-       // 3.27 "result" object:
-       auto result = (*results)[0];
-       ASSERT_JSON_STRING_PROPERTY_EQ (result, "ruleId", "error");
-       ASSERT_JSON_STRING_PROPERTY_EQ (result, "level", "error"); // 3.27.10
- 
-       {
- 	// 3.27.11:
- 	auto message
- 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (result, "message");
- 	ASSERT_JSON_STRING_PROPERTY_EQ (message, "text",
- 					"this is a test: 42");
-       }
- 
-       // 3.27.12:
-       auto locations
- 	= EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (result, "locations");
-       ASSERT_EQ (locations->size (), 0);
-     }
-   }
- }
- 
- /* As above, but with a "real" location_t.  */
- 
- static void
- test_simple_log_2 (const sarif_generation_options &sarif_gen_opts,
- 		   const line_table_case &case_)
- {
-   auto_fix_quotes fix_quotes;
- 
-   const char *const content
-     /* 000000000111111
-        123456789012345.  */
-     = "unsinged int i;\n";
-   diagnostic_show_locus_fixture f (case_, content);
-   location_t line_end = linemap_position_for_column (line_table, 31);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   test_sarif_diagnostic_context dc (f.get_filename (), sarif_gen_opts);
- 
-   const location_t typo_loc
-     = make_location (linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 8));
- 
-   rich_location richloc (line_table, typo_loc);
-   dc.report (DK_ERROR, richloc, nullptr, 0,
- 	     "did you misspell %qs again?",
- 	     "unsigned");
- 
-   auto log_ptr = dc.flush_to_object ();
- 
-   // 3.13 sarifLog:
-   auto log = log_ptr.get ();
- 
-   auto runs = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (log, "runs"); // 3.13.4
-   ASSERT_EQ (runs->size (), 1);
- 
-   // 3.14 "run" object:
-   auto run = (*runs)[0];
- 
-   {
-     // 3.14.23:
-     auto results = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "results");
-     ASSERT_EQ (results->size (), 1);
- 
-     {
-       // 3.27 "result" object:
-       auto result = (*results)[0];
-       ASSERT_JSON_STRING_PROPERTY_EQ (result, "ruleId", "error");
-       ASSERT_JSON_STRING_PROPERTY_EQ (result, "level", "error"); // 3.27.10
- 
-       {
- 	// 3.27.11:
- 	auto message
- 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (result, "message");
- 	ASSERT_JSON_STRING_PROPERTY_EQ (message, "text",
- 					"did you misspell `unsigned' again?");
-       }
- 
-       // 3.27.12:
-       auto locations
- 	= EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (result, "locations");
-       ASSERT_EQ (locations->size (), 1);
- 
-       {
- 	// 3.28 "location" object:
- 	auto location = (*locations)[0];
- 
- 	auto physical_location
- 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (location,
- 						     "physicalLocation");
- 	{
- 	  auto region
- 	    = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (physical_location,
- 						       "region");
- 	  ASSERT_JSON_INT_PROPERTY_EQ (region, "startLine", 1);
- 	  ASSERT_JSON_INT_PROPERTY_EQ (region, "startColumn", 1);
- 	  ASSERT_JSON_INT_PROPERTY_EQ (region, "endColumn", 9);
- 	}
- 	{
- 	  auto context_region
- 	    = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (physical_location,
- 						       "contextRegion");
- 	  ASSERT_JSON_INT_PROPERTY_EQ (context_region, "startLine", 1);
- 
- 	  {
- 	    auto snippet
- 	      = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (context_region,
- 							 "snippet");
- 
- 	    /* We expect the snippet's "text" to be a copy of the content.  */
- 	    ASSERT_JSON_STRING_PROPERTY_EQ (snippet, "text",  f.m_content);
- 	  }
- 	}
-       }
-     }
-   }
- }
- 
- /* Assuming that a single diagnostic has been emitted within
-    LOG, get a json::object for the result object.  */
- 
- static const json::object *
- get_result_from_log (const sarif_log *log)
- {
-   auto runs = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (log, "runs"); // 3.13.4
-   ASSERT_EQ (runs->size (), 1);
- 
-   // 3.14 "run" object:
-   auto run = (*runs)[0];
- 
-   // 3.14.23:
-   auto results = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "results");
-   ASSERT_EQ (results->size (), 1);
- 
-   // 3.27 "result" object:
-   auto result = (*results)[0];
-   return expect_json_object (SELFTEST_LOCATION, result);
- }
- 
- static const json::object *
- get_message_from_result (const sarif_result &result)
- {
-   // 3.27.11:
-   auto message_obj
-     = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (&result, "message");
-   return message_obj;
- }
- 
- /* Assuming that a single diagnostic has been emitted to
-    DC, get a json::object for the messsage object within
-    the result.  */
- 
- static const json::object *
- get_message_from_log (const sarif_log *log)
- {
-   auto result_obj = get_result_from_log (log);
- 
-   // 3.27.11:
-   auto message_obj
-     = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (result_obj, "message");
-   return message_obj;
- }
- 
- /* Tests of messages with embedded links; see SARIF v2.1.0 3.11.6.  */
- 
- static void
- test_message_with_embedded_link (const sarif_generation_options &sarif_gen_opts)
- {
-   auto_fix_quotes fix_quotes;
-   {
-     test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
-     rich_location richloc (line_table, UNKNOWN_LOCATION);
-     dc.report (DK_ERROR, richloc, nullptr, 0,
- 	       "before %{text%} after",
- 	       "http://example.com");
-     std::unique_ptr<sarif_log> log = dc.flush_to_object ();
- 
-     auto message_obj = get_message_from_log (log.get ());
-     ASSERT_JSON_STRING_PROPERTY_EQ
-       (message_obj, "text",
-        "before [text](http://example.com) after");
-   }
- 
-   /* Escaping in message text.
-      This is "EXAMPLE 1" from 3.11.6.  */
-   {
-     test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
-     rich_location richloc (line_table, UNKNOWN_LOCATION);
- 
-     /* Disable "unquoted sequence of 2 consecutive punctuation
-        characters `]\' in format" warning.  */
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic push
- #  pragma GCC diagnostic ignored "-Wformat-diag"
- #endif
-     dc.report (DK_ERROR, richloc, nullptr, 0,
- 	       "Prohibited term used in %{para[0]\\spans[2]%}.",
- 	       "1");
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic pop
- #endif
- 
-     std::unique_ptr<sarif_log> log = dc.flush_to_object ();
- 
-     auto message_obj = get_message_from_log (log.get ());
-     ASSERT_JSON_STRING_PROPERTY_EQ
-       (message_obj, "text",
-        "Prohibited term used in [para\\[0\\]\\\\spans\\[2\\]](1).");
-     /* This isn't exactly what EXAMPLE 1 of the spec has; reported as
-        https://github.com/oasis-tcs/sarif-spec/issues/656  */
-   }
- 
-   /* Urlifier.  */
-   {
-     class test_urlifier : public urlifier
-     {
-     public:
-       char *
-       get_url_for_quoted_text (const char *p, size_t sz) const final override
-       {
- 	if (!strncmp (p, "-foption", sz))
- 	  return xstrdup ("http://example.com");
- 	return nullptr;
-       }
-     };
- 
-     test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
-     dc.push_owned_urlifier (std::make_unique<test_urlifier> ());
-     rich_location richloc (line_table, UNKNOWN_LOCATION);
-     dc.report (DK_ERROR, richloc, nullptr, 0,
- 	       "foo %<-foption%> %<unrecognized%> bar");
-     std::unique_ptr<sarif_log> log = dc.flush_to_object ();
- 
-     auto message_obj = get_message_from_log (log.get ());
-     ASSERT_JSON_STRING_PROPERTY_EQ
-       (message_obj, "text",
-        "foo `[-foption](http://example.com)' `unrecognized' bar");
-   }
- }
- 
- /* Verify that braces in messages get escaped, as per
-    3.11.5 ("Messages with placeholders").  */
- 
- static void
- test_message_with_braces (const sarif_generation_options &sarif_gen_opts)
- {
-   auto_fix_quotes fix_quotes;
-   {
-     test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
-     rich_location richloc (line_table, UNKNOWN_LOCATION);
-     dc.report (DK_ERROR, richloc, nullptr, 0,
- 	       "open brace: %qs close brace: %qs",
- 	       "{", "}");
-     std::unique_ptr<sarif_log> log = dc.flush_to_object ();
- 
-     auto message_obj = get_message_from_log (log.get ());
-     ASSERT_JSON_STRING_PROPERTY_EQ
-       (message_obj, "text",
-        "open brace: `{{' close brace: `}}'");
-   }
- }
- 
- static void
- test_buffering (const sarif_generation_options &sarif_gen_opts)
- {
-   test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
- 
-   diagnostic_buffer buf_a (dc);
-   diagnostic_buffer buf_b (dc);
- 
-   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
- 
-   ASSERT_EQ (dc.diagnostic_count (DK_ERROR), 0);
-   ASSERT_EQ (buf_a.diagnostic_count (DK_ERROR), 0);
-   ASSERT_EQ (buf_b.diagnostic_count (DK_ERROR), 0);
-   ASSERT_EQ (dc.num_results (), 0);
-   ASSERT_TRUE (buf_a.empty_p ());
-   ASSERT_TRUE (buf_b.empty_p ());
- 
-   /* Unbuffered diagnostic.  */
-   {
-     dc.report (DK_ERROR, rich_loc, nullptr, 0,
- 	       "message 1");
- 
-     ASSERT_EQ (dc.diagnostic_count (DK_ERROR), 1);
-     ASSERT_EQ (buf_a.diagnostic_count (DK_ERROR), 0);
-     ASSERT_EQ (buf_b.diagnostic_count (DK_ERROR), 0);
-     ASSERT_EQ (dc.num_results (), 1);
-     sarif_result &result_obj = dc.get_result (0);
-     auto message_obj = get_message_from_result (result_obj);
-     ASSERT_JSON_STRING_PROPERTY_EQ (message_obj, "text",
- 				    "message 1");
-     ASSERT_TRUE (buf_a.empty_p ());
-     ASSERT_TRUE (buf_b.empty_p ());
-   }
- 
-   /* Buffer diagnostic into buffer A.  */
-   {
-     dc.set_diagnostic_buffer (&buf_a);
-     dc.report (DK_ERROR, rich_loc, nullptr, 0,
- 	       "message in buffer a");
-     ASSERT_EQ (dc.diagnostic_count (DK_ERROR), 1);
-     ASSERT_EQ (buf_a.diagnostic_count (DK_ERROR), 1);
-     ASSERT_EQ (buf_b.diagnostic_count (DK_ERROR), 0);
-     ASSERT_EQ (dc.num_results (), 1);
-     ASSERT_FALSE (buf_a.empty_p ());
-     ASSERT_TRUE (buf_b.empty_p ());
-   }
- 
-   /* Buffer diagnostic into buffer B.  */
-   {
-     dc.set_diagnostic_buffer (&buf_b);
-     dc.report (DK_ERROR, rich_loc, nullptr, 0,
- 	       "message in buffer b");
-     ASSERT_EQ (dc.diagnostic_count (DK_ERROR), 1);
-     ASSERT_EQ (buf_a.diagnostic_count (DK_ERROR), 1);
-     ASSERT_EQ (buf_b.diagnostic_count (DK_ERROR), 1);
-     ASSERT_EQ (dc.num_results (), 1);
-     ASSERT_FALSE (buf_a.empty_p ());
-     ASSERT_FALSE (buf_b.empty_p ());
-   }
- 
-   /* Flush buffer B to dc.  */
-   {
-     dc.flush_diagnostic_buffer (buf_b);
-     ASSERT_EQ (dc.diagnostic_count (DK_ERROR), 2);
-     ASSERT_EQ (buf_a.diagnostic_count (DK_ERROR), 1);
-     ASSERT_EQ (buf_b.diagnostic_count (DK_ERROR), 0);
-     ASSERT_EQ (dc.num_results (), 2);
-     sarif_result &result_1_obj = dc.get_result (1);
-     auto message_1_obj = get_message_from_result (result_1_obj);
-     ASSERT_JSON_STRING_PROPERTY_EQ (message_1_obj, "text",
- 				    "message in buffer b");
-     ASSERT_FALSE (buf_a.empty_p ());
-     ASSERT_TRUE (buf_b.empty_p ());
-   }
- 
-   /* Clear buffer A.  */
-   {
-     dc.clear_diagnostic_buffer (buf_a);
-     ASSERT_EQ (dc.diagnostic_count (DK_ERROR), 2);
-     ASSERT_EQ (buf_a.diagnostic_count (DK_ERROR), 0);
-     ASSERT_EQ (buf_b.diagnostic_count (DK_ERROR), 0);
-     ASSERT_EQ (dc.num_results (), 2);
-     ASSERT_TRUE (buf_a.empty_p ());
-     ASSERT_TRUE (buf_b.empty_p ());
-   }
- }
- 
- template <class ...ArgTypes>
- static void
- for_each_sarif_gen_option (void (*callback) (const sarif_generation_options &,
- 					     ArgTypes ...),
- 			   ArgTypes ...args)
- {
-   sarif_generation_options sarif_gen_opts;
-   for (int version_idx = 0;
-        version_idx < (int)sarif_version::num_versions;
-        ++version_idx)
-     {
-       sarif_gen_opts.m_version = static_cast<enum sarif_version> (version_idx);
- 
-       callback (sarif_gen_opts, args...);
-     }
- }
- 
- static void
- run_line_table_case_tests_per_version (const line_table_case &case_)
- {
-   for_each_sarif_gen_option<const line_table_case &>
-     (test_make_location_object, case_);
- 
-   for_each_sarif_gen_option<const line_table_case &>
-     (test_simple_log_2, case_);
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- diagnostic_format_sarif_cc_tests ()
- {
-   test_sarif_array_of_unique_1 ();
-   test_sarif_array_of_unique_2 ();
- 
-   for_each_sarif_gen_option (test_simple_log);
-   for_each_sarif_gen_option (test_message_with_embedded_link);
-   for_each_sarif_gen_option (test_message_with_braces);
-   for_each_sarif_gen_option (test_buffering);
- 
-   /* Run tests per (SARIF gen-option, line-table-case) pair.  */
-   for_each_line_table_case (run_line_table_case_tests_per_version);
- }
- 
- } // namespace selftest
- 
- #endif /* CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-format-sarif.h gcc-16-20250727/gcc/diagnostic-format-sarif.h
*** gcc-16-20250720/gcc/diagnostic-format-sarif.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-format-sarif.h	Thu Jan  1 00:00:00 1970
***************
*** 1,186 ****
- /* SARIF output for diagnostics.
-    Copyright (C) 2023-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_FORMAT_SARIF_H
- #define GCC_DIAGNOSTIC_FORMAT_SARIF_H
- 
- #include "json.h"
- #include "diagnostic-format.h"
- #include "diagnostic-output-file.h"
- #include "logical-location.h"
- 
- /* Enum for choosing what format to serializing the generated SARIF into.  */
- 
- enum class sarif_serialization_kind
- {
-    json,
- 
-    num_values
- };
- 
- extern diagnostic_output_file
- diagnostic_output_format_open_sarif_file (diagnostic_context &context,
- 					  line_maps *line_maps,
- 					  const char *base_file_name,
- 					  enum sarif_serialization_kind serialization_kind);
- 
- extern diagnostic_output_format &
- diagnostic_output_format_init_sarif_stderr (diagnostic_context &context,
- 					    const line_maps *line_maps,
- 					    bool formatted);
- extern diagnostic_output_format &
- diagnostic_output_format_init_sarif_file (diagnostic_context &context,
- 					  line_maps *line_maps,
- 					  bool formatted,
- 					  const char *base_file_name);
- extern diagnostic_output_format &
- diagnostic_output_format_init_sarif_stream (diagnostic_context &context,
- 					    const line_maps *line_maps,
- 					    bool formatted,
- 					    FILE *stream);
- 
- /* Abstract base class for handling JSON output vs other kinds of
-    serialization of the json tree.  */
- 
- class sarif_serialization_format
- {
- public:
-   virtual ~sarif_serialization_format () {}
-   virtual void write_to_file (FILE *outf,
- 			      const json::value &top) = 0;
- };
- 
- /* Concrete subclass for serializing SARIF as JSON.  */
- 
- class sarif_serialization_format_json : public sarif_serialization_format
- {
- public:
-   sarif_serialization_format_json (bool formatted)
-   : m_formatted (formatted)
-   {
-   }
-   void write_to_file (FILE *outf, const json::value &top) final override;
- 
- private:
-   bool m_formatted;
- };
- 
- /* Control of SARIF generation.  */
- 
- enum class sarif_version
- {
-   v2_1_0,
-   v2_2_prerelease_2024_08_08,
- 
-   num_versions
- };
- 
- /* A bundle of state for controlling what to put in SARIF output,
-    such as which version of SARIF to generate
-    (as opposed to SARIF *serialization* options, such as formatting).  */
- 
- struct sarif_generation_options
- {
-   sarif_generation_options ();
- 
-   enum sarif_version m_version;
-   bool m_state_graph;
- };
- 
- extern std::unique_ptr<diagnostic_output_format>
- make_sarif_sink (diagnostic_context &context,
- 		 const line_maps &line_maps,
- 		 std::unique_ptr<sarif_serialization_format> serialization_format,
- 		 const sarif_generation_options &sarif_gen_opts,
- 		 diagnostic_output_file output_file);
- 
- class sarif_builder;
- class sarif_location_manager;
- 
- namespace diagnostics {
- namespace digraphs {
-   class digraph;
-   class node;
-   class edge;
- }}
- 
- /* Concrete subclass of json::object for SARIF property bags
-    (SARIF v2.1.0 section 3.8).  */
- 
- class sarif_property_bag : public json::object
- {
- public:
-   void set_logical_location (const char *property_name,
- 			     sarif_builder &,
- 			     logical_location logical_loc);
-   void set_graph (const char *property_name,
- 		  sarif_builder &,
- 		  sarif_location_manager *sarif_location_mgr,
- 		  const diagnostics::digraphs::digraph &g);
- };
- 
- /* Concrete subclass of json::object for SARIF objects that can
-    contain property bags (as per SARIF v2.1.0 section 3.8.1, which has:
-    "In addition to those properties that are explicitly documented, every
-    object defined in this document MAY contain a property named properties
-    whose value is a property bag.")  */
- 
- class sarif_object : public json::object
- {
- public:
-   sarif_property_bag &get_or_create_properties ();
- };
- 
- /* Subclass of sarif_object for SARIF "graph" objects
-    (SARIF v2.1.0 section 3.39).  */
- 
- class sarif_graph : public sarif_object
- {
- };
- 
- /* Subclass of sarif_object for SARIF "node" objects
-    (SARIF v2.1.0 section 3.40).  */
- 
- class sarif_node : public sarif_object
- {
- };
- 
- /* Subclass of sarif_object for SARIF "edge" objects
-    (SARIF v2.1.0 section 3.41).  */
- 
- class sarif_edge : public sarif_object
- {
- };
- 
- extern std::unique_ptr<sarif_graph>
- make_sarif_graph (const diagnostics::digraphs::digraph &g,
- 		  sarif_builder *builder,
- 		  sarif_location_manager *sarif_location_mgr);
- 
- extern std::unique_ptr<sarif_node>
- make_sarif_node (const diagnostics::digraphs::node &n,
- 		 sarif_builder *builder,
- 		 sarif_location_manager *sarif_location_mgr);
- 
- extern std::unique_ptr<sarif_edge>
- make_sarif_edge (const diagnostics::digraphs::edge &e,
- 		 sarif_builder *builder);
- 
- #endif /* ! GCC_DIAGNOSTIC_FORMAT_SARIF_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-format-text.cc gcc-16-20250727/gcc/diagnostic-format-text.cc
*** gcc-16-20250720/gcc/diagnostic-format-text.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-format-text.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,733 ****
- /* Classic text-based output of diagnostics.
-    Copyright (C) 1999-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- 
- #include "config.h"
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "version.h"
- #include "intl.h"
- #include "diagnostic.h"
- #include "diagnostic-color.h"
- #include "diagnostic-url.h"
- #include "diagnostic-metadata.h"
- #include "diagnostic-path.h"
- #include "diagnostic-client-data-hooks.h"
- #include "diagnostic-diagram.h"
- #include "diagnostic-format-text.h"
- #include "diagnostic-buffer.h"
- #include "text-art/theme.h"
- 
- /* Disable warnings about quoting issues in the pp_xxx calls below
-    that (intentionally) don't follow GCC diagnostic conventions.  */
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic push
- #  pragma GCC diagnostic ignored "-Wformat-diag"
- #endif
- 
- /* Concrete buffering implementation subclass for JSON output.  */
- 
- class diagnostic_text_format_buffer : public diagnostic_per_format_buffer
- {
- public:
-   friend class diagnostic_text_output_format;
- 
-   diagnostic_text_format_buffer (diagnostic_output_format &format);
- 
-   void dump (FILE *out, int indent) const final override;
- 
-   bool empty_p () const final override;
-   void move_to (diagnostic_per_format_buffer &dest) final override;
-   void clear () final override;
-   void flush () final override;
- 
- private:
-   diagnostic_output_format &m_format;
-   output_buffer m_output_buffer;
- };
- 
- /* class diagnostic_text_format_buffer : public diagnostic_per_format_buffer.  */
- 
- diagnostic_text_format_buffer::
- diagnostic_text_format_buffer (diagnostic_output_format &format)
- : m_format (format)
- {
-   m_output_buffer.m_flush_p = false;
- }
- 
- void
- diagnostic_text_format_buffer::dump (FILE *out, int indent) const
- {
-   fprintf (out, "%*sdiagnostic_text_format_buffer:\n", indent, "");
-   m_output_buffer.dump (out, indent + 2);
- }
- 
- bool
- diagnostic_text_format_buffer::empty_p () const
- {
-   return output_buffer_last_position_in_text (&m_output_buffer) == nullptr;
- }
- 
- void
- diagnostic_text_format_buffer::move_to (diagnostic_per_format_buffer &base_dest)
- {
-   diagnostic_text_format_buffer &dest
-     = static_cast<diagnostic_text_format_buffer &> (base_dest);
-   const char *str = output_buffer_formatted_text (&m_output_buffer);
-   output_buffer_append_r (&dest.m_output_buffer, str, strlen (str));
- 
-   obstack_free (m_output_buffer.m_obstack,
- 		obstack_base (m_output_buffer.m_obstack));
-   m_output_buffer.m_line_length = 0;
- }
- 
- void
- diagnostic_text_format_buffer::clear ()
- {
-   pretty_printer *const pp = m_format.get_printer ();
-   output_buffer *const old_output_buffer = pp_buffer (pp);
- 
-   pp_buffer (pp) = &m_output_buffer;
- 
-   pp_clear_output_area (pp);
-   gcc_assert (empty_p ());
- 
-   pp_buffer (pp) = old_output_buffer;
- }
- 
- void
- diagnostic_text_format_buffer::flush ()
- {
-   pretty_printer *const pp = m_format.get_printer ();
-   output_buffer *const old_output_buffer = pp_buffer (pp);
- 
-   pp_buffer (pp) = &m_output_buffer;
- 
-   pp_really_flush (pp);
-   gcc_assert (empty_p ());
- 
-   pp_buffer (pp) = old_output_buffer;
- }
- 
- /* class diagnostic_text_output_format : public diagnostic_output_format.  */
- 
- diagnostic_text_output_format::~diagnostic_text_output_format ()
- {
-   /* Some of the errors may actually have been warnings.  */
-   if (m_context.diagnostic_count (DK_WERROR))
-     {
-       pretty_printer *pp = get_printer ();
-       /* -Werror was given.  */
-       if (m_context.warning_as_error_requested_p ())
- 	pp_verbatim (pp,
- 		     _("%s: all warnings being treated as errors"),
- 		     progname);
-       /* At least one -Werror= was given.  */
-       else
- 	pp_verbatim (pp,
- 		     _("%s: some warnings being treated as errors"),
- 		     progname);
-       pp_newline_and_flush (pp);
-     }
- 
-   if (m_includes_seen)
-     {
-       delete m_includes_seen;
-       m_includes_seen = nullptr;
-     }
- }
- 
- void
- diagnostic_text_output_format::dump (FILE *out, int indent) const
- {
-   fprintf (out, "%*sdiagnostic_text_output_format\n", indent, "");
-   fprintf (out, "%*sm_follows_reference_printer: %s\n",
- 	   indent, "",
- 	   m_follows_reference_printer ? "true" : "false");
-   diagnostic_output_format::dump (out, indent);
-   fprintf (out, "%*ssaved_output_buffer:\n", indent + 2, "");
-   if (m_saved_output_buffer)
-     m_saved_output_buffer->dump (out, indent + 4);
-   else
-     fprintf (out, "%*s(none):\n", indent + 4, "");
- }
- 
- void
- diagnostic_text_output_format::set_buffer (diagnostic_per_format_buffer *base)
- {
-   diagnostic_text_format_buffer * const buffer
-     = static_cast<diagnostic_text_format_buffer *> (base);
- 
-   pretty_printer *const pp = get_printer ();
- 
-   if (!m_saved_output_buffer)
-     m_saved_output_buffer = pp_buffer (pp);
- 
-   if (buffer)
-     pp_buffer (pp) = &buffer->m_output_buffer;
-   else
-     {
-       gcc_assert (m_saved_output_buffer);
-       pp_buffer (pp) = m_saved_output_buffer;
-     }
- }
- 
- std::unique_ptr<diagnostic_per_format_buffer>
- diagnostic_text_output_format::make_per_format_buffer ()
- {
-   return std::make_unique<diagnostic_text_format_buffer> (*this);
- }
- 
- /* Implementation of diagnostic_output_format::on_report_diagnostic vfunc
-    for GCC's standard textual output.  */
- 
- void
- diagnostic_text_output_format::
- on_report_diagnostic (const diagnostic_info &diagnostic,
- 		      diagnostic_t orig_diag_kind)
- {
-   pretty_printer *pp = get_printer ();
- 
-   (*diagnostic_text_starter (&m_context)) (*this, &diagnostic);
- 
-   pp_output_formatted_text (pp, m_context.get_urlifier ());
- 
-   if (m_context.m_show_cwe)
-     print_any_cwe (diagnostic);
- 
-   if (m_context.m_show_rules)
-     print_any_rules (diagnostic);
- 
-   if (m_context.m_show_option_requested)
-     print_option_information (diagnostic, orig_diag_kind);
- 
-   /* If we're showing nested diagnostics, then print the location
-      on a new line, indented.  */
-   if (m_show_nesting && m_show_locations_in_nesting)
-     {
-       const int nesting_level = get_context ().get_diagnostic_nesting_level ();
-       if (nesting_level > 0)
- 	{
- 	  location_t loc = diagnostic_location (&diagnostic);
- 	  pp_set_prefix (pp, nullptr);
- 	  char *indent_prefix = build_indent_prefix (false);
- 	  /* Only print changes of location.  */
- 	  if (loc != get_context ().m_last_location
- 	      && loc > BUILTINS_LOCATION)
- 	    {
- 	      const expanded_location s
- 		= diagnostic_expand_location (&diagnostic);
- 	      label_text location_text = get_location_text (s);
- 	      pp_newline (pp);
- 	      pp_printf (pp, "%s%s", indent_prefix, location_text.get ());
- 	    }
- 	  pp_set_prefix (pp, indent_prefix);
- 	}
-     }
- 
-   (*diagnostic_text_finalizer (&m_context)) (*this,
- 					     &diagnostic,
- 					     orig_diag_kind);
- 
-   if (m_show_nesting && m_show_locations_in_nesting)
-     get_context ().m_last_location = diagnostic_location (&diagnostic);
- }
- 
- void
- diagnostic_text_output_format::on_report_verbatim (text_info &text)
- {
-   pp_format_verbatim (get_printer (), &text);
-   pp_newline_and_flush (get_printer ());
- }
- 
- void
- diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram)
- {
-   pretty_printer *const pp = get_printer ();
- 
-   char *saved_prefix = pp_take_prefix (pp);
-   pp_set_prefix (pp, nullptr);
-   /* Use a newline before and after and a two-space indent
-      to make the diagram stand out a little from the wall of text.  */
-   pp_newline (pp);
-   diagram.get_canvas ().print_to_pp (pp, "  ");
-   pp_newline (pp);
-   pp_set_prefix (pp, saved_prefix);
-   pp_flush (pp);
- }
- 
- void
- diagnostic_text_output_format::
- after_diagnostic (const diagnostic_info &diagnostic)
- {
-   if (const diagnostic_path *path = diagnostic.richloc->get_path ())
-     print_path (*path);
- }
- 
- /* Return a malloc'd string describing a location and the severity of the
-    diagnostic, e.g. "foo.c:42:10: error: ".
- 
-    If m_show_nesting, then the above will be preceded by indentation to show
-    the level, and a bullet point.
- 
-    The caller is responsible for freeing the memory.  */
- char *
- diagnostic_text_output_format::
- build_prefix (const diagnostic_info &diagnostic) const
- {
-   gcc_assert (diagnostic.kind < DK_LAST_DIAGNOSTIC_KIND);
- 
-   const char *text = _(get_diagnostic_kind_text (diagnostic.kind));
-   const char *text_cs = "", *text_ce = "";
-   pretty_printer *pp = get_printer ();
- 
-   if (const char *color_name = diagnostic_get_color_for_kind (diagnostic.kind))
-     {
-       text_cs = colorize_start (pp_show_color (pp), color_name);
-       text_ce = colorize_stop (pp_show_color (pp));
-     }
- 
-   const int nesting_level = get_context ().get_diagnostic_nesting_level ();
-   if (m_show_nesting && nesting_level > 0)
-     {
-       char *indent_prefix = build_indent_prefix (true);
- 
-       /* Reduce verbosity of nested diagnostics by not printing "note: "
- 	 all the time.  */
-       if (diagnostic.kind == DK_NOTE)
- 	return indent_prefix;
- 
-       char *result = build_message_string ("%s%s%s%s", indent_prefix,
- 					   text_cs, text, text_ce);
-       free (indent_prefix);
-       return result;
-     }
-   else
-     {
-       const expanded_location s = diagnostic_expand_location (&diagnostic);
-       label_text location_text = get_location_text (s);
-       return build_message_string ("%s %s%s%s", location_text.get (),
- 				   text_cs, text, text_ce);
-     }
- }
- 
- /* Same as build_prefix, but only the source FILE is given.  */
- char *
- diagnostic_text_output_format::file_name_as_prefix (const char *f) const
- {
-   pretty_printer *const pp = get_printer ();
-   const char *locus_cs
-     = colorize_start (pp_show_color (pp), "locus");
-   const char *locus_ce = colorize_stop (pp_show_color (pp));
-   return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
- }
- 
- /* Get the unicode code point for bullet points when showing
-    nested diagnostics.  */
- 
- static unsigned
- get_bullet_point_unichar (bool unicode)
- {
-   if (unicode)
-     return 0x2022; /* U+2022: Bullet */
-   else
-     return '*';
- }
- 
- /* Return true if DC's theme supports unicode characters.  */
- 
- static bool
- use_unicode_p (const diagnostic_context &dc)
- {
-   if (text_art::theme *theme = dc.get_diagram_theme ())
-     return theme->unicode_p ();
-   else
-     return false;
- }
- 
- /* Get the unicode code point for bullet points when showing
-    nested diagnostics.  */
- 
- static unsigned
- get_bullet_point_unichar (diagnostic_context &dc)
- {
-   return get_bullet_point_unichar (use_unicode_p (dc));
- }
- 
- /* Return a malloc'd string for use as a prefix to show indentation.
-    If m_show_nesting is false, or we're at the top-level, then the
-    result will be the empty string.
- 
-    If m_show_nesting, then the result will contain indentation to show
-    the nesting level, then either a bullet point (if WITH_BULLET is true),
-    or a space.
- 
-    The caller is responsible for freeing the memory.  */
- 
- char *
- diagnostic_text_output_format::build_indent_prefix (bool with_bullet) const
- {
-   if (!m_show_nesting)
-     return xstrdup ("");
- 
-   const int nesting_level = get_context ().get_diagnostic_nesting_level ();
-   if (nesting_level == 0)
-     return xstrdup ("");
- 
-   pretty_printer pp;
-   for (int i = 0; i < nesting_level; i++)
-     pp_string (&pp, "  ");
-   if (with_bullet)
-     pp_unicode_character (&pp, get_bullet_point_unichar (get_context ()));
-   else
-     pp_space (&pp);
-   pp_space (&pp);
-   if (m_show_nesting_levels)
-     pp_printf (&pp, "(level %i):", nesting_level);
-   return xstrdup (pp_formatted_text (&pp));
- }
- 
- /* Add a purely textual note with text GMSGID and with LOCATION.  */
- 
- void
- diagnostic_text_output_format::append_note (location_t location,
- 					    const char * gmsgid, ...)
- {
-   diagnostic_context *context = &get_context ();
- 
-   diagnostic_info diagnostic;
-   va_list ap;
-   rich_location richloc (line_table, location);
- 
-   va_start (ap, gmsgid);
-   diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
-   if (context->m_inhibit_notes_p)
-     {
-       va_end (ap);
-       return;
-     }
-   pretty_printer *pp = get_printer ();
-   char *saved_prefix = pp_take_prefix (pp);
-   pp_set_prefix (pp, build_prefix (diagnostic));
-   pp_format (pp, &diagnostic.message);
-   pp_output_formatted_text (pp);
-   pp_destroy_prefix (pp);
-   pp_set_prefix (pp, saved_prefix);
-   pp_newline (pp);
-   diagnostic_show_locus (context, get_source_printing_options (),
- 			 &richloc, DK_NOTE, pp);
-   va_end (ap);
- }
- 
- bool
- diagnostic_text_output_format::follows_reference_printer_p () const
- {
-   return m_follows_reference_printer;
- }
- 
- void
- diagnostic_text_output_format::
- update_printer ()
- {
-   pretty_printer *copy_from_pp
-     = (m_follows_reference_printer
-        ? get_context ().get_reference_printer ()
-        : m_printer.get ());
-   const bool show_color = pp_show_color (copy_from_pp);
-   const diagnostic_url_format url_format = copy_from_pp->get_url_format ();
- 
-   m_printer = get_context ().clone_printer ();
- 
-   pp_show_color (m_printer.get ()) = show_color;
-   m_printer->set_url_format (url_format);
-   // ...etc
- 
-   m_source_printing = get_context ().m_source_printing;
- }
- 
- /* If DIAGNOSTIC has a CWE identifier, print it.
- 
-    For example, if the diagnostic metadata associates it with CWE-119,
-    " [CWE-119]" will be printed, suitably colorized, and with a URL of a
-    description of the security issue.  */
- 
- void
- diagnostic_text_output_format::print_any_cwe (const diagnostic_info &diagnostic)
- {
-   if (!diagnostic.metadata)
-     return;
- 
-   int cwe = diagnostic.metadata->get_cwe ();
-   if (cwe)
-     {
-       pretty_printer * const pp = get_printer ();
-       char *saved_prefix = pp_take_prefix (pp);
-       pp_string (pp, " [");
-       const char *kind_color = diagnostic_get_color_for_kind (diagnostic.kind);
-       pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
-       if (pp->supports_urls_p ())
- 	{
- 	  char *cwe_url = get_cwe_url (cwe);
- 	  pp_begin_url (pp, cwe_url);
- 	  free (cwe_url);
- 	}
-       pp_printf (pp, "CWE-%i", cwe);
-       pp_set_prefix (pp, saved_prefix);
-       if (pp->supports_urls_p ())
- 	pp_end_url (pp);
-       pp_string (pp, colorize_stop (pp_show_color (pp)));
-       pp_character (pp, ']');
-     }
- }
- 
- /* If DIAGNOSTIC has any rules associated with it, print them.
- 
-    For example, if the diagnostic metadata associates it with a rule
-    named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
-    with any URL provided by the rule.  */
- 
- void
- diagnostic_text_output_format::
- print_any_rules (const diagnostic_info &diagnostic)
- {
-   if (!diagnostic.metadata)
-     return;
- 
-   for (unsigned idx = 0; idx < diagnostic.metadata->get_num_rules (); idx++)
-     {
-       const diagnostic_metadata::rule &rule
- 	= diagnostic.metadata->get_rule (idx);
-       if (char *desc = rule.make_description ())
- 	{
- 	  pretty_printer * const pp = get_printer ();
- 	  char *saved_prefix = pp_take_prefix (pp);
- 	  pp_string (pp, " [");
- 	  const char *kind_color
- 	    = diagnostic_get_color_for_kind (diagnostic.kind);
- 	  pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
- 	  char *url = nullptr;
- 	  if (pp->supports_urls_p ())
- 	    {
- 	      url = rule.make_url ();
- 	      if (url)
- 		pp_begin_url (pp, url);
- 	    }
- 	  pp_string (pp, desc);
- 	  pp_set_prefix (pp, saved_prefix);
- 	  if (pp->supports_urls_p ())
- 	    if (url)
- 	      pp_end_url (pp);
- 	  free (url);
- 	  pp_string (pp, colorize_stop (pp_show_color (pp)));
- 	  pp_character (pp, ']');
- 	  free (desc);
- 	}
-     }
- }
- 
- /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
-    printer, e.g. " [-Werror=uninitialized]".
-    Subroutine of diagnostic_context::report_diagnostic.  */
- 
- void
- diagnostic_text_output_format::
- print_option_information (const diagnostic_info &diagnostic,
- 			  diagnostic_t orig_diag_kind)
- {
-   if (char *option_text
-       = m_context.make_option_name (diagnostic.option_id,
- 				    orig_diag_kind, diagnostic.kind))
-     {
-       char *option_url = nullptr;
-       pretty_printer * const pp = get_printer ();
-       if (pp->supports_urls_p ())
- 	option_url = m_context.make_option_url (diagnostic.option_id);
-       pp_string (pp, " [");
-       const char *kind_color = diagnostic_get_color_for_kind (diagnostic.kind);
-       pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
-       if (option_url)
- 	pp_begin_url (pp, option_url);
-       pp_string (pp, option_text);
-       if (option_url)
- 	{
- 	  pp_end_url (pp);
- 	  free (option_url);
- 	}
-       pp_string (pp, colorize_stop (pp_show_color (pp)));
-       pp_character (pp, ']');
-       free (option_text);
-     }
- }
- 
- /* Only dump the "In file included from..." stack once for each file.  */
- 
- bool
- diagnostic_text_output_format::includes_seen_p (const line_map_ordinary *map)
- {
-   /* No include path for main.  */
-   if (MAIN_FILE_P (map))
-     return true;
- 
-   /* Always identify C++ modules, at least for now.  */
-   auto probe = map;
-   if (linemap_check_ordinary (map)->reason == LC_RENAME)
-     /* The module source file shows up as LC_RENAME inside LC_MODULE.  */
-     probe = linemap_included_from_linemap (line_table, map);
-   if (MAP_MODULE_P (probe))
-     return false;
- 
-   if (!m_includes_seen)
-     m_includes_seen = new hash_set<location_t, false, location_hash>;
- 
-   /* Hash the location of the #include directive to better handle files
-      that are included multiple times with different macros defined.  */
-   return m_includes_seen->add (linemap_included_from (map));
- }
- 
- label_text
- diagnostic_text_output_format::
- get_location_text (const expanded_location &s) const
- {
-   diagnostic_column_policy column_policy (get_context ());
-   return column_policy.get_location_text (s,
- 					  show_column_p (),
- 					  pp_show_color (get_printer ()));
- }
- 
- /* Helpers for writing lang-specific starters/finalizers for text output.  */
- 
- /* Return a formatted line and column ':%line:%column'.  Elided if
-    line == 0 or col < 0.  (A column of 0 may be valid due to the
-    -fdiagnostics-column-origin option.)
-    The result is a statically allocated buffer.  */
- 
- const char *
- maybe_line_and_column (int line, int col)
- {
-   static char result[32];
- 
-   if (line)
-     {
-       size_t l
- 	= snprintf (result, sizeof (result),
- 		    col >= 0 ? ":%d:%d" : ":%d", line, col);
-       gcc_checking_assert (l < sizeof (result));
-     }
-   else
-     result[0] = 0;
-   return result;
- }
- 
- void
- diagnostic_text_output_format::report_current_module (location_t where)
- {
-   pretty_printer *pp = get_printer ();
-   const line_map_ordinary *map = nullptr;
- 
-   if (pp_needs_newline (pp))
-     {
-       pp_newline (pp);
-       pp_needs_newline (pp) = false;
-     }
- 
-   if (where <= BUILTINS_LOCATION)
-     return;
- 
-   linemap_resolve_location (line_table, where,
- 			    LRK_MACRO_DEFINITION_LOCATION,
- 			    &map);
- 
-   if (map && m_last_module != map)
-     {
-       m_last_module = map;
-       if (!includes_seen_p (map))
- 	{
- 	  bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
- 	  expanded_location s = {};
- 	  do
- 	    {
- 	      where = linemap_included_from (map);
- 	      map = linemap_included_from_linemap (line_table, map);
- 	      bool is_module = MAP_MODULE_P (map);
- 	      s.file = LINEMAP_FILE (map);
- 	      s.line = SOURCE_LINE (map, where);
- 	      int col = -1;
- 	      if (first && show_column_p ())
- 		{
- 		  s.column = SOURCE_COLUMN (map, where);
- 		  col = get_column_policy ().converted_column (s);
- 		}
- 	      const char *line_col = maybe_line_and_column (s.line, col);
- 	      static const char *const msgs[] =
- 		{
- 		 nullptr,
- 		 N_("                 from"),
- 		 N_("In file included from"),	/* 2 */
- 		 N_("        included from"),
- 		 N_("In module"),		/* 4 */
- 		 N_("of module"),
- 		 N_("In module imported at"),	/* 6 */
- 		 N_("imported at"),
- 		};
- 
- 	      unsigned index = (was_module ? 6 : is_module ? 4
- 				: need_inc ? 2 : 0) + !first;
- 
- 	      pp_verbatim (pp, "%s%s %r%s%s%R",
- 			   first ? "" : was_module ? ", " : ",\n",
- 			   _(msgs[index]),
- 			   "locus", s.file, line_col);
- 	      first = false, need_inc = was_module, was_module = is_module;
- 	    }
- 	  while (!includes_seen_p (map));
- 	  pp_verbatim (pp, ":");
- 	  pp_newline (pp);
- 	}
-     }
- }
- 
- void
- default_diagnostic_text_starter (diagnostic_text_output_format &text_output,
- 				 const diagnostic_info *diagnostic)
- {
-   text_output.report_current_module (diagnostic_location (diagnostic));
-   pretty_printer *const pp = text_output.get_printer ();
-   pp_set_prefix (pp, text_output.build_prefix (*diagnostic));
- }
- 
- void
- default_diagnostic_text_finalizer (diagnostic_text_output_format &text_output,
- 				   const diagnostic_info *diagnostic,
- 				   diagnostic_t)
- {
-   pretty_printer *const pp = text_output.get_printer ();
-   char *saved_prefix = pp_take_prefix (pp);
-   pp_set_prefix (pp, nullptr);
-   pp_newline (pp);
-   diagnostic_show_locus (&text_output.get_context (),
- 			 text_output.get_source_printing_options (),
- 			 diagnostic->richloc, diagnostic->kind, pp);
-   pp_set_prefix (pp, saved_prefix);
-   pp_flush (pp);
- }
- 
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic pop
- #endif
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-format-text.h gcc-16-20250727/gcc/diagnostic-format-text.h
*** gcc-16-20250720/gcc/diagnostic-format-text.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-format-text.h	Thu Jan  1 00:00:00 1970
***************
*** 1,171 ****
- /* Classic text-based output of diagnostics.
-    Copyright (C) 2023-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_FORMAT_TEXT_H
- #define GCC_DIAGNOSTIC_FORMAT_TEXT_H
- 
- #include "diagnostic-format.h"
- 
- /* Subclass of diagnostic_output_format for classic text-based output
-    to stderr.
- 
-    Uses diagnostic_context.m_text_callbacks to provide client-specific
-    textual output (e.g. include paths, macro expansions, etc).  */
- 
- class diagnostic_text_output_format : public diagnostic_output_format
- {
- public:
-   diagnostic_text_output_format (diagnostic_context &context,
- 				 diagnostic_source_printing_options *source_printing = nullptr,
- 				 bool follows_reference_printer = false)
-   : diagnostic_output_format (context),
-     m_saved_output_buffer (nullptr),
-     m_column_policy (context),
-     m_last_module (nullptr),
-     m_includes_seen (nullptr),
-     m_source_printing (source_printing
- 		       ? *source_printing
- 		       : context.m_source_printing),
-     m_follows_reference_printer (follows_reference_printer),
-     m_show_nesting (false),
-     m_show_nesting_levels (false)
-   {}
-   ~diagnostic_text_output_format ();
- 
-   void dump (FILE *out, int indent) const override;
- 
-   std::unique_ptr<diagnostic_per_format_buffer>
-   make_per_format_buffer () final override;
-   void set_buffer (diagnostic_per_format_buffer *) final override;
- 
-   void on_begin_group () override {}
-   void on_end_group () override {}
-   void on_report_diagnostic (const diagnostic_info &,
- 			     diagnostic_t orig_diag_kind) override;
-   void on_report_verbatim (text_info &) final override;
-   void on_diagram (const diagnostic_diagram &diagram) override;
-   void after_diagnostic (const diagnostic_info &) override;
-   bool machine_readable_stderr_p () const final override
-   {
-     return false;
-   }
-   bool follows_reference_printer_p () const final override;
- 
-   void update_printer () override;
- 
-   void
-   report_global_digraph (const diagnostics::digraphs::lazy_digraph &) final override
-   {
-     // no-op for text
-   }
- 
-   /* Helpers for writing lang-specific starters/finalizers for text output.  */
-   char *build_prefix (const diagnostic_info &) const;
-   void report_current_module (location_t where);
-   void append_note (location_t location,
- 		    const char * gmsgid, ...) ATTRIBUTE_GCC_DIAG(3,4);
- 
- 
-   char *file_name_as_prefix (const char *) const;
- 
-   char *build_indent_prefix (bool with_bullet) const;
- 
-   void print_path (const diagnostic_path &path);
- 
-   bool show_column_p () const { return get_context ().m_show_column; }
- 
-   const diagnostic_column_policy &get_column_policy () const
-   {
-     return m_column_policy;
-   }
-   diagnostic_location_print_policy get_location_print_policy () const;
- 
-   bool show_nesting_p () const { return m_show_nesting; }
-   bool show_locations_in_nesting_p () const
-   {
-     return m_show_locations_in_nesting;
-   }
- 
-   void set_show_nesting (bool show_nesting) { m_show_nesting = show_nesting; }
-   void set_show_locations_in_nesting (bool val)
-   {
-     m_show_locations_in_nesting = val;
-   }
-   void set_show_nesting_levels (bool show_nesting_levels)
-   {
-     m_show_nesting_levels = show_nesting_levels;
-   }
- 
-   label_text get_location_text (const expanded_location &s) const;
- 
-   diagnostic_source_printing_options &get_source_printing_options ()
-   {
-     return m_source_printing;
-   }
-   const diagnostic_source_printing_options &get_source_printing_options () const
-   {
-     return m_source_printing;
-   }
- 
- protected:
-   void print_any_cwe (const diagnostic_info &diagnostic);
-   void print_any_rules (const diagnostic_info &diagnostic);
-   void print_option_information (const diagnostic_info &diagnostic,
- 				 diagnostic_t orig_diag_kind);
- 
-   bool includes_seen_p (const line_map_ordinary *map);
- 
-   /* For handling diagnostic_buffer.  */
-   output_buffer *m_saved_output_buffer;
- 
-   diagnostic_column_policy m_column_policy;
- 
-   /* Used to detect when the input file stack has changed since last
-      described.  */
-   const line_map_ordinary *m_last_module;
- 
-   /* Include files that report_current_module has already listed the
-      include path for.  */
-   hash_set<location_t, false, location_hash> *m_includes_seen;
- 
-   diagnostic_source_printing_options &m_source_printing;
- 
-   /* If true, this is the initial default text output format created
-      when the diagnostic_context was created, and, in particular, before
-      initializations of color and m_url_format.  Hence this should follow
-      the dc's reference printer for these.
-      If false, this text output was created after the dc was created, and
-      thus tracks its own values for color and m_url_format.  */
-   bool m_follows_reference_printer;
- 
-   /* If true, then use indentation to show the nesting structure of
-      nested diagnostics, and print locations on separate lines after the
-      diagnostic message, rather than as a prefix to the message.  */
-   bool m_show_nesting;
- 
-   /* Set to false to suppress location-printing when showing nested
-      diagnostics, for use in DejaGnu tests.  */
-   bool m_show_locations_in_nesting;
- 
-   /* If true, then add "(level N):" when printing nested diagnostics.  */
-   bool m_show_nesting_levels;
- };
- 
- #endif /* ! GCC_DIAGNOSTIC_FORMAT_TEXT_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-format.h gcc-16-20250727/gcc/diagnostic-format.h
*** gcc-16-20250720/gcc/diagnostic-format.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-format.h	Thu Jan  1 00:00:00 1970
***************
*** 1,106 ****
- /* Declarations for managing different output formats for diagnostics.
-    Copyright (C) 2023-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_FORMAT_H
- #define GCC_DIAGNOSTIC_FORMAT_H
- 
- #include "diagnostic.h"
- 
- class diagnostic_per_format_buffer;
- 
- /* Abstract base class for a particular output format for diagnostics;
-    each value of -fdiagnostics-output-format= will have its own
-    implementation.  */
- 
- class diagnostic_output_format
- {
- public:
-   virtual ~diagnostic_output_format () {}
- 
-   virtual void dump (FILE *out, int indent) const;
- 
-   /* Vfunc for notifying this format what the primary input file is,
-      e.g. for titles of HTML, for SARIF's artifact metadata.  */
-   virtual void set_main_input_filename (const char *) {}
- 
-   /* Vfunc for making an appropriate diagnostic_per_format_buffer
-      subclass for this format.  */
-   virtual std::unique_ptr<diagnostic_per_format_buffer>
-   make_per_format_buffer () = 0;
- 
-   /* Vfunc to be called when call a diagnostic_buffer is set on
-      a diagnostic_context, to update this format.  The per_format_buffer
-      will be one created by make_per_format_buffer above and thus be
-      of the correct subclass.  */
-   virtual void set_buffer (diagnostic_per_format_buffer *) = 0;
- 
-   virtual void on_begin_group () = 0;
-   virtual void on_end_group () = 0;
- 
-   /* Vfunc with responsibility for phase 3 of formatting the message
-      and "printing" the result.  */
-   virtual void on_report_diagnostic (const diagnostic_info &,
- 				     diagnostic_t orig_diag_kind) = 0;
- 
-   virtual void on_report_verbatim (text_info &);
- 
-   virtual void on_diagram (const diagnostic_diagram &diagram) = 0;
-   virtual void after_diagnostic (const diagnostic_info &) = 0;
-   virtual bool machine_readable_stderr_p () const = 0;
-   virtual bool follows_reference_printer_p () const = 0;
- 
-   /* Vfunc called when the diagnostic_context changes its
-      reference printer (either to a new subclass of pretty_printer
-      or when color/url options change).
-      Subclasses should update their m_printer accordingly.  */
-   virtual void update_printer () = 0;
- 
-   virtual void
-   report_global_digraph (const diagnostics::digraphs::lazy_digraph &) = 0;
- 
-   diagnostic_context &get_context () const { return m_context; }
-   pretty_printer *get_printer () const { return m_printer.get (); }
- 
-   text_art::theme *get_diagram_theme () const
-   {
-     return m_context.get_diagram_theme ();
-   }
- 
-   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
- 
- protected:
-   diagnostic_output_format (diagnostic_context &context)
-   : m_context (context),
-     m_printer (context.clone_printer ())
-   {}
- 
- protected:
-   diagnostic_context &m_context;
-   std::unique_ptr<pretty_printer> m_printer;
- };
- 
- extern void
- diagnostic_output_format_init (diagnostic_context &,
- 			       const char *main_input_filename_,
- 			       const char *base_file_name,
- 			       enum diagnostics_output_format,
- 			       bool json_formatting);
- 
- #endif /* ! GCC_DIAGNOSTIC_FORMAT_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-global-context.cc gcc-16-20250727/gcc/diagnostic-global-context.cc
*** gcc-16-20250720/gcc/diagnostic-global-context.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-global-context.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 27,37 ****
  #include "coretypes.h"
  #include "intl.h"
  #include "diagnostic.h"
! #include "diagnostic-format.h"
  
! /* A diagnostic_context surrogate for stderr.  */
! static diagnostic_context global_diagnostic_context;
! diagnostic_context *global_dc = &global_diagnostic_context;
  
  /* Standard error reporting routines in increasing order of severity.  */
  
--- 27,37 ----
  #include "coretypes.h"
  #include "intl.h"
  #include "diagnostic.h"
! #include "diagnostics/sink.h"
  
! /* A diagnostics::context surrogate for stderr.  */
! static diagnostics::context global_diagnostic_context;
! diagnostics::context *global_dc = &global_diagnostic_context;
  
  /* Standard error reporting routines in increasing order of severity.  */
  
*************** verbatim (const char *gmsgid, ...)
*** 49,61 ****
    va_end (ap);
  }
  
! /* Wrapper around diagnostic_context::diagnostic_impl
     implying global_dc and taking a variable argument list.  */
  
  bool
! emit_diagnostic (diagnostic_t kind,
  		 location_t location,
! 		 diagnostic_option_id option_id,
  		 const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
--- 49,61 ----
    va_end (ap);
  }
  
! /* Wrapper around diagnostics::context::diagnostic_impl
     implying global_dc and taking a variable argument list.  */
  
  bool
! emit_diagnostic (enum diagnostics::kind kind,
  		 location_t location,
! 		 diagnostics::option_id option_id,
  		 const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
*************** emit_diagnostic (diagnostic_t kind,
*** 71,79 ****
  /* As above, but for rich_location *.  */
  
  bool
! emit_diagnostic (diagnostic_t kind,
  		 rich_location *richloc,
! 		 diagnostic_option_id option_id,
  		 const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
--- 71,79 ----
  /* As above, but for rich_location *.  */
  
  bool
! emit_diagnostic (enum diagnostics::kind kind,
  		 rich_location *richloc,
! 		 diagnostics::option_id option_id,
  		 const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
*************** emit_diagnostic (diagnostic_t kind,
*** 88,96 ****
  /* As above, but taking a variable argument list.  */
  
  bool
! emit_diagnostic_valist (diagnostic_t kind,
  			location_t location,
! 			diagnostic_option_id option_id,
  			const char *gmsgid, va_list *ap)
  {
    rich_location richloc (line_table, location);
--- 88,96 ----
  /* As above, but taking a variable argument list.  */
  
  bool
! emit_diagnostic_valist (enum diagnostics::kind kind,
  			location_t location,
! 			diagnostics::option_id option_id,
  			const char *gmsgid, va_list *ap)
  {
    rich_location richloc (line_table, location);
*************** emit_diagnostic_valist (diagnostic_t kin
*** 101,110 ****
  /* As above, but with rich_location and metadata.  */
  
  bool
! emit_diagnostic_valist_meta (diagnostic_t kind,
  			     rich_location *richloc,
! 			     const diagnostic_metadata *metadata,
! 			     diagnostic_option_id option_id,
  			     const char *gmsgid, va_list *ap)
  {
    return global_dc->diagnostic_impl (richloc, metadata, option_id,
--- 101,110 ----
  /* As above, but with rich_location and metadata.  */
  
  bool
! emit_diagnostic_valist_meta (enum diagnostics::kind kind,
  			     rich_location *richloc,
! 			     const diagnostics::metadata *metadata,
! 			     diagnostics::option_id option_id,
  			     const char *gmsgid, va_list *ap)
  {
    return global_dc->diagnostic_impl (richloc, metadata, option_id,
*************** inform (location_t location, const char
*** 120,126 ****
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_NOTE);
    va_end (ap);
  }
  
--- 120,127 ----
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::note);
    va_end (ap);
  }
  
*************** inform (rich_location *richloc, const ch
*** 133,139 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap, DK_NOTE);
    va_end (ap);
  }
  
--- 134,141 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::note);
    va_end (ap);
  }
  
*************** inform_n (location_t location, unsigned
*** 149,155 ****
    rich_location richloc (line_table, location);
    global_dc->diagnostic_n_impl (&richloc, nullptr, -1, n,
  				singular_gmsgid, plural_gmsgid,
! 				&ap, DK_NOTE);
    va_end (ap);
  }
  
--- 151,157 ----
    rich_location richloc (line_table, location);
    global_dc->diagnostic_n_impl (&richloc, nullptr, -1, n,
  				singular_gmsgid, plural_gmsgid,
! 				&ap, diagnostics::kind::note);
    va_end (ap);
  }
  
*************** inform_n (location_t location, unsigned
*** 157,170 ****
     to the relevant language specification but is likely to be buggy anyway.
     Returns true if the warning was printed, false if it was inhibited.  */
  bool
! warning (diagnostic_option_id option_id, const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
! 					 gmsgid, &ap, DK_WARNING);
    va_end (ap);
    return ret;
  }
--- 159,173 ----
     to the relevant language specification but is likely to be buggy anyway.
     Returns true if the warning was printed, false if it was inhibited.  */
  bool
! warning (diagnostics::option_id option_id, const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
! 					 gmsgid, &ap,
! 					 diagnostics::kind::warning);
    va_end (ap);
    return ret;
  }
*************** warning (diagnostic_option_id option_id,
*** 175,181 ****
  
  bool
  warning_at (location_t location,
! 	    diagnostic_option_id option_id,
  	    const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
--- 178,184 ----
  
  bool
  warning_at (location_t location,
! 	    diagnostics::option_id option_id,
  	    const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
*************** warning_at (location_t location,
*** 183,189 ****
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
! 					 gmsgid, &ap, DK_WARNING);
    va_end (ap);
    return ret;
  }
--- 186,193 ----
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
! 					 gmsgid, &ap,
! 					 diagnostics::kind::warning);
    va_end (ap);
    return ret;
  }
*************** warning_at (location_t location,
*** 192,198 ****
  
  bool
  warning_at (rich_location *richloc,
! 	    diagnostic_option_id option_id,
  	    const char *gmsgid, ...)
  {
    gcc_assert (richloc);
--- 196,202 ----
  
  bool
  warning_at (rich_location *richloc,
! 	    diagnostics::option_id option_id,
  	    const char *gmsgid, ...)
  {
    gcc_assert (richloc);
*************** warning_at (rich_location *richloc,
*** 201,207 ****
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
! 					 gmsgid, &ap, DK_WARNING);
    va_end (ap);
    return ret;
  }
--- 205,212 ----
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
! 					 gmsgid, &ap,
! 					 diagnostics::kind::warning);
    va_end (ap);
    return ret;
  }
*************** warning_at (rich_location *richloc,
*** 210,217 ****
  
  bool
  warning_meta (rich_location *richloc,
! 	      const diagnostic_metadata &metadata,
! 	      diagnostic_option_id option_id,
  	      const char *gmsgid, ...)
  {
    gcc_assert (richloc);
--- 215,222 ----
  
  bool
  warning_meta (rich_location *richloc,
! 	      const diagnostics::metadata &metadata,
! 	      diagnostics::option_id option_id,
  	      const char *gmsgid, ...)
  {
    gcc_assert (richloc);
*************** warning_meta (rich_location *richloc,
*** 220,226 ****
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, &metadata, option_id,
! 					 gmsgid, &ap, DK_WARNING);
    va_end (ap);
    return ret;
  }
--- 225,232 ----
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, &metadata, option_id,
! 					 gmsgid, &ap,
! 					 diagnostics::kind::warning);
    va_end (ap);
    return ret;
  }
*************** warning_meta (rich_location *richloc,
*** 229,235 ****
  
  bool
  warning_n (rich_location *richloc,
! 	   diagnostic_option_id option_id,
  	   unsigned HOST_WIDE_INT n,
  	   const char *singular_gmsgid, const char *plural_gmsgid, ...)
  {
--- 235,241 ----
  
  bool
  warning_n (rich_location *richloc,
! 	   diagnostics::option_id option_id,
  	   unsigned HOST_WIDE_INT n,
  	   const char *singular_gmsgid, const char *plural_gmsgid, ...)
  {
*************** warning_n (rich_location *richloc,
*** 240,246 ****
    va_start (ap, plural_gmsgid);
    bool ret = global_dc->diagnostic_n_impl (richloc, nullptr, option_id, n,
  					   singular_gmsgid, plural_gmsgid,
! 					   &ap, DK_WARNING);
    va_end (ap);
    return ret;
  }
--- 246,252 ----
    va_start (ap, plural_gmsgid);
    bool ret = global_dc->diagnostic_n_impl (richloc, nullptr, option_id, n,
  					   singular_gmsgid, plural_gmsgid,
! 					   &ap, diagnostics::kind::warning);
    va_end (ap);
    return ret;
  }
*************** warning_n (rich_location *richloc,
*** 251,257 ****
  
  bool
  warning_n (location_t location,
! 	   diagnostic_option_id option_id,
  	   unsigned HOST_WIDE_INT n,
  	   const char *singular_gmsgid, const char *plural_gmsgid, ...)
  {
--- 257,263 ----
  
  bool
  warning_n (location_t location,
! 	   diagnostics::option_id option_id,
  	   unsigned HOST_WIDE_INT n,
  	   const char *singular_gmsgid, const char *plural_gmsgid, ...)
  {
*************** warning_n (location_t location,
*** 261,267 ****
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_n_impl (&richloc, nullptr, option_id, n,
  					   singular_gmsgid, plural_gmsgid,
! 					   &ap, DK_WARNING);
    va_end (ap);
    return ret;
  }
--- 267,273 ----
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_n_impl (&richloc, nullptr, option_id, n,
  					   singular_gmsgid, plural_gmsgid,
! 					   &ap, diagnostics::kind::warning);
    va_end (ap);
    return ret;
  }
*************** warning_n (location_t location,
*** 281,287 ****
  
  bool
  pedwarn (location_t location,
! 	 diagnostic_option_id option_id,
  	 const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
--- 287,293 ----
  
  bool
  pedwarn (location_t location,
! 	 diagnostics::option_id option_id,
  	 const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
*************** pedwarn (location_t location,
*** 289,295 ****
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
! 					 gmsgid, &ap, DK_PEDWARN);
    va_end (ap);
    return ret;
  }
--- 295,302 ----
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
! 					 gmsgid, &ap,
! 					 diagnostics::kind::pedwarn);
    va_end (ap);
    return ret;
  }
*************** pedwarn (location_t location,
*** 298,304 ****
  
  bool
  pedwarn (rich_location *richloc,
! 	 diagnostic_option_id option_id,
  	 const char *gmsgid, ...)
  {
    gcc_assert (richloc);
--- 305,311 ----
  
  bool
  pedwarn (rich_location *richloc,
! 	 diagnostics::option_id option_id,
  	 const char *gmsgid, ...)
  {
    gcc_assert (richloc);
*************** pedwarn (rich_location *richloc,
*** 307,313 ****
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
! 					 gmsgid, &ap, DK_PEDWARN);
    va_end (ap);
    return ret;
  }
--- 314,321 ----
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
! 					 gmsgid, &ap,
! 					 diagnostics::kind::pedwarn);
    va_end (ap);
    return ret;
  }
*************** permerror (location_t location, const ch
*** 327,333 ****
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 					 DK_PERMERROR);
    va_end (ap);
    return ret;
  }
--- 335,341 ----
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 					 diagnostics::kind::permerror);
    va_end (ap);
    return ret;
  }
*************** permerror (rich_location *richloc, const
*** 343,349 ****
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap,
! 					 DK_PERMERROR);
    va_end (ap);
    return ret;
  }
--- 351,357 ----
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap,
! 					 diagnostics::kind::permerror);
    va_end (ap);
    return ret;
  }
*************** permerror (rich_location *richloc, const
*** 354,360 ****
  
  bool
  permerror_opt (location_t location,
! 	       diagnostic_option_id option_id,
  	       const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
--- 362,368 ----
  
  bool
  permerror_opt (location_t location,
! 	       diagnostics::option_id option_id,
  	       const char *gmsgid, ...)
  {
    auto_diagnostic_group d;
*************** permerror_opt (location_t location,
*** 362,368 ****
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
! 					 gmsgid, &ap, DK_PERMERROR);
    va_end (ap);
    return ret;
  }
--- 370,377 ----
    va_start (ap, gmsgid);
    rich_location richloc (line_table, location);
    bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id,
! 					 gmsgid, &ap,
! 					 diagnostics::kind::permerror);
    va_end (ap);
    return ret;
  }
*************** permerror_opt (location_t location,
*** 371,377 ****
  
  bool
  permerror_opt (rich_location *richloc,
! 	       diagnostic_option_id option_id,
  	       const char *gmsgid, ...)
  {
    gcc_assert (richloc);
--- 380,386 ----
  
  bool
  permerror_opt (rich_location *richloc,
! 	       diagnostics::option_id option_id,
  	       const char *gmsgid, ...)
  {
    gcc_assert (richloc);
*************** permerror_opt (rich_location *richloc,
*** 380,386 ****
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
! 					 gmsgid, &ap, DK_PERMERROR);
    va_end (ap);
    return ret;
  }
--- 389,396 ----
    va_list ap;
    va_start (ap, gmsgid);
    bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id,
! 					 gmsgid, &ap,
! 					 diagnostics::kind::permerror);
    va_end (ap);
    return ret;
  }
*************** error (const char *gmsgid, ...)
*** 394,400 ****
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_ERROR);
    va_end (ap);
  }
  
--- 404,411 ----
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::error);
    va_end (ap);
  }
  
*************** error_n (location_t location, unsigned H
*** 410,416 ****
    rich_location richloc (line_table, location);
    global_dc->diagnostic_n_impl (&richloc, nullptr, -1, n,
  				singular_gmsgid, plural_gmsgid,
! 				&ap, DK_ERROR);
    va_end (ap);
  }
  
--- 421,427 ----
    rich_location richloc (line_table, location);
    global_dc->diagnostic_n_impl (&richloc, nullptr, -1, n,
  				singular_gmsgid, plural_gmsgid,
! 				&ap, diagnostics::kind::error);
    va_end (ap);
  }
  
*************** error_at (location_t loc, const char *gm
*** 422,428 ****
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, loc);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_ERROR);
    va_end (ap);
  }
  
--- 433,440 ----
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, loc);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::error);
    va_end (ap);
  }
  
*************** error_at (rich_location *richloc, const
*** 436,449 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap, DK_ERROR);
    va_end (ap);
  }
  
  /* Same as above, but with metadata.  */
  
  void
! error_meta (rich_location *richloc, const diagnostic_metadata &metadata,
  	    const char *gmsgid, ...)
  {
    gcc_assert (richloc);
--- 448,462 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::error);
    va_end (ap);
  }
  
  /* Same as above, but with metadata.  */
  
  void
! error_meta (rich_location *richloc, const diagnostics::metadata &metadata,
  	    const char *gmsgid, ...)
  {
    gcc_assert (richloc);
*************** error_meta (rich_location *richloc, cons
*** 451,457 ****
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   global_dc->diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap, DK_ERROR);
    va_end (ap);
  }
  
--- 464,471 ----
    auto_diagnostic_group d;
    va_list ap;
    va_start (ap, gmsgid);
!   global_dc->diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap,
! 			      diagnostics::kind::error);
    va_end (ap);
  }
  
*************** sorry (const char *gmsgid, ...)
*** 465,471 ****
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_SORRY);
    va_end (ap);
  }
  
--- 479,486 ----
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::sorry);
    va_end (ap);
  }
  
*************** sorry_at (location_t loc, const char *gm
*** 477,483 ****
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, loc);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_SORRY);
    va_end (ap);
  }
  
--- 492,499 ----
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, loc);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::sorry);
    va_end (ap);
  }
  
*************** fatal_error (location_t loc, const char
*** 499,505 ****
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, loc);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_FATAL);
    va_end (ap);
  
    gcc_unreachable ();
--- 515,522 ----
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, loc);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::fatal);
    va_end (ap);
  
    gcc_unreachable ();
*************** internal_error (const char *gmsgid, ...)
*** 514,520 ****
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_ICE);
    va_end (ap);
  
    gcc_unreachable ();
--- 531,538 ----
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::ice);
    va_end (ap);
  
    gcc_unreachable ();
*************** internal_error_no_backtrace (const char
*** 530,536 ****
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, DK_ICE_NOBT);
    va_end (ap);
  
    gcc_unreachable ();
--- 548,555 ----
    va_list ap;
    va_start (ap, gmsgid);
    rich_location richloc (line_table, input_location);
!   global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap,
! 			      diagnostics::kind::ice_nobt);
    va_end (ap);
  
    gcc_unreachable ();
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-label-effects.h gcc-16-20250727/gcc/diagnostic-label-effects.h
*** gcc-16-20250720/gcc/diagnostic-label-effects.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-label-effects.h	Thu Jan  1 00:00:00 1970
***************
*** 1,58 ****
- /* Classes for adding special effects when quoting source code.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- 
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_LABEL_EFFECTS_H
- #define GCC_DIAGNOSTIC_LABEL_EFFECTS_H
- 
- /* Abstract base class for describing special effects when printing
-    a label when quoting source code.  */
- 
- class label_effects
- {
- public:
-   virtual ~label_effects () {}
- 
-   /* Adding links between labels, e.g. for visualizing control flow
-      in execution paths.  */
-   virtual bool has_in_edge (unsigned range_idx) const = 0;
-   virtual bool has_out_edge (unsigned range_idx) const = 0;
- };
- 
- /* A class to hold state when quoting a run of lines of source code.  */
- 
- class diagnostic_source_effect_info
- {
- public:
-   diagnostic_source_effect_info ()
-   : m_leading_in_edge_column (-1),
-     m_trailing_out_edge_column (-1)
-   {
-   }
- 
-   /* The column for an incoming link to the first label,
-      or -1 if no such link.  */
-   int m_leading_in_edge_column;
- 
-   /* The column for an outgoing link from the final label,
-      or -1 if no such link.  */
-   int m_trailing_out_edge_column;
- };
- 
- #endif /* GCC_DIAGNOSTIC_LABEL_EFFECTS_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-macro-unwinding.cc gcc-16-20250727/gcc/diagnostic-macro-unwinding.cc
*** gcc-16-20250720/gcc/diagnostic-macro-unwinding.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-macro-unwinding.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,222 ****
- /* Code for unwinding macro expansions in diagnostics.
-    Copyright (C) 1999-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "tree.h"
- #include "diagnostic.h"
- #include "diagnostic-macro-unwinding.h"
- #include "diagnostic-format-text.h"
- #include "intl.h"
- 
- /* This is a pair made of a location and the line map it originated
-    from.  It's used in the maybe_unwind_expanded_macro_loc function
-    below.  */
- struct loc_map_pair
- {
-   const line_map_macro *map;
-   location_t where;
- };
- 
- 
- /* Unwind the different macro expansions that lead to the token which
-    location is WHERE and emit diagnostics showing the resulting
-    unwound macro expansion trace.  Let's look at an example to see how
-    the trace looks like.  Suppose we have this piece of code,
-    artificially annotated with the line numbers to increase
-    legibility:
- 
-     $ cat -n test.c
-       1    #define OPERATE(OPRD1, OPRT, OPRD2) \
-       2      OPRD1 OPRT OPRD2;
-       3
-       4    #define SHIFTL(A,B) \
-       5      OPERATE (A,<<,B)
-       6
-       7    #define MULT(A) \
-       8      SHIFTL (A,1)
-       9
-      10    void
-      11    g ()
-      12    {
-      13      MULT (1.0);// 1.0 << 1; <-- so this is an error.
-      14    }
- 
-    Here is the diagnostic that we want the compiler to generate:
- 
-     test.c: In function ‘g’:
-     test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’)
-     test.c:2:9: note: in definition of macro 'OPERATE'
-     test.c:8:3: note: in expansion of macro 'SHIFTL'
-     test.c:13:3: note: in expansion of macro 'MULT'
- 
-    The part that goes from the third to the fifth line of this
-    diagnostic (the lines containing the 'note:' string) is called the
-    unwound macro expansion trace.  That's the part generated by this
-    function.  */
- 
- void
- maybe_unwind_expanded_macro_loc (diagnostic_text_output_format &text_output,
-                                  location_t where)
- {
-   const struct line_map *map;
-   auto_vec<loc_map_pair> loc_vec;
-   unsigned ix;
-   loc_map_pair loc, *iter;
- 
-   const location_t original_loc = where;
- 
-   map = linemap_lookup (line_table, where);
-   if (!linemap_macro_expansion_map_p (map))
-     return;
- 
-   /* Let's unwind the macros that got expanded and led to the token
-      which location is WHERE.  We are going to store these macros into
-      LOC_VEC, so that we can later walk it at our convenience to
-      display a somewhat meaningful trace of the macro expansion
-      history to the user.  Note that the first macro of the trace
-      (which is OPERATE in the example above) is going to be stored at
-      the beginning of LOC_VEC.  */
- 
-   do
-     {
-       loc.where = where;
-       loc.map = linemap_check_macro (map);
- 
-       loc_vec.safe_push (loc);
- 
-       /* WHERE is the location of a token inside the expansion of a
-          macro.  MAP is the map holding the locations of that macro
-          expansion.  Let's get the location of the token inside the
-          context that triggered the expansion of this macro.
-          This is basically how we go "down" in the trace of macro
-          expansions that led to WHERE.  */
-       where = linemap_unwind_toward_expansion (line_table, where, &map);
-     } while (linemap_macro_expansion_map_p (map));
- 
-   /* Now map is set to the map of the location in the source that
-      first triggered the macro expansion.  This must be an ordinary map.  */
-   const line_map_ordinary *ord_map = linemap_check_ordinary (map);
- 
-   /* Walk LOC_VEC and print the macro expansion trace, unless the
-      first macro which expansion triggered this trace was expanded
-      inside a system header.  */
-   int saved_location_line =
-     expand_location_to_spelling_point (original_loc).line;
- 
-   if (!LINEMAP_SYSP (ord_map))
-     FOR_EACH_VEC_ELT (loc_vec, ix, iter)
-       {
- 	/* Sometimes, in the unwound macro expansion trace, we want to
- 	   print a part of the context that shows where, in the
- 	   definition of the relevant macro, is the token (we are
- 	   looking at) used.  That is the case in the introductory
- 	   comment of this function, where we print:
- 
- 	       test.c:2:9: note: in definition of macro 'OPERATE'.
- 
- 	   We print that "macro definition context" because the
- 	   diagnostic line (emitted by the call to
- 	   pp_ouput_formatted_text in diagnostic_report_diagnostic):
- 
- 	       test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’)
- 
- 	   does not point into the definition of the macro where the
- 	   token '<<' (that is an argument to the function-like macro
- 	   OPERATE) is used.  So we must "display" the line of that
- 	   macro definition context to the user somehow.
- 
- 	   A contrario, when the first interesting diagnostic line
- 	   points into the definition of the macro, we don't need to
- 	   display any line for that macro definition in the trace
- 	   anymore, otherwise it'd be redundant.  */
- 
-         /* Okay, now here is what we want.  For each token resulting
-            from macro expansion we want to show: 1/ where in the
-            definition of the macro the token comes from; 2/ where the
-            macro got expanded.  */
- 
-         /* Resolve the location iter->where into the locus 1/ of the
-            comment above.  */
-         location_t resolved_def_loc =
-           linemap_resolve_location (line_table, iter->where,
-                                     LRK_MACRO_DEFINITION_LOCATION, nullptr);
- 
- 	/* Don't print trace for locations that are reserved or from
- 	   within a system header.  */
-         const line_map_ordinary *m = nullptr;
-         location_t l =
-           linemap_resolve_location (line_table, resolved_def_loc,
-                                     LRK_SPELLING_LOCATION,  &m);
- 	location_t l0 = l;
- 	if (IS_ADHOC_LOC (l0))
- 	  l0 = get_location_from_adhoc_loc (line_table, l0);
- 	if (l0 < RESERVED_LOCATION_COUNT || LINEMAP_SYSP (m))
-           continue;
- 
- 	/* We need to print the context of the macro definition only
- 	   when the locus of the first displayed diagnostic (displayed
- 	   before this trace) was inside the definition of the
- 	   macro.  */
- 	const int resolved_def_loc_line = SOURCE_LINE (m, l0);
-         if (ix == 0 && saved_location_line != resolved_def_loc_line)
-           {
- 	    text_output.append_note (resolved_def_loc,
- 				     "in definition of macro %qs",
- 				     linemap_map_get_macro_name (iter->map));
-             /* At this step, as we've printed the context of the macro
-                definition, we don't want to print the context of its
-                expansion, otherwise, it'd be redundant.  */
-             continue;
-           }
- 
-         /* Resolve the location of the expansion point of the macro
-            which expansion gave the token represented by def_loc.
-            This is the locus 2/ of the earlier comment.  */
-         location_t resolved_exp_loc =
-           linemap_resolve_location (line_table,
-                                     iter->map->get_expansion_point_location (),
-                                     LRK_MACRO_DEFINITION_LOCATION, nullptr);
- 
- 	text_output.append_note (resolved_exp_loc,
- 				 "in expansion of macro %qs",
- 				 linemap_map_get_macro_name (iter->map));
-       }
- }
- 
- /*  This is a diagnostic finalizer implementation that is aware of
-     virtual locations produced by libcpp.
- 
-     It has to be called by the diagnostic finalizer of front ends that
-     uses libcpp and wish to get diagnostics involving tokens resulting
-     from macro expansion.
- 
-     For a given location, if said location belongs to a token
-     resulting from a macro expansion, this starter prints the context
-     of the token.  E.g, for multiply nested macro expansion, it
-     unwinds the nested macro expansions and prints them in a manner
-     that is similar to what is done for function call stacks, or
-     template instantiation contexts.  */
- void
- virt_loc_aware_diagnostic_finalizer (diagnostic_text_output_format &text_output,
- 				     const diagnostic_info *diagnostic)
- {
-   maybe_unwind_expanded_macro_loc (text_output, diagnostic_location (diagnostic));
- }
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-macro-unwinding.h gcc-16-20250727/gcc/diagnostic-macro-unwinding.h
*** gcc-16-20250720/gcc/diagnostic-macro-unwinding.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-macro-unwinding.h	Thu Jan  1 00:00:00 1970
***************
*** 1,29 ****
- /* Code for unwinding macro expansions in diagnostics.
-    Copyright (C) 2000-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_MACRO_UNWINDING_H
- #define GCC_DIAGNOSTIC_MACRO_UNWINDING_H
- 
- void virt_loc_aware_diagnostic_finalizer (diagnostic_text_output_format &,
- 					  const diagnostic_info *);
- 
- extern void maybe_unwind_expanded_macro_loc (diagnostic_text_output_format &,
- 					     location_t where);
- 
- #endif /* ! GCC_DIAGNOSTIC_MACRO_UNWINDING_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-metadata.h gcc-16-20250727/gcc/diagnostic-metadata.h
*** gcc-16-20250720/gcc/diagnostic-metadata.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-metadata.h	Thu Jan  1 00:00:00 1970
***************
*** 1,120 ****
- /* Additional metadata for a diagnostic.
-    Copyright (C) 2019-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_METADATA_H
- #define GCC_DIAGNOSTIC_METADATA_H
- 
- class sarif_object;
- 
- namespace diagnostics {
-   namespace digraphs {
-     class lazy_digraphs;
-   } // namespace digraphs
- } // namespace diagnostics
- 
- /* A bundle of additional metadata that can be associated with a
-    diagnostic.
- 
-    This supports an optional CWE identifier, and zero or more
-    "rules".
- 
-    Additionally, this provides a place to associate a diagnostic
-    with zero or more directed graphs.  */
- 
- class diagnostic_metadata
- {
-  public:
-   /* Abstract base class for referencing a rule that has been violated,
-      such as within a coding standard, or within a specification.  */
-   class rule
-   {
-   public:
-     virtual char *make_description () const = 0;
-     virtual char *make_url () const = 0;
-   };
- 
-   /* Concrete subclass.  */
-   class precanned_rule : public rule
-   {
-   public:
-     precanned_rule (const char *desc, const char *url)
-     : m_desc (desc), m_url (url)
-     {}
- 
-     char *make_description () const final override
-     {
-       return m_desc ? xstrdup (m_desc) : NULL;
-     }
- 
-     char *make_url () const final override
-     {
-       return m_url ? xstrdup (m_url) : NULL;
-     }
- 
-   private:
-     const char *m_desc;
-     const char *m_url;
-   };
- 
-   diagnostic_metadata () : m_cwe (0), m_lazy_digraphs (nullptr) {}
-   virtual ~diagnostic_metadata () {}
- 
-   /* Hook for SARIF output to allow for adding diagnostic-specific
-      properties to  the result object's property bag.  */
-   virtual void
-   maybe_add_sarif_properties (sarif_object &/*result_obj*/) const
-   {
-   }
- 
-   void add_cwe (int cwe) { m_cwe = cwe; }
-   int get_cwe () const { return m_cwe; }
- 
-   /* Associate R with the diagnostic.  R must outlive
-      the metadata.  */
-   void add_rule (const rule &r)
-   {
-     m_rules.safe_push (&r);
-   }
- 
-   unsigned get_num_rules () const { return m_rules.length (); }
-   const rule &get_rule (unsigned idx) const { return *(m_rules[idx]); }
- 
-   void
-   set_lazy_digraphs (const diagnostics::digraphs::lazy_digraphs *lazy_digraphs)
-   {
-     m_lazy_digraphs = lazy_digraphs;
-   }
- 
-   const diagnostics::digraphs::lazy_digraphs *
-   get_lazy_digraphs () const
-   {
-     return m_lazy_digraphs;
-   }
- 
-  private:
-   int m_cwe;
-   auto_vec<const rule *> m_rules;
- 
-   /* An optional way to create directed graphs associated with the
-      diagnostic, for the sinks that support this (e.g. SARIF).  */
-   const diagnostics::digraphs::lazy_digraphs *m_lazy_digraphs;
- };
- 
- #endif /* ! GCC_DIAGNOSTIC_METADATA_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-output-file.h gcc-16-20250727/gcc/diagnostic-output-file.h
*** gcc-16-20250720/gcc/diagnostic-output-file.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-output-file.h	Thu Jan  1 00:00:00 1970
***************
*** 1,107 ****
- /* RAII class for managing FILE * for diagnostic formats.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_OUTPUT_FILE_H
- #define GCC_DIAGNOSTIC_OUTPUT_FILE_H
- 
- /* RAII class for wrapping a FILE * that could be borrowed or owned,
-    along with the underlying filename.  */
- 
- class diagnostic_output_file
- {
- public:
-   diagnostic_output_file ()
-   : m_outf (nullptr),
-     m_owned (false),
-     m_filename ()
-   {
-   }
-   diagnostic_output_file (FILE *outf, bool owned, label_text filename)
-   : m_outf (outf),
-     m_owned (owned),
-     m_filename (std::move (filename))
-   {
-     gcc_assert (m_filename.get ());
-     if (m_owned)
-       gcc_assert (m_outf);
-   }
-   ~diagnostic_output_file ()
-   {
-     if (m_owned)
-       {
- 	gcc_assert (m_outf);
- 	fclose (m_outf);
-       }
-   }
-   diagnostic_output_file (const diagnostic_output_file &other) = delete;
-   diagnostic_output_file (diagnostic_output_file &&other)
-   : m_outf (other.m_outf),
-     m_owned (other.m_owned),
-     m_filename (std::move (other.m_filename))
-   {
-     other.m_outf = nullptr;
-     other.m_owned = false;
- 
-     gcc_assert (m_filename.get ());
-     if (m_owned)
-       gcc_assert (m_outf);
-   }
-   diagnostic_output_file &
-   operator= (const diagnostic_output_file &other) = delete;
-   diagnostic_output_file &
-   operator= (diagnostic_output_file &&other)
-   {
-     if (m_owned)
-       {
- 	gcc_assert (m_outf);
- 	fclose (m_outf);
-       }
- 
-     m_outf = other.m_outf;
-     other.m_outf = nullptr;
- 
-     m_owned = other.m_owned;
-     other.m_owned = false;
- 
-     m_filename = std::move (other.m_filename);
- 
-     if (m_owned)
-       gcc_assert (m_outf);
-     return *this;
-   }
- 
-   operator bool () const { return m_outf != nullptr; }
-   FILE *get_open_file () const { return m_outf; }
-   const char *get_filename () const { return m_filename.get (); }
- 
-   static diagnostic_output_file
-   try_to_open (diagnostic_context &context,
- 	       line_maps *line_maps,
- 	       const char *base_file_name,
- 	       const char *extension,
- 	       bool binary);
- 
- private:
-   FILE *m_outf;
-   bool m_owned;
-   label_text m_filename;
- };
- 
- #endif /* ! GCC_DIAGNOSTIC_OUTPUT_FILE_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-output-spec.cc gcc-16-20250727/gcc/diagnostic-output-spec.cc
*** gcc-16-20250720/gcc/diagnostic-output-spec.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-output-spec.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,849 ****
- /* Support for the DSL of -fdiagnostics-add-output= and
-    -fdiagnostics-set-output=.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- /* This file implements the domain-specific language for the options
-    -fdiagnostics-add-output= and -fdiagnostics-set-output=, and for
-    the "diagnostic_manager_add_sink_from_spec" entrypoint to
-    libgdiagnostics.  */
- 
- #include "config.h"
- #define INCLUDE_ARRAY
- #define INCLUDE_STRING
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "version.h"
- #include "intl.h"
- #include "diagnostic.h"
- #include "diagnostic-color.h"
- #include "diagnostic-format.h"
- #include "diagnostic-format-html.h"
- #include "diagnostic-format-text.h"
- #include "diagnostic-format-sarif.h"
- #include "selftest.h"
- #include "selftest-diagnostic.h"
- #include "pretty-print-markup.h"
- #include "diagnostic-output-spec.h"
- 
- /* A namespace for handling the DSL of the arguments of
-    -fdiagnostics-add-output= and -fdiagnostics-set-output=.  */
- 
- namespace diagnostics_output_spec {
- 
- /* Decls.  */
- 
- struct scheme_name_and_params
- {
-   std::string m_scheme_name;
-   std::vector<std::pair<std::string, std::string>> m_kvs;
- };
- 
- /* Class for parsing the arguments of -fdiagnostics-add-output= and
-    -fdiagnostics-set-output=, and making diagnostic_output_format
-    instances (or issuing errors).  */
- 
- class output_factory
- {
- public:
-   class scheme_handler
-   {
-   public:
-     scheme_handler (std::string scheme_name)
-     : m_scheme_name (std::move (scheme_name))
-     {}
-     virtual ~scheme_handler () {}
- 
-     const std::string &get_scheme_name () const { return m_scheme_name; }
- 
-     virtual std::unique_ptr<diagnostic_output_format>
-     make_sink (const context &ctxt,
- 	       diagnostic_context &dc,
- 	       const char *unparsed_arg,
- 	       const scheme_name_and_params &parsed_arg) const = 0;
- 
-   protected:
-     bool
-     parse_bool_value (const context &ctxt,
- 		      const char *unparsed_arg,
- 		      const std::string &key,
- 		      const std::string &value,
- 		      bool &out) const
-     {
-       if (value == "yes")
- 	{
- 	  out = true;
- 	  return true;
- 	}
-       else if (value == "no")
- 	{
- 	  out = false;
- 	  return true;
- 	}
-       else
- 	{
- 	  ctxt.report_error
- 	    ("%<%s%s%>:"
- 	     " unexpected value %qs for key %qs; expected %qs or %qs",
- 	     ctxt.get_option_name (), unparsed_arg,
- 	     value.c_str (),
- 	     key.c_str (),
- 	     "yes", "no");
- 
- 	  return false;
- 	}
-     }
-     template <typename EnumType, size_t NumValues>
-     bool
-     parse_enum_value (const context &ctxt,
- 		      const char *unparsed_arg,
- 		      const std::string &key,
- 		      const std::string &value,
- 		      const std::array<std::pair<const char *, EnumType>, NumValues> &value_names,
- 		      EnumType &out) const
-     {
-       for (auto &iter : value_names)
- 	if (value == iter.first)
- 	  {
- 	    out = iter.second;
- 	    return true;
- 	  }
- 
-       auto_vec<const char *> known_values;
-       for (auto iter : value_names)
- 	known_values.safe_push (iter.first);
-       pp_markup::comma_separated_quoted_strings e (known_values);
-       ctxt.report_error
- 	("%<%s%s%>:"
- 	 " unexpected value %qs for key %qs; known values: %e",
- 	 ctxt.get_option_name (), unparsed_arg,
- 	 value.c_str (),
- 	 key.c_str (),
- 	 &e);
-       return false;
-     }
- 
-   private:
-     const std::string m_scheme_name;
-   };
- 
-   output_factory ();
- 
-   std::unique_ptr<diagnostic_output_format>
-   make_sink (const context &ctxt,
- 	     diagnostic_context &dc,
- 	     const char *unparsed_arg,
- 	     const scheme_name_and_params &parsed_arg);
- 
-   const scheme_handler *get_scheme_handler (const std::string &scheme_name);
- 
- private:
-   std::vector<std::unique_ptr<scheme_handler>> m_scheme_handlers;
- };
- 
- class text_scheme_handler : public output_factory::scheme_handler
- {
- public:
-   text_scheme_handler () : scheme_handler ("text") {}
- 
-   std::unique_ptr<diagnostic_output_format>
-   make_sink (const context &ctxt,
- 	     diagnostic_context &dc,
- 	     const char *unparsed_arg,
- 	     const scheme_name_and_params &parsed_arg) const final override;
- };
- 
- class sarif_scheme_handler : public output_factory::scheme_handler
- {
- public:
-   sarif_scheme_handler () : scheme_handler ("sarif") {}
- 
-   std::unique_ptr<diagnostic_output_format>
-   make_sink (const context &ctxt,
- 	     diagnostic_context &dc,
- 	     const char *unparsed_arg,
- 	     const scheme_name_and_params &parsed_arg) const final override;
- 
- private:
-   static sarif_generation_options
-   make_sarif_gen_opts (enum sarif_version version,
- 		       bool state_graph);
- 
-   static std::unique_ptr<sarif_serialization_format>
-   make_sarif_serialization_object (enum sarif_serialization_kind);
- };
- 
- class html_scheme_handler : public output_factory::scheme_handler
- {
- public:
-   html_scheme_handler () : scheme_handler ("experimental-html") {}
- 
-   std::unique_ptr<diagnostic_output_format>
-   make_sink (const context &ctxt,
- 	     diagnostic_context &dc,
- 	     const char *unparsed_arg,
- 	     const scheme_name_and_params &parsed_arg) const final override;
- };
- 
- /* struct context.  */
- 
- void
- context::report_error (const char *gmsgid, ...) const
- {
-   va_list ap;
-   va_start (ap, gmsgid);
-   report_error_va (gmsgid, &ap);
-   va_end (ap);
- }
- 
- void
- context::report_unknown_key (const char *unparsed_arg,
- 			     const std::string &key,
- 			     const std::string &scheme_name,
- 			     auto_vec<const char *> &known_keys) const
- {
-   pp_markup::comma_separated_quoted_strings e (known_keys);
-   report_error
-     ("%<%s%s%>:"
-      " unknown key %qs for format %qs; known keys: %e",
-      get_option_name (), unparsed_arg,
-      key.c_str (), scheme_name.c_str (), &e);
- }
- 
- void
- context::report_missing_key (const char *unparsed_arg,
- 			     const std::string &key,
- 			     const std::string &scheme_name,
- 			     const char *metavar) const
- {
-   report_error
-     ("%<%s%s%>:"
-      " missing required key %qs for format %qs;"
-      " try %<%s%s:%s=%s%>",
-      get_option_name (), unparsed_arg,
-      key.c_str (), scheme_name.c_str (),
-      get_option_name (), scheme_name.c_str (), key.c_str (), metavar);
- }
- 
- diagnostic_output_file
- context::open_output_file (label_text &&filename) const
- {
-   FILE *outf = fopen (filename.get (), "w");
-   if (!outf)
-     {
-       report_error ("unable to open %qs: %m", filename.get ());
-       return diagnostic_output_file (nullptr, false, std::move (filename));
-     }
-   return diagnostic_output_file (outf, true, std::move (filename));
- }
- 
- static std::unique_ptr<scheme_name_and_params>
- parse (const context &ctxt, const char *unparsed_arg)
- {
-   scheme_name_and_params result;
-   if (const char *const colon = strchr (unparsed_arg, ':'))
-     {
-       result.m_scheme_name = std::string (unparsed_arg, colon - unparsed_arg);
-       /* Expect zero of more of KEY=VALUE,KEY=VALUE, etc  .*/
-       const char *iter = colon + 1;
-       const char *last_separator = ":";
-       while (iter)
- 	{
- 	  /* Look for a non-empty key string followed by '='.  */
- 	  const char *eq = strchr (iter, '=');
- 	  if (eq == nullptr || eq == iter)
- 	    {
- 	      /* Missing '='.  */
- 	      ctxt.report_error
- 		("%<%s%s%>:"
- 		 " expected KEY=VALUE-style parameter for format %qs"
- 		 " after %qs;"
- 		 " got %qs",
- 		 ctxt.get_option_name (), unparsed_arg,
- 		 result.m_scheme_name.c_str (),
- 		 last_separator,
- 		 iter);
- 	      return nullptr;
- 	    }
- 	  std::string key = std::string (iter, eq - iter);
- 	  std::string value;
- 	  const char *comma = strchr (iter, ',');
- 	  if (comma)
- 	    {
- 	      value = std::string (eq + 1, comma - (eq + 1));
- 	      iter = comma + 1;
- 	      last_separator = ",";
- 	    }
- 	  else
- 	    {
- 	      value = std::string (eq + 1);
- 	      iter = nullptr;
- 	    }
- 	  result.m_kvs.push_back ({std::move (key), std::move (value)});
- 	}
-     }
-   else
-     result.m_scheme_name = unparsed_arg;
-   return std::make_unique<scheme_name_and_params> (std::move (result));
- }
- 
- std::unique_ptr<diagnostic_output_format>
- context::parse_and_make_sink (const char *unparsed_arg,
- 			      diagnostic_context &dc)
- {
-   auto parsed_arg = diagnostics_output_spec::parse (*this, unparsed_arg);
-   if (!parsed_arg)
-     return nullptr;
- 
-   diagnostics_output_spec::output_factory factory;
-   return factory.make_sink (*this, dc, unparsed_arg, *parsed_arg);
- }
- 
- /* class output_factory::scheme_handler.  */
- 
- /* class output_factory.  */
- 
- output_factory::output_factory ()
- {
-   m_scheme_handlers.push_back (std::make_unique<text_scheme_handler> ());
-   m_scheme_handlers.push_back (std::make_unique<sarif_scheme_handler> ());
-   m_scheme_handlers.push_back (std::make_unique<html_scheme_handler> ());
- }
- 
- const output_factory::scheme_handler *
- output_factory::get_scheme_handler (const std::string &scheme_name)
- {
-   for (auto &iter : m_scheme_handlers)
-     if (iter->get_scheme_name () == scheme_name)
-       return iter.get ();
-   return nullptr;
- }
- 
- std::unique_ptr<diagnostic_output_format>
- output_factory::make_sink (const context &ctxt,
- 			   diagnostic_context &dc,
- 			   const char *unparsed_arg,
- 			   const scheme_name_and_params &parsed_arg)
- {
-   auto scheme_handler = get_scheme_handler (parsed_arg.m_scheme_name);
-   if (!scheme_handler)
-     {
-       auto_vec<const char *> strings;
-       for (auto &iter : m_scheme_handlers)
- 	strings.safe_push (iter->get_scheme_name ().c_str ());
-       pp_markup::comma_separated_quoted_strings e (strings);
-       ctxt.report_error ("%<%s%s%>:"
- 			 " unrecognized format %qs; known formats: %e",
- 			 ctxt.get_option_name (), unparsed_arg,
- 			 parsed_arg.m_scheme_name.c_str (), &e);
-       return nullptr;
-     }
- 
-   return scheme_handler->make_sink (ctxt, dc, unparsed_arg, parsed_arg);
- }
- 
- /* class text_scheme_handler : public output_factory::scheme_handler.  */
- 
- std::unique_ptr<diagnostic_output_format>
- text_scheme_handler::make_sink (const context &ctxt,
- 				diagnostic_context &dc,
- 				const char *unparsed_arg,
- 				const scheme_name_and_params &parsed_arg) const
- {
-   bool show_color = pp_show_color (dc.get_reference_printer ());
-   bool show_nesting = false;
-   bool show_locations_in_nesting = true;
-   bool show_levels = false;
-   for (auto& iter : parsed_arg.m_kvs)
-     {
-       const std::string &key = iter.first;
-       const std::string &value = iter.second;
-       if (key == "color")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value, show_color))
- 	    return nullptr;
- 	  continue;
- 	}
-       if (key == "experimental-nesting")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- 				 show_nesting))
- 	    return nullptr;
- 	  continue;
- 	}
-       if (key == "experimental-nesting-show-locations")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- 				 show_locations_in_nesting))
- 	    return nullptr;
- 	  continue;
- 	}
-       if (key == "experimental-nesting-show-levels")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value, show_levels))
- 	    return nullptr;
- 	  continue;
- 	}
- 
-       /* Key not found.  */
-       auto_vec<const char *> known_keys;
-       known_keys.safe_push ("color");
-       known_keys.safe_push ("experimental-nesting");
-       known_keys.safe_push ("experimental-nesting-show-locations");
-       known_keys.safe_push ("experimental-nesting-show-levels");
-       ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
- 			       known_keys);
-       return nullptr;
-     }
- 
-   auto sink = std::make_unique<diagnostic_text_output_format> (dc);
-   sink->set_show_nesting (show_nesting);
-   sink->set_show_locations_in_nesting (show_locations_in_nesting);
-   sink->set_show_nesting_levels (show_levels);
-   return sink;
- }
- 
- /* class sarif_scheme_handler : public output_factory::scheme_handler.  */
- 
- std::unique_ptr<diagnostic_output_format>
- sarif_scheme_handler::make_sink (const context &ctxt,
- 				 diagnostic_context &dc,
- 				 const char *unparsed_arg,
- 				 const scheme_name_and_params &parsed_arg) const
- {
-   label_text filename;
-   enum sarif_serialization_kind serialization_kind
-     = sarif_serialization_kind::json;
-   enum sarif_version version = sarif_version::v2_1_0;
-   bool state_graph = false;
-   for (auto& iter : parsed_arg.m_kvs)
-     {
-       const std::string &key = iter.first;
-       const std::string &value = iter.second;
-       if (key == "file")
- 	{
- 	  filename = label_text::take (xstrdup (value.c_str ()));
- 	  continue;
- 	}
-       if (key == "serialization")
- 	{
- 	  static const std::array<std::pair<const char *, enum sarif_serialization_kind>,
- 				  (size_t)sarif_serialization_kind::num_values> value_names
- 	    {{{"json", sarif_serialization_kind::json}}};
- 
- 	  if (!parse_enum_value<enum sarif_serialization_kind>
- 		 (ctxt, unparsed_arg,
- 		  key, value,
- 		  value_names,
- 		  serialization_kind))
- 	    return nullptr;
- 	  continue;
- 	}
-       if (key == "version")
- 	{
- 	  static const std::array<std::pair<const char *, enum sarif_version>,
- 				  (size_t)sarif_version::num_versions> value_names
- 	    {{{"2.1", sarif_version::v2_1_0},
- 	      {"2.2-prerelease", sarif_version::v2_2_prerelease_2024_08_08}}};
- 
- 	    if (!parse_enum_value<enum sarif_version> (ctxt, unparsed_arg,
- 						       key, value,
- 						       value_names,
- 						       version))
- 	    return nullptr;
- 	  continue;
- 	}
-       if (key == "state-graphs")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- 				 state_graph))
- 	    return nullptr;
- 	  continue;
- 	}
- 
-       /* Key not found.  */
-       auto_vec<const char *> known_keys;
-       known_keys.safe_push ("file");
-       known_keys.safe_push ("serialization");
-       known_keys.safe_push ("state-graphs");
-       known_keys.safe_push ("version");
-       ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
- 			       known_keys);
-       return nullptr;
-     }
- 
-   diagnostic_output_file output_file;
-   if (filename.get ())
-     output_file = ctxt.open_output_file (std::move (filename));
-   else
-     // Default filename
-     {
-       const char *basename = ctxt.get_base_filename ();
-       if (!basename)
- 	{
- 	  ctxt.report_missing_key (unparsed_arg,
- 				   "file",
- 				   get_scheme_name (),
- 				   "FILENAME");
- 	  return nullptr;
- 	}
-       output_file
- 	= diagnostic_output_format_open_sarif_file
- 	    (dc,
- 	     ctxt.get_affected_location_mgr (),
- 	     basename,
- 	     serialization_kind);
-     }
-   if (!output_file)
-     return nullptr;
- 
-   auto sarif_gen_opts = make_sarif_gen_opts (version, state_graph);
- 
-   auto serialization_obj = make_sarif_serialization_object (serialization_kind);
- 
-   auto sink = make_sarif_sink (dc,
- 			       *ctxt.get_affected_location_mgr (),
- 			       std::move (serialization_obj),
- 			       sarif_gen_opts,
- 			       std::move (output_file));
-   return sink;
- }
- 
- sarif_generation_options
- sarif_scheme_handler::make_sarif_gen_opts (enum sarif_version version,
- 					   bool state_graph)
- {
-   sarif_generation_options sarif_gen_opts;
-   sarif_gen_opts.m_version = version;
-   sarif_gen_opts.m_state_graph = state_graph;
-   return sarif_gen_opts;
- }
- 
- std::unique_ptr<sarif_serialization_format>
- sarif_scheme_handler::
- make_sarif_serialization_object (enum sarif_serialization_kind kind)
- {
-   switch (kind)
-     {
-     default:
-       gcc_unreachable ();
-     case sarif_serialization_kind::json:
-       return std::make_unique<sarif_serialization_format_json> (true);
-       break;
-     }
- }
- 
- /* class html_scheme_handler : public output_factory::scheme_handler.  */
- 
- std::unique_ptr<diagnostic_output_format>
- html_scheme_handler::make_sink (const context &ctxt,
- 				diagnostic_context &dc,
- 				const char *unparsed_arg,
- 				const scheme_name_and_params &parsed_arg) const
- {
-   bool css = true;
-   label_text filename;
-   bool javascript = true;
-   bool show_state_diagrams = false;
-   bool show_state_diagrams_sarif = false;
-   bool show_state_diagrams_dot_src = false;
-   for (auto& iter : parsed_arg.m_kvs)
-     {
-       const std::string &key = iter.first;
-       const std::string &value = iter.second;
-       if (key == "css")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- 				 css))
- 	    return nullptr;
- 	  continue;
- 	}
-       if (key == "file")
- 	{
- 	  filename = label_text::take (xstrdup (value.c_str ()));
- 	  continue;
- 	}
-       if (key == "javascript")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- 				 javascript))
- 	    return nullptr;
- 	  continue;
- 	}
-       if (key == "show-state-diagrams")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- 				 show_state_diagrams))
- 	    return nullptr;
- 	  continue;
- 	}
-       if (key == "show-state-diagrams-dot-src")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- 				 show_state_diagrams_dot_src))
- 	    return nullptr;
- 	  continue;
- 	}
-       if (key == "show-state-diagrams-sarif")
- 	{
- 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
- 				 show_state_diagrams_sarif))
- 	    return nullptr;
- 	  continue;
- 	}
- 
-       /* Key not found.  */
-       auto_vec<const char *> known_keys;
-       known_keys.safe_push ("css");
-       known_keys.safe_push ("file");
-       known_keys.safe_push ("javascript");
-       known_keys.safe_push ("show-state-diagrams");
-       known_keys.safe_push ("show-state-diagram-dot-src");
-       known_keys.safe_push ("show-state-diagram-sarif");
-       ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
- 			       known_keys);
-       return nullptr;
-     }
- 
-   diagnostic_output_file output_file;
-   if (filename.get ())
-     output_file = ctxt.open_output_file (std::move (filename));
-   else
-     // Default filename
-     {
-       const char *basename = ctxt.get_base_filename ();
-       if (!basename)
- 	{
- 	  ctxt.report_missing_key (unparsed_arg,
- 				   "file",
- 				   get_scheme_name (),
- 				   "FILENAME");
- 	  return nullptr;
- 	}
-       output_file
- 	= diagnostic_output_format_open_html_file
- 	    (dc,
- 	     ctxt.get_affected_location_mgr (),
- 	     basename);
-     }
-   if (!output_file)
-     return nullptr;
- 
-   html_generation_options html_gen_opts;
-   html_gen_opts.m_css = css;
-   html_gen_opts.m_javascript = javascript;
-   html_gen_opts.m_show_state_diagrams = show_state_diagrams;
-   html_gen_opts.m_show_state_diagrams_sarif = show_state_diagrams_sarif;
-   html_gen_opts.m_show_state_diagrams_dot_src = show_state_diagrams_dot_src;
- 
-   auto sink = make_html_sink (dc,
- 			      *ctxt.get_affected_location_mgr (),
- 			      html_gen_opts,
- 			      std::move (output_file));
-   return sink;
- }
- 
- } // namespace diagnostics_output_spec
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* RAII class to temporarily override "progname" to the
-    string "PROGNAME".  */
- 
- class auto_fix_progname
- {
- public:
-   auto_fix_progname ()
-   {
-     m_old_progname = progname;
-     progname = "PROGNAME";
-   }
- 
-   ~auto_fix_progname ()
-   {
-     progname = m_old_progname;
-   }
- 
- private:
-   const char *m_old_progname;
- };
- 
- struct parser_test
- {
-   class test_spec_context : public diagnostics_output_spec::gcc_spec_context
-   {
-   public:
-     test_spec_context (diagnostic_context &dc,
- 		       line_maps *location_mgr,
- 		       location_t loc,
- 		       const char *option_name)
-     : gcc_spec_context (dc,
- 			location_mgr,
- 			location_mgr,
- 			loc,
- 			option_name)
-     {
-     }
- 
-     const char *
-     get_base_filename () const final override
-     {
-       return "BASE_FILENAME";
-     }
-   };
- 
-   parser_test ()
-   : m_dc (),
-     m_ctxt (m_dc, line_table, UNKNOWN_LOCATION, "-fOPTION="),
-     m_fmt (m_dc.get_output_format (0))
-   {
-     pp_buffer (m_fmt.get_printer ())->m_flush_p = false;
-   }
- 
-   std::unique_ptr<diagnostics_output_spec::scheme_name_and_params>
-   parse (const char *unparsed_arg)
-   {
-     return diagnostics_output_spec::parse (m_ctxt, unparsed_arg);
-   }
- 
-   bool execution_failed_p () const
-   {
-     return m_dc.execution_failed_p ();
-   }
- 
-   const char *
-   get_diagnostic_text () const
-   {
-     return pp_formatted_text (m_fmt.get_printer ());
-   }
- 
- private:
-   test_diagnostic_context m_dc;
-   test_spec_context m_ctxt;
-   diagnostic_output_format &m_fmt;
- };
- 
- /* Selftests.  */
- 
- static void
- test_output_arg_parsing ()
- {
-   auto_fix_quotes fix_quotes;
-   auto_fix_progname fix_progname;
- 
-   /* Minimal correct example.  */
-   {
-     parser_test pt;
-     auto result = pt.parse ("foo");
-     ASSERT_EQ (result->m_scheme_name, "foo");
-     ASSERT_EQ (result->m_kvs.size (), 0);
-     ASSERT_FALSE (pt.execution_failed_p ());
-   }
- 
-   /* Stray trailing colon with no key/value pairs.  */
-   {
-     parser_test pt;
-     auto result = pt.parse ("foo:");
-     ASSERT_EQ (result, nullptr);
-     ASSERT_TRUE (pt.execution_failed_p ());
-     ASSERT_STREQ (pt.get_diagnostic_text (),
- 		  "PROGNAME: error: `-fOPTION=foo:':"
- 		  " expected KEY=VALUE-style parameter for format `foo'"
- 		  " after `:';"
- 		  " got `'\n");
-   }
- 
-   /* No key before '='.  */
-   {
-     parser_test pt;
-     auto result = pt.parse ("foo:=");
-     ASSERT_EQ (result, nullptr);
-     ASSERT_TRUE (pt.execution_failed_p ());
-     ASSERT_STREQ (pt.get_diagnostic_text (),
- 		  "PROGNAME: error: `-fOPTION=foo:=':"
- 		  " expected KEY=VALUE-style parameter for format `foo'"
- 		  " after `:';"
- 		  " got `='\n");
-   }
- 
-   /* No value for key.  */
-   {
-     parser_test pt;
-     auto result = pt.parse ("foo:key,");
-     ASSERT_EQ (result, nullptr);
-     ASSERT_TRUE (pt.execution_failed_p ());
-     ASSERT_STREQ (pt.get_diagnostic_text (),
- 		  "PROGNAME: error: `-fOPTION=foo:key,':"
- 		  " expected KEY=VALUE-style parameter for format `foo'"
- 		  " after `:';"
- 		  " got `key,'\n");
-   }
- 
-   /* Correct example, with one key/value pair.  */
-   {
-     parser_test pt;
-     auto result = pt.parse ("foo:key=value");
-     ASSERT_EQ (result->m_scheme_name, "foo");
-     ASSERT_EQ (result->m_kvs.size (), 1);
-     ASSERT_EQ (result->m_kvs[0].first, "key");
-     ASSERT_EQ (result->m_kvs[0].second, "value");
-     ASSERT_FALSE (pt.execution_failed_p ());
-   }
- 
-   /* Stray trailing comma.  */
-   {
-     parser_test pt;
-     auto result = pt.parse ("foo:key=value,");
-     ASSERT_EQ (result, nullptr);
-     ASSERT_TRUE (pt.execution_failed_p ());
-     ASSERT_STREQ (pt.get_diagnostic_text (),
- 		  "PROGNAME: error: `-fOPTION=foo:key=value,':"
- 		  " expected KEY=VALUE-style parameter for format `foo'"
- 		  " after `,';"
- 		  " got `'\n");
-   }
- 
-   /* Correct example, with two key/value pairs.  */
-   {
-     parser_test pt;
-     auto result = pt.parse ("foo:color=red,shape=circle");
-     ASSERT_EQ (result->m_scheme_name, "foo");
-     ASSERT_EQ (result->m_kvs.size (), 2);
-     ASSERT_EQ (result->m_kvs[0].first, "color");
-     ASSERT_EQ (result->m_kvs[0].second, "red");
-     ASSERT_EQ (result->m_kvs[1].first, "shape");
-     ASSERT_EQ (result->m_kvs[1].second, "circle");
-     ASSERT_FALSE (pt.execution_failed_p ());
-   }
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- diagnostic_output_spec_cc_tests ()
- {
-   test_output_arg_parsing ();
- }
- 
- } // namespace selftest
- 
- 
- #endif /* #if CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-output-spec.h gcc-16-20250727/gcc/diagnostic-output-spec.h
*** gcc-16-20250720/gcc/diagnostic-output-spec.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-output-spec.h	Thu Jan  1 00:00:00 1970
***************
*** 1,116 ****
- /* Support for the DSL of -fdiagnostics-add-output= and
-    -fdiagnostics-set-output=.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_OUTPUT_SPEC_H
- #define GCC_DIAGNOSTIC_OUTPUT_SPEC_H
- 
- #include "diagnostic-format.h"
- #include "diagnostic-output-file.h"
- 
- namespace diagnostics_output_spec {
- 
- /* An abstract base class for handling the DSL of -fdiagnostics-add-output=
-    and -fdiagnostics-set-output=.  */
- 
- class context
- {
-  public:
-   std::unique_ptr<diagnostic_output_format>
-   parse_and_make_sink (const char *,
- 		       diagnostic_context &dc);
- 
-   void
-   report_error (const char *gmsgid, ...) const
-     ATTRIBUTE_GCC_DIAG(2,3);
- 
-   void
-   report_unknown_key (const char *unparsed_arg,
- 		      const std::string &key,
- 		      const std::string &scheme_name,
- 		      auto_vec<const char *> &known_keys) const;
- 
-   void
-   report_missing_key (const char *unparsed_arg,
- 		      const std::string &key,
- 		      const std::string &scheme_name,
- 		      const char *metavar) const;
- 
-   diagnostic_output_file
-   open_output_file (label_text &&filename) const;
- 
-   const char *
-   get_option_name () const { return m_option_name; }
- 
-   line_maps *
-   get_affected_location_mgr () const { return m_affected_location_mgr; }
- 
-   virtual ~context () {}
- 
-   virtual void
-   report_error_va (const char *gmsgid, va_list *ap) const = 0;
- 
-   virtual const char *
-   get_base_filename () const = 0;
- 
- protected:
-   context (const char *option_name,
- 	   line_maps *affected_location_mgr)
-   : m_option_name (option_name),
-     m_affected_location_mgr (affected_location_mgr)
-   {
-   }
- 
-   const char *m_option_name;
-   line_maps *m_affected_location_mgr;
- };
- 
- /* A subclass that implements reporting errors via a diagnostic_context.  */
- 
- struct gcc_spec_context : public diagnostics_output_spec::context
- {
- public:
-   gcc_spec_context (diagnostic_context &dc,
- 		    line_maps *affected_location_mgr,
- 		    line_maps *control_location_mgr,
- 		    location_t loc,
- 		    const char *option_name)
-   : context (option_name, affected_location_mgr),
-     m_dc (dc),
-     m_control_location_mgr (control_location_mgr),
-     m_loc (loc)
-   {}
- 
-   void report_error_va (const char *gmsgid, va_list *ap) const final override
-     ATTRIBUTE_GCC_DIAG(2, 0)
-   {
-     m_dc.begin_group ();
-     rich_location richloc (m_control_location_mgr, m_loc);
-     m_dc.diagnostic_impl (&richloc, nullptr, -1, gmsgid, ap, DK_ERROR);
-     m_dc.end_group ();
-   }
- 
-   diagnostic_context &m_dc;
-   line_maps *m_control_location_mgr;
-   location_t m_loc;
- };
- 
- } // namespace diagnostics_output_spec
- 
- #endif
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-path-output.cc gcc-16-20250727/gcc/diagnostic-path-output.cc
*** gcc-16-20250720/gcc/diagnostic-path-output.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-path-output.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,2713 ****
- /* Printing paths through the code associated with a diagnostic.
-    Copyright (C) 2019-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #include "config.h"
- #define INCLUDE_ALGORITHM
- #define INCLUDE_MAP
- #define INCLUDE_STRING
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "diagnostic.h"
- #include "diagnostic-macro-unwinding.h"
- #include "intl.h"
- #include "diagnostic-path.h"
- #include "gcc-rich-location.h"
- #include "diagnostic-color.h"
- #include "diagnostic-event-id.h"
- #include "diagnostic-label-effects.h"
- #include "pretty-print-markup.h"
- #include "selftest.h"
- #include "selftest-diagnostic.h"
- #include "selftest-diagnostic-path.h"
- #include "text-art/theme.h"
- #include "diagnostic-format-text.h"
- #include "diagnostic-format-html.h"
- #include "xml.h"
- #include "xml-printer.h"
- 
- /* Disable warnings about missing quoting in GCC diagnostics for the print
-    calls below.  */
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic push
- #  pragma GCC diagnostic ignored "-Wformat-diag"
- #endif
- 
- /* Anonymous namespace for path-printing code.  */
- 
- namespace {
- 
- /* A bundle of state for printing a path.  */
- 
- class path_print_policy
- {
- public:
-   path_print_policy (const diagnostic_text_output_format &text_output)
-   : m_source_policy (text_output.get_context ())
-   {
-   }
- 
-   path_print_policy (const diagnostic_context &dc)
-   : m_source_policy (dc)
-   {
-   }
- 
-   text_art::theme *
-   get_diagram_theme () const
-   {
-     return m_source_policy.get_diagram_theme ();
-   }
- 
-   const diagnostic_source_print_policy &
-   get_source_policy () const { return m_source_policy; }
- 
- private:
-   diagnostic_source_print_policy m_source_policy;
- };
- 
- /* Subclass of range_label for showing a particular event
-    when showing a consecutive run of events within a diagnostic_path as
-    labelled ranges within one gcc_rich_location.  */
- 
- class path_label : public range_label
- {
-  public:
-   path_label (const diagnostic_path &path,
- 	      const pretty_printer &ref_pp,
- 	      unsigned start_idx,
- 	      bool colorize,
- 	      bool allow_emojis)
-   : m_path (path),
-     m_ref_pp (ref_pp),
-     m_start_idx (start_idx), m_effects (*this),
-     m_colorize (colorize), m_allow_emojis (allow_emojis)
-   {}
- 
-   label_text get_text (unsigned range_idx) const final override
-   {
-     unsigned event_idx = m_start_idx + range_idx;
-     const diagnostic_event &event = m_path.get_event (event_idx);
- 
-     const diagnostic_event::meaning meaning (event.get_meaning ());
- 
-     auto pp = m_ref_pp.clone ();
-     pp_show_color (pp.get ()) = m_colorize;
-     diagnostic_event_id_t event_id (event_idx);
- 
-     pp_printf (pp.get (), "%@", &event_id);
-     pp_space (pp.get ());
- 
-     if (meaning.m_verb == diagnostic_event::verb::danger
- 	&& m_allow_emojis)
-       {
- 	pp_unicode_character (pp.get (), 0x26A0); /* U+26A0 WARNING SIGN.  */
- 	/* Append U+FE0F VARIATION SELECTOR-16 to select the emoji
- 	   variation of the char.  */
- 	pp_unicode_character (pp.get (), 0xFE0F);
- 	/* U+26A0 WARNING SIGN has East_Asian_Width == Neutral, but in its
- 	   emoji variant is printed (by vte at least) with a 2nd half
- 	   overlapping the next char.  Hence we add two spaces here: a space
- 	   to be covered by this overlap, plus another space of padding.  */
- 	pp_string (pp.get (), "  ");
-       }
- 
-     event.print_desc (*pp.get ());
- 
-     label_text result
-       = label_text::take (xstrdup (pp_formatted_text (pp.get ())));
-     return result;
-   }
- 
-   const label_effects *get_effects (unsigned /*range_idx*/) const final override
-   {
-     return &m_effects;
-   }
- 
-  private:
-   class path_label_effects : public label_effects
-   {
-   public:
-     path_label_effects (const path_label &path_label)
-     : m_path_label (path_label)
-     {
-     }
-     bool has_in_edge (unsigned range_idx) const final override
-     {
-       if (const diagnostic_event *prev_event
- 	    = m_path_label.get_prev_event (range_idx))
- 	return prev_event->connect_to_next_event_p ();
-       return false;
-     }
-     bool has_out_edge (unsigned range_idx) const final override
-     {
-       const diagnostic_event &event = m_path_label.get_event (range_idx);
-       return event.connect_to_next_event_p ();
-     }
- 
-   private:
-     const path_label &m_path_label;
-   };
- 
-   const diagnostic_event &get_event (unsigned range_idx) const
-   {
-     unsigned event_idx = m_start_idx + range_idx;
-     return m_path.get_event (event_idx);
-   }
- 
-   const diagnostic_event *get_prev_event (unsigned range_idx) const
-   {
-     if (m_start_idx + range_idx == 0)
-       return nullptr;
-     unsigned event_idx = m_start_idx + range_idx - 1;
-     return &m_path.get_event (event_idx);
-   }
- 
-   const diagnostic_path &m_path;
-   const pretty_printer &m_ref_pp;
-   unsigned m_start_idx;
-   path_label_effects m_effects;
-   const bool m_colorize;
-   const bool m_allow_emojis;
- };
- 
- /* Return true if E1 and E2 can be consolidated into the same run of events
-    when printing a diagnostic_path.  */
- 
- static bool
- can_consolidate_events (const diagnostic_path &path,
- 			const diagnostic_event &e1,
- 			unsigned ev1_idx,
- 			const diagnostic_event &e2,
- 			unsigned ev2_idx,
- 			bool check_locations)
- {
-   if (e1.get_thread_id () != e2.get_thread_id ())
-     return false;
- 
-   if (!path.same_function_p (ev1_idx, ev2_idx))
-     return false;
- 
-   if (e1.get_stack_depth () != e2.get_stack_depth ())
-     return false;
- 
-   if (check_locations)
-     {
-       location_t loc1 = e1.get_location ();
-       location_t loc2 = e2.get_location ();
- 
-       if (loc1 < RESERVED_LOCATION_COUNT
- 	  || loc2 < RESERVED_LOCATION_COUNT)
- 	return false;
- 
-       /* Neither can be macro-based.  */
-       if (linemap_location_from_macro_expansion_p (line_table, loc1))
- 	return false;
-       if (linemap_location_from_macro_expansion_p (line_table, loc2))
- 	return false;
-     }
- 
-   /* Passed all the tests.  */
-   return true;
- }
- 
- struct event_range;
- struct path_summary;
- class thread_event_printer;
- 
- /* A bundle of information about all of the events in a diagnostic_path
-    relating to a specific path, for use by path_summary.  */
- 
- class per_thread_summary
- {
- public:
-   per_thread_summary (const diagnostic_path &path,
- 		      const logical_location_manager &logical_loc_mgr,
- 		      label_text name, unsigned swimlane_idx)
-   : m_path (path),
-     m_logical_loc_mgr (logical_loc_mgr),
-     m_name (std::move (name)),
-     m_swimlane_idx (swimlane_idx),
-     m_last_event (nullptr),
-     m_min_depth (INT_MAX),
-     m_max_depth (INT_MIN)
-   {}
- 
-   void update_depth_limits (int stack_depth)
-   {
-     if (stack_depth < m_min_depth)
-       m_min_depth = stack_depth;
-     if (stack_depth > m_max_depth)
-       m_max_depth = stack_depth;
-   }
- 
-   const char *get_name () const { return m_name.get (); }
-   unsigned get_swimlane_index () const { return m_swimlane_idx; }
- 
-   bool interprocedural_p () const;
- 
- private:
-   friend struct path_summary;
-   friend class thread_event_printer;
-   friend struct event_range;
- 
-   const diagnostic_path &m_path;
-   const logical_location_manager &m_logical_loc_mgr;
- 
-   const label_text m_name;
- 
-   /* The "swimlane index" is the order in which this per_thread_summary
-      was created, for use when printing the events.  */
-   const unsigned m_swimlane_idx;
- 
-   // The event ranges specific to this thread:
-   auto_vec<event_range *> m_event_ranges;
- 
-   const diagnostic_event *m_last_event;
- 
-   int m_min_depth;
-   int m_max_depth;
- };
- 
- /* A stack frame for use in HTML output, holding child stack frames,
-    and event ranges. */
- 
- struct stack_frame
- {
-   stack_frame (std::unique_ptr<stack_frame> parent,
- 	       logical_location logical_loc,
- 	       int stack_depth)
-   : m_parent (std::move (parent)),
-     m_logical_loc (logical_loc),
-     m_stack_depth (stack_depth)
-   {}
- 
-   std::unique_ptr<stack_frame> m_parent;
-   logical_location m_logical_loc;
-   const int m_stack_depth;
- };
- 
- /* Begin emitting content relating to a new stack frame within PARENT.
-    Allocated a new stack_frame and return it.  */
- 
- static std::unique_ptr<stack_frame>
- begin_html_stack_frame (xml::printer &xp,
- 			std::unique_ptr<stack_frame> parent,
- 			logical_location logical_loc,
- 			int stack_depth,
- 			const logical_location_manager *logical_loc_mgr)
- {
-   if (logical_loc)
-     {
-       gcc_assert (logical_loc_mgr);
-       xp.push_tag_with_class ("table", "stack-frame-with-margin", false);
-       xp.push_tag ("tr", false);
-       {
- 	xp.push_tag_with_class ("td", "interprocmargin", false);
- 	xp.set_attr ("style", "padding-left: 100px");
- 	xp.pop_tag ("td");
-       }
-       xp.push_tag_with_class ("td", "stack-frame", false);
-       label_text funcname
- 	= logical_loc_mgr->get_name_for_path_output (logical_loc);
-       if (funcname.get ())
- 	{
- 	  xp.push_tag_with_class ("div", "frame-funcname", false);
- 	  xp.push_tag ("span", true);
- 	  xp.add_text (funcname.get ());
- 	  xp.pop_tag ("span");
- 	  xp.pop_tag ("div");
- 	}
-     }
-   return std::make_unique<stack_frame> (std::move (parent),
- 					logical_loc,
- 					stack_depth);
- }
- 
- /* Finish emitting content for FRAME and delete it.
-    Return parent.  */
- 
- static std::unique_ptr<stack_frame>
- end_html_stack_frame (xml::printer &xp,
- 		      std::unique_ptr<stack_frame> frame)
- {
-   auto parent = std::move (frame->m_parent);
-   if (frame->m_logical_loc)
-     {
-       xp.pop_tag ("td");
-       xp.pop_tag ("tr");
-       xp.pop_tag ("table");
-     }
-   return parent;
- }
- 
- /* Append an HTML <div> element to XP containing an SVG arrow representing
-    a change in stack depth from OLD_DEPTH to NEW_DEPTH.  */
- 
- static void
- emit_svg_arrow (xml::printer &xp, int old_depth, int new_depth)
- {
-   const int pixels_per_depth = 100;
-   const int min_depth = MIN (old_depth, new_depth);
-   const int base_x = 20;
-   const int excess = 30;
-   const int last_x
-     = base_x + (old_depth - min_depth) * pixels_per_depth;
-   const int this_x
-     = base_x + (new_depth - min_depth) * pixels_per_depth;
-   pretty_printer tmp_pp;
-   pretty_printer *pp = &tmp_pp;
-   pp_printf (pp, "<div class=\"%s\">\n",
- 	     old_depth < new_depth
- 	     ? "between-ranges-call" : "between-ranges-return");
-   pp_printf (pp, "  <svg height=\"30\" width=\"%i\">\n",
- 	     MAX (last_x, this_x) + excess);
-   pp_string
-     (pp,
-      "    <defs>\n"
-      "      <marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"7\"\n"
-      "              refX=\"0\" refY=\"3.5\" orient=\"auto\" stroke=\"#0088ce\" fill=\"#0088ce\">\n"
-      "      <polygon points=\"0 0, 10 3.5, 0 7\"/>\n"
-      "      </marker>\n"
-      "    </defs>\n");
-   pp_printf (pp,
- 	     "    <polyline points=\"%i,0 %i,10 %i,10 %i,20\"\n",
- 	     last_x, last_x, this_x, this_x);
-   pp_string
-     (pp,
-      "              style=\"fill:none;stroke: #0088ce\"\n"
-      "              marker-end=\"url(#arrowhead)\"/>\n"
-      "  </svg>\n"
-      "</div>\n\n");
-   xp.add_raw (pp_formatted_text (pp));
- }
- 
- /* A range of consecutive events within a diagnostic_path, all within the
-    same thread, and with the same fndecl and stack_depth, and which are suitable
-    to print with a single call to diagnostic_show_locus.  */
- struct event_range
- {
-   /* A struct for tracking the mergability of labels on a particular
-      source line.  In particular, track information about links between
-      labels to ensure that we only consolidate events involving links
-      that the source-printing code is able to handle (splitting them
-      otherwise).  */
-   struct per_source_line_info
-   {
-     void init (int line)
-     {
-       m_line = line;
-       m_has_in_edge = false;
-       m_has_out_edge = false;
-       m_min_label_source_column = INT_MAX;
-       m_max_label_source_column = INT_MIN;
-     }
- 
-     /* Return true if our source-printing/labelling/linking code can handle
-        the events already on this source line, *and* a new event at COLUMN.  */
-     bool
-     can_add_label_for_event_p (bool has_in_edge,
- 			       const diagnostic_event *prev_event,
- 			       bool has_out_edge,
- 			       int column) const
-     {
-       /* Any existing in-edge has to be the left-most label on its
- 	 source line.  */
-       if (m_has_in_edge && column < m_min_label_source_column)
- 	return false;
-       /* Any existing out-edge has to be the right-most label on its
- 	 source line.  */
-       if (m_has_out_edge && column > m_max_label_source_column)
- 	return false;
-       /* Can't have more than one in-edge.  */
-       if (m_has_in_edge && has_in_edge)
- 	return false;
-       /* Can't have more than one out-edge.  */
-       if (m_has_out_edge && has_out_edge)
- 	return false;
- 
-       if (has_in_edge)
- 	{
- 	  /* Any new in-edge needs to be the left-most label on its
- 	     source line.  */
- 	  if (column > m_min_label_source_column)
- 	    return false;
- 
- 	  gcc_assert (prev_event);
- 	  const location_t prev_loc = prev_event->get_location ();
- 	  expanded_location prev_exploc
- 	    = linemap_client_expand_location_to_spelling_point
- 		(line_table, prev_loc, LOCATION_ASPECT_CARET);
- 	  /* The destination in-edge's line number has to be <= the
- 	     source out-edge's line number (if any).  */
- 	  if (prev_exploc.line >= m_line)
- 	    return false;
- 	}
- 
-       /* Any new out-edge needs to be the right-most label on its
- 	 source line.  */
-       if (has_out_edge)
- 	if (column < m_max_label_source_column)
- 	  return false;
- 
-       /* All checks passed; we can add the new event at COLUMN.  */
-       return true;
-     }
- 
-     void
-     add_label_for_event (bool has_in_edge, bool has_out_edge, int column)
-     {
-       if (has_in_edge)
- 	m_has_in_edge = true;
-       if (has_out_edge)
- 	m_has_out_edge = true;
-       m_min_label_source_column = std::min (m_min_label_source_column, column);
-       m_max_label_source_column = std::max (m_max_label_source_column, column);
-     }
- 
-     int m_line;
-     bool m_has_in_edge;
-     bool m_has_out_edge;
-     int m_min_label_source_column;
-     int m_max_label_source_column;
-   };
- 
-   event_range (const diagnostic_path &path,
- 	       const pretty_printer &ref_pp,
- 	       unsigned start_idx,
- 	       const diagnostic_event &initial_event,
- 	       per_thread_summary &t,
- 	       bool show_event_links,
- 	       bool colorize_labels,
- 	       bool allow_emojis)
-   : m_path (path),
-     m_initial_event (initial_event),
-     m_logical_loc (initial_event.get_logical_location ()),
-     m_stack_depth (initial_event.get_stack_depth ()),
-     m_start_idx (start_idx), m_end_idx (start_idx),
-     m_path_label (path, ref_pp,
- 		  start_idx, colorize_labels, allow_emojis),
-     m_richloc (initial_event.get_location (), &m_path_label, nullptr),
-     m_thread_id (initial_event.get_thread_id ()),
-     m_per_thread_summary (t),
-     m_show_event_links (show_event_links)
-   {
-     if (m_show_event_links)
-       {
- 	expanded_location exploc
- 	  = linemap_client_expand_location_to_spelling_point
- 	  (line_table, initial_event.get_location (), LOCATION_ASPECT_CARET);
- 	per_source_line_info &source_line_info
- 	  = get_per_source_line_info (exploc.line);
- 
- 	const diagnostic_event *prev_thread_event = t.m_last_event;
- 	const bool has_in_edge
- 	  = (prev_thread_event
- 	     ? prev_thread_event->connect_to_next_event_p ()
- 	     : false);
- 	const bool has_out_edge = initial_event.connect_to_next_event_p ();
- 
- 	source_line_info.add_label_for_event
- 	  (has_in_edge, has_out_edge, exploc.column);
-       }
-   }
- 
-   per_source_line_info &
-   get_per_source_line_info (int source_line)
-   {
-     bool existed = false;
-     per_source_line_info &result
-       = m_source_line_info_map.get_or_insert (source_line, &existed);
-     if (!existed)
-       result.init (source_line);
-     return result;
-   }
- 
-   bool maybe_add_event (const path_print_policy &policy,
- 			const diagnostic_event &new_ev,
- 			unsigned new_ev_idx,
- 			bool check_rich_locations)
-   {
-     if (!can_consolidate_events (m_path,
- 				 m_initial_event, m_start_idx,
- 				 new_ev, new_ev_idx,
- 				 check_rich_locations))
-       return false;
- 
-     /* Verify compatibility of the new label and existing labels
-        with respect to the link-printing code.  */
-     expanded_location exploc
-       = linemap_client_expand_location_to_spelling_point
-       (line_table, new_ev.get_location (), LOCATION_ASPECT_CARET);
-     per_source_line_info &source_line_info
-       = get_per_source_line_info (exploc.line);
-     const diagnostic_event *prev_event = nullptr;
-     if (new_ev_idx > 0)
-       prev_event = &m_path.get_event (new_ev_idx - 1);
-     const bool has_in_edge = (prev_event
- 			      ? prev_event->connect_to_next_event_p ()
- 			      : false);
-     const bool has_out_edge = new_ev.connect_to_next_event_p ();
-     if (m_show_event_links)
-       if (!source_line_info.can_add_label_for_event_p
- 	  (has_in_edge, prev_event,
- 	   has_out_edge, exploc.column))
- 	return false;
- 
-     /* Potentially verify that the locations are sufficiently close.  */
-     if (check_rich_locations)
-       if (!m_richloc.add_location_if_nearby (policy.get_source_policy (),
- 					     new_ev.get_location (),
- 					     false, &m_path_label))
- 	return false;
- 
-     m_end_idx = new_ev_idx;
-     m_per_thread_summary.m_last_event = &new_ev;
- 
-     if (m_show_event_links)
-       source_line_info.add_label_for_event
- 	(has_in_edge, has_out_edge, exploc.column);
- 
-     return true;
-   }
- 
-   /* Print the events in this range to PP, typically as a single
-      call to diagnostic_show_locus.  */
- 
-   void print_as_text (pretty_printer &pp,
- 		      diagnostic_text_output_format &text_output,
- 		      diagnostic_source_effect_info *effect_info)
-   {
-     location_t initial_loc = m_initial_event.get_location ();
- 
-     diagnostic_context &dc = text_output.get_context ();
- 
-     /* Emit a span indicating the filename (and line/column) if the
-        line has changed relative to the last call to
-        diagnostic_show_locus.  */
-     if (dc.m_source_printing.enabled)
-       {
- 	expanded_location exploc
- 	  = linemap_client_expand_location_to_spelling_point
- 	  (line_table, initial_loc, LOCATION_ASPECT_CARET);
- 	if (exploc.file != LOCATION_FILE (dc.m_last_location))
- 	  {
- 	    diagnostic_location_print_policy loc_policy (text_output);
- 	    loc_policy.print_text_span_start (dc, pp, exploc);
- 	  }
-       }
- 
-     /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
-        primary location for an event, diagnostic_show_locus won't print
-        anything.
- 
-        In particular the label for the event won't get printed.
-        Fail more gracefully in this case by showing the event
-        index and text, at no particular location.  */
-     if (get_pure_location (initial_loc) <= BUILTINS_LOCATION)
-       {
- 	for (unsigned i = m_start_idx; i <= m_end_idx; i++)
- 	  {
- 	    const diagnostic_event &iter_event = m_path.get_event (i);
- 	    diagnostic_event_id_t event_id (i);
- 	    pp_printf (&pp, " %@: ", &event_id);
- 	    iter_event.print_desc (pp);
- 	    pp_newline (&pp);
- 	  }
- 	return;
-       }
- 
-     /* Call diagnostic_show_locus to show the events using labels.  */
-     diagnostic_show_locus (&dc, text_output.get_source_printing_options (),
- 			   &m_richloc, DK_DIAGNOSTIC_PATH, &pp,
- 			   effect_info);
- 
-     /* If we have a macro expansion, show the expansion to the user.  */
-     if (linemap_location_from_macro_expansion_p (line_table, initial_loc))
-       {
- 	gcc_assert (m_start_idx == m_end_idx);
- 	maybe_unwind_expanded_macro_loc (text_output, initial_loc);
-       }
-   }
- 
-   /* Print the events in this range to XP, typically as a single
-      call to diagnostic_show_locus_as_html.  */
- 
-   void print_as_html (xml::printer &xp,
- 		      diagnostic_context &dc,
- 		      diagnostic_source_effect_info *effect_info,
- 		      html_label_writer *event_label_writer)
-   {
-     location_t initial_loc = m_initial_event.get_location ();
- 
-     /* Emit a span indicating the filename (and line/column) if the
-        line has changed relative to the last call to
-        diagnostic_show_locus.  */
-     if (dc.m_source_printing.enabled)
-       {
- 	expanded_location exploc
- 	  = linemap_client_expand_location_to_spelling_point
- 	  (line_table, initial_loc, LOCATION_ASPECT_CARET);
- 	if (exploc.file != LOCATION_FILE (dc.m_last_location))
- 	  {
- 	    diagnostic_location_print_policy loc_policy (dc);
- 	    loc_policy.print_html_span_start (dc, xp, exploc);
- 	  }
-       }
- 
-     /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
-        primary location for an event, diagnostic_show_locus_as_html won't print
-        anything.
- 
-        In particular the label for the event won't get printed.
-        Fail more gracefully in this case by showing the event
-        index and text, at no particular location.  */
-     if (get_pure_location (initial_loc) <= BUILTINS_LOCATION)
-       {
- 	for (unsigned i = m_start_idx; i <= m_end_idx; i++)
- 	  {
- 	    const diagnostic_event &iter_event = m_path.get_event (i);
- 	    diagnostic_event_id_t event_id (i);
- 	    pretty_printer pp;
- 	    pp_printf (&pp, " %@: ", &event_id);
- 	    iter_event.print_desc (pp);
- 	    if (event_label_writer)
- 	      event_label_writer->begin_label ();
- 	    xp.add_text_from_pp (pp);
- 	    if (event_label_writer)
- 	      event_label_writer->end_label ();
- 	  }
- 	return;
-       }
- 
-     /* Call diagnostic_show_locus_as_html to show the source,
-        showing events using labels.  */
-     diagnostic_show_locus_as_html (&dc, dc.m_source_printing,
- 				   &m_richloc, DK_DIAGNOSTIC_PATH, xp,
- 				   effect_info, event_label_writer);
- 
-     // TODO: show macro expansions
-   }
- 
-   const diagnostic_path &m_path;
-   const diagnostic_event &m_initial_event;
-   logical_location m_logical_loc;
-   int m_stack_depth;
-   unsigned m_start_idx;
-   unsigned m_end_idx;
-   path_label m_path_label;
-   gcc_rich_location m_richloc;
-   diagnostic_thread_id_t m_thread_id;
-   per_thread_summary &m_per_thread_summary;
-   hash_map<int_hash<int, -1, -2>,
- 	   per_source_line_info> m_source_line_info_map;
-   bool m_show_event_links;
- };
- 
- /* A struct for grouping together the events in a diagnostic_path into
-    ranges of events, partitioned by thread and by stack frame (i.e. by fndecl
-    and stack depth).  */
- 
- struct path_summary
- {
-   path_summary (const path_print_policy &policy,
- 		const pretty_printer &ref_pp,
- 		const diagnostic_path &path,
- 		bool check_rich_locations,
- 		bool colorize = false,
- 		bool show_event_links = true);
- 
-   const logical_location_manager &get_logical_location_manager () const
-   {
-     return m_logical_loc_mgr;
-   }
-   unsigned get_num_ranges () const { return m_ranges.length (); }
-   bool multithreaded_p () const { return m_per_thread_summary.length () > 1; }
- 
-   const per_thread_summary &get_events_for_thread_id (diagnostic_thread_id_t tid)
-   {
-     per_thread_summary **slot = m_thread_id_to_events.get (tid);
-     gcc_assert (slot);
-     gcc_assert (*slot);
-     return **slot;
-   }
- 
-   const logical_location_manager &m_logical_loc_mgr;
-   auto_delete_vec <event_range> m_ranges;
-   auto_delete_vec <per_thread_summary> m_per_thread_summary;
-   hash_map<int_hash<diagnostic_thread_id_t, -1, -2>,
- 	   per_thread_summary *> m_thread_id_to_events;
- 
- private:
-   per_thread_summary &
-   get_or_create_events_for_thread_id (const diagnostic_path &path,
- 				      diagnostic_thread_id_t tid)
-   {
-     if (per_thread_summary **slot = m_thread_id_to_events.get (tid))
-       return **slot;
- 
-     const diagnostic_thread &thread = path.get_thread (tid);
-     per_thread_summary *pts
-       = new per_thread_summary (path,
- 				m_logical_loc_mgr,
- 				thread.get_name (false),
- 				m_per_thread_summary.length ());
-     m_thread_id_to_events.put (tid, pts);
-     m_per_thread_summary.safe_push (pts);
-     return *pts;
-   }
- };
- 
- /* Return true iff there is more than one stack frame used by the events
-    of this thread.  */
- 
- bool
- per_thread_summary::interprocedural_p () const
- {
-   if (m_event_ranges.is_empty ())
-     return false;
-   int first_stack_depth = m_event_ranges[0]->m_stack_depth;
-   for (auto range : m_event_ranges)
-     {
-       if (!m_path.same_function_p (m_event_ranges[0]->m_start_idx,
- 				   range->m_start_idx))
- 	  return true;
-       if (range->m_stack_depth != first_stack_depth)
- 	return true;
-     }
-   return false;
- }
- 
- /* path_summary's ctor.  */
- 
- path_summary::path_summary (const path_print_policy &policy,
- 			    const pretty_printer &ref_pp,
- 			    const diagnostic_path &path,
- 			    bool check_rich_locations,
- 			    bool colorize,
- 			    bool show_event_links)
- : m_logical_loc_mgr (path.get_logical_location_manager ())
- {
-   const unsigned num_events = path.num_events ();
- 
-   event_range *cur_event_range = nullptr;
-   for (unsigned idx = 0; idx < num_events; idx++)
-     {
-       const diagnostic_event &event = path.get_event (idx);
-       const diagnostic_thread_id_t thread_id = event.get_thread_id ();
-       per_thread_summary &pts
- 	= get_or_create_events_for_thread_id (path, thread_id);
- 
-       pts.update_depth_limits (event.get_stack_depth ());
- 
-       if (cur_event_range)
- 	if (cur_event_range->maybe_add_event (policy,
- 					      event,
- 					      idx, check_rich_locations))
- 	  continue;
- 
-       auto theme = policy.get_diagram_theme ();
-       const bool allow_emojis = theme ? theme->emojis_p () : false;
-       cur_event_range = new event_range (path, ref_pp,
- 					 idx, event, pts,
- 					 show_event_links,
- 					 colorize,
- 					 allow_emojis);
-       m_ranges.safe_push (cur_event_range);
-       pts.m_event_ranges.safe_push (cur_event_range);
-       pts.m_last_event = &event;
-     }
- }
- 
- /* Write SPACES to PP.  */
- 
- static void
- write_indent (pretty_printer *pp, int spaces)
- {
-   for (int i = 0; i < spaces; i++)
-     pp_space (pp);
- }
- 
- static const int base_indent = 2;
- static const int per_frame_indent = 2;
- 
- /* A bundle of state for printing event_range instances for a particular
-    thread.  */
- 
- class thread_event_printer
- {
- public:
-   thread_event_printer (const per_thread_summary &t, bool show_depths)
-   : m_per_thread_summary (t),
-     m_show_depths (show_depths),
-     m_cur_indent (base_indent),
-     m_vbar_column_for_depth (),
-     m_num_printed (0)
-   {
-   }
- 
-   /* Get the previous event_range within this thread, if any.  */
-   const event_range *get_any_prev_range () const
-   {
-     if (m_num_printed > 0)
-       return m_per_thread_summary.m_event_ranges[m_num_printed - 1];
-     else
-       return nullptr;
-   }
- 
-   /* Get the next event_range within this thread, if any.  */
-   const event_range *get_any_next_range () const
-   {
-     if (m_num_printed < m_per_thread_summary.m_event_ranges.length () - 1)
-       return m_per_thread_summary.m_event_ranges[m_num_printed + 1];
-     else
-       return nullptr;
-   }
- 
-   void
-   print_swimlane_for_event_range_as_text (diagnostic_text_output_format &text_output,
- 					  pretty_printer *pp,
- 					  const logical_location_manager &logical_loc_mgr,
- 					  event_range *range,
- 					  diagnostic_source_effect_info *effect_info)
-   {
-     gcc_assert (pp);
-     const char *const line_color = "path";
-     const char *start_line_color
-       = colorize_start (pp_show_color (pp), line_color);
-     const char *end_line_color = colorize_stop (pp_show_color (pp));
- 
-     text_art::ascii_theme fallback_theme;
-     text_art::theme *theme = text_output.get_diagram_theme ();
-     if (!theme)
-       theme = &fallback_theme;
- 
-     cppchar_t depth_marker_char = theme->get_cppchar
-       (text_art::theme::cell_kind::INTERPROCEDURAL_DEPTH_MARKER);
-     /* e.g. "|".  */
- 
-     const bool interprocedural_p = m_per_thread_summary.interprocedural_p ();
- 
-     write_indent (pp, m_cur_indent);
-     if (const event_range *prev_range = get_any_prev_range ())
-       {
- 	if (range->m_stack_depth > prev_range->m_stack_depth)
- 	  {
- 	    gcc_assert (interprocedural_p);
- 	    /* Show pushed stack frame(s).  */
- 	    cppchar_t left = theme->get_cppchar
- 	      (text_art::theme::cell_kind::INTERPROCEDURAL_PUSH_FRAME_LEFT);
- 	    cppchar_t middle = theme->get_cppchar
- 	      (text_art::theme::cell_kind::INTERPROCEDURAL_PUSH_FRAME_MIDDLE);
- 	    cppchar_t right = theme->get_cppchar
- 	      (text_art::theme::cell_kind::INTERPROCEDURAL_PUSH_FRAME_RIGHT);
- 	    /* e.g. "+--> ".  */
- 	    pp_string (pp, start_line_color);
- 	    pp_unicode_character (pp, left);
- 	    pp_unicode_character (pp, middle);
- 	    pp_unicode_character (pp, middle);
- 	    pp_unicode_character (pp, right);
- 	    pp_space (pp);
- 	    pp_string (pp, end_line_color);
- 	    m_cur_indent += 5;
- 	  }
-       }
-     if (range->m_logical_loc)
-       {
- 	label_text name
- 	  (logical_loc_mgr.get_name_for_path_output (range->m_logical_loc));
- 	if (name.get ())
- 	  pp_printf (pp, "%qs: ", name.get ());
-       }
-     if (range->m_start_idx == range->m_end_idx)
-       pp_printf (pp, "event %i",
- 		 range->m_start_idx + 1);
-     else
-       pp_printf (pp, "events %i-%i",
- 		 range->m_start_idx + 1, range->m_end_idx + 1);
-     if (m_show_depths)
-       pp_printf (pp, " (depth %i)", range->m_stack_depth);
-     pp_newline (pp);
- 
-     /* Print a run of events.  */
-     if (interprocedural_p)
-       {
- 	write_indent (pp, m_cur_indent + per_frame_indent);
- 	pp_string (pp, start_line_color);
- 	pp_unicode_character (pp, depth_marker_char);
- 	pp_string (pp, end_line_color);
- 	pp_newline (pp);
- 
- 	char *saved_prefix = pp_take_prefix (pp);
- 	char *prefix;
- 	{
- 	  pretty_printer tmp_pp;
- 	  write_indent (&tmp_pp, m_cur_indent + per_frame_indent);
- 	  pp_string (&tmp_pp, start_line_color);
- 	  pp_unicode_character (&tmp_pp, depth_marker_char);
- 	  pp_string (&tmp_pp, end_line_color);
- 	  prefix = xstrdup (pp_formatted_text (&tmp_pp));
- 	}
- 	pp_set_prefix (pp, prefix);
- 	pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
- 	range->print_as_text (*pp, text_output, effect_info);
- 	pp_set_prefix (pp, saved_prefix);
- 
- 	write_indent (pp, m_cur_indent + per_frame_indent);
- 	pp_string (pp, start_line_color);
- 	pp_unicode_character (pp, depth_marker_char);
- 	pp_string (pp, end_line_color);
- 	pp_newline (pp);
-       }
-     else
-       range->print_as_text (*pp, text_output, effect_info);
- 
-     if (const event_range *next_range = get_any_next_range ())
-       {
- 	if (range->m_stack_depth > next_range->m_stack_depth)
- 	  {
- 	    if (m_vbar_column_for_depth.get (next_range->m_stack_depth))
- 	      {
- 		/* Show returning from stack frame(s), by printing
- 		   something like:
- 		   "                   |\n"
- 		   "     <-------------+\n"
- 		   "     |\n".  */
- 		gcc_assert (interprocedural_p);
- 		cppchar_t left = theme->get_cppchar
- 		  (text_art::theme::cell_kind::INTERPROCEDURAL_POP_FRAMES_LEFT);
- 		cppchar_t middle = theme->get_cppchar
- 		  (text_art::theme::cell_kind::INTERPROCEDURAL_POP_FRAMES_MIDDLE);
- 		cppchar_t right = theme->get_cppchar
- 		  (text_art::theme::cell_kind::INTERPROCEDURAL_POP_FRAMES_RIGHT);
- 		int vbar_for_next_frame
- 		  = *m_vbar_column_for_depth.get (next_range->m_stack_depth);
- 
- 		int indent_for_next_frame
- 		  = vbar_for_next_frame - per_frame_indent;
- 		write_indent (pp, vbar_for_next_frame);
- 		pp_string (pp, start_line_color);
- 		pp_unicode_character (pp, left);
- 		for (int i = indent_for_next_frame + per_frame_indent;
- 		     i < m_cur_indent + per_frame_indent - 1; i++)
- 		  pp_unicode_character (pp, middle);
- 		pp_unicode_character (pp, right);
- 		pp_string (pp, end_line_color);
- 		pp_newline (pp);
- 		m_cur_indent = indent_for_next_frame;
- 
- 		write_indent (pp, vbar_for_next_frame);
- 		pp_string (pp, start_line_color);
- 		pp_unicode_character (pp, depth_marker_char);
- 		pp_string (pp, end_line_color);
- 		pp_newline (pp);
- 	      }
- 	    else
- 	      {
- 		/* Handle disjoint paths (e.g. a callback at some later
- 		   time).  */
- 		m_cur_indent = base_indent;
- 	      }
- 	  }
- 	else if (range->m_stack_depth < next_range->m_stack_depth)
- 	  {
- 	    /* Prepare to show pushed stack frame.  */
- 	    gcc_assert (interprocedural_p);
- 	    gcc_assert (range->m_stack_depth != EMPTY);
- 	    gcc_assert (range->m_stack_depth != DELETED);
- 	    m_vbar_column_for_depth.put (range->m_stack_depth,
- 					 m_cur_indent + per_frame_indent);
- 	    m_cur_indent += per_frame_indent;
- 	  }
-       }
- 
-     m_num_printed++;
-   }
- 
-   void
-   print_swimlane_for_event_range_as_html (diagnostic_context &dc,
- 					  xml::printer &xp,
- 					  html_label_writer *event_label_writer,
- 					  event_range *range,
- 					  diagnostic_source_effect_info *effect_info)
-   {
-     range->print_as_html (xp, dc, effect_info, event_label_writer);
-     m_num_printed++;
-   }
- 
-   int get_cur_indent () const { return m_cur_indent; }
- 
- private:
-   const per_thread_summary &m_per_thread_summary;
-   bool m_show_depths;
- 
-   /* Print the ranges.  */
-   int m_cur_indent;
- 
-   /* Keep track of column numbers of existing '|' characters for
-      stack depths we've already printed.  */
-   static const int EMPTY = -1;
-   static const int DELETED = -2;
-   typedef int_hash <int, EMPTY, DELETED> vbar_hash;
-   hash_map <vbar_hash, int> m_vbar_column_for_depth;
- 
-   /* How many event ranges within this swimlane have we printed.
-      This is the index of the next event_range to print.  */
-   unsigned  m_num_printed;
- };
- 
- /* Print path_summary PS to TEXT_OUTPUT, giving an overview of the
-    interprocedural calls and returns.
- 
-    Print the event descriptions in a nested form, printing the event
-    descriptions within calls to diagnostic_show_locus, using labels to
-    show the events:
- 
-    'foo' (events 1-2)
-      | NN |
-      |    |
-      +--> 'bar' (events 3-4)
-             | NN |
-             |    |
-             +--> 'baz' (events 5-6)
-                    | NN |
-                    |    |
-      <------------ +
-      |
-    'foo' (events 7-8)
-      | NN |
-      |    |
-      +--> 'bar' (events 9-10)
-             | NN |
-             |    |
-             +--> 'baz' (events 11-12)
-                    | NN |
-                    |    |
- 
-    If SHOW_DEPTHS is true, append " (depth N)" to the header of each run
-    of events.
- 
-    For events with UNKNOWN_LOCATION, print a summary of each the event.  */
- 
- static void
- print_path_summary_as_text (const path_summary &ps,
- 			    diagnostic_text_output_format &text_output,
- 			    bool show_depths)
- {
-   pretty_printer *const pp = text_output.get_printer ();
- 
-   std::vector<thread_event_printer> thread_event_printers;
-   for (auto t : ps.m_per_thread_summary)
-     thread_event_printers.push_back (thread_event_printer (*t, show_depths));
- 
-   unsigned i;
-   event_range *range;
-   int last_out_edge_column = -1;
-   FOR_EACH_VEC_ELT (ps.m_ranges, i, range)
-     {
-       const int swimlane_idx
- 	= range->m_per_thread_summary.get_swimlane_index ();
-       if (ps.multithreaded_p ())
- 	if (i == 0 || ps.m_ranges[i - 1]->m_thread_id != range->m_thread_id)
- 	  {
- 	    if (i > 0)
- 	      pp_newline (pp);
- 	    pp_printf (pp, "Thread: %qs",
- 		       range->m_per_thread_summary.get_name ());
- 	    pp_newline (pp);
- 	  }
-       thread_event_printer &tep = thread_event_printers[swimlane_idx];
-       /* Wire up any trailing out-edge from previous range to leading in-edge
- 	 of this range.  */
-       diagnostic_source_effect_info effect_info;
-       effect_info.m_leading_in_edge_column = last_out_edge_column;
-       tep.print_swimlane_for_event_range_as_text
- 	(text_output, pp,
- 	 ps.get_logical_location_manager (),
- 	 range, &effect_info);
-       last_out_edge_column = effect_info.m_trailing_out_edge_column;
-     }
- }
- 
- /* Print PS as HTML to XP, using DC and, if non-null EVENT_LABEL_WRITER.  */
- 
- static void
- print_path_summary_as_html (const path_summary &ps,
- 			    diagnostic_context &dc,
- 			    xml::printer &xp,
- 			    html_label_writer *event_label_writer,
- 			    bool show_depths)
- {
-   std::vector<thread_event_printer> thread_event_printers;
-   for (auto t : ps.m_per_thread_summary)
-     thread_event_printers.push_back (thread_event_printer (*t, show_depths));
- 
-   const logical_location_manager *logical_loc_mgr
-     = dc.get_logical_location_manager ();
- 
-   xp.push_tag_with_class ("div", "event-ranges", false);
- 
-   /* Group the ranges into stack frames.  */
-   std::unique_ptr<stack_frame> curr_frame;
-   unsigned i;
-   event_range *range;
-   int last_out_edge_column = -1;
-   FOR_EACH_VEC_ELT (ps.m_ranges, i, range)
-     {
-       const int swimlane_idx
- 	= range->m_per_thread_summary.get_swimlane_index ();
- 
-       const logical_location this_logical_loc = range->m_logical_loc;
-       const int this_depth = range->m_stack_depth;
-       if (curr_frame)
- 	{
- 	  int old_stack_depth = curr_frame->m_stack_depth;
- 	  if (this_depth > curr_frame->m_stack_depth)
- 	    {
- 	      emit_svg_arrow (xp, old_stack_depth, this_depth);
- 	      curr_frame
- 		= begin_html_stack_frame (xp,
- 					  std::move (curr_frame),
- 					  range->m_logical_loc,
- 					  range->m_stack_depth,
- 					  logical_loc_mgr);
- 	    }
- 	  else
- 	    {
- 	      while (this_depth < curr_frame->m_stack_depth
- 		     || this_logical_loc != curr_frame->m_logical_loc)
- 		{
- 		  curr_frame = end_html_stack_frame (xp, std::move (curr_frame));
- 		  if (curr_frame == nullptr)
- 		    {
- 		      curr_frame
- 			= begin_html_stack_frame (xp,
- 						  nullptr,
- 						  range->m_logical_loc,
- 						  range->m_stack_depth,
- 						  logical_loc_mgr);
- 		      break;
- 		    }
- 		}
- 	      emit_svg_arrow (xp, old_stack_depth, this_depth);
- 	    }
- 	}
-       else
- 	{
- 	  curr_frame = begin_html_stack_frame (xp,
- 					       nullptr,
- 					       range->m_logical_loc,
- 					       range->m_stack_depth,
- 					       logical_loc_mgr);
- 	}
- 
-       xp.push_tag_with_class ("table", "event-range-with-margin", false);
-       xp.push_tag ("tr", false);
-       xp.push_tag_with_class ("td", "event-range", false);
-       xp.push_tag_with_class ("div", "events-hdr", true);
-       if (range->m_logical_loc)
- 	{
- 	  gcc_assert (logical_loc_mgr);
- 	  label_text funcname
- 	    = logical_loc_mgr->get_name_for_path_output (range->m_logical_loc);
- 	  if (funcname.get ())
- 	    {
- 	      xp.push_tag_with_class ("span", "funcname", true);
- 	      xp.add_text (funcname.get ());
- 	      xp.pop_tag ("span");
- 	      xp.add_text (": ");
- 	    }
- 	}
-       {
- 	xp.push_tag_with_class ("span", "event-ids", true);
- 	pretty_printer pp;
- 	if (range->m_start_idx == range->m_end_idx)
- 	  pp_printf (&pp, "event %i",
- 		     range->m_start_idx + 1);
- 	else
- 	  pp_printf (&pp, "events %i-%i",
- 		     range->m_start_idx + 1, range->m_end_idx + 1);
- 	xp.add_text_from_pp (pp);
- 	xp.pop_tag ("span");
-       }
-       if (show_depths)
- 	{
- 	  xp.add_text (" ");
- 	  xp.push_tag_with_class ("span", "depth", true);
- 	  pretty_printer pp;
- 	  pp_printf (&pp, "(depth %i)", range->m_stack_depth);
- 	  xp.add_text_from_pp (pp);
- 	  xp.pop_tag ("span");
- 	}
-       xp.pop_tag ("div");
- 
-       /* Print a run of events.  */
-       thread_event_printer &tep = thread_event_printers[swimlane_idx];
-       /* Wire up any trailing out-edge from previous range to leading in-edge
- 	 of this range.  */
-       diagnostic_source_effect_info effect_info;
-       effect_info.m_leading_in_edge_column = last_out_edge_column;
-       tep.print_swimlane_for_event_range_as_html (dc, xp, event_label_writer,
- 						  range, &effect_info);
-       last_out_edge_column = effect_info.m_trailing_out_edge_column;
- 
-       xp.pop_tag ("td");
-       xp.pop_tag ("tr");
-       xp.pop_tag ("table");
-     }
- 
-   /* Close outstanding frames.  */
-   while (curr_frame)
-     curr_frame = end_html_stack_frame (xp, std::move (curr_frame));
- 
-   xp.pop_tag ("div");
- }
- 
- } /* end of anonymous namespace for path-printing code.  */
- 
- class element_event_desc : public pp_element
- {
- public:
-   element_event_desc (const diagnostic_event &event)
-   : m_event (event)
-   {
-   }
- 
-   void add_to_phase_2 (pp_markup::context &ctxt) final override
-   {
-     auto pp = ctxt.m_pp.clone ();
-     m_event.print_desc (*pp.get ());
-     pp_string (&ctxt.m_pp, pp_formatted_text (pp.get ()));
-   }
- 
- private:
-   const diagnostic_event &m_event;
- };
- 
- /* Print PATH according to the context's path_format.  */
- 
- void
- diagnostic_text_output_format::print_path (const diagnostic_path &path)
- {
-   const unsigned num_events = path.num_events ();
- 
-   switch (get_context ().get_path_format ())
-     {
-     case DPF_NONE:
-       /* Do nothing.  */
-       return;
- 
-     case DPF_SEPARATE_EVENTS:
-       {
- 	/* A note per event.  */
- 	auto &logical_loc_mgr = path.get_logical_location_manager ();
- 	for (unsigned i = 0; i < num_events; i++)
- 	  {
- 	    const diagnostic_event &event = path.get_event (i);
- 	    element_event_desc e_event_desc (event);
- 	    diagnostic_event_id_t event_id (i);
- 	    if (get_context ().show_path_depths_p ())
- 	      {
- 		int stack_depth = event.get_stack_depth ();
- 		/* -fdiagnostics-path-format=separate-events doesn't print
- 		   fndecl information, so with -fdiagnostics-show-path-depths
- 		   print the fndecls too, if any.  */
- 		if (logical_location logical_loc
- 		      = event.get_logical_location ())
- 		  {
- 		    label_text name
- 		      (logical_loc_mgr.get_name_for_path_output (logical_loc));
- 		    inform (event.get_location (),
- 			    "%@ %e (fndecl %qs, depth %i)",
- 			    &event_id, &e_event_desc,
- 			    name.get (), stack_depth);
- 		  }
- 		else
- 		  inform (event.get_location (),
- 			  "%@ %e (depth %i)",
- 			  &event_id, &e_event_desc,
- 			  stack_depth);
- 	      }
- 	    else
- 	      inform (event.get_location (),
- 		      "%@ %e", &event_id, &e_event_desc);
- 	  }
-       }
-       break;
- 
-     case DPF_INLINE_EVENTS:
-       {
- 	/* Consolidate related events.  */
- 	path_print_policy policy (*this);
- 	pretty_printer *const pp = get_printer ();
- 	const bool check_rich_locations = true;
- 	const bool colorize = pp_show_color (pp);
- 	const bool show_event_links = m_source_printing.show_event_links_p;
- 	path_summary summary (policy,
- 			      *pp,
- 			      path,
- 			      check_rich_locations,
- 			      colorize,
- 			      show_event_links);
- 	char *saved_prefix = pp_take_prefix (pp);
- 	pp_set_prefix (pp, nullptr);
- 	print_path_summary_as_text (summary, *this,
- 				    get_context ().show_path_depths_p ());
- 	pp_flush (pp);
- 	pp_set_prefix (pp, saved_prefix);
-       }
-       break;
-     }
- }
- 
- /* Print PATH as HTML to XP, using DC and DSPP for settings.
-    If non-null, use EVENT_LABEL_WRITER when writing events.  */
- 
- void
- print_path_as_html (xml::printer &xp,
- 		    const diagnostic_path &path,
- 		    diagnostic_context &dc,
- 		    html_label_writer *event_label_writer,
- 		    const diagnostic_source_print_policy &dspp)
- {
-   path_print_policy policy (dc);
-   const bool check_rich_locations = true;
-   const bool colorize = false;
-   const diagnostic_source_printing_options &source_printing_opts
-     = dspp.get_options ();
-   const bool show_event_links = source_printing_opts.show_event_links_p;
-   path_summary summary (policy,
- 			*dc.get_reference_printer (),
- 			path,
- 			check_rich_locations,
- 			colorize,
- 			show_event_links);
-   print_path_summary_as_html (summary, dc, xp, event_label_writer,
- 			      dc.show_path_depths_p ());
- }
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* Return true iff all events in PATH have locations for which column data
-    is available, so that selftests that require precise string output can
-    bail out for awkward line_table cases.  */
- 
- static bool
- path_events_have_column_data_p (const diagnostic_path &path)
- {
-   for (unsigned idx = 0; idx < path.num_events (); idx++)
-     {
-       location_t event_loc = path.get_event (idx).get_location ();
-       if (line_table->get_pure_location (event_loc)
- 	  > LINE_MAP_MAX_LOCATION_WITH_COLS)
- 	return false;
-       if (line_table->get_start (event_loc) > LINE_MAP_MAX_LOCATION_WITH_COLS)
- 	return false;
-       if (line_table->get_finish (event_loc) > LINE_MAP_MAX_LOCATION_WITH_COLS)
- 	return false;
-     }
-   return true;
- }
- 
- /* Verify that empty paths are handled gracefully.  */
- 
- static void
- test_empty_path (pretty_printer *event_pp)
- {
-   test_diagnostic_path path (event_pp);
-   ASSERT_FALSE (path.interprocedural_p ());
- 
-   test_diagnostic_context dc;
-   diagnostic_text_output_format text_output (dc);
-   path_print_policy policy (text_output);
-   path_summary summary (policy, *event_pp, path, false);
-   ASSERT_EQ (summary.get_num_ranges (), 0);
- 
-   print_path_summary_as_text (summary, text_output, true);
-   ASSERT_STREQ ("",
- 		pp_formatted_text (text_output.get_printer ()));
- }
- 
- /* Verify that print_path_summary works on a purely intraprocedural path.  */
- 
- static void
- test_intraprocedural_path (pretty_printer *event_pp)
- {
-   test_diagnostic_path path (event_pp);
-   const char *const funcname = "foo";
-   path.add_event (UNKNOWN_LOCATION, funcname, 0, "first %qs", "free");
-   path.add_event (UNKNOWN_LOCATION, funcname, 0, "double %qs", "free");
- 
-   ASSERT_FALSE (path.interprocedural_p ());
- 
-   test_diagnostic_context dc;
-   diagnostic_text_output_format text_output (dc);
-   path_print_policy policy (text_output);
-   path_summary summary (policy, *event_pp, path, false, false, false);
-   ASSERT_EQ (summary.get_num_ranges (), 1);
- 
-   print_path_summary_as_text (summary, text_output, true);
-   ASSERT_STREQ ("  `foo': events 1-2 (depth 0)\n"
- 		" (1): first `free'\n"
- 		" (2): double `free'\n",
- 		pp_formatted_text (text_output.get_printer ()));
- }
- 
- /* Verify that print_path_summary works on an interprocedural path.  */
- 
- static void
- test_interprocedural_path_1 (pretty_printer *event_pp)
- {
-   test_diagnostic_path path (event_pp);
-   path.add_entry ("test", 0);
-   path.add_call ("test", 0, "make_boxed_int");
-   path.add_call ("make_boxed_int", 1, "wrapped_malloc");
-   path.add_event (UNKNOWN_LOCATION,
- 		  "wrapped_malloc", 2, "calling malloc");
-   path.add_return ("test", 0);
-   path.add_call ("test", 0, "free_boxed_int");
-   path.add_call ("free_boxed_int", 1, "wrapped_free");
-   path.add_event (UNKNOWN_LOCATION, "wrapped_free", 2, "calling free");
-   path.add_return ("test", 0);
-   path.add_call ("test", 0, "free_boxed_int");
-   path.add_call ("free_boxed_int", 1, "wrapped_free");
-   path.add_event (UNKNOWN_LOCATION, "wrapped_free", 2, "calling free");
-   ASSERT_EQ (path.num_events (), 18);
- 
-   ASSERT_TRUE (path.interprocedural_p ());
- 
-   {
-     test_diagnostic_context dc;
-     diagnostic_text_output_format text_output (dc, nullptr, false);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, false);
-     ASSERT_EQ (summary.get_num_ranges (), 9);
- 
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     print_path_summary_as_text (summary, text_output, true);
-     ASSERT_STREQ
-       ("  `test': events 1-2 (depth 0)\n"
-        "    |\n"
-        "    | (1): entering `test'\n"
-        "    | (2): calling `make_boxed_int'\n"
-        "    |\n"
-        "    +--> `make_boxed_int': events 3-4 (depth 1)\n"
-        "           |\n"
-        "           | (3): entering `make_boxed_int'\n"
-        "           | (4): calling `wrapped_malloc'\n"
-        "           |\n"
-        "           +--> `wrapped_malloc': events 5-6 (depth 2)\n"
-        "                  |\n"
-        "                  | (5): entering `wrapped_malloc'\n"
-        "                  | (6): calling malloc\n"
-        "                  |\n"
-        "    <-------------+\n"
-        "    |\n"
-        "  `test': events 7-8 (depth 0)\n"
-        "    |\n"
-        "    | (7): returning to `test'\n"
-        "    | (8): calling `free_boxed_int'\n"
-        "    |\n"
-        "    +--> `free_boxed_int': events 9-10 (depth 1)\n"
-        "           |\n"
-        "           | (9): entering `free_boxed_int'\n"
-        "           | (10): calling `wrapped_free'\n"
-        "           |\n"
-        "           +--> `wrapped_free': events 11-12 (depth 2)\n"
-        "                  |\n"
-        "                  | (11): entering `wrapped_free'\n"
-        "                  | (12): calling free\n"
-        "                  |\n"
-        "    <-------------+\n"
-        "    |\n"
-        "  `test': events 13-14 (depth 0)\n"
-        "    |\n"
-        "    | (13): returning to `test'\n"
-        "    | (14): calling `free_boxed_int'\n"
-        "    |\n"
-        "    +--> `free_boxed_int': events 15-16 (depth 1)\n"
-        "           |\n"
-        "           | (15): entering `free_boxed_int'\n"
-        "           | (16): calling `wrapped_free'\n"
-        "           |\n"
-        "           +--> `wrapped_free': events 17-18 (depth 2)\n"
-        "                  |\n"
-        "                  | (17): entering `wrapped_free'\n"
-        "                  | (18): calling free\n"
-        "                  |\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, false);
-     print_path_summary_as_text (summary, text_output, true);
-     ASSERT_STREQ
-       ("  `test': events 1-2 (depth 0)\n"
-        "    │\n"
-        "    │ (1): entering `test'\n"
-        "    │ (2): calling `make_boxed_int'\n"
-        "    │\n"
-        "    └──> `make_boxed_int': events 3-4 (depth 1)\n"
-        "           │\n"
-        "           │ (3): entering `make_boxed_int'\n"
-        "           │ (4): calling `wrapped_malloc'\n"
-        "           │\n"
-        "           └──> `wrapped_malloc': events 5-6 (depth 2)\n"
-        "                  │\n"
-        "                  │ (5): entering `wrapped_malloc'\n"
-        "                  │ (6): calling malloc\n"
-        "                  │\n"
-        "    <─────────────┘\n"
-        "    │\n"
-        "  `test': events 7-8 (depth 0)\n"
-        "    │\n"
-        "    │ (7): returning to `test'\n"
-        "    │ (8): calling `free_boxed_int'\n"
-        "    │\n"
-        "    └──> `free_boxed_int': events 9-10 (depth 1)\n"
-        "           │\n"
-        "           │ (9): entering `free_boxed_int'\n"
-        "           │ (10): calling `wrapped_free'\n"
-        "           │\n"
-        "           └──> `wrapped_free': events 11-12 (depth 2)\n"
-        "                  │\n"
-        "                  │ (11): entering `wrapped_free'\n"
-        "                  │ (12): calling free\n"
-        "                  │\n"
-        "    <─────────────┘\n"
-        "    │\n"
-        "  `test': events 13-14 (depth 0)\n"
-        "    │\n"
-        "    │ (13): returning to `test'\n"
-        "    │ (14): calling `free_boxed_int'\n"
-        "    │\n"
-        "    └──> `free_boxed_int': events 15-16 (depth 1)\n"
-        "           │\n"
-        "           │ (15): entering `free_boxed_int'\n"
-        "           │ (16): calling `wrapped_free'\n"
-        "           │\n"
-        "           └──> `wrapped_free': events 17-18 (depth 2)\n"
-        "                  │\n"
-        "                  │ (17): entering `wrapped_free'\n"
-        "                  │ (18): calling free\n"
-        "                  │\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
- 
- }
- 
- /* Example where we pop the stack to an intermediate frame, rather than the
-    initial one.  */
- 
- static void
- test_interprocedural_path_2 (pretty_printer *event_pp)
- {
-   test_diagnostic_path path (event_pp);
-   path.add_entry ("foo", 0);
-   path.add_call ("foo", 0, "bar");
-   path.add_call ("bar", 1, "baz");
-   path.add_return ("bar", 1);
-   path.add_call ("bar", 1, "baz");
-   ASSERT_EQ (path.num_events (), 8);
- 
-   ASSERT_TRUE (path.interprocedural_p ());
- 
-   {
-     test_diagnostic_context dc;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, false);
-     ASSERT_EQ (summary.get_num_ranges (), 5);
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     print_path_summary_as_text (summary, text_output, true);
-     ASSERT_STREQ
-       ("  `foo': events 1-2 (depth 0)\n"
-        "    |\n"
-        "    | (1): entering `foo'\n"
-        "    | (2): calling `bar'\n"
-        "    |\n"
-        "    +--> `bar': events 3-4 (depth 1)\n"
-        "           |\n"
-        "           | (3): entering `bar'\n"
-        "           | (4): calling `baz'\n"
-        "           |\n"
-        "           +--> `baz': event 5 (depth 2)\n"
-        "                  |\n"
-        "                  | (5): entering `baz'\n"
-        "                  |\n"
-        "           <------+\n"
-        "           |\n"
-        "         `bar': events 6-7 (depth 1)\n"
-        "           |\n"
-        "           | (6): returning to `bar'\n"
-        "           | (7): calling `baz'\n"
-        "           |\n"
-        "           +--> `baz': event 8 (depth 2)\n"
-        "                  |\n"
-        "                  | (8): entering `baz'\n"
-        "                  |\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, false);
-     print_path_summary_as_text (summary, text_output, true);
-     ASSERT_STREQ
-       ("  `foo': events 1-2 (depth 0)\n"
-        "    │\n"
-        "    │ (1): entering `foo'\n"
-        "    │ (2): calling `bar'\n"
-        "    │\n"
-        "    └──> `bar': events 3-4 (depth 1)\n"
-        "           │\n"
-        "           │ (3): entering `bar'\n"
-        "           │ (4): calling `baz'\n"
-        "           │\n"
-        "           └──> `baz': event 5 (depth 2)\n"
-        "                  │\n"
-        "                  │ (5): entering `baz'\n"
-        "                  │\n"
-        "           <──────┘\n"
-        "           │\n"
-        "         `bar': events 6-7 (depth 1)\n"
-        "           │\n"
-        "           │ (6): returning to `bar'\n"
-        "           │ (7): calling `baz'\n"
-        "           │\n"
-        "           └──> `baz': event 8 (depth 2)\n"
-        "                  │\n"
-        "                  │ (8): entering `baz'\n"
-        "                  │\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
- }
- 
- /* Verify that print_path_summary is sane in the face of a recursive
-    diagnostic_path.  */
- 
- static void
- test_recursion (pretty_printer *event_pp)
- {
-  test_diagnostic_path path (event_pp);
-   path.add_entry ("factorial", 0);
-   for (int depth = 0; depth < 3; depth++)
-     path.add_call ("factorial", depth, "factorial");
-   ASSERT_EQ (path.num_events (), 7);
- 
-   ASSERT_TRUE (path.interprocedural_p ());
- 
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
- 
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, false);
-     ASSERT_EQ (summary.get_num_ranges (), 4);
- 
-     print_path_summary_as_text (summary, text_output, true);
-     ASSERT_STREQ
-       ("  `factorial': events 1-2 (depth 0)\n"
-        "    |\n"
-        "    | (1): entering `factorial'\n"
-        "    | (2): calling `factorial'\n"
-        "    |\n"
-        "    +--> `factorial': events 3-4 (depth 1)\n"
-        "           |\n"
-        "           | (3): entering `factorial'\n"
-        "           | (4): calling `factorial'\n"
-        "           |\n"
-        "           +--> `factorial': events 5-6 (depth 2)\n"
-        "                  |\n"
-        "                  | (5): entering `factorial'\n"
-        "                  | (6): calling `factorial'\n"
-        "                  |\n"
-        "                  +--> `factorial': event 7 (depth 3)\n"
-        "                         |\n"
-        "                         | (7): entering `factorial'\n"
-        "                         |\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
- 
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, false);
-     print_path_summary_as_text (summary, text_output, true);
-     ASSERT_STREQ
-       ("  `factorial': events 1-2 (depth 0)\n"
-        "    │\n"
-        "    │ (1): entering `factorial'\n"
-        "    │ (2): calling `factorial'\n"
-        "    │\n"
-        "    └──> `factorial': events 3-4 (depth 1)\n"
-        "           │\n"
-        "           │ (3): entering `factorial'\n"
-        "           │ (4): calling `factorial'\n"
-        "           │\n"
-        "           └──> `factorial': events 5-6 (depth 2)\n"
-        "                  │\n"
-        "                  │ (5): entering `factorial'\n"
-        "                  │ (6): calling `factorial'\n"
-        "                  │\n"
-        "                  └──> `factorial': event 7 (depth 3)\n"
-        "                         │\n"
-        "                         │ (7): entering `factorial'\n"
-        "                         │\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
- }
- 
- /* Helper class for writing tests of control flow visualization.  */
- 
- class control_flow_test
- {
- public:
-   control_flow_test (const location &loc,
- 		     const line_table_case &case_,
- 		     const char *content)
-   : m_tmp_file (loc, ".c", content,
- 		/* gcc_rich_location::add_location_if_nearby implicitly
- 		   uses global_dc's file_cache, so we need to evict
- 		   tmp when we're done.  */
- 		&global_dc->get_file_cache ()),
-     m_ltt (case_)
-   {
-     m_ord_map
-       = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
- 					     m_tmp_file.get_filename (), 0));
-     linemap_line_start (line_table, 1, 100);
-   }
- 
-   location_t get_line_and_column (int line, int column)
-   {
-     return linemap_position_for_line_and_column (line_table, m_ord_map,
- 						 line, column);
-   }
- 
-   location_t get_line_and_columns (int line, int first_column, int last_column)
-   {
-     return get_line_and_columns (line,
- 				 first_column, first_column, last_column);
-   }
- 
-   location_t get_line_and_columns (int line,
- 				   int first_column,
- 				   int caret_column,
- 				   int last_column)
-   {
-     return make_location (get_line_and_column (line, caret_column),
- 			  get_line_and_column (line, first_column),
- 			  get_line_and_column (line, last_column));
-   }
- 
- private:
-   temp_source_file m_tmp_file;
-   line_table_test m_ltt;
-   const line_map_ordinary *m_ord_map;
- };
- 
- /* Example of event edges where all events can go in the same layout,
-    testing the 6 combinations of:
-    - ASCII vs Unicode vs event links off
-    - line numbering on and off.  */
- 
- static void
- test_control_flow_1 (const line_table_case &case_,
- 		     pretty_printer *event_pp)
- {
-   /* Create a tempfile and write some text to it.
-      ...000000000111111111122222222223333333333.
-      ...123456789012345678901234567890123456789.  */
-   const char *content
-     = ("int test (int *p)\n" /* line 1.  */
-        "{\n"                 /* line 2.  */
-        "  if (p)\n"          /* line 3.  */
-        "    return 0;\n"     /* line 4.  */
-        "  return *p;\n"      /* line 5.  */
-        "}\n");               /* line 6.  */
- 
-   control_flow_test t (SELFTEST_LOCATION, case_, content);
- 
-   const location_t conditional = t.get_line_and_column (3, 7);
-   const location_t cfg_dest = t.get_line_and_column (5, 10);
- 
-   test_diagnostic_path path (event_pp);
-   path.add_event (conditional, nullptr, 0,
- 		  "following %qs branch (when %qs is NULL)...",
- 		  "false", "p");
-   path.connect_to_next_event ();
- 
-   path.add_event (cfg_dest, nullptr, 0,
- 		  "...to here");
-   path.add_event (cfg_dest, nullptr, 0,
- 		  "dereference of NULL %qs",
- 		  "p");
- 
-   if (!path_events_have_column_data_p (path))
-     return;
- 
- 
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     dc.m_source_printing.show_event_links_p = true;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-3\n"
-        "FILENAME:3:7:\n"
-        "   if (p)\n"
-        "       ^\n"
-        "       |\n"
-        "       (1) following `false' branch (when `p' is NULL)... ->-+\n"
-        "                                                             |\n"
-        "FILENAME:5:10:\n"
-        "                                                             |\n"
-        "+------------------------------------------------------------+\n"
-        "|  return *p;\n"
-        "|         ~\n"
-        "|         |\n"
-        "+-------->(2) ...to here\n"
-        "          (3) dereference of NULL `p'\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     dc.m_source_printing.show_event_links_p = false;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-3\n"
-        "FILENAME:3:7:\n"
-        "   if (p)\n"
-        "       ^\n"
-        "       |\n"
-        "       (1) following `false' branch (when `p' is NULL)...\n"
-        "FILENAME:5:10:\n"
-        "   return *p;\n"
-        "          ~\n"
-        "          |\n"
-        "          (2) ...to here\n"
-        "          (3) dereference of NULL `p'\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     dc.m_source_printing.show_line_numbers_p = true;
-     dc.m_source_printing.show_event_links_p = true;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-3\n"
-        "FILENAME:3:7:\n"
-        "    3 |   if (p)\n"
-        "      |       ^\n"
-        "      |       |\n"
-        "      |       (1) following `false' branch (when `p' is NULL)... ->-+\n"
-        "      |                                                             |\n"
-        "      |                                                             |\n"
-        "      |+------------------------------------------------------------+\n"
-        "    4 ||    return 0;\n"
-        "    5 ||  return *p;\n"
-        "      ||         ~\n"
-        "      ||         |\n"
-        "      |+-------->(2) ...to here\n"
-        "      |          (3) dereference of NULL `p'\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     dc.m_source_printing.show_line_numbers_p = true;
-     dc.m_source_printing.show_event_links_p = false;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-3\n"
-        "FILENAME:3:7:\n"
-        "    3 |   if (p)\n"
-        "      |       ^\n"
-        "      |       |\n"
-        "      |       (1) following `false' branch (when `p' is NULL)...\n"
-        "    4 |     return 0;\n"
-        "    5 |   return *p;\n"
-        "      |          ~\n"
-        "      |          |\n"
-        "      |          (2) ...to here\n"
-        "      |          (3) dereference of NULL `p'\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
-     dc.m_source_printing.show_event_links_p = true;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-3\n"
-        "FILENAME:3:7:\n"
-        "   if (p)\n"
-        "       ^\n"
-        "       |\n"
-        "       (1) following `false' branch (when `p' is NULL)... ─>─┐\n"
-        "                                                             │\n"
-        "FILENAME:5:10:\n"
-        "                                                             │\n"
-        "┌────────────────────────────────────────────────────────────┘\n"
-        "│  return *p;\n"
-        "│         ~\n"
-        "│         |\n"
-        "└────────>(2) ...to here\n"
-        "          (3) dereference of NULL `p'\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
-     dc.m_source_printing.show_event_links_p = true;
-     dc.m_source_printing.show_line_numbers_p = true;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-3\n"
-        "FILENAME:3:7:\n"
-        "    3 |   if (p)\n"
-        "      |       ^\n"
-        "      |       |\n"
-        "      |       (1) following `false' branch (when `p' is NULL)... ─>─┐\n"
-        "      |                                                             │\n"
-        "      |                                                             │\n"
-        "      |┌────────────────────────────────────────────────────────────┘\n"
-        "    4 |│    return 0;\n"
-        "    5 |│  return *p;\n"
-        "      |│         ~\n"
-        "      |│         |\n"
-        "      |└────────>(2) ...to here\n"
-        "      |          (3) dereference of NULL `p'\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
- }
- 
- /* Complex example involving a backedge.  */
- 
- static void
- test_control_flow_2 (const line_table_case &case_,
- 		     pretty_printer *event_pp)
- {
-   /* Create a tempfile and write some text to it.
-      ...000000000111111111122222222223333333333.
-      ...123456789012345678901234567890123456789.  */
-   const char *content
-     = ("int for_loop_noop_next (struct node *n)\n" /* <--------- line 1.  */
-        "{\n" /* <----------------------------------------------- line 2.  */
-        "  int sum = 0;\n" /* <---------------------------------- line 3.  */
-        "  for (struct node *iter = n; iter; iter->next)\n" /* <- line 4.  */
-        "    sum += n->val;\n" /* <------------------------------ line 5.  */
-        "  return sum;\n" /* <----------------------------------- line 6.  */
-        "}\n");  /* <-------------------------------------------- line 7.  */
-   /* Adapted from infinite-loop-linked-list.c where
-      "iter->next" should be "iter = iter->next".  */
- 
-   control_flow_test t (SELFTEST_LOCATION, case_, content);
- 
-   const location_t iter_test = t.get_line_and_columns (4, 31, 34);
-   const location_t loop_body_start = t.get_line_and_columns (5, 12, 17);
-   const location_t loop_body_end = t.get_line_and_columns (5, 5, 9, 17);
- 
-   test_diagnostic_path path (event_pp);
-   path.add_event (iter_test, nullptr, 0, "infinite loop here");
- 
-   path.add_event (iter_test, nullptr, 0, "looping from here...");
-   path.connect_to_next_event ();
- 
-   path.add_event (loop_body_start, nullptr, 0, "...to here");
- 
-   path.add_event (loop_body_end, nullptr, 0, "looping back...");
-   path.connect_to_next_event ();
- 
-   path.add_event (iter_test, nullptr, 0, "...to here");
- 
-   if (!path_events_have_column_data_p (path))
-     return;
- 
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     dc.m_source_printing.show_event_links_p = true;
-     dc.m_source_printing.show_line_numbers_p = true;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-3\n"
-        "FILENAME:4:31:\n"
-        "    4 |   for (struct node *iter = n; iter; iter->next)\n"
-        "      |                               ^~~~\n"
-        "      |                               |\n"
-        "      |                               (1) infinite loop here\n"
-        "      |                               (2) looping from here... ->-+\n"
-        "      |                                                           |\n"
-        "      |                                                           |\n"
-        "      |+----------------------------------------------------------+\n"
-        "    5 ||    sum += n->val;\n"
-        "      ||           ~~~~~~              \n"
-        "      ||           |\n"
-        "      |+---------->(3) ...to here\n"
-        /* We need to start an new event_range here as event (4) is to the
- 	  left of event (3), and thus (4) would mess up the in-edge to (3).  */
-        "  event 4\n"
-        "    5 |     sum += n->val;\n"
-        "      |     ~~~~^~~~~~~~~\n"
-        "      |         |\n"
-        "      |         (4) looping back... ->-+\n"
-        "      |                                |\n"
-        /* We need to start an new event_range here as event (4) with an
- 	  out-edge is on a later line (line 5) than its destination event (5),
- 	  on line 4.  */
-        "  event 5\n"
-        "      |                                |\n"
-        "      |+-------------------------------+\n"
-        "    4 ||  for (struct node *iter = n; iter; iter->next)\n"
-        "      ||                              ^~~~\n"
-        "      ||                              |\n"
-        "      |+----------------------------->(5) ...to here\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
- }
- 
- /* Complex example involving a backedge and both an in-edge and out-edge
-    on the same line.  */
- 
- static void
- test_control_flow_3 (const line_table_case &case_,
- 		     pretty_printer *event_pp)
- {
-   /* Create a tempfile and write some text to it.
-      ...000000000111111111122222222223333333333.
-      ...123456789012345678901234567890123456789.  */
-   const char *content
-     = ("void test_missing_comparison_in_for_condition_1 (int n)\n"
-        "{\n" /* <------------------------- line 2.  */
-        "  for (int i = 0; n; i++)\n" /* <- line 3.  */
-        "    {\n" /* <--------------------- line 4.  */
-        "    }\n" /* <--------------------- line 5.  */
-        "}\n"); /* <----------------------- line 6.  */
-   /* Adapted from infinite-loop-1.c where the condition should have been
-      "i < n", rather than just "n".  */
- 
-   control_flow_test t (SELFTEST_LOCATION, case_, content);
- 
-   const location_t iter_test = t.get_line_and_column (3, 19);
-   const location_t iter_next = t.get_line_and_columns (3, 22, 24);
- 
-   test_diagnostic_path path (event_pp);
-   path.add_event (iter_test, nullptr, 0, "infinite loop here");
- 
-   path.add_event (iter_test, nullptr, 0, "looping from here...");
-   path.connect_to_next_event ();
- 
-   path.add_event (iter_next, nullptr, 0, "...to here");
- 
-   path.add_event (iter_next, nullptr, 0, "looping back...");
-   path.connect_to_next_event ();
- 
-   path.add_event (iter_test, nullptr, 0, "...to here");
- 
-   if (!path_events_have_column_data_p (path))
-     return;
- 
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     dc.m_source_printing.show_event_links_p = true;
-     dc.m_source_printing.show_line_numbers_p = true;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-2\n"
-        "FILENAME:3:19:\n"
-        "    3 |   for (int i = 0; n; i++)\n"
-        "      |                   ^\n"
-        "      |                   |\n"
-        "      |                   (1) infinite loop here\n"
-        "      |                   (2) looping from here... ->-+\n"
-        "      |                                               |\n"
-        "  events 3-4\n"
-        "      |                                               |\n"
-        "      |+----------------------------------------------+\n"
-        "    3 ||  for (int i = 0; n; i++)\n"
-        "      ||                     ^~~\n"
-        "      ||                     |\n"
-        "      |+-------------------->(3) ...to here\n"
-        "      |                      (4) looping back... ->-+\n"
-        "      |                                             |\n"
-        /* We need to start an new event_range here as event (4) with an
- 	  out-edge is on the same line as its destination event (5), but
- 	  to the right, which we can't handle as a single event_range. */
-        "  event 5\n"
-        "      |                                             |\n"
-        "      |+--------------------------------------------+\n"
-        "    3 ||  for (int i = 0; n; i++)\n"
-        "      ||                  ^\n"
-        "      ||                  |\n"
-        "      |+----------------->(5) ...to here\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
- }
- 
- /* Implementation of ASSERT_CFG_EDGE_PATH_STREQ.  */
- 
- static void
- assert_cfg_edge_path_streq (const location &loc,
- 			    pretty_printer *event_pp,
- 			    const location_t src_loc,
- 			    const location_t dst_loc,
- 			    const char *expected_str)
- {
-   test_diagnostic_path path (event_pp);
-   path.add_event (src_loc, nullptr, 0, "from here...");
-   path.connect_to_next_event ();
- 
-   path.add_event (dst_loc, nullptr, 0, "...to here");
- 
-   if (!path_events_have_column_data_p (path))
-     return;
- 
-   test_diagnostic_context dc;
-   dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-   dc.m_source_printing.show_event_links_p = true;
-   dc.m_source_printing.show_line_numbers_p = true;
-   diagnostic_text_output_format text_output (dc);
-   path_print_policy policy (text_output);
-   path_summary summary (policy, *event_pp, path, true);
-   print_path_summary_as_text (summary, text_output, false);
-   ASSERT_STREQ_AT (loc, expected_str,
- 		   pp_formatted_text (text_output.get_printer ()));
- }
- 
- /* Assert that if we make a path with an event with "from here..." at SRC_LOC
-    leading to an event "...to here" at DST_LOC that we print the path
-    as EXPECTED_STR.  */
- 
- #define ASSERT_CFG_EDGE_PATH_STREQ(SRC_LOC, DST_LOC, EXPECTED_STR) \
-   assert_cfg_edge_path_streq ((SELFTEST_LOCATION), (event_pp),	   \
- 			      (SRC_LOC), (DST_LOC), (EXPECTED_STR))
- 
- /* Various examples of edge, trying to cover all combinations of:
-    - relative x positive of src label and dst label
-    - relative y position of labels:
-      - on same line
-      - on next line
-      - on line after next
-      - big gap, where src is before dst
-      - big gap, where src is after dst
-    and other awkward cases.  */
- 
- static void
- test_control_flow_4 (const line_table_case &case_,
- 		     pretty_printer *event_pp)
- {
-   std::string many_lines;
-   for (int i = 1; i <= 100; i++)
-     /* ............000000000111
-        ............123456789012.  */
-     many_lines += "LHS      RHS\n";
-   control_flow_test t (SELFTEST_LOCATION, case_, many_lines.c_str ());
- 
-   /* Same line.  */
-   {
-     /* LHS -> RHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (3, 1, 3),
-        t.get_line_and_columns (3, 10, 12),
-        ("  event 1\n"
- 	"FILENAME:3:1:\n"
- 	"    3 | LHS      RHS\n"
- 	"      | ^~~\n"
- 	"      | |\n"
- 	"      | (1) from here... ->-+\n"
- 	"      |                     |\n"
- 	"  event 2\n"
- 	"      |                     |\n"
- 	"      |+--------------------+\n"
- 	"    3 ||LHS      RHS\n"
- 	"      ||         ^~~\n"
- 	"      ||         |\n"
- 	"      |+-------->(2) ...to here\n"));
- 
-     /*  RHS -> LHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (3, 10, 12),
-        t.get_line_and_columns (3, 1, 3),
-        ("  event 1\n"
- 	"FILENAME:3:10:\n"
- 	"    3 | LHS      RHS\n"
- 	"      |          ^~~\n"
- 	"      |          |\n"
- 	"      |          (1) from here... ->-+\n"
- 	"      |                              |\n"
- 	"  event 2\n"
- 	"      |                              |\n"
- 	"      |+-----------------------------+\n"
- 	"    3 ||LHS      RHS\n"
- 	"      ||^~~\n"
- 	"      |||\n"
- 	"      |+(2) ...to here\n"));
-   }
- 
-   /* Next line.  */
-   {
-     /* LHS -> RHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (3, 1, 3),
-        t.get_line_and_columns (4, 5, 7),
-        ("  events 1-2\n"
- 	"FILENAME:3:1:\n"
- 	"    3 | LHS      RHS\n"
- 	"      | ^~~\n"
- 	"      | |\n"
- 	"      | (1) from here... ->-+\n"
- 	"      |                     |\n"
- 	"      |                     |\n"
- 	"      |+--------------------+\n"
- 	"    4 ||LHS      RHS\n"
- 	"      ||    ~~~\n"
- 	"      ||    |\n"
- 	"      |+--->(2) ...to here\n"));
- 
-     /*  RHS -> LHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (3, 10, 12),
-        t.get_line_and_columns (4, 1, 3),
-        ("  events 1-2\n"
- 	"FILENAME:3:10:\n"
- 	"    3 | LHS      RHS\n"
- 	"      |          ^~~\n"
- 	"      |          |\n"
- 	"      |          (1) from here... ->-+\n"
- 	"      |                              |\n"
- 	"      |                              |\n"
- 	"      |+-----------------------------+\n"
- 	"    4 ||LHS      RHS\n"
- 	"      ||~~~       \n"
- 	"      |||\n"
- 	"      |+(2) ...to here\n"));
-   }
- 
-   /* Line after next.  */
-   {
-     /* LHS -> RHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (3, 1, 3),
-        t.get_line_and_columns (5, 10, 12),
-        ("  events 1-2\n"
- 	"FILENAME:3:1:\n"
- 	"    3 | LHS      RHS\n"
- 	"      | ^~~\n"
- 	"      | |\n"
- 	"      | (1) from here... ->-+\n"
- 	"      |                     |\n"
- 	"      |                     |\n"
- 	"      |+--------------------+\n"
- 	"    4 ||LHS      RHS\n"
- 	"    5 ||LHS      RHS\n"
- 	"      ||         ~~~\n"
- 	"      ||         |\n"
- 	"      |+-------->(2) ...to here\n"));
- 
-     /*  RHS -> LHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (3, 10, 12),
-        t.get_line_and_columns (5, 1, 3),
-        ("  events 1-2\n"
- 	"FILENAME:3:10:\n"
- 	"    3 | LHS      RHS\n"
- 	"      |          ^~~\n"
- 	"      |          |\n"
- 	"      |          (1) from here... ->-+\n"
- 	"      |                              |\n"
- 	"      |                              |\n"
- 	"      |+-----------------------------+\n"
- 	"    4 ||LHS      RHS\n"
- 	"    5 ||LHS      RHS\n"
- 	"      ||~~~       \n"
- 	"      |||\n"
- 	"      |+(2) ...to here\n"));
-   }
- 
-   /* Big gap, increasing line number.  */
-   {
-     /* LHS -> RHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (3, 1, 3),
-        t.get_line_and_columns (97, 10, 12),
-        ("  events 1-2\n"
- 	"FILENAME:3:1:\n"
- 	"    3 | LHS      RHS\n"
- 	"      | ^~~\n"
- 	"      | |\n"
- 	"      | (1) from here... ->-+\n"
- 	"      |                     |\n"
- 	"......\n"
- 	"      |                     |\n"
- 	"      |+--------------------+\n"
- 	"   97 ||LHS      RHS\n"
- 	"      ||         ~~~\n"
- 	"      ||         |\n"
- 	"      |+-------->(2) ...to here\n"));
- 
-     /*  RHS -> LHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (3, 10, 12),
-        t.get_line_and_columns (97, 1, 3),
-        ("  events 1-2\n"
- 	"FILENAME:3:10:\n"
- 	"    3 | LHS      RHS\n"
- 	"      |          ^~~\n"
- 	"      |          |\n"
- 	"      |          (1) from here... ->-+\n"
- 	"      |                              |\n"
- 	"......\n"
- 	"      |                              |\n"
- 	"      |+-----------------------------+\n"
- 	"   97 ||LHS      RHS\n"
- 	"      ||~~~       \n"
- 	"      |||\n"
- 	"      |+(2) ...to here\n"));
-   }
- 
-   /* Big gap, decreasing line number.  */
-   {
-     /* LHS -> RHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (97, 1, 3),
-        t.get_line_and_columns (3, 10, 12),
-        ("  event 1\n"
- 	"FILENAME:97:1:\n"
- 	"   97 | LHS      RHS\n"
- 	"      | ^~~\n"
- 	"      | |\n"
- 	"      | (1) from here... ->-+\n"
- 	"      |                     |\n"
- 	"  event 2\n"
- 	"      |                     |\n"
- 	"      |+--------------------+\n"
- 	"    3 ||LHS      RHS\n"
- 	"      ||         ^~~\n"
- 	"      ||         |\n"
- 	"      |+-------->(2) ...to here\n"));
- 
-     /*  RHS -> LHS.  */
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (97, 10, 12),
-        t.get_line_and_columns (3, 1, 3),
-        ("  event 1\n"
- 	"FILENAME:97:10:\n"
- 	"   97 | LHS      RHS\n"
- 	"      |          ^~~\n"
- 	"      |          |\n"
- 	"      |          (1) from here... ->-+\n"
- 	"      |                              |\n"
- 	"  event 2\n"
- 	"      |                              |\n"
- 	"      |+-----------------------------+\n"
- 	"    3 ||LHS      RHS\n"
- 	"      ||^~~\n"
- 	"      |||\n"
- 	"      |+(2) ...to here\n"));
-   }
- 
-   /* Unknown src.  */
-   {
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (UNKNOWN_LOCATION,
-        t.get_line_and_columns (3, 10, 12),
-        ("  event 1\n"
- 	" (1): from here...\n"
- 	"  event 2\n"
- 	"FILENAME:3:10:\n"
- 	"    3 | LHS      RHS\n"
- 	"      |          ^~~\n"
- 	"      |          |\n"
- 	"      |+-------->(2) ...to here\n"));
-   }
- 
-   /* Unknown dst.  */
-   {
-     ASSERT_CFG_EDGE_PATH_STREQ
-       (t.get_line_and_columns (3, 1, 3),
-        UNKNOWN_LOCATION,
-        ("  event 1\n"
- 	"FILENAME:3:1:\n"
- 	"    3 | LHS      RHS\n"
- 	"      | ^~~\n"
- 	"      | |\n"
- 	"      | (1) from here... ->-+\n"
- 	"      |                     |\n"
- 	"  event 2\n"
- 	"FILENAME:\n"
- 	" (2): ...to here\n"));
-   }
- }
- 
- /* Another complex example, adapted from data-model-20.c.  */
- 
- static void
- test_control_flow_5 (const line_table_case &case_,
- 		     pretty_printer *event_pp)
- {
-   /* Create a tempfile and write some text to it.
-      ...000000000111111111122222222223333333333444444444455555555556666666666.
-      ...123456789012345678901234567890123456789012345678901234567890123456789.  */
-   const char *content
-     = ("  if ((arr = (struct foo **)malloc(n * sizeof(struct foo *))) == NULL)\n"
-        "    return NULL;\n" /* <------------------------- line 2.  */
-        "\n" /* <----------------------------------------- line 3.  */
-        "  for (i = 0; i < n; i++) {\n" /* <-------------- line 4.  */
-        "    if ((arr[i] = (struct foo *)malloc(sizeof(struct foo))) == NULL) {\n");
- 
-   control_flow_test t (SELFTEST_LOCATION, case_, content);
- 
-   test_diagnostic_path path (event_pp);
-   /* (1) */
-   path.add_event (t.get_line_and_column (1, 6), nullptr, 0,
- 		  "following %qs branch (when %qs is non-NULL)...",
- 		  "false", "arr");
-   path.connect_to_next_event ();
- 
-   /* (2) */
-   path.add_event (t.get_line_and_columns (4, 8, 10, 12), nullptr, 0,
- 		  "...to here");
- 
-   /* (3) */
-   path.add_event (t.get_line_and_columns (4, 15, 17, 19), nullptr, 0,
- 		  "following %qs branch (when %qs)...",
- 		  "true", "i < n");
-   path.connect_to_next_event ();
- 
-   /* (4) */
-   path.add_event (t.get_line_and_column (5, 13), nullptr, 0,
- 		  "...to here");
- 
-   /* (5) */
-   path.add_event (t.get_line_and_columns (5, 33, 58), nullptr, 0,
- 		  "allocated here");
- 
-   if (!path_events_have_column_data_p (path))
-     return;
- 
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     dc.m_source_printing.show_event_links_p = true;
-     dc.m_source_printing.show_line_numbers_p = true;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-5\n"
-        "FILENAME:1:6:\n"
-        "    1 |   if ((arr = (struct foo **)malloc(n * sizeof(struct foo *))) == NULL)\n"
-        "      |      ^\n"
-        "      |      |\n"
-        "      |      (1) following `false' branch (when `arr' is non-NULL)... ->-+\n"
-        "      |                                                                  |\n"
-        "......\n"
-        "      |                                                                  |\n"
-        "      |+-----------------------------------------------------------------+\n"
-        "    4 ||  for (i = 0; i < n; i++) {\n"
-        "      ||       ~~~~~  ~~~~~\n"
-        "      ||         |      |\n"
-        "      ||         |      (3) following `true' branch (when `i < n')... ->-+\n"
-        "      |+-------->(2) ...to here                                          |\n"
-        "      |                                                                  |\n"
-        "      |                                                                  |\n"
-        "      |+-----------------------------------------------------------------+\n"
-        "    5 ||    if ((arr[i] = (struct foo *)malloc(sizeof(struct foo))) == NULL) {\n"
-        "      ||            ~                   ~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
-        "      ||            |                   |\n"
-        "      |+----------->(4) ...to here      (5) allocated here\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
- }
- 
- /* Another complex example, adapted from loop-3.c.  */
- 
- static void
- test_control_flow_6 (const line_table_case &case_,
- 		     pretty_printer *event_pp)
- {
-   /* Create a tempfile and write some text to it.
-      ...000000000111111111122222222223333333.
-      ...123456789012345678901234567890123456.  */
-   const char *content
-     = ("#include <stdlib.h>\n" /* <------------------ line 1.  */
-        "\n" /* <------------------------------------- line 2.  */
-        "void test(int c)\n" /* <--------------------- line 3.  */
-        "{\n" /* <------------------------------------ line 4.  */
-        "  int i;\n" /* <----------------------------- line 5.  */
-        "  char *buffer = (char*)malloc(256);\n" /* <- line 6.  */
-        "\n" /* <------------------------------------- line 7.  */
-        "  for (i=0; i<255; i++) {\n" /* <------------ line 8.  */
-        "    buffer[i] = c;\n" /* <------------------- line 9.  */
-        "\n" /* <------------------------------------- line 10.  */
-        "    free(buffer);\n" /* <-------------------- line 11.  */
-        "  }\n"); /* <-------------------------------- line 12.  */
- 
-   control_flow_test t (SELFTEST_LOCATION, case_, content);
- 
-   test_diagnostic_path path (event_pp);
-   /* (1) */
-   path.add_event (t.get_line_and_columns (6, 25, 35), nullptr, 0,
- 		  "allocated here");
- 
-   /* (2) */
-   path.add_event (t.get_line_and_columns (8, 13, 14, 17), nullptr, 0,
- 		  "following %qs branch (when %qs)...",
- 		  "true", "i <= 254");
-   path.connect_to_next_event ();
- 
-   /* (3) */
-   path.add_event (t.get_line_and_columns (9, 5, 15, 17), nullptr, 0,
- 		  "...to here");
- 
-   /* (4) */
-   path.add_event (t.get_line_and_columns (8, 13, 14, 17), nullptr, 0,
- 		  "following %qs branch (when %qs)...",
- 		  "true", "i <= 254");
-   path.connect_to_next_event ();
- 
-   /* (5) */
-   path.add_event (t.get_line_and_columns (9, 5, 15, 17), nullptr, 0,
- 		  "...to here");
- 
-   if (!path_events_have_column_data_p (path))
-     return;
- 
-   {
-     test_diagnostic_context dc;
-     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
-     dc.m_source_printing.show_event_links_p = true;
-     dc.m_source_printing.show_line_numbers_p = true;
-     diagnostic_text_output_format text_output (dc);
-     path_print_policy policy (text_output);
-     path_summary summary (policy, *event_pp, path, true);
-     print_path_summary_as_text (summary, text_output, false);
-     ASSERT_STREQ
-       ("  events 1-3\n"
-        "FILENAME:6:25:\n"
-        "    6 |   char *buffer = (char*)malloc(256);\n"
-        "      |                         ^~~~~~~~~~~\n"
-        "      |                         |\n"
-        "      |                         (1) allocated here\n"
-        "    7 | \n"
-        "    8 |   for (i=0; i<255; i++) {\n"
-        "      |             ~~~~~        \n"
-        "      |              |\n"
-        "      |              (2) following `true' branch (when `i <= 254')... ->-+\n"
-        "      |                                                                  |\n"
-        "      |                                                                  |\n"
-        "      |+-----------------------------------------------------------------+\n"
-        "    9 ||    buffer[i] = c;\n"
-        "      ||    ~~~~~~~~~~~~~        \n"
-        "      ||              |\n"
-        "      |+------------->(3) ...to here\n"
-        "  events 4-5\n"
-        "    8 |   for (i=0; i<255; i++) {\n"
-        "      |             ~^~~~\n"
-        "      |              |\n"
-        "      |              (4) following `true' branch (when `i <= 254')... ->-+\n"
-        "      |                                                                  |\n"
-        "      |                                                                  |\n"
-        "      |+-----------------------------------------------------------------+\n"
-        "    9 ||    buffer[i] = c;\n"
-        "      ||    ~~~~~~~~~~~~~\n"
-        "      ||              |\n"
-        "      |+------------->(5) ...to here\n",
-        pp_formatted_text (text_output.get_printer ()));
-   }
- }
- 
- static void
- control_flow_tests (const line_table_case &case_)
- {
-   pretty_printer pp;
-   pp_show_color (&pp) = false;
- 
-   test_control_flow_1 (case_, &pp);
-   test_control_flow_2 (case_, &pp);
-   test_control_flow_3 (case_, &pp);
-   test_control_flow_4 (case_, &pp);
-   test_control_flow_5 (case_, &pp);
-   test_control_flow_6 (case_, &pp);
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- diagnostic_path_output_cc_tests ()
- {
-   pretty_printer pp;
-   pp_show_color (&pp) = false;
- 
-   auto_fix_quotes fix_quotes;
-   test_empty_path (&pp);
-   test_intraprocedural_path (&pp);
-   test_interprocedural_path_1 (&pp);
-   test_interprocedural_path_2 (&pp);
-   test_recursion (&pp);
-   for_each_line_table_case (control_flow_tests);
- }
- 
- } // namespace selftest
- 
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic pop
- #endif
- 
- #endif /* #if CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-path.cc gcc-16-20250727/gcc/diagnostic-path.cc
*** gcc-16-20250720/gcc/diagnostic-path.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-path.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,230 ****
- /* Paths through the code associated with a diagnostic.
-    Copyright (C) 2019-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #include "config.h"
- #define INCLUDE_ALGORITHM
- #define INCLUDE_MAP
- #define INCLUDE_STRING
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "diagnostic.h"
- #include "diagnostic-path.h"
- #include "diagnostic-state-graphs.h"
- 
- /* Disable warnings about missing quoting in GCC diagnostics for the print
-    calls below.  */
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic push
- #  pragma GCC diagnostic ignored "-Wformat-diag"
- #endif
- 
- /* class diagnostic_event.  */
- 
- /* struct diagnostic_event::meaning.  */
- 
- void
- diagnostic_event::meaning::dump_to_pp (pretty_printer *pp) const
- {
-   bool need_comma = false;
-   pp_character (pp, '{');
-   if (const char *verb_str = maybe_get_verb_str (m_verb))
-     {
-       pp_printf (pp, "verb: %qs", verb_str);
-       need_comma = true;
-     }
-   if (const char *noun_str = maybe_get_noun_str (m_noun))
-     {
-       if (need_comma)
- 	pp_string (pp, ", ");
-       pp_printf (pp, "noun: %qs", noun_str);
-       need_comma = true;
-     }
-   if (const char *property_str = maybe_get_property_str (m_property))
-     {
-       if (need_comma)
- 	pp_string (pp, ", ");
-       pp_printf (pp, "property: %qs", property_str);
-       need_comma = true;
-     }
-   pp_character (pp, '}');
- }
- 
- /* Get a string (or nullptr) for V suitable for use within a SARIF
-    threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
- 
- const char *
- diagnostic_event::meaning::maybe_get_verb_str (enum verb v)
- {
-   switch (v)
-     {
-     default:
-       gcc_unreachable ();
-     case verb::unknown:
-       return nullptr;
-     case verb::acquire:
-       return "acquire";
-     case verb::release:
-       return "release";
-     case verb::enter:
-       return "enter";
-     case verb::exit:
-       return "exit";
-     case verb::call:
-       return "call";
-     case verb::return_:
-       return "return";
-     case verb::branch:
-       return "branch";
-     case verb::danger:
-       return "danger";
-     }
- }
- 
- /* Get a string (or nullptr) for N suitable for use within a SARIF
-    threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
- 
- const char *
- diagnostic_event::meaning::maybe_get_noun_str (enum noun n)
- {
-   switch (n)
-     {
-     default:
-       gcc_unreachable ();
-     case noun::unknown:
-       return nullptr;
-     case noun::taint:
-       return "taint";
-     case noun::sensitive:
-       return "sensitive";
-     case noun::function:
-       return "function";
-     case noun::lock:
-       return "lock";
-     case noun::memory:
-       return "memory";
-     case noun::resource:
-       return "resource";
-     }
- }
- 
- /* Get a string (or nullptr) for P suitable for use within a SARIF
-    threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
- 
- const char *
- diagnostic_event::meaning::maybe_get_property_str (enum property p)
- {
-   switch (p)
-     {
-     default:
-       gcc_unreachable ();
-     case property::unknown:
-       return nullptr;
-     case property::true_:
-       return "true";
-     case property::false_:
-       return "false";
-     }
- }
- 
- /* Generate a label_text containing the description of this event
-    (for debugging/logging purposes).  */
- 
- label_text
- diagnostic_event::get_desc (pretty_printer &ref_pp) const
- {
-   auto pp = ref_pp.clone ();
-   pp_show_color (pp.get ()) = false;
-   print_desc (*pp.get ());
-   return label_text::take (xstrdup (pp_formatted_text (pp.get ())));
- }
- 
- // Base implementation of diagnostic_event::maybe_make_diagnostic_state_graph
- 
- std::unique_ptr<diagnostics::digraphs::digraph>
- diagnostic_event::maybe_make_diagnostic_state_graph (bool) const
- {
-   // Don't attempt to make a state graph:
-   return nullptr;
- }
- 
- /* class diagnostic_path.  */
- 
- /* Subroutine of diagnostic_path::interprocedural_p.
-    Look for the first event in this path that is within a function
-    i.e. has a non-null logical location for which function_p is true.
-    If found, write its index to *OUT_IDX and return true.
-    Otherwise return false.  */
- 
- bool
- diagnostic_path::get_first_event_in_a_function (unsigned *out_idx) const
- {
-   const unsigned num = num_events ();
-   for (unsigned i = 0; i < num; i++)
-     {
-       const diagnostic_event &event = get_event (i);
-       if (logical_location logical_loc = event.get_logical_location ())
- 	if (m_logical_loc_mgr.function_p (logical_loc))
- 	  {
- 	    *out_idx = i;
- 	    return true;
- 	  }
-     }
-   return false;
- }
- 
- /* Return true if the events in this path involve more than one
-    function, or false if it is purely intraprocedural.  */
- 
- bool
- diagnostic_path::interprocedural_p () const
- {
-   /* Ignore leading events that are outside of any function.  */
-   unsigned first_fn_event_idx;
-   if (!get_first_event_in_a_function (&first_fn_event_idx))
-     return false;
- 
-   const diagnostic_event &first_fn_event = get_event (first_fn_event_idx);
-   int first_fn_stack_depth = first_fn_event.get_stack_depth ();
- 
-   const unsigned num = num_events ();
-   for (unsigned i = first_fn_event_idx + 1; i < num; i++)
-     {
-       if (!same_function_p (first_fn_event_idx, i))
- 	return true;
-       if (get_event (i).get_stack_depth () != first_fn_stack_depth)
- 	return true;
-     }
-   return false;
- }
- 
- /* Print PATH by emitting a dummy "note" associated with it.  */
- 
- DEBUG_FUNCTION
- void debug (diagnostic_path *path)
- {
-   rich_location richloc (line_table, UNKNOWN_LOCATION);
-   richloc.set_path (path);
-   inform (&richloc, "debug path");
- }
- 
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic pop
- #endif
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-path.h gcc-16-20250727/gcc/diagnostic-path.h
*** gcc-16-20250720/gcc/diagnostic-path.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-path.h	Thu Jan  1 00:00:00 1970
***************
*** 1,244 ****
- /* Paths through the code associated with a diagnostic.
-    Copyright (C) 2019-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_PATH_H
- #define GCC_DIAGNOSTIC_PATH_H
- 
- #include "diagnostic.h" /* for ATTRIBUTE_GCC_DIAG.  */
- #include "diagnostic-event-id.h"
- #include "logical-location.h"
- 
- namespace xml { class document; }
- 
- class sarif_builder;
- class sarif_object;
- 
- namespace diagnostics {
- namespace digraphs {
-   class digraph;
- } // namespace digraphs
- } //namespace diagnostics
- 
- /* A diagnostic_path is an optional additional piece of metadata associated
-    with a diagnostic (via its rich_location).
- 
-    It describes a sequence of events predicted by the compiler that
-    lead to the problem occurring, with their locations in the user's source,
-    and text descriptions.
- 
-    For example, the following error has a 3-event path:
- 
-      test.c: In function 'demo':
-      test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which
-        requires a non-NULL parameter
-         29 |     PyList_Append(list, item);
-            |     ^~~~~~~~~~~~~~~~~~~~~~~~~
-        'demo': events 1-3
-         25 |   list = PyList_New(0);
-            |          ^~~~~~~~~~~~~
-            |          |
-            |          (1) when 'PyList_New' fails, returning NULL
-         26 |
-         27 |   for (i = 0; i < count; i++) {
-            |   ~~~
-            |   |
-            |   (2) when 'i < count'
-         28 |     item = PyLong_FromLong(random());
-         29 |     PyList_Append(list, item);
-            |     ~~~~~~~~~~~~~~~~~~~~~~~~~
-            |     |
-            |     (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
- 
-     The diagnostic-printing code has consolidated the path into a single
-     run of events, since all the events are near each other and within the same
-     function; more complicated examples (such as interprocedural paths)
-     might be printed as multiple runs of events.  */
- 
- /* Abstract base classes, describing events within a path, and the paths
-    themselves.  */
- 
- /* One event within a diagnostic_path.  */
- 
- class diagnostic_event
- {
-  public:
-   /* Enums for giving a sense of what this event means.
-      Roughly corresponds to SARIF v2.1.0 section 3.38.8.  */
-   enum class verb
-   {
-     unknown,
- 
-     acquire,
-     release,
-     enter,
-     exit,
-     call,
-     return_,
-     branch,
- 
-     danger
-   };
-   enum class noun
-   {
-     unknown,
- 
-     taint,
-     sensitive, // this one isn't in SARIF v2.1.0; filed as https://github.com/oasis-tcs/sarif-spec/issues/530
-     function,
-     lock,
-     memory,
-     resource
-   };
-   enum class property
-   {
-     unknown,
- 
-     true_,
-     false_
-   };
-   /* A bundle of such enums, allowing for descriptions of the meaning of
-      an event, such as
-      - "acquire memory": meaning (verb::acquire, noun::memory)
-      - "take true branch"": meaning (verb::branch, property::true)
-      - "return from function": meaning (verb::return, noun::function)
-      etc, as per SARIF's threadFlowLocation "kinds" property
-      (SARIF v2.1.0 section 3.38.8).  */
-   struct meaning
-   {
-     meaning ()
-     : m_verb (verb::unknown),
-       m_noun (noun::unknown),
-       m_property (property::unknown)
-     {
-     }
-     meaning (enum verb verb, enum noun noun)
-     : m_verb (verb), m_noun (noun), m_property (property::unknown)
-     {
-     }
-     meaning (enum verb verb, enum property property)
-     : m_verb (verb), m_noun (noun::unknown), m_property (property)
-     {
-     }
- 
-     void dump_to_pp (pretty_printer *pp) const;
- 
-     static const char *maybe_get_verb_str (enum verb);
-     static const char *maybe_get_noun_str (enum noun);
-     static const char *maybe_get_property_str (enum property);
- 
-     enum verb m_verb;
-     enum noun m_noun;
-     enum property m_property;
-   };
- 
-   virtual ~diagnostic_event () {}
- 
-   virtual location_t get_location () const = 0;
- 
-   /* Stack depth, so that consumers can visualize the interprocedural
-      calls, returns, and frame nesting.  */
-   virtual int get_stack_depth () const = 0;
- 
-   /* Print a localized (and possibly colorized) description of this event.  */
-   virtual void print_desc (pretty_printer &pp) const = 0;
- 
-   /* Get a logical location for this event, or null if there is none.  */
-   virtual logical_location get_logical_location () const = 0;
- 
-   virtual meaning get_meaning () const = 0;
- 
-   /* True iff we should draw a line connecting this event to the
-      next event (e.g. to highlight control flow).  */
-   virtual bool connect_to_next_event_p () const = 0;
- 
-   virtual diagnostic_thread_id_t get_thread_id () const = 0;
- 
-   /* Hook for SARIF output to allow for adding diagnostic-specific
-      properties to the threadFlowLocation object's property bag.  */
-   virtual void
-   maybe_add_sarif_properties (sarif_builder &,
- 			      sarif_object &/*thread_flow_loc_obj*/) const
-   {
-   }
- 
-   /* Hook for capturing state at this event, potentially for visualizing
-      in HTML output, or for adding to SARIF.  */
-   virtual std::unique_ptr<diagnostics::digraphs::digraph>
-   maybe_make_diagnostic_state_graph (bool debug) const;
- 
-   label_text get_desc (pretty_printer &ref_pp) const;
- };
- 
- /* Abstract base class representing a thread of execution within
-    a diagnostic_path.
-    Each diagnostic_event is associated with one thread.
-    Typically there is just one thread per diagnostic_path. */
- 
- class diagnostic_thread
- {
- public:
-   virtual ~diagnostic_thread () {}
-   virtual label_text get_name (bool can_colorize) const = 0;
- };
- 
- /* Abstract base class for getting at a sequence of events.  */
- 
- class diagnostic_path
- {
-  public:
-   virtual ~diagnostic_path () {}
-   virtual unsigned num_events () const = 0;
-   virtual const diagnostic_event & get_event (int idx) const = 0;
-   virtual unsigned num_threads () const = 0;
-   virtual const diagnostic_thread &
-   get_thread (diagnostic_thread_id_t) const = 0;
- 
-   /* Return true iff the two events are both within the same function,
-      or both outside of any function.  */
-   virtual bool
-   same_function_p (int event_idx_a,
- 		   int event_idx_b) const = 0;
- 
-   bool interprocedural_p () const;
-   bool multithreaded_p () const;
- 
-   const logical_location_manager &get_logical_location_manager () const
-   {
-     return m_logical_loc_mgr;
-   }
- 
- protected:
-   diagnostic_path (const logical_location_manager &logical_loc_mgr)
-   : m_logical_loc_mgr (logical_loc_mgr)
-   {
-   }
- 
- private:
-   bool get_first_event_in_a_function (unsigned *out_idx) const;
- 
-   const logical_location_manager &m_logical_loc_mgr;
- };
- 
- /* Concrete subclasses of the above can be found in
-    simple-diagnostic-path.h.  */
- 
- extern void debug (diagnostic_path *path);
- 
- #endif /* ! GCC_DIAGNOSTIC_PATH_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-show-locus.cc gcc-16-20250727/gcc/diagnostic-show-locus.cc
*** gcc-16-20250720/gcc/diagnostic-show-locus.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-show-locus.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,7018 ****
- /* Diagnostic subroutines for printing source-code
-    Copyright (C) 1999-2025 Free Software Foundation, Inc.
-    Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #include "config.h"
- #define INCLUDE_MAP
- #define INCLUDE_STRING
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "version.h"
- #include "demangle.h"
- #include "intl.h"
- #include "backtrace.h"
- #include "diagnostic.h"
- #include "diagnostic-color.h"
- #include "gcc-rich-location.h"
- #include "text-range-label.h"
- #include "selftest.h"
- #include "selftest-diagnostic.h"
- #include "selftest-diagnostic-show-locus.h"
- #include "cpplib.h"
- #include "text-art/types.h"
- #include "text-art/theme.h"
- #include "diagnostic-label-effects.h"
- #include "xml.h"
- #include "xml-printer.h"
- 
- #ifdef HAVE_TERMIOS_H
- # include <termios.h>
- #endif
- 
- #ifdef GWINSZ_IN_SYS_IOCTL
- # include <sys/ioctl.h>
- #endif
- 
- /* Disable warnings about quoting issues in the pp_xxx calls below
-    that (intentionally) don't follow GCC diagnostic conventions.  */
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic push
- #  pragma GCC diagnostic ignored "-Wformat-diag"
- #endif
- 
- /* Classes for rendering source code and diagnostics, within an
-    anonymous namespace.
-    The work is done by "class layout", which embeds and uses
-    "class colorizer" and "class layout_range" to get things done.  */
- 
- namespace {
- 
- /* The state at a given point of the source code, assuming that we're
-    in a range: which range are we in, and whether we should draw a caret at
-    this point.  */
- 
- struct point_state
- {
-   int range_idx;
-   bool draw_caret_p;
- };
- 
- /* A class to inject colorization codes when printing the diagnostic locus
-    as text.
- 
-    It has one kind of colorization for each of:
-      - normal text
-      - range 0 (the "primary location")
-      - range 1
-      - range 2
- 
-    The class caches the lookup of the color codes for the above.
- 
-    The class also has responsibility for tracking which of the above is
-    active, filtering out unnecessary changes.  This allows
-    layout_printer::print_source_line and layout_printer::print_annotation_line
-    to simply request a colorization code for *every* character they print,
-    via this class, and have the filtering be done for them here.  */
- 
- class colorizer
- {
-  public:
-   colorizer (pretty_printer &pp,
- 	     const rich_location &richloc,
- 	     diagnostic_t diagnostic_kind);
-   ~colorizer ();
- 
-   void set_range (int range_idx)
-   {
-     /* If we have a specific highlight color for the range, use it.  */
-     if (pp_show_highlight_colors (&m_pp))
-       {
- 	const location_range *const loc_range = m_richloc.get_range (range_idx);
- 	if (loc_range->m_highlight_color)
- 	  {
- 	    set_named_color (loc_range->m_highlight_color);
- 	    return;
- 	  }
-       }
- 
-     /* Otherwise, we emphasize the primary location, then alternate between
-        two colors for the secondary locations.
-        But if we're printing a run of events in a diagnostic path, that
-        makes no sense, so print all of them with the same colorization.  */
-     if (m_diagnostic_kind == DK_DIAGNOSTIC_PATH)
-       set_state (0);
-     else
-       set_state (range_idx);
-   }
-   void set_cfg_edge () { set_state (0); }
-   void set_normal_text () { set_state (STATE_NORMAL_TEXT); }
-   void set_fixit_insert () { set_state (STATE_FIXIT_INSERT); }
-   void set_fixit_delete () { set_state (STATE_FIXIT_DELETE); }
-   void set_named_color (const char *color);
- 
-  private:
-   void set_state (int state);
-   void begin_state (int state);
-   void finish_state (int state);
-   const char *get_color_by_name (const char *);
- 
-  private:
-   static const int STATE_NORMAL_TEXT = -1;
-   static const int STATE_FIXIT_INSERT  = -2;
-   static const int STATE_FIXIT_DELETE  = -3;
-   static const int STATE_NAMED_COLOR  = -4;
- 
-   pretty_printer &m_pp;
-   const rich_location &m_richloc;
-   diagnostic_t m_diagnostic_kind;
-   int m_current_state;
-   const char *m_range1;
-   const char *m_range2;
-   const char *m_fixit_insert;
-   const char *m_fixit_delete;
-   const char *m_stop_color;
-   std::string m_current_named_color;
- };
- 
- /* In order to handle multibyte sources properly, all of this logic needs to be
-    aware of the distinction between the number of bytes and the number of
-    display columns occupied by a character, which are not the same for non-ASCII
-    characters.  For example, the Unicode pi symbol, U+03C0, is encoded in UTF-8
-    as "\xcf\x80", and thus occupies 2 bytes of space while only occupying 1
-    display column when it is output.  A typical emoji, such as U+1F602 (in
-    UTF-8, "\xf0\x9f\x98\x82"), requires 4 bytes and has a display width of 2.
- 
-    The below example line, which is also used for selftests below, shows how the
-    display column and byte column are related:
- 
-      0000000001111111111222222   display
-      1234567890123456789012345   columns
-      SS_foo = P_bar.SS_fieldP;
-      0000000111111111222222223   byte
-      1356789012456789134567891   columns
- 
-    Here SS represents the two display columns for the U+1F602 emoji, and P
-    represents the one display column for the U+03C0 pi symbol.  As an example, a
-    diagnostic pointing to the final P on this line is at byte column 29 and
-    display column 24.  This reflects the fact that the three extended characters
-    before the final P occupy cumulatively 5 more bytes than they do display
-    columns (a difference of 2 for each of the two SSs, and one for the other P).
- 
-    One or the other of the two column units is more useful depending on the
-    context.  For instance, in order to output the caret at the correct location,
-    we need to count display columns; in order to colorize a source line, we need
-    to count the bytes.  All locations are provided to us as byte counts, which
-    we augment with the display column on demand so that it can be used when
-    needed.  This is not the most efficient way to do things since it requires
-    looping over the whole line each time, but it should be fine for the purpose
-    of outputting diagnostics.
- 
-    In order to keep straight which units (byte or display) are in use at a
-    given time, the following enum lets us specify that explicitly.  */
- 
- enum column_unit {
-   /* Measured in raw bytes.  */
-   CU_BYTES = 0,
- 
-   /* Measured in display units.  */
-   CU_DISPLAY_COLS,
- 
-   /* For arrays indexed by column_unit.  */
-   CU_NUM_UNITS
- };
- 
- /* Utility class to augment an exploc with the corresponding display column.  */
- 
- class exploc_with_display_col : public expanded_location
- {
-  public:
-   exploc_with_display_col (file_cache &fc,
- 			   const expanded_location &exploc,
- 			   const cpp_char_column_policy &policy,
- 			   enum location_aspect aspect)
-   : expanded_location (exploc),
-     m_display_col (location_compute_display_column (fc, exploc, policy))
-   {
-     if (exploc.column > 0)
-       {
- 	/* m_display_col is now the final column of the byte.
- 	   If escaping has happened, we may want the first column instead.  */
- 	if (aspect != LOCATION_ASPECT_FINISH)
- 	  {
- 	    expanded_location prev_exploc (exploc);
- 	    prev_exploc.column--;
- 	    int prev_display_col
- 	      = (location_compute_display_column (fc, prev_exploc, policy));
- 	    m_display_col = prev_display_col + 1;
- 	  }
-       }
-   }
- 
-   int m_display_col;
- };
- 
- 
- /* A point within a layout_range; similar to an exploc_with_display_col,
-    but after filtering on file.  */
- 
- class layout_point
- {
-  public:
-   layout_point (const exploc_with_display_col &exploc)
-     : m_line (exploc.line)
-   {
-     m_columns[CU_BYTES] = exploc.column;
-     m_columns[CU_DISPLAY_COLS] = exploc.m_display_col;
-   }
- 
-   linenum_type m_line;
-   int m_columns[CU_NUM_UNITS];
- };
- 
- /* A class for use by "class layout" below: a filtered location_range.  */
- 
- class layout_range
- {
-  public:
-   layout_range (const exploc_with_display_col &start_exploc,
- 		const exploc_with_display_col &finish_exploc,
- 		enum range_display_kind range_display_kind,
- 		const exploc_with_display_col &caret_exploc,
- 		unsigned original_idx,
- 		const range_label *label);
- 
-   bool contains_point (linenum_type row, int column,
- 		       enum column_unit col_unit) const;
-   bool intersects_line_p (linenum_type row) const;
- 
-   bool has_in_edge () const;
-   bool has_out_edge () const;
- 
-   layout_point m_start;
-   layout_point m_finish;
-   enum range_display_kind m_range_display_kind;
-   layout_point m_caret;
-   unsigned m_original_idx;
-   const range_label *m_label;
- };
- 
- /* A struct for use by layout::print_source_line for telling
-    layout::print_annotation_line the extents of the source line that
-    it printed, so that underlines can be clipped appropriately.  Units
-    are 1-based display columns.  */
- 
- struct line_bounds
- {
-   int m_first_non_ws_disp_col;
-   int m_last_non_ws_disp_col;
- 
-   line_bounds ()
-   {
-     m_first_non_ws_disp_col = INT_MAX;
-     m_last_non_ws_disp_col = 0;
-   }
- };
- 
- /* A range of contiguous source lines within a layout (e.g. "lines 5-10"
-    or "line 23").  During the layout ctor, layout::calculate_line_spans
-    splits the pertinent source lines into a list of disjoint line_span
-    instances (e.g. lines 5-10, lines 15-20, line 23).  */
- 
- class line_span
- {
- public:
-   line_span (linenum_type first_line, linenum_type last_line)
-     : m_first_line (first_line), m_last_line (last_line)
-   {
-     gcc_assert (first_line <= last_line);
-   }
-   linenum_type get_first_line () const { return m_first_line; }
-   linenum_type get_last_line () const { return m_last_line; }
- 
-   bool contains_line_p (linenum_type line) const
-   {
-     return line >= m_first_line && line <= m_last_line;
-   }
- 
-   static int comparator (const void *p1, const void *p2)
-   {
-     const line_span *ls1 = (const line_span *)p1;
-     const line_span *ls2 = (const line_span *)p2;
-     int first_line_cmp = compare (ls1->m_first_line, ls2->m_first_line);
-     if (first_line_cmp)
-       return first_line_cmp;
-     return compare (ls1->m_last_line, ls2->m_last_line);
-   }
- 
-   linenum_type m_first_line;
-   linenum_type m_last_line;
- };
- 
- #if CHECKING_P
- 
- /* Selftests for line_span.  */
- 
- static void
- test_line_span ()
- {
-   line_span line_one (1, 1);
-   ASSERT_EQ (1, line_one.get_first_line ());
-   ASSERT_EQ (1, line_one.get_last_line ());
-   ASSERT_FALSE (line_one.contains_line_p (0));
-   ASSERT_TRUE (line_one.contains_line_p (1));
-   ASSERT_FALSE (line_one.contains_line_p (2));
- 
-   line_span lines_1_to_3 (1, 3);
-   ASSERT_EQ (1, lines_1_to_3.get_first_line ());
-   ASSERT_EQ (3, lines_1_to_3.get_last_line ());
-   ASSERT_TRUE (lines_1_to_3.contains_line_p (1));
-   ASSERT_TRUE (lines_1_to_3.contains_line_p (3));
- 
-   ASSERT_EQ (0, line_span::comparator (&line_one, &line_one));
-   ASSERT_GT (line_span::comparator (&lines_1_to_3, &line_one), 0);
-   ASSERT_LT (line_span::comparator (&line_one, &lines_1_to_3), 0);
- 
-   /* A linenum > 2^31.  */
-   const linenum_type LARGEST_LINE = 0xffffffff;
-   line_span largest_line (LARGEST_LINE, LARGEST_LINE);
-   ASSERT_EQ (LARGEST_LINE, largest_line.get_first_line ());
-   ASSERT_EQ (LARGEST_LINE, largest_line.get_last_line ());
- 
-   ASSERT_GT (line_span::comparator (&largest_line, &line_one), 0);
-   ASSERT_LT (line_span::comparator (&line_one, &largest_line), 0);
- }
- 
- #endif /* #if CHECKING_P */
- 
- /* A bundle of information containing how to print unicode
-    characters and bytes when quoting source code.
- 
-    Provides a unified place to support escaping some subset
-    of characters to some format.
- 
-    Extends char_column_policy; printing is split out to avoid
-    libcpp having to know about pretty_printer.  */
- 
- struct char_display_policy : public cpp_char_column_policy
- {
-  public:
-   char_display_policy (int tabstop,
- 		       int (*width_cb) (cppchar_t c),
- 		       void (*print_text_cb) (to_text &sink,
- 					      const cpp_decoded_char &cp),
- 		       void (*print_html_cb) (to_html &sink,
- 					      const cpp_decoded_char &cp))
-   : cpp_char_column_policy (tabstop, width_cb),
-     m_print_text_cb (print_text_cb),
-     m_print_html_cb (print_html_cb)
-   {
-   }
- 
-   void (*m_print_text_cb) (to_text &sink,
- 			   const cpp_decoded_char &cp);
-   void (*m_print_html_cb) (to_html &sink,
- 			   const cpp_decoded_char &cp);
- };
- 
- template <typename Sink> class layout_printer;
- 
- } // anonymous namespace
- 
- /* This code is written generically to write either:
-    - text, to a pretty_printer, potentially with colorization codes, or
-    - html, to an xml::printer, with nested HTML tags.
- 
-    This is handled via a "Sink" template, which is either to_text
-    or to_html.  */
- 
- /* Writing text output.  */
- 
- struct to_text
- {
-   friend class layout_printer<to_text>;
- 
-   // This is a RAII class for HTML, but is a no-op for text.
-   struct auto_check_tag_nesting
-   {
-     auto_check_tag_nesting (to_text &) {}
-   };
- 
-   to_text (pretty_printer &pp,
- 	   colorizer &colorizer)
-   : m_pp (pp),
-     m_colorizer (&colorizer)
-   {
-     m_saved_rule = pp_prefixing_rule (&m_pp);
-     pp_prefixing_rule (&m_pp) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
-   }
-   to_text (pretty_printer &pp,
- 	   colorizer *colorizer)
-   : m_pp (pp),
-     m_colorizer (colorizer)
-   {
-     m_saved_rule = pp_prefixing_rule (&m_pp);
-     pp_prefixing_rule (&m_pp) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
-   }
-   ~to_text ()
-   {
- 
-     pp_prefixing_rule (&m_pp) = m_saved_rule;
-   }
- 
-   static bool is_text () { return true; }
-   static bool is_html () { return false; }
- 
-   void emit_text_prefix ()
-   {
-     pp_emit_prefix (&m_pp);
-   }
- 
-   void push_html_tag (std::string, bool)
-   {
-     // no-op for text
-   }
-   void push_html_tag_with_class (std::string, std::string, bool)
-   {
-     // no-op for text
-   }
-   void pop_html_tag (const char *)
-   {
-     // no-op for text
-   }
- 
-   void add_html_tag_with_class (std::string, std::string, bool)
-   {
-     // no-op for text
-   }
- 
-   void add_space ()
-   {
-     pp_space (&m_pp);
-   }
- 
-   void add_character (cppchar_t ch)
-   {
-     pp_unicode_character (&m_pp, ch);
-   }
- 
-   void add_utf8_byte (char b)
-   {
-     pp_character (&m_pp, b);
-   }
- 
-   void add_text (const char *text)
-   {
-     pp_string (&m_pp, text);
-   }
- 
-   void print_decoded_char (const char_display_policy &char_policy,
- 			   cpp_decoded_char cp)
-   {
-     char_policy.m_print_text_cb (*this, cp);
-   }
- 
-   void colorize_text_ensure_normal ()
-   {
-     gcc_assert (m_colorizer);
-     m_colorizer->set_normal_text ();
-   }
- 
-   void colorize_text_for_range_idx (int range_idx)
-   {
-     gcc_assert (m_colorizer);
-     m_colorizer->set_range (range_idx);
-   }
- 
-   void colorize_text_for_cfg_edge ()
-   {
-     gcc_assert (m_colorizer);
-     m_colorizer->set_cfg_edge ();
-   }
- 
-   void colorize_text_for_fixit_insert ()
-   {
-     gcc_assert (m_colorizer);
-     m_colorizer->set_fixit_insert ();
-   }
- 
-   void colorize_text_for_fixit_delete ()
-   {
-     gcc_assert (m_colorizer);
-     m_colorizer->set_fixit_delete ();
-   }
- 
-   void
-   invoke_start_span_fn (const diagnostic_source_print_policy &source_policy,
- 			const diagnostic_location_print_policy &loc_policy,
- 			const expanded_location &exploc)
-   {
-     source_policy.get_text_start_span_fn () (loc_policy, *this, exploc);
-   }
- 
-   // Text-specific functions
-   void add_newline ()
-   {
-     pp_newline (&m_pp);
-   }
- 
-   pretty_printer &m_pp;
- private:
-   colorizer *m_colorizer;
-   diagnostic_prefixing_rule_t m_saved_rule;
- };
- 
- /* Writing HTML output.  */
- 
- struct to_html
- {
-   friend class layout_printer<to_html>;
- 
-   // RAII class for ensuring that the tags nested correctly
-   struct auto_check_tag_nesting : public xml::auto_check_tag_nesting
-   {
-   public:
-     auto_check_tag_nesting (to_html &sink)
-     : xml::auto_check_tag_nesting (sink.m_xp)
-     {
-     }
-   };
- 
-   to_html (xml::printer &xp,
- 	   const rich_location *richloc,
- 	   html_label_writer *html_label_writer)
-   : m_xp (xp),
-     m_richloc (richloc),
-     m_html_label_writer (html_label_writer)
-   {}
- 
-   static bool is_text () { return false; }
-   static bool is_html () { return true; }
- 
-   void emit_text_prefix ()
-   {
-     // no-op for HTML
-   }
- 
-   void push_html_tag (std::string name,
- 		      bool preserve_whitespace)
-   {
-     m_xp.push_tag (std::move (name), preserve_whitespace);
-   }
- 
-   void push_html_tag_with_class (std::string name,
- 				 std::string class_,
- 				 bool preserve_whitespace)
-   {
-     m_xp.push_tag_with_class (std::move (name),
- 			      std::move (class_),
- 			      preserve_whitespace);
-   }
- 
-   void pop_html_tag (const char *expected_name)
-   {
-     m_xp.pop_tag (expected_name);
-   }
- 
-   void add_html_tag_with_class (std::string name,
- 				std::string class_,
- 				bool preserve_whitespace)
-   {
-     auto element = std::make_unique<xml::element> (std::move (name),
- 						   preserve_whitespace);
-     element->set_attr ("class", std::move (class_));
-     m_xp.append (std::move (element));
-   }
- 
-   void add_raw_html (const char *src)
-   {
-     m_xp.add_raw (src);
-   }
- 
-   void add_space ()
-   {
-     m_xp.add_text (" ");
-   }
- 
-   void add_character (cppchar_t ch)
-   {
-     pp_clear_output_area (&m_scratch_pp);
-     pp_unicode_character (&m_scratch_pp, ch);
-     m_xp.add_text_from_pp (m_scratch_pp);
-   }
- 
-   void add_utf8_byte (char b)
-   {
-     m_xp.add_text (std::string (1, b));
-   }
- 
-   void add_text (const char *text)
-   {
-     m_xp.add_text (text);
-   }
- 
-   void print_decoded_char (const char_display_policy &char_policy,
- 			   cpp_decoded_char cp)
-   {
-     char_policy.m_print_html_cb (*this, cp);
-   }
- 
-   void colorize_text_ensure_normal ()
-   {
-     // no-op for HTML
-   }
- 
-   void colorize_text_for_cfg_edge ()
-   {
-     // no-op for HTML
-   }
- 
-   void colorize_text_for_fixit_insert ()
-   {
-     // no-op for HTML
-   }
- 
-   void colorize_text_for_fixit_delete ()
-   {
-     // no-op for HTML
-   }
- 
-   void
-   invoke_start_span_fn (const diagnostic_source_print_policy &source_policy,
- 			const diagnostic_location_print_policy &loc_policy,
- 			const expanded_location &exploc)
-   {
-     source_policy.get_html_start_span_fn () (loc_policy, *this, exploc);
-   }
- 
-   const location_range *
-   get_location_range_by_idx (int range_idx)
-   {
-     if (!m_richloc)
-       return nullptr;
-     return m_richloc->get_range (range_idx);
-   }
- 
-   const char *
-   get_highlight_color_for_range_idx (int range_idx)
-   {
-     const location_range *const loc_range
-       = get_location_range_by_idx (range_idx);
-     if (!loc_range)
-       return nullptr;
-     return loc_range->m_highlight_color;
-   }
- 
-   xml::printer &m_xp;
-   const rich_location *m_richloc;
- private:
-   html_label_writer *m_html_label_writer;
-   pretty_printer m_scratch_pp;
- };
- 
- void
- diagnostic_location_print_policy::
- print_text_span_start (const diagnostic_context &dc,
- 		       pretty_printer &pp,
- 		       const expanded_location &exploc)
- {
-   to_text sink (pp, nullptr);
-   diagnostic_source_print_policy source_policy (dc);
-   source_policy.get_text_start_span_fn () (*this, sink, exploc);
- }
- 
- void
- diagnostic_location_print_policy::
- print_html_span_start (const diagnostic_context &dc,
- 		       xml::printer &xp,
- 		       const expanded_location &exploc)
- {
-   to_html sink (xp, nullptr, nullptr);
-   diagnostic_source_print_policy source_policy (dc);
-   source_policy.get_html_start_span_fn () (*this, sink, exploc);
- }
- 
- pretty_printer *
- get_printer (to_text &sink)
- {
-   return &sink.m_pp;
- }
- 
- template<>
- void
- default_diagnostic_start_span_fn<to_text> (const diagnostic_location_print_policy &loc_policy,
- 					   to_text &sink,
- 					   expanded_location exploc)
- {
-   const diagnostic_column_policy &column_policy
-     = loc_policy.get_column_policy ();
-   label_text text
-     = column_policy.get_location_text (exploc,
- 				       loc_policy.show_column_p (),
- 				       pp_show_color (&sink.m_pp));
-   pp_string (&sink.m_pp, text.get ());
-   pp_newline (&sink.m_pp);
- }
- 
- template<>
- void
- default_diagnostic_start_span_fn<to_html> (const diagnostic_location_print_policy &loc_policy,
- 					   to_html &sink,
- 					   expanded_location exploc)
- {
-   const diagnostic_column_policy &column_policy
-     = loc_policy.get_column_policy ();
-   label_text text
-     = column_policy.get_location_text (exploc,
- 				       loc_policy.show_column_p (),
- 				       false);
-   sink.m_xp.push_tag_with_class ("span", "location", true);
-   sink.m_xp.add_text (text.get ());
-   sink.m_xp.pop_tag ("span");
- }
- 
- namespace {
- 
- /* A class to control the overall layout when printing a diagnostic.
- 
-    The layout is determined within the constructor.
- 
-    Printing the layout is handled by class layout_printer.  This separation
-    is to avoid depending on the pretty_printer in the layout.
- 
-    We assume we have disjoint ranges.  */
- 
- class layout
- {
-  public:
-   friend class layout_printer<to_text>;
-   friend class layout_printer<to_html>;
- 
-   layout (const diagnostic_source_print_policy &source_policy,
- 	  const rich_location &richloc,
- 	  diagnostic_source_effect_info *effect_info = nullptr);
- 
-   bool maybe_add_location_range (const location_range *loc_range,
- 				 unsigned original_idx,
- 				 bool restrict_to_current_line_spans);
- 
-   int get_num_line_spans () const { return m_line_spans.length (); }
-   const line_span *get_line_span (int idx) const { return &m_line_spans[idx]; }
- 
-   int get_linenum_width () const { return m_linenum_width; }
-   int get_x_offset_display () const { return m_x_offset_display; }
- 
-   bool print_heading_for_line_span_index_p (int line_span_idx) const;
- 
-   expanded_location get_expanded_location (const line_span *) const;
- 
-   void on_bad_codepoint (const char *ptr, cppchar_t ch, size_t ch_sz);
- 
-  private:
-   bool will_show_line_p (linenum_type row) const;
-   bool should_print_annotation_line_p (linenum_type row) const;
- 
-   bool annotation_line_showed_range_p (linenum_type line, int start_column,
- 				       int finish_column) const;
-   bool validate_fixit_hint_p (const fixit_hint *hint);
- 
-   void calculate_line_spans ();
-   void calculate_linenum_width ();
-   void calculate_x_offset_display ();
- 
-   bool
-   get_state_at_point (/* Inputs.  */
- 		      linenum_type row, int column,
- 		      int first_non_ws, int last_non_ws,
- 		      enum column_unit col_unit,
- 		      /* Outputs.  */
- 		      point_state *out_state) const;
- 
-   int
-   get_x_bound_for_row (linenum_type row, int caret_column,
- 		       int last_non_ws) const;
- 
-  private:
-   bool compatible_locations_p (location_t loc_a, location_t loc_b) const;
- 
-   const diagnostic_source_printing_options &m_options;
-   const line_maps *m_line_table;
-   file_cache &m_file_cache;
-   const text_art::ascii_theme m_fallback_theme;
-   const text_art::theme &m_theme;
-   diagnostic_source_effect_info *m_effect_info;
-   char_display_policy m_char_policy;
-   location_t m_primary_loc;
-   exploc_with_display_col m_exploc;
-   auto_vec <layout_range> m_layout_ranges;
-   auto_vec <const fixit_hint *> m_fixit_hints;
-   auto_vec <line_span> m_line_spans;
-   int m_linenum_width;
-   int m_x_offset_display;
-   bool m_escape_on_output;
- };
- 
- class line_label;
- 
- enum class margin_kind
- {
-   normal,
-   insertion,
-   ruler
- };
- 
- /* A bundle of state for printing a particular layout
-    to a particular Sink (either to_text or to_html).  */
- template <typename Sink>
- class layout_printer
- {
- public:
-   layout_printer (Sink &sink,
- 		  const layout &layout,
- 		  bool is_diagnostic_path);
- 
-   void print (const diagnostic_source_print_policy &source_policy);
- 
- private:
-   const diagnostic_source_printing_options &
-   get_options () const { return m_layout.m_options; }
- 
-   const text_art::theme &
-   get_theme () const { return m_layout.m_theme; }
- 
-   void show_ruler (int max_column);
-   void print_gap_in_line_numbering ();
-   void print_leading_fixits (linenum_type row);
-   void print_line (linenum_type row);
-   line_bounds print_source_line (linenum_type row, const char *line,
- 				 int line_bytes);
-   void print_leftmost_column ();
-   void start_annotation_line (enum margin_kind);
-   void end_line ();
-   void print_annotation_line (linenum_type row, const line_bounds lbounds);
-   void print_any_labels (linenum_type row);
-   void begin_label (int state_idx, bool is_label_text);
-   void end_label (int state_idx, bool is_label_text);
-   void print_trailing_fixits (linenum_type row);
- 
-   void
-   move_to_column (int *column, int dest_column, bool add_left_margin);
- 
-   void print_any_right_to_left_edge_lines ();
- 
-   void set_in_range (int range_idx);
-   void set_outside_range ();
- 
- private:
-   Sink &m_sink;
-   const layout &m_layout;
-   bool m_is_diagnostic_path;
- 
-   bool m_was_in_range_p;
-   int m_last_range_idx;
- 
-   /* Fields for handling links between labels (e.g. for showing CFG edges
-      in execution paths).
-      Note that the logic for printing such links makes various simplifying
-      assumptions about the set of labels in the rich_location, and users
-      of this code will need to split up labels into separate rich_location
-      instances to respect these assumptions, or the output will look wrong.
-      See the diagnostic_path-printing code for more information.  */
- 
-   /* An enum for describing the state of the leftmost column,
-      used for showing links between labels.
-      Consider e.g.
-      .x0000000001111111111222222222233333333334444444444.
-      .x1234567890123456789012345678901234567890123456789.
-      |      |                                    <- none
-      |      (9) following ‘false’ branch... ->-+ <- none
-      |                                         | <- none
-      |                                         | <- none
-      |+----------------------------------------+ <- rewinding to lhs
-      ||  result->i = i;                          <- at lhs
-      ||  ~~~~~~~~~~^~~                           <- at lhs
-      ||            |                             <- at lhs
-      |+----------->(10) ...to here               <- indenting to dest
-      ^^
-      ||
-      |leftmost column ("x" above).
-      "margin".  */
-   enum class link_lhs_state {
-     none,
-     rewinding_to_lhs,
-     at_lhs,
-     indenting_to_dest
-   } m_link_lhs_state;
- 
-   /* The column of the current link on the RHS, if any, or
-      -1 if there is none.
-      Consider e.g.
-      .x0000000001111111111222222222233333333334444444444.
-      .x1234567890123456789012345678901234567890123456789.
-      |      |                                     <- -1
-      |      (10) following ‘false’ branch... ->-+ <- 42
-      |                                          | <- 42
-      |                                          | <- 42
-      |+-----------------------------------------+ <- 42
-      ||  result->i = i;                           <- -1
-      ||  ~~~~~~~~~~^~~                            <- -1
-      ||            |                              <- -1
-      |+----------->(11) ...to here                <- -1.  */
-   int m_link_rhs_column;
- };
- 
- /* Implementation of "class colorizer".  */
- 
- /* The constructor for "colorizer".  Lookup and store color codes for the
-    different kinds of things we might need to print.  */
- 
- colorizer::colorizer (pretty_printer &pp,
- 		      const rich_location &richloc,
- 		      diagnostic_t diagnostic_kind) :
-   m_pp (pp),
-   m_richloc (richloc),
-   m_diagnostic_kind (diagnostic_kind),
-   m_current_state (STATE_NORMAL_TEXT)
- {
-   m_range1 = get_color_by_name ("range1");
-   m_range2 = get_color_by_name ("range2");
-   m_fixit_insert = get_color_by_name ("fixit-insert");
-   m_fixit_delete = get_color_by_name ("fixit-delete");
-   m_stop_color = colorize_stop (pp_show_color (&m_pp));
- }
- 
- /* The destructor for "colorize".  If colorization is on, print a code to
-    turn it off.  */
- 
- colorizer::~colorizer ()
- {
-   finish_state (m_current_state);
- }
- 
- /* Update state, changing to the specific named color and printing its
-    color codes.  */
- 
- void
- colorizer::set_named_color (const char *color)
- {
-   if (m_current_state == STATE_NAMED_COLOR
-       && color == m_current_named_color)
-     return;
-   finish_state (m_current_state);
-   m_current_state = STATE_NAMED_COLOR;
-   pp_string (&m_pp, colorize_start (pp_show_color (&m_pp), color));
-   m_current_named_color = color;
- }
- 
- /* Update state, printing color codes if necessary if there's a state
-    change.  */
- 
- void
- colorizer::set_state (int new_state)
- {
-   if (m_current_state != new_state)
-     {
-       finish_state (m_current_state);
-       m_current_state = new_state;
-       begin_state (new_state);
-     }
- }
- 
- /* Turn on any colorization for STATE.  */
- 
- void
- colorizer::begin_state (int state)
- {
-   switch (state)
-     {
-     case STATE_NORMAL_TEXT:
-       break;
- 
-     case STATE_FIXIT_INSERT:
-       pp_string (&m_pp, m_fixit_insert);
-       break;
- 
-     case STATE_FIXIT_DELETE:
-       pp_string (&m_pp, m_fixit_delete);
-       break;
- 
-     case STATE_NAMED_COLOR:
-       /* Should be handled by colorizer::set_named_color.  */
-       gcc_unreachable ();
- 
-     case 0:
-       /* Make range 0 be the same color as the "kind" text
- 	 (error vs warning vs note).  */
-       pp_string
- 	(&m_pp,
- 	 colorize_start (pp_show_color (&m_pp),
- 			 diagnostic_get_color_for_kind (m_diagnostic_kind)));
-       break;
- 
-     case 1:
-       pp_string (&m_pp, m_range1);
-       break;
- 
-     case 2:
-       pp_string (&m_pp, m_range2);
-       break;
- 
-     default:
-       /* For ranges beyond 2, alternate between color 1 and color 2.  */
-       {
- 	gcc_assert (state > 2);
- 	pp_string (&m_pp,
- 		   state % 2 ? m_range1 : m_range2);
-       }
-       break;
-     }
- }
- 
- /* Turn off any colorization for STATE.  */
- 
- void
- colorizer::finish_state (int state)
- {
-   if (state != STATE_NORMAL_TEXT)
-     pp_string (&m_pp, m_stop_color);
- }
- 
- /* Get the color code for NAME (or the empty string if
-    colorization is disabled).  */
- 
- const char *
- colorizer::get_color_by_name (const char *name)
- {
-   return colorize_start (pp_show_color (&m_pp), name);
- }
- 
- /* Implementation of class layout_range.  */
- 
- /* The constructor for class layout_range.
-    Initialize various layout_point fields from expanded_location
-    equivalents; we've already filtered on file.  */
- 
- layout_range::layout_range (const exploc_with_display_col &start_exploc,
- 			    const exploc_with_display_col &finish_exploc,
- 			    enum range_display_kind range_display_kind,
- 			    const exploc_with_display_col &caret_exploc,
- 			    unsigned original_idx,
- 			    const range_label *label)
- : m_start (start_exploc),
-   m_finish (finish_exploc),
-   m_range_display_kind (range_display_kind),
-   m_caret (caret_exploc),
-   m_original_idx (original_idx),
-   m_label (label)
- {
- }
- 
- /* Is (column, row) within the given range?
-    We've already filtered on the file.
- 
-    Ranges are closed (both limits are within the range).
- 
-    Example A: a single-line range:
-      start:  (col=22, line=2)
-      finish: (col=38, line=2)
- 
-   |00000011111111112222222222333333333344444444444
-   |34567890123456789012345678901234567890123456789
- --+-----------------------------------------------
- 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
- 02|bbbbbbbbbbbbbbbbbbbSwwwwwwwwwwwwwwwFaaaaaaaaaaa
- 03|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- 
-    Example B: a multiline range with
-      start:  (col=14, line=3)
-      finish: (col=08, line=5)
- 
-   |00000011111111112222222222333333333344444444444
-   |34567890123456789012345678901234567890123456789
- --+-----------------------------------------------
- 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
- 02|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
- 03|bbbbbbbbbbbSwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
- 04|wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
- 05|wwwwwFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- 06|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- --+-----------------------------------------------
- 
-    Legend:
-    - 'b' indicates a point *before* the range
-    - 'S' indicates the start of the range
-    - 'w' indicates a point within the range
-    - 'F' indicates the finish of the range (which is
- 	 within it).
-    - 'a' indicates a subsequent point *after* the range.
- 
-    COL_UNIT controls whether we check the byte column or
-    the display column; one or the other is more convenient
-    depending on the context.  */
- 
- bool
- layout_range::contains_point (linenum_type row, int column,
- 			      enum column_unit col_unit) const
- {
-   gcc_assert (m_start.m_line <= m_finish.m_line);
-   /* ...but the equivalent isn't true for the columns;
-      consider example B in the comment above.  */
- 
-   if (row < m_start.m_line)
-     /* Points before the first line of the range are
-        outside it (corresponding to line 01 in example A
-        and lines 01 and 02 in example B above).  */
-     return false;
- 
-   if (row == m_start.m_line)
-     /* On same line as start of range (corresponding
-        to line 02 in example A and line 03 in example B).  */
-     {
-       if (column < m_start.m_columns[col_unit])
- 	/* Points on the starting line of the range, but
- 	   before the column in which it begins.  */
- 	return false;
- 
-       if (row < m_finish.m_line)
- 	/* This is a multiline range; the point
- 	   is within it (corresponds to line 03 in example B
- 	   from column 14 onwards) */
- 	return true;
-       else
- 	{
- 	  /* This is a single-line range.  */
- 	  gcc_assert (row == m_finish.m_line);
- 	  return column <= m_finish.m_columns[col_unit];
- 	}
-     }
- 
-   /* The point is in a line beyond that containing the
-      start of the range: lines 03 onwards in example A,
-      and lines 04 onwards in example B.  */
-   gcc_assert (row > m_start.m_line);
- 
-   if (row > m_finish.m_line)
-     /* The point is beyond the final line of the range
-        (lines 03 onwards in example A, and lines 06 onwards
-        in example B).  */
-     return false;
- 
-   if (row < m_finish.m_line)
-     {
-       /* The point is in a line that's fully within a multiline
- 	 range (e.g. line 04 in example B).  */
-       gcc_assert (m_start.m_line < m_finish.m_line);
-       return true;
-     }
- 
-   gcc_assert (row ==  m_finish.m_line);
- 
-   return column <= m_finish.m_columns[col_unit];
- }
- 
- /* Does this layout_range contain any part of line ROW?  */
- 
- bool
- layout_range::intersects_line_p (linenum_type row) const
- {
-   gcc_assert (m_start.m_line <= m_finish.m_line);
-   if (row < m_start.m_line)
-     return false;
-   if (row > m_finish.m_line)
-     return false;
-   return true;
- }
- 
- /* Return true if this layout_range should have an in-edge.  */
- 
- bool
- layout_range::has_in_edge () const
- {
-   if (!m_label)
-     return false;
-   const label_effects *effects = m_label->get_effects (m_original_idx);
-   if (!effects)
-     return false;
- 
-   return effects->has_in_edge (m_original_idx);
- }
- 
- /* Return true if this layout_range should have an out-edge.  */
- 
- bool
- layout_range::has_out_edge () const
- {
-   if (!m_label)
-     return false;
-   const label_effects *effects = m_label->get_effects (m_original_idx);
-   if (!effects)
-     return false;
- 
-   return effects->has_out_edge (m_original_idx);
- }
- 
- #if CHECKING_P
- 
- /* Default for when we don't care what the tab expansion is set to.  */
- static const int def_tabstop = 8;
- 
- static cpp_char_column_policy def_policy ()
- {
-   return cpp_char_column_policy (def_tabstop, cpp_wcwidth);
- }
- 
- /* Create some expanded locations for testing layout_range.  The filename
-    member of the explocs is set to the empty string.  This member will only be
-    inspected by the calls to location_compute_display_column() made from the
-    layout_point constructors.  That function will check for an empty filename
-    argument and not attempt to open it, rather treating the non-existent data
-    as if the display width were the same as the byte count.  Tests exercising a
-    real difference between byte count and display width are performed later,
-    e.g. in test_diagnostic_show_locus_one_liner_utf8().  */
- 
- static layout_range
- make_range (file_cache &fc,
- 	    int start_line, int start_col, int end_line, int end_col)
- {
-   const expanded_location start_exploc
-     = {"", start_line, start_col, nullptr, false};
-   const expanded_location finish_exploc
-     = {"", end_line, end_col, nullptr, false};
-   return layout_range (exploc_with_display_col (fc,
- 						start_exploc, def_policy (),
- 						LOCATION_ASPECT_START),
- 		       exploc_with_display_col (fc,
- 						finish_exploc, def_policy (),
- 						LOCATION_ASPECT_FINISH),
- 		       SHOW_RANGE_WITHOUT_CARET,
- 		       exploc_with_display_col (fc,
- 						start_exploc, def_policy (),
- 						LOCATION_ASPECT_CARET),
- 		       0, nullptr);
- }
- 
- /* Selftests for layout_range::contains_point and
-    layout_range::intersects_line_p.  */
- 
- /* Selftest for layout_range, where the layout_range
-    is a range with start==end i.e. a single point.  */
- 
- static void
- test_layout_range_for_single_point ()
- {
-   file_cache fc;
-   layout_range point = make_range (fc, 7, 10, 7, 10);
- 
-   /* Tests for layout_range::contains_point.  */
- 
-   for (int i = 0; i != CU_NUM_UNITS; ++i)
-     {
-       const enum column_unit col_unit = (enum column_unit) i;
- 
-       /* Before the line.  */
-       ASSERT_FALSE (point.contains_point (6, 1, col_unit));
- 
-       /* On the line, but before start.  */
-       ASSERT_FALSE (point.contains_point (7, 9, col_unit));
- 
-       /* At the point.  */
-       ASSERT_TRUE (point.contains_point (7, 10, col_unit));
- 
-       /* On the line, after the point.  */
-       ASSERT_FALSE (point.contains_point (7, 11, col_unit));
- 
-       /* After the line.  */
-       ASSERT_FALSE (point.contains_point (8, 1, col_unit));
-     }
- 
-   /* Tests for layout_range::intersects_line_p.  */
-   ASSERT_FALSE (point.intersects_line_p (6));
-   ASSERT_TRUE (point.intersects_line_p (7));
-   ASSERT_FALSE (point.intersects_line_p (8));
- }
- 
- /* Selftest for layout_range, where the layout_range
-    is the single-line range shown as "Example A" above.  */
- 
- static void
- test_layout_range_for_single_line ()
- {
-   file_cache fc;
-   layout_range example_a = make_range (fc, 2, 22, 2, 38);
- 
-   /* Tests for layout_range::contains_point.  */
- 
-   for (int i = 0; i != CU_NUM_UNITS; ++i)
-     {
-       const enum column_unit col_unit = (enum column_unit) i;
- 
-       /* Before the line.  */
-       ASSERT_FALSE (example_a.contains_point (1, 1, col_unit));
- 
-       /* On the line, but before start.  */
-       ASSERT_FALSE (example_a.contains_point (2, 21, col_unit));
- 
-       /* On the line, at the start.  */
-       ASSERT_TRUE (example_a.contains_point (2, 22, col_unit));
- 
-       /* On the line, within the range.  */
-       ASSERT_TRUE (example_a.contains_point (2, 23, col_unit));
- 
-       /* On the line, at the end.  */
-       ASSERT_TRUE (example_a.contains_point (2, 38, col_unit));
- 
-       /* On the line, after the end.  */
-       ASSERT_FALSE (example_a.contains_point (2, 39, col_unit));
- 
-       /* After the line.  */
-       ASSERT_FALSE (example_a.contains_point (2, 39, col_unit));
-     }
- 
-   /* Tests for layout_range::intersects_line_p.  */
-   ASSERT_FALSE (example_a.intersects_line_p (1));
-   ASSERT_TRUE (example_a.intersects_line_p (2));
-   ASSERT_FALSE (example_a.intersects_line_p (3));
- }
- 
- /* Selftest for layout_range, where the layout_range
-    is the multi-line range shown as "Example B" above.  */
- 
- static void
- test_layout_range_for_multiple_lines ()
- {
-   file_cache fc;
-   layout_range example_b = make_range (fc, 3, 14, 5, 8);
- 
-   /* Tests for layout_range::contains_point.  */
- 
-   for (int i = 0; i != CU_NUM_UNITS; ++i)
-     {
-       const enum column_unit col_unit = (enum column_unit) i;
- 
-       /* Before first line.  */
-       ASSERT_FALSE (example_b.contains_point (1, 1, col_unit));
- 
-       /* On the first line, but before start.  */
-       ASSERT_FALSE (example_b.contains_point (3, 13, col_unit));
- 
-       /* At the start.  */
-       ASSERT_TRUE (example_b.contains_point (3, 14, col_unit));
- 
-       /* On the first line, within the range.  */
-       ASSERT_TRUE (example_b.contains_point (3, 15, col_unit));
- 
-       /* On an interior line.
- 	 The column number should not matter; try various boundary
- 	 values.  */
-       ASSERT_TRUE (example_b.contains_point (4, 1, col_unit));
-       ASSERT_TRUE (example_b.contains_point (4, 7, col_unit));
-       ASSERT_TRUE (example_b.contains_point (4, 8, col_unit));
-       ASSERT_TRUE (example_b.contains_point (4, 9, col_unit));
-       ASSERT_TRUE (example_b.contains_point (4, 13, col_unit));
-       ASSERT_TRUE (example_b.contains_point (4, 14, col_unit));
-       ASSERT_TRUE (example_b.contains_point (4, 15, col_unit));
- 
-       /* On the final line, before the end.  */
-       ASSERT_TRUE (example_b.contains_point (5, 7, col_unit));
- 
-       /* On the final line, at the end.  */
-       ASSERT_TRUE (example_b.contains_point (5, 8, col_unit));
- 
-       /* On the final line, after the end.  */
-       ASSERT_FALSE (example_b.contains_point (5, 9, col_unit));
- 
-       /* After the line.  */
-       ASSERT_FALSE (example_b.contains_point (6, 1, col_unit));
-     }
- 
-   /* Tests for layout_range::intersects_line_p.  */
-   ASSERT_FALSE (example_b.intersects_line_p (2));
-   ASSERT_TRUE (example_b.intersects_line_p (3));
-   ASSERT_TRUE (example_b.intersects_line_p (4));
-   ASSERT_TRUE (example_b.intersects_line_p (5));
-   ASSERT_FALSE (example_b.intersects_line_p (6));
- }
- 
- #endif /* #if CHECKING_P */
- 
- /* Given a source line LINE of length LINE_BYTES bytes, determine the length
-    (still in bytes, not display cols) without any trailing whitespace.  */
- 
- static int
- get_line_bytes_without_trailing_whitespace (const char *line, int line_bytes)
- {
-   int result = line_bytes;
-   while (result > 0)
-     {
-       char ch = line[result - 1];
-       if (ch == ' ' || ch == '\t' || ch == '\r')
- 	result--;
-       else
- 	break;
-     }
-   gcc_assert (result >= 0);
-   gcc_assert (result <= line_bytes);
-   gcc_assert (result == 0 ||
- 	      (line[result - 1] != ' '
- 	       && line[result -1] != '\t'
- 	       && line[result -1] != '\r'));
-   return result;
- }
- 
- #if CHECKING_P
- 
- /* A helper function for testing get_line_bytes_without_trailing_whitespace.  */
- 
- static void
- assert_eq (const char *line, int expected_bytes)
- {
-   int actual_value
-     = get_line_bytes_without_trailing_whitespace (line, strlen (line));
-   ASSERT_EQ (actual_value, expected_bytes);
- }
- 
- /* Verify that get_line_bytes_without_trailing_whitespace is sane for
-    various inputs.  It is not required to handle newlines.  */
- 
- static void
- test_get_line_bytes_without_trailing_whitespace ()
- {
-   assert_eq ("", 0);
-   assert_eq (" ", 0);
-   assert_eq ("\t", 0);
-   assert_eq ("\r", 0);
-   assert_eq ("hello world", 11);
-   assert_eq ("hello world     ", 11);
-   assert_eq ("hello world     \t\t  ", 11);
-   assert_eq ("hello world\r", 11);
- }
- 
- #endif /* #if CHECKING_P */
- 
- /* Helper function for layout's ctor, for sanitizing locations relative
-    to the primary location within a diagnostic.
- 
-    Compare LOC_A and LOC_B to see if it makes sense to print underlines
-    connecting their expanded locations.  Doing so is only guaranteed to
-    make sense if the locations share the same macro expansion "history"
-    i.e. they can be traced through the same macro expansions, eventually
-    reaching an ordinary map.
- 
-    This may be too strong a condition, but it effectively sanitizes
-    PR c++/70105, which has an example of printing an expression where the
-    final location of the expression is in a different macro, which
-    erroneously was leading to hundreds of lines of irrelevant source
-    being printed.  */
- 
- bool
- layout::compatible_locations_p (location_t loc_a, location_t loc_b) const
- {
-   if (IS_ADHOC_LOC (loc_a))
-     loc_a = get_location_from_adhoc_loc (m_line_table, loc_a);
-   if (IS_ADHOC_LOC (loc_b))
-     loc_b = get_location_from_adhoc_loc (m_line_table, loc_b);
- 
-   /* If either location is one of the special locations outside of a
-      linemap, they are only compatible if they are equal.  */
-   if (loc_a < RESERVED_LOCATION_COUNT
-       || loc_b < RESERVED_LOCATION_COUNT)
-     return loc_a == loc_b;
- 
-   const line_map *map_a = linemap_lookup (m_line_table, loc_a);
-   linemap_assert (map_a);
- 
-   const line_map *map_b = linemap_lookup (m_line_table, loc_b);
-   linemap_assert (map_b);
- 
-   /* Are they within the same map?  */
-   if (map_a == map_b)
-     {
-       /* Are both within the same macro expansion?  */
-       if (linemap_macro_expansion_map_p (map_a))
- 	{
- 	  /* If so, then they're only compatible if either both are
- 	     from the macro definition, or both from the macro arguments.  */
- 	  bool loc_a_from_defn
- 	    = linemap_location_from_macro_definition_p (m_line_table, loc_a);
- 	  bool loc_b_from_defn
- 	    = linemap_location_from_macro_definition_p (m_line_table, loc_b);
- 	  if (loc_a_from_defn != loc_b_from_defn)
- 	    return false;
- 
- 	  /* Expand each location towards the spelling location, and
- 	     recurse.  */
- 	  const line_map_macro *macro_map = linemap_check_macro (map_a);
- 	  location_t loc_a_toward_spelling
- 	    = linemap_macro_map_loc_unwind_toward_spelling (m_line_table,
- 							    macro_map,
- 							    loc_a);
- 	  location_t loc_b_toward_spelling
- 	    = linemap_macro_map_loc_unwind_toward_spelling (m_line_table,
- 							    macro_map,
- 							    loc_b);
- 	  return compatible_locations_p (loc_a_toward_spelling,
- 					 loc_b_toward_spelling);
- 	}
- 
-       /* Otherwise they are within the same ordinary map.  */
-       return true;
-     }
-   else
-     {
-       /* Within different maps.  */
- 
-       /* If either is within a macro expansion, they are incompatible.  */
-       if (linemap_macro_expansion_map_p (map_a)
- 	  || linemap_macro_expansion_map_p (map_b))
- 	return false;
- 
-       /* Within two different ordinary maps; they are compatible iff they
- 	 are in the same file.  */
-       const line_map_ordinary *ord_map_a = linemap_check_ordinary (map_a);
-       const line_map_ordinary *ord_map_b = linemap_check_ordinary (map_b);
-       return ord_map_a->to_file == ord_map_b->to_file;
-     }
- }
- 
- /* Comparator for sorting fix-it hints.  */
- 
- static int
- fixit_cmp (const void *p_a, const void *p_b)
- {
-   const fixit_hint * hint_a = *static_cast<const fixit_hint * const *> (p_a);
-   const fixit_hint * hint_b = *static_cast<const fixit_hint * const *> (p_b);
-   return hint_a->get_start_loc () - hint_b->get_start_loc ();
- }
- 
- /* Callbacks for use when not escaping the source.  */
- 
- /* The default callback for char_column_policy::m_width_cb is cpp_wcwidth.  */
- 
- /* Callback for char_display_policy::m_print_cb for printing source chars
-    when not escaping the source.  */
- 
- template <class Sink>
- static void
- default_print_decoded_ch (Sink &sink,
- 			  const cpp_decoded_char &decoded_ch)
- {
-   for (const char *ptr = decoded_ch.m_start_byte;
-        ptr != decoded_ch.m_next_byte; ptr++)
-     {
-       if (*ptr == '\0' || *ptr == '\r')
- 	{
- 	  sink.add_space ();
- 	  continue;
- 	}
- 
-       sink.add_utf8_byte (*ptr);
-     }
- }
- 
- /* Callbacks for use with DIAGNOSTICS_ESCAPE_FORMAT_BYTES.  */
- 
- static const int width_per_escaped_byte = 4;
- 
- /* Callback for char_column_policy::m_width_cb for determining the
-    display width when escaping with DIAGNOSTICS_ESCAPE_FORMAT_BYTES.  */
- 
- static int
- escape_as_bytes_width (cppchar_t ch)
- {
-   if (ch < 0x80 && ISPRINT (ch))
-     return cpp_wcwidth (ch);
-   else
-     {
-       if (ch <=   0x7F) return 1 * width_per_escaped_byte;
-       if (ch <=  0x7FF) return 2 * width_per_escaped_byte;
-       if (ch <= 0xFFFF) return 3 * width_per_escaped_byte;
-       return 4 * width_per_escaped_byte;
-     }
- }
- 
- /* Callback for char_display_policy::m_print_cb for printing source chars
-    when escaping with DIAGNOSTICS_ESCAPE_FORMAT_BYTES.  */
- 
- template <typename Sink>
- static void
- escape_as_bytes_print (Sink &sink,
- 		       const cpp_decoded_char &decoded_ch)
- {
-   if (!decoded_ch.m_valid_ch)
-     {
-       for (const char *iter = decoded_ch.m_start_byte;
- 	   iter != decoded_ch.m_next_byte; ++iter)
- 	{
- 	  char buf[16];
- 	  sprintf (buf, "<%02x>", (unsigned char)*iter);
- 	  sink.add_text (buf);
- 	}
-       return;
-     }
- 
-   cppchar_t ch = decoded_ch.m_ch;
-   if (ch < 0x80 && ISPRINT (ch))
-     sink.add_character (ch);
-   else
-     {
-       for (const char *iter = decoded_ch.m_start_byte;
- 	   iter < decoded_ch.m_next_byte; ++iter)
- 	{
- 	  char buf[16];
- 	  sprintf (buf, "<%02x>", (unsigned char)*iter);
- 	  sink.add_text (buf);
- 	}
-     }
- }
- 
- /* Callbacks for use with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE.  */
- 
- /* Callback for char_column_policy::m_width_cb for determining the
-    display width when escaping with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE.  */
- 
- static int
- escape_as_unicode_width (cppchar_t ch)
- {
-   if (ch < 0x80 && ISPRINT (ch))
-     return cpp_wcwidth (ch);
-   else
-     {
-       // Width of "<U+%04x>"
-       if (ch > 0xfffff)
- 	return 10;
-       else if (ch > 0xffff)
- 	return 9;
-       else
- 	return 8;
-     }
- }
- 
- /* Callback for char_display_policy::m_print_cb for printing source chars
-    when escaping with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE.  */
- 
- template <typename Sink>
- static void
- escape_as_unicode_print (Sink &sink,
- 			 const cpp_decoded_char &decoded_ch)
- {
-   if (!decoded_ch.m_valid_ch)
-     {
-       escape_as_bytes_print<Sink> (sink, decoded_ch);
-       return;
-     }
- 
-   cppchar_t ch = decoded_ch.m_ch;
-   if (ch < 0x80 && ISPRINT (ch))
-     sink.add_character (ch);
-   else
-     {
-       char buf[16];
-       sprintf (buf, "<U+%04X>", ch);
-       sink.add_text (buf);
-     }
- }
- 
- /* Populate a char_display_policy based on SOURCE_POLICY and RICHLOC.  */
- 
- static char_display_policy
- make_char_policy (const diagnostic_source_print_policy &source_policy,
- 		  const rich_location &richloc)
- {
-   /* The default is to not escape non-ASCII bytes.  */
-   char_display_policy result
-     (source_policy.get_column_policy ().get_tabstop (),
-      cpp_wcwidth,
-      default_print_decoded_ch<to_text>,
-      default_print_decoded_ch<to_html>);
- 
-   /* If the diagnostic suggests escaping non-ASCII bytes, then
-      use policy from user-supplied options.  */
-   if (richloc.escape_on_output_p ())
-     {
-       result.m_undecoded_byte_width = width_per_escaped_byte;
-       switch (source_policy.get_escape_format ())
- 	{
- 	default:
- 	  gcc_unreachable ();
- 	case DIAGNOSTICS_ESCAPE_FORMAT_UNICODE:
- 	  result.m_width_cb = escape_as_unicode_width;
- 	  result.m_print_text_cb = escape_as_unicode_print<to_text>;
- 	  result.m_print_html_cb = escape_as_unicode_print<to_html>;
- 	  break;
- 	case DIAGNOSTICS_ESCAPE_FORMAT_BYTES:
- 	  result.m_width_cb = escape_as_bytes_width;
- 	  result.m_print_text_cb = escape_as_bytes_print<to_text>;
- 	  result.m_print_html_cb = escape_as_bytes_print<to_html>;
- 	  break;
- 	}
-     }
- 
-   return result;
- }
- 
- /* Implementation of class layout.  */
- 
- /* Constructor for class layout.
- 
-    Filter the ranges from the rich_location to those that we can
-    sanely print, populating m_layout_ranges and m_fixit_hints.
-    Determine the range of lines that we will print, splitting them
-    up into an ordered list of disjoint spans of contiguous line numbers.
-    Determine m_x_offset_display, to ensure that the primary caret
-    will fit within the max_width provided by the diagnostic_context.  */
- 
- layout::layout (const diagnostic_source_print_policy &source_policy,
- 		const rich_location &richloc,
- 		diagnostic_source_effect_info *effect_info)
- : m_options (source_policy.get_options ()),
-   m_line_table (richloc.get_line_table ()),
-   m_file_cache (source_policy.get_file_cache ()),
-   /* Ensure we have a non-null m_theme. */
-   m_theme (source_policy.get_diagram_theme ()
- 	   ? *source_policy.get_diagram_theme ()
- 	   : *static_cast <const text_art::theme *> (&m_fallback_theme)),
-   m_effect_info (effect_info),
-   m_char_policy (make_char_policy (source_policy, richloc)),
-   m_primary_loc (richloc.get_range (0)->m_loc),
-   m_exploc (m_file_cache,
- 	    richloc.get_expanded_location (0), m_char_policy,
- 	    LOCATION_ASPECT_CARET),
-   m_layout_ranges (richloc.get_num_locations ()),
-   m_fixit_hints (richloc.get_num_fixit_hints ()),
-   m_line_spans (1 + richloc.get_num_locations ()),
-   m_linenum_width (0),
-   m_x_offset_display (0),
-   m_escape_on_output (richloc.escape_on_output_p ())
- {
-   for (unsigned int idx = 0; idx < richloc.get_num_locations (); idx++)
-     {
-       /* This diagnostic printer can only cope with "sufficiently sane" ranges.
- 	 Ignore any ranges that are awkward to handle.  */
-       const location_range *loc_range = richloc.get_range (idx);
-       maybe_add_location_range (loc_range, idx, false);
-     }
- 
-   /* Populate m_fixit_hints, filtering to only those that are in the
-      same file.  */
-   for (unsigned int i = 0; i < richloc.get_num_fixit_hints (); i++)
-     {
-       const fixit_hint *hint = richloc.get_fixit_hint (i);
-       if (validate_fixit_hint_p (hint))
- 	m_fixit_hints.safe_push (hint);
-     }
- 
-   /* Sort m_fixit_hints.  */
-   m_fixit_hints.qsort (fixit_cmp);
- 
-   /* Populate the indicated members.  */
-   calculate_line_spans ();
-   calculate_linenum_width ();
-   calculate_x_offset_display ();
- }
- 
- 
- /* Attempt to add LOC_RANGE to m_layout_ranges, filtering them to
-    those that we can sanely print.
- 
-    ORIGINAL_IDX is the index of LOC_RANGE within its rich_location,
-    (for use as extrinsic state by label ranges).
- 
-    If RESTRICT_TO_CURRENT_LINE_SPANS is true, then LOC_RANGE is also
-    filtered against this layout instance's current line spans: it
-    will only be added if the location is fully within the lines
-    already specified by other locations.
- 
-    Return true iff LOC_RANGE was added.  */
- 
- bool
- layout::maybe_add_location_range (const location_range *loc_range,
- 				  unsigned original_idx,
- 				  bool restrict_to_current_line_spans)
- {
-   gcc_assert (loc_range);
- 
-   /* Split the "range" into caret and range information.  */
-   source_range src_range = get_range_from_loc (m_line_table, loc_range->m_loc);
- 
-   /* Expand the various locations.  */
-   expanded_location start
-     = linemap_client_expand_location_to_spelling_point
-     (m_line_table, src_range.m_start, LOCATION_ASPECT_START);
-   expanded_location finish
-     = linemap_client_expand_location_to_spelling_point
-     (m_line_table, src_range.m_finish, LOCATION_ASPECT_FINISH);
-   expanded_location caret
-     = linemap_client_expand_location_to_spelling_point
-     (m_line_table, loc_range->m_loc, LOCATION_ASPECT_CARET);
- 
-   /* If any part of the range isn't in the same file as the primary
-      location of this diagnostic, ignore the range.  */
-   if (start.file != m_exploc.file)
-     return false;
-   if (finish.file != m_exploc.file)
-     return false;
-   if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
-     if (caret.file != m_exploc.file)
-       return false;
- 
-   /* Sanitize the caret location for non-primary ranges.  */
-   if (m_layout_ranges.length () > 0)
-     if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
-       if (!compatible_locations_p (loc_range->m_loc, m_primary_loc))
- 	/* Discard any non-primary ranges that can't be printed
- 	   sanely relative to the primary location.  */
- 	return false;
- 
-   /* If there's no column information, then don't try to print
-      annotation lines for this range.  */
-   enum range_display_kind range_display_kind
-     = loc_range->m_range_display_kind;
-   if (start.column == 0
-       || finish.column == 0
-       || caret.column == 0)
-     range_display_kind = SHOW_LINES_WITHOUT_RANGE;
- 
-   /* Everything is now known to be in the correct source file,
-      but it may require further sanitization.  */
-   layout_range ri (exploc_with_display_col (m_file_cache,
- 					    start, m_char_policy,
- 					    LOCATION_ASPECT_START),
- 		   exploc_with_display_col (m_file_cache,
- 					    finish, m_char_policy,
- 					    LOCATION_ASPECT_FINISH),
- 		   range_display_kind,
- 		   exploc_with_display_col (m_file_cache,
- 					    caret, m_char_policy,
- 					    LOCATION_ASPECT_CARET),
- 		   original_idx, loc_range->m_label);
- 
-   /* If we have a range that finishes before it starts (perhaps
-      from something built via macro expansion), printing the
-      range is likely to be nonsensical.  Also, attempting to do so
-      breaks assumptions within the printing code  (PR c/68473).
-      Similarly, don't attempt to print ranges if one or both ends
-      of the range aren't sane to print relative to the
-      primary location (PR c++/70105).  */
-   if (start.line > finish.line
-       || !compatible_locations_p (src_range.m_start, m_primary_loc)
-       || !compatible_locations_p (src_range.m_finish, m_primary_loc))
-     {
-       /* Is this the primary location?  */
-       if (m_layout_ranges.length () == 0)
- 	{
- 	  /* We want to print the caret for the primary location, but
- 	     we must sanitize away m_start and m_finish.  */
- 	  ri.m_start = ri.m_caret;
- 	  ri.m_finish = ri.m_caret;
- 	}
-       else
- 	/* This is a non-primary range; ignore it.  */
- 	return false;
-     }
- 
-   /* Potentially filter to just the lines already specified by other
-      locations.  This is for use by gcc_rich_location::add_location_if_nearby.
-      The layout ctor doesn't use it, and can't because m_line_spans
-      hasn't been set up at that point.  */
-   if (restrict_to_current_line_spans)
-     {
-       if (!will_show_line_p (start.line))
- 	return false;
-       if (!will_show_line_p (finish.line))
- 	return false;
-       if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
- 	if (!will_show_line_p (caret.line))
- 	  return false;
-     }
- 
-   /* Passed all the tests; add the range to m_layout_ranges so that
-      it will be printed.  */
-   m_layout_ranges.safe_push (ri);
-   return true;
- }
- 
- /* Return true iff ROW is within one of the line spans for this layout.  */
- 
- bool
- layout::will_show_line_p (linenum_type row) const
- {
-   for (int line_span_idx = 0; line_span_idx < get_num_line_spans ();
-        line_span_idx++)
-     {
-       const line_span *line_span = get_line_span (line_span_idx);
-       if (line_span->contains_line_p (row))
- 	return true;
-     }
-   return false;
- }
- 
- /* Print a line showing a gap in the line numbers, for showing the boundary
-    between two line spans.  */
- 
- template<>
- void
- layout_printer<to_text>::print_gap_in_line_numbering ()
- {
-   gcc_assert (m_layout.m_options.show_line_numbers_p);
- 
-   m_sink.emit_text_prefix ();
- 
-   for (int i = 0; i < m_layout.get_linenum_width () + 1; i++)
-     m_sink.add_character ('.');
- 
-   m_sink.add_newline ();
- }
- 
- template<>
- void
- layout_printer<to_html>::print_gap_in_line_numbering ()
- {
-   gcc_assert (m_layout.m_options.show_line_numbers_p);
- 
-   m_sink.add_raw_html
-     ("<tbody class=\"line-span-jump\">\n"
-      "<tr class=\"line-span-jump-row\">"
-      "<td class=\"linenum-gap\">[...]</td>"
-      "<td class=\"source-gap\"/></tr>\n"
-      "</tbody>\n");
- }
- 
- /* Return true iff we should print a heading when starting the
-    line span with the given index.  */
- 
- bool
- layout::print_heading_for_line_span_index_p (int line_span_idx) const
- {
-   /* We print a heading for every change of line span, hence for every
-      line span after the initial one.  */
-   if (line_span_idx > 0)
-     return true;
- 
-   /* We also do it for the initial span if the primary location of the
-      diagnostic is in a different span.  */
-   if (m_exploc.line > (int)get_line_span (0)->m_last_line)
-     return true;
- 
-   return false;
- }
- 
- /* Get an expanded_location for the first location of interest within
-    the given line_span.
-    Used when printing a heading to indicate a new line span.  */
- 
- expanded_location
- layout::get_expanded_location (const line_span *line_span) const
- {
-   /* Whenever possible, use the caret location.  */
-   if (line_span->contains_line_p (m_exploc.line))
-     return m_exploc;
- 
-   /* Otherwise, use the start of the first range that's present
-      within the line_span.  */
-   for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
-     {
-       const layout_range *lr = &m_layout_ranges[i];
-       if (line_span->contains_line_p (lr->m_start.m_line))
- 	{
- 	  expanded_location exploc = m_exploc;
- 	  exploc.line = lr->m_start.m_line;
- 	  exploc.column = lr->m_start.m_columns[CU_BYTES];
- 	  return exploc;
- 	}
-     }
- 
-   /* Otherwise, use the location of the first fixit-hint present within
-      the line_span.  */
-   for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
-     {
-       const fixit_hint *hint = m_fixit_hints[i];
-       location_t loc = hint->get_start_loc ();
-       expanded_location exploc = expand_location (loc);
-       if (line_span->contains_line_p (exploc.line))
- 	return exploc;
-     }
- 
-   /* It should not be possible to have a line span that didn't
-      contain any of the layout_range or fixit_hint instances.  */
-   gcc_unreachable ();
-   return m_exploc;
- }
- 
- /* Determine if HINT is meaningful to print within this layout.  */
- 
- bool
- layout::validate_fixit_hint_p (const fixit_hint *hint)
- {
-   if (LOCATION_FILE (hint->get_start_loc ()) != m_exploc.file)
-     return false;
-   if (LOCATION_FILE (hint->get_next_loc ()) != m_exploc.file)
-     return false;
- 
-   return true;
- }
- 
- /* Determine the range of lines affected by HINT.
-    This assumes that HINT has already been filtered by
-    validate_fixit_hint_p, and so affects the correct source file.  */
- 
- static line_span
- get_line_span_for_fixit_hint (const fixit_hint *hint)
- {
-   gcc_assert (hint);
- 
-   int start_line = LOCATION_LINE (hint->get_start_loc ());
- 
-   /* For line-insertion fix-it hints, add the previous line to the
-      span, to give the user more context on the proposed change.  */
-   if (hint->ends_with_newline_p ())
-     if (start_line > 1)
-       start_line--;
- 
-   return line_span (start_line,
- 		    LOCATION_LINE (hint->get_next_loc ()));
- }
- 
- /* We want to print the pertinent source code at a diagnostic.  The
-    rich_location can contain multiple locations.  This will have been
-    filtered into m_exploc (the caret for the primary location) and
-    m_layout_ranges, for those ranges within the same source file.
- 
-    We will print a subset of the lines within the source file in question,
-    as a collection of "spans" of lines.
- 
-    This function populates m_line_spans with an ordered, disjoint list of
-    the line spans of interest.
- 
-    Printing a gap between line spans takes one line, so, when printing
-    line numbers, we allow a gap of up to one line between spans when
-    merging, since it makes more sense to print the source line rather than a
-    "gap-in-line-numbering" line.  When not printing line numbers, it's
-    better to be more explicit about what's going on, so keeping them as
-    separate spans is preferred.
- 
-    For example, if the primary range is on lines 8-10, with secondary ranges
-    covering lines 5-6 and lines 13-15:
- 
-      004
-      005                   |RANGE 1
-      006                   |RANGE 1
-      007
-      008  |PRIMARY RANGE
-      009  |PRIMARY CARET
-      010  |PRIMARY RANGE
-      011
-      012
-      013                                |RANGE 2
-      014                                |RANGE 2
-      015                                |RANGE 2
-      016
- 
-    With line numbering on, we want two spans: lines 5-10 and lines 13-15.
- 
-    With line numbering off (with span headers), we want three spans: lines 5-6,
-    lines 8-10, and lines 13-15.  */
- 
- void
- layout::calculate_line_spans ()
- {
-   /* This should only be called once, by the ctor.  */
-   gcc_assert (m_line_spans.length () == 0);
- 
-   /* Populate tmp_spans with individual spans, for each of
-      m_exploc, and for m_layout_ranges.  */
-   auto_vec<line_span> tmp_spans (1 + m_layout_ranges.length ());
-   tmp_spans.safe_push (line_span (m_exploc.line, m_exploc.line));
-   for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
-     {
-       const layout_range *lr = &m_layout_ranges[i];
-       gcc_assert (lr->m_start.m_line <= lr->m_finish.m_line);
-       tmp_spans.safe_push (line_span (lr->m_start.m_line,
- 				      lr->m_finish.m_line));
-     }
- 
-   /* Also add spans for any fix-it hints, in case they cover other lines.  */
-   for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
-     {
-       const fixit_hint *hint = m_fixit_hints[i];
-       gcc_assert (hint);
-       tmp_spans.safe_push (get_line_span_for_fixit_hint (hint));
-     }
- 
-   /* Sort them.  */
-   tmp_spans.qsort(line_span::comparator);
- 
-   /* Now iterate through tmp_spans, copying into m_line_spans, and
-      combining where possible.  */
-   gcc_assert (tmp_spans.length () > 0);
-   m_line_spans.safe_push (tmp_spans[0]);
-   for (unsigned int i = 1; i < tmp_spans.length (); i++)
-     {
-       line_span *current = &m_line_spans[m_line_spans.length () - 1];
-       const line_span *next = &tmp_spans[i];
-       gcc_assert (next->m_first_line >= current->m_first_line);
-       const int merger_distance = m_options.show_line_numbers_p ? 1 : 0;
-       if ((linenum_arith_t)next->m_first_line
- 	  <= (linenum_arith_t)current->m_last_line + 1 + merger_distance)
- 	{
- 	  /* We can merge them. */
- 	  if (next->m_last_line > current->m_last_line)
- 	    current->m_last_line = next->m_last_line;
- 	}
-       else
- 	{
- 	  /* No merger possible.  */
- 	  m_line_spans.safe_push (*next);
- 	}
-     }
- 
-   /* Verify the result, in m_line_spans.  */
-   gcc_assert (m_line_spans.length () > 0);
-   for (unsigned int i = 1; i < m_line_spans.length (); i++)
-     {
-       const line_span *prev = &m_line_spans[i - 1];
-       const line_span *next = &m_line_spans[i];
-       /* The individual spans must be sane.  */
-       gcc_assert (prev->m_first_line <= prev->m_last_line);
-       gcc_assert (next->m_first_line <= next->m_last_line);
-       /* The spans must be ordered.  */
-       gcc_assert (prev->m_first_line < next->m_first_line);
-       /* There must be a gap of at least one line between separate spans.  */
-       gcc_assert ((prev->m_last_line + 1) < next->m_first_line);
-     }
- }
- 
- /* Determine how many display columns need to be reserved for line numbers,
-    based on the largest line number that will be needed, and populate
-    m_linenum_width.  */
- 
- void
- layout::calculate_linenum_width ()
- {
-   gcc_assert (m_line_spans.length () > 0);
-   const line_span *last_span = &m_line_spans[m_line_spans.length () - 1];
-   int highest_line = last_span->m_last_line;
-   if (highest_line < 0)
-     highest_line = 0;
-   m_linenum_width = num_digits (highest_line);
-   /* If we're showing jumps in the line-numbering, allow at least 3 chars.  */
-   if (m_line_spans.length () > 1)
-     m_linenum_width = MAX (m_linenum_width, 3);
-   /* If there's a minimum margin width, apply it (subtracting 1 for the space
-      after the line number.  */
-   m_linenum_width = MAX (m_linenum_width, m_options.min_margin_width - 1);
- }
- 
- /* Calculate m_x_offset_display, which improves readability in case the source
-    line of interest is longer than the user's display.  All lines output will be
-    shifted to the left (so that their beginning is no longer displayed) by
-    m_x_offset_display display columns, so that the caret is in a reasonable
-    location.  */
- 
- void
- layout::calculate_x_offset_display ()
- {
-   m_x_offset_display = 0;
- 
-   const int max_width = m_options.max_width;
-   if (!max_width)
-     {
-       /* Nothing to do, the width is not capped.  */
-       return;
-     }
- 
-   const char_span line = m_file_cache.get_source_line (m_exploc.file,
- 						       m_exploc.line);
-   if (!line)
-     {
-       /* Nothing to do, we couldn't find the source line.  */
-       return;
-     }
-   int caret_display_column = m_exploc.m_display_col;
-   const int line_bytes
-     = get_line_bytes_without_trailing_whitespace (line.get_buffer (),
- 						  line.length ());
-   int eol_display_column
-     = cpp_display_width (line.get_buffer (), line_bytes, m_char_policy);
-   if (caret_display_column > eol_display_column
-       || !caret_display_column)
-     {
-       /* This does not make sense, so don't try to do anything in this case.  */
-       return;
-     }
- 
-   /* Adjust caret and eol positions to include the left margin.  If we are
-      outputting line numbers, then the left margin is equal to m_linenum_width
-      plus three for the " | " which follows it.  Otherwise the left margin width
-      is equal to 1, because layout::print_source_line() will prefix each line
-      with a space.  */
-   const int source_display_cols = eol_display_column;
-   int left_margin_size = 1;
-   if (m_options.show_line_numbers_p)
-       left_margin_size = m_linenum_width + 3;
-   caret_display_column += left_margin_size;
-   eol_display_column += left_margin_size;
- 
-   if (eol_display_column <= max_width)
-     {
-       /* Nothing to do, everything fits in the display.  */
-       return;
-     }
- 
-   /* The line is too long for the display.  Calculate an offset such that the
-      caret is not too close to the right edge of the screen.  It will be
-      CARET_LINE_MARGIN display columns from the right edge, unless it is closer
-      than that to the end of the source line anyway.  */
-   int right_margin_size = CARET_LINE_MARGIN;
-   right_margin_size = MIN (eol_display_column - caret_display_column,
- 			   right_margin_size);
-   if (right_margin_size + left_margin_size >= max_width)
-     {
-       /* The max_width is very small, so anything we try to do will not be very
- 	 effective; just punt in this case and output with no offset.  */
-       return;
-     }
-   const int max_caret_display_column = max_width - right_margin_size;
-   if (caret_display_column > max_caret_display_column)
-     {
-       m_x_offset_display = caret_display_column - max_caret_display_column;
-       /* Make sure we don't offset the line into oblivion.  */
-       static const int min_cols_visible = 2;
-       if (source_display_cols - m_x_offset_display < min_cols_visible)
- 	m_x_offset_display = 0;
-     }
- }
- 
- /* Print line ROW of source code, potentially colorized at any ranges, and
-    return the line bounds.  LINE is the source line (not necessarily
-    0-terminated) and LINE_BYTES is its length in bytes.  In order to handle both
-    colorization and tab expansion, this function tracks the line position in
-    both byte and display column units.  */
- 
- template<typename Sink>
- line_bounds
- layout_printer<Sink>::print_source_line (linenum_type row,
- 					 const char *line,
- 					 int line_bytes)
- {
-   m_sink.colorize_text_ensure_normal ();
-   m_sink.push_html_tag ("tr", true);
-   m_sink.emit_text_prefix ();
-   if (m_layout.m_options.show_line_numbers_p)
-     {
-       m_sink.push_html_tag_with_class ("td", "linenum", true);
-       int width = num_digits (row);
-       for (int i = 0; i < m_layout.get_linenum_width () - width; i++)
- 	m_sink.add_space ();
-       char buf[20];
-       sprintf (buf, "%i", row);
-       m_sink.add_text (buf);
-       if (Sink::is_text ())
- 	m_sink.add_text (" |");
-       m_sink.pop_html_tag ("td");
-     }
- 
-   m_sink.push_html_tag_with_class ("td", "left-margin", true);
-   print_leftmost_column ();
-   m_sink.pop_html_tag ("td");
- 
-   /* We will stop printing the source line at any trailing whitespace.  */
-   line_bytes = get_line_bytes_without_trailing_whitespace (line,
- 							   line_bytes);
- 
-   /* This object helps to keep track of which display column we are at, which is
-      necessary for computing the line bounds in display units, for doing
-      tab expansion, and for implementing m_x_offset_display.  */
-   cpp_display_width_computation dw (line, line_bytes, m_layout.m_char_policy);
- 
-   m_sink.push_html_tag_with_class ("td", "source", true);
- 
-   /* Skip the first m_x_offset_display display columns.  In case the leading
-      portion that will be skipped ends with a character with wcwidth > 1, then
-      it is possible we skipped too much, so account for that by padding with
-      spaces.  Note that this does the right thing too in case a tab was the last
-      character to be skipped over; the tab is effectively replaced by the
-      correct number of trailing spaces needed to offset by the desired number of
-      display columns.  */
-   for (int skipped_display_cols
- 	 = dw.advance_display_cols (m_layout.m_x_offset_display);
-        skipped_display_cols > m_layout.m_x_offset_display; --skipped_display_cols)
-     m_sink.add_space ();
- 
-   /* Print the line and compute the line_bounds.  */
-   line_bounds lbounds;
-   while (!dw.done ())
-     {
-       /* Assuming colorization is enabled for the caret and underline
- 	 characters, we may also colorize the associated characters
- 	 within the source line.
- 
- 	 For frontends that generate range information, we color the
- 	 associated characters in the source line the same as the
- 	 carets and underlines in the annotation line, to make it easier
- 	 for the reader to see the pertinent code.
- 
- 	 For frontends that only generate carets, we don't colorize the
- 	 characters above them, since this would look strange (e.g.
- 	 colorizing just the first character in a token).  */
-       if (m_layout.m_options.colorize_source_p)
- 	{
- 	  bool in_range_p;
- 	  point_state state;
- 	  const int start_byte_col = dw.bytes_processed () + 1;
- 	  in_range_p = m_layout.get_state_at_point (row, start_byte_col,
- 						    0, INT_MAX,
- 						    CU_BYTES,
- 						    &state);
- 	  if (in_range_p)
- 	    set_in_range (state.range_idx);
- 	  else
- 	    set_outside_range ();
- 	}
- 
-       /* Get the display width of the next character to be output, expanding
- 	 tabs and replacing some control bytes with spaces as necessary.  */
-       const char *c = dw.next_byte ();
-       const int start_disp_col = dw.display_cols_processed () + 1;
-       cpp_decoded_char cp;
-       const int this_display_width = dw.process_next_codepoint (&cp);
-       if (*c == '\t')
- 	{
- 	  /* The returned display width is the number of spaces into which the
- 	     tab should be expanded.  */
- 	  for (int i = 0; i != this_display_width; ++i)
- 	    m_sink.add_space ();
- 	  continue;
- 	}
- 
-       /* We have a (possibly multibyte) character to output; update the line
- 	 bounds if it is not whitespace.  */
-       if (*c != ' ')
- 	{
- 	  lbounds.m_last_non_ws_disp_col = dw.display_cols_processed ();
- 	  if (lbounds.m_first_non_ws_disp_col == INT_MAX)
- 	    lbounds.m_first_non_ws_disp_col = start_disp_col;
- 	}
- 
-       /* Output the character.  */
-       m_sink.print_decoded_char (m_layout.m_char_policy, cp);
-       c = dw.next_byte ();
-     }
-   set_outside_range ();
-   end_line ();
-   return lbounds;
- }
- 
- /* Determine if we should print an annotation line for ROW.
-    i.e. if any of m_layout_ranges contains ROW.  */
- 
- bool
- layout::should_print_annotation_line_p (linenum_type row) const
- {
-   layout_range *range;
-   int i;
-   FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
-     {
-       if (range->m_range_display_kind == SHOW_LINES_WITHOUT_RANGE)
- 	return false;
-       if (range->intersects_line_p (row))
- 	return true;
-     }
-   return false;
- }
- 
- /* Print the leftmost column after the margin, which is used for showing
-    links between labels (e.g. for CFG edges in execution paths).  */
- 
- template<typename Sink>
- void
- layout_printer<Sink>::print_leftmost_column ()
- {
-   if (!get_options ().show_event_links_p)
-     gcc_assert (m_link_lhs_state == link_lhs_state::none);
- 
-   switch (m_link_lhs_state)
-     {
-     default:
-       gcc_unreachable ();
-     case link_lhs_state::none:
-       m_sink.add_space ();
-       break;
-     case link_lhs_state::rewinding_to_lhs:
-       {
- 	m_sink.colorize_text_for_cfg_edge ();
- 	const cppchar_t ch = get_theme ().get_cppchar
- 	  (text_art::theme::cell_kind::CFG_FROM_LEFT_TO_DOWN);
- 	m_sink.add_character (ch);
- 	m_sink.colorize_text_ensure_normal ();
-       }
-       break;
-     case link_lhs_state::at_lhs:
-       {
- 	m_sink.colorize_text_for_cfg_edge ();
- 	const cppchar_t ch = get_theme ().get_cppchar
- 	  (text_art::theme::cell_kind::CFG_DOWN);
- 	m_sink.add_character (ch);
- 	m_sink.colorize_text_ensure_normal ();
-       }
-       break;
-     case link_lhs_state::indenting_to_dest:
-       {
- 	m_sink.colorize_text_for_cfg_edge ();
- 	const cppchar_t ch = get_theme ().get_cppchar
- 	  (text_art::theme::cell_kind::CFG_FROM_DOWN_TO_RIGHT);
- 	m_sink.add_character (ch);
- 	m_sink.colorize_text_ensure_normal ();
-       }
-       break;
-     }
- }
- 
- /* Begin an annotation line for either text or html output
- 
-    If m_show_line_numbers_p, print the left margin, which is empty
-    for annotation lines.
-    After any left margin, print a leftmost column, which is used for
-    showing links between labels (e.g. for CFG edges in execution paths).
- 
-    For text sinks, this also first prints the text prefix.
-    For html sinks, this also pushes <tr> and <td> open tags, where the
-    <td> is for the coming annotations.  */
- 
- template<typename Sink>
- void
- layout_printer<Sink>::start_annotation_line (enum margin_kind margin)
- {
-   m_sink.emit_text_prefix ();
-   m_sink.push_html_tag ("tr", true);
- 
-   char margin_char = (margin == margin_kind::insertion
- 		      ? '+'
- 		      : ' ');
- 
-   if (get_options ().show_line_numbers_p)
-     {
-       /* Print the margin.  If MARGIN_CHAR != ' ', then print up to 3
- 	 of it, right-aligned, padded with spaces.  */
-       m_sink.push_html_tag_with_class ("td", "linenum", true);
-       int i;
-       for (i = 0; i < m_layout.m_linenum_width - 3; i++)
- 	m_sink.add_space ();
-       for (; i < m_layout.m_linenum_width; i++)
- 	m_sink.add_character (margin_char);
-       if (Sink::is_text ())
- 	m_sink.add_text (" |");
-       m_sink.pop_html_tag ("td");
-     }
- 
-   m_sink.push_html_tag_with_class ("td", "left-margin", true);
-   if (margin == margin_kind::insertion)
-     m_sink.add_character (margin_char);
-   else
-     print_leftmost_column ();
-   m_sink.pop_html_tag ("td");
- 
-   m_sink.push_html_tag_with_class ("td",
- 				   (margin == margin_kind::ruler
- 				    ? "ruler"
- 				    : "annotation"),
- 				   true);
- }
- 
- /* End a source or annotation line: text implementation.
-    Reset any colorization and emit a newline.  */
- 
- template<>
- void
- layout_printer<to_text>::end_line ()
- {
-   m_sink.colorize_text_ensure_normal ();
-   m_sink.add_newline ();
- }
- 
- /* End a source or annotation line: HTML implementation.
-    Close the <td> and <tr> tags.  */
- 
- template<>
- void
- layout_printer<to_html>::end_line ()
- {
-   m_sink.pop_html_tag ("td");
-   m_sink.pop_html_tag ("tr");
- }
- 
- /* Handle the various transitions between being-in-range and
-    not-being-in-a-range, and between ranges.  */
- 
- template<typename Sink>
- void
- layout_printer<Sink>::set_in_range (int range_idx)
- {
-   if (m_was_in_range_p)
-     {
-       if (m_last_range_idx != range_idx)
- 	{
- 	  /* transition between ranges.  */
- 	  end_label (m_last_range_idx, false);
- 	  begin_label (range_idx, false);
- 	}
-     }
-   else
-     {
-       /* transition from "not in a range" to "in a range".  */
-       begin_label (range_idx, false);
-       m_was_in_range_p = true;
-     }
-   m_last_range_idx = range_idx;
- }
- 
- template<typename Sink>
- void
- layout_printer<Sink>::set_outside_range ()
- {
-   if (m_was_in_range_p)
-     /* transition from "in a range" to "not in a range".  */
-     end_label (m_last_range_idx, false);
-   m_was_in_range_p = false;
- }
- 
- /* Print a line consisting of the caret/underlines for the given
-    source line.  */
- 
- template<typename Sink>
- void
- layout_printer<Sink>::print_annotation_line (linenum_type row,
- 					     const line_bounds lbounds)
- {
-   int x_bound = m_layout.get_x_bound_for_row (row,
- 					      m_layout.m_exploc.m_display_col,
- 					      lbounds.m_last_non_ws_disp_col);
- 
-   start_annotation_line (margin_kind::normal);
- 
-   for (int column = 1 + m_layout.m_x_offset_display; column < x_bound; column++)
-     {
-       bool in_range_p;
-       point_state state;
-       in_range_p = m_layout.get_state_at_point (row, column,
- 						lbounds.m_first_non_ws_disp_col,
- 						lbounds.m_last_non_ws_disp_col,
- 						CU_DISPLAY_COLS,
- 						&state);
-       if (in_range_p)
- 	set_in_range (state.range_idx);
-       else
- 	set_outside_range ();
- 
-       if (in_range_p)
- 	{
- 	  /* Within a range.  Draw either the caret or an underline.  */
- 	  if (state.draw_caret_p)
- 	    {
- 	      /* Draw the caret.  */
- 	      char caret_char;
- 	      if (state.range_idx < rich_location::STATICALLY_ALLOCATED_RANGES)
- 		caret_char = get_options ().caret_chars[state.range_idx];
- 	      else
- 		caret_char = '^';
- 	      m_sink.add_character (caret_char);
- 	    }
- 	  else
- 	    m_sink.add_character ('~');
- 	}
-       else
- 	{
- 	  /* Not in a range.  */
- 	  m_sink.add_character (' ');
- 	}
-     }
- 
-   set_outside_range ();
- 
-   end_line ();
- }
- 
- /* A version of label_text that can live inside a vec.
-    Requires manual cleanup via maybe_free.  */
- 
- struct pod_label_text
- {
-   pod_label_text ()
-   : m_buffer (nullptr), m_caller_owned (false)
-   {}
- 
-   pod_label_text (label_text &&other)
-   : m_buffer (const_cast<char*> (other.get ())),
-     m_caller_owned (other.is_owner ())
-   {
-     other.release ();
-   }
- 
-   void maybe_free ()
-   {
-     if (m_caller_owned)
-       free (m_buffer);
-   }
- 
-   char *m_buffer;
-   bool m_caller_owned;
- };
- 
- /* Implementation detail of layout::print_any_labels.
- 
-    A label within the given row of source.  */
- 
- class line_label
- {
- public:
-   line_label (unsigned original_range_idx,
- 	      int state_idx, int column,
- 	      label_text text,
- 	      bool has_in_edge,
- 	      bool has_out_edge)
-   : m_original_range_idx (original_range_idx),
-     m_state_idx (state_idx), m_column (column),
-     m_text (std::move (text)), m_label_line (0), m_has_vbar (true),
-     m_has_in_edge (has_in_edge),
-     m_has_out_edge (has_out_edge)
-   {
-     /* Using styled_string rather than cpp_display_width here
-        lets us skip SGR formatting characters for color and URLs.
-        It doesn't handle tabs and unicode escaping, but we don't
-        expect to see either of those in labels.  */
-     text_art::style_manager sm;
-     text_art::styled_string str (sm, m_text.m_buffer);
-     m_display_width = str.calc_canvas_width ();
-   }
- 
-   /* Sorting is primarily by column, then by state index.  */
-   static int comparator (const void *p1, const void *p2)
-   {
-     const line_label *ll1 = (const line_label *)p1;
-     const line_label *ll2 = (const line_label *)p2;
-     int column_cmp = compare (ll1->m_column, ll2->m_column);
-     if (column_cmp)
-       return column_cmp;
-     /* Order by reverse state index, so that labels are printed
-        in order of insertion into the rich_location when the
-        sorted list is walked backwards.  */
-     return -compare (ll1->m_state_idx, ll2->m_state_idx);
-   }
- 
-   unsigned m_original_range_idx;
-   int m_state_idx;
-   int m_column;
-   pod_label_text m_text;
-   size_t m_display_width;
-   int m_label_line;
-   bool m_has_vbar;
-   bool m_has_in_edge;
-   bool m_has_out_edge;
- };
- 
- /* Implementations of layout_printer::{begin,end}_label for
-    to_text and to_html.
- 
-    RANGE_IDX is the index of the range within the rich_location.
- 
-    IS_LABEL_TEXT is true for the text of the label,
-    false when quoting the source code, underlining the source
-    code, and for the vertical bars connecting the underlines
-    to the text of the label.  */
- 
- template<>
- void
- layout_printer<to_text>::begin_label (int range_idx,
- 				      bool is_label_text)
- {
-   /* Colorize the text, unless it's for labels for events in a
-      diagnostic_path.  */
-   if (is_label_text && m_is_diagnostic_path)
-     return;
- 
-   gcc_assert (m_sink.m_colorizer);
-   m_sink.m_colorizer->set_range (range_idx);
- }
- 
- template<>
- void
- layout_printer<to_html>::begin_label (int range_idx,
- 				      bool is_label_text)
- {
-   if (is_label_text && m_sink.m_html_label_writer)
-     m_sink.m_html_label_writer->begin_label ();
- 
-   if (const char *highlight_color
- 	= m_sink.get_highlight_color_for_range_idx (range_idx))
-     m_sink.m_xp.push_tag_with_class ("span", highlight_color);
- }
- 
- template<>
- void
- layout_printer<to_text>::end_label (int, bool)
- {
-   m_sink.colorize_text_ensure_normal ();
- }
- 
- template<>
- void
- layout_printer<to_html>::end_label (int range_idx,
- 				    bool is_label_text)
- {
-   if (m_sink.get_highlight_color_for_range_idx (range_idx))
-     m_sink.m_xp.pop_tag ("span");
- 
-   if (is_label_text && m_sink.m_html_label_writer)
-     m_sink.m_html_label_writer->end_label ();
- }
- 
- /* Print any labels in this row.  */
- template <typename Sink>
- void
- layout_printer<Sink>::print_any_labels (linenum_type row)
- {
-   int i;
-   auto_vec<line_label> labels;
- 
-   /* Gather the labels that are to be printed into "labels".  */
-   {
-     layout_range *range;
-     FOR_EACH_VEC_ELT (m_layout.m_layout_ranges, i, range)
-       {
- 	/* Most ranges don't have labels, so reject this first.  */
- 	if (range->m_label == nullptr)
- 	  continue;
- 
- 	/* The range's caret must be on this line.  */
- 	if (range->m_caret.m_line != row)
- 	  continue;
- 
- 	/* Reject labels that aren't fully visible due to clipping
- 	   by m_x_offset_display.  */
- 	const int disp_col = range->m_caret.m_columns[CU_DISPLAY_COLS];
- 	if (disp_col <= m_layout.m_x_offset_display)
- 	  continue;
- 
- 	label_text text;
- 	text = range->m_label->get_text (range->m_original_idx);
- 
- 	/* Allow for labels that return nullptr from their get_text
- 	   implementation (so e.g. such labels can control their own
- 	   visibility).  */
- 	if (text.get () == nullptr)
- 	  continue;
- 
- 	labels.safe_push (line_label (range->m_original_idx,
- 				      i, disp_col, std::move (text),
- 				      range->has_in_edge (),
- 				      range->has_out_edge ()));
-       }
-   }
- 
-   /* Bail out if there are no labels on this row.  */
-   if (labels.length () == 0)
-     return;
- 
-   /* Sort them.  */
-   labels.qsort(line_label::comparator);
- 
-   /* Figure out how many "label lines" we need, and which
-      one each label is printed in.
- 
-      For example, if the labels aren't too densely packed,
-      we can fit them on the same line, giving two "label lines":
- 
-        foo + bar
-        ~~~   ~~~
-        |     |        : label line 0
-        l0    l1       : label line 1
- 
-      If they would touch each other or overlap, then we need
-      additional "label lines":
- 
-        foo + bar
-        ~~~   ~~~
-        |     |             : label line 0
-        |     label 1       : label line 1
-        label 0             : label line 2
- 
-      Place the final label on label line 1, and work backwards, adding
-      label lines as needed.
- 
-      If multiple labels are at the same place, put them on separate
-      label lines:
- 
-        foo + bar
-            ^               : label line 0
-            |               : label line 1
-            label 0         : label line 2
-            label 1         : label line 3.  */
- 
-   int max_label_line = 1;
-   int label_line_with_in_edge = -1;
-   {
-     int next_column = INT_MAX;
-     line_label *label;
-     FOR_EACH_VEC_ELT_REVERSE (labels, i, label)
-       {
- 	/* Would this label "touch" or overlap the next label?  */
- 	if (label->m_column + label->m_display_width >= (size_t)next_column)
- 	  {
- 	    max_label_line++;
- 
- 	    /* If we've already seen labels with the same column, suppress the
- 	       vertical bar for subsequent ones in this backwards iteration;
- 	       hence only the one with the highest label_line has m_has_vbar set.  */
- 	    if (label->m_column == next_column)
- 	      label->m_has_vbar = false;
- 	  }
- 
- 	label->m_label_line = max_label_line;
- 	if (get_options ().show_event_links_p)
- 	  if (label->m_has_in_edge)
- 	    label_line_with_in_edge = max_label_line;
- 	next_column = label->m_column;
-       }
-   }
- 
-   gcc_assert (labels.length () > 0);
- 
-   /* Print the "label lines".  For each label within the line, print
-      either a vertical bar ('|') for the labels that are lower down, or the
-      labels themselves once we've reached their line.  */
-   {
-     for (int label_line = 0; label_line <= max_label_line; label_line++)
-       {
- 	if (label_line == label_line_with_in_edge)
- 	  {
- 	    gcc_assert (get_options ().show_event_links_p);
- 	    m_link_lhs_state = link_lhs_state::indenting_to_dest;
- 	  }
- 	start_annotation_line (margin_kind::normal);
- 
- 	int column = 1 + m_layout.m_x_offset_display;
- 	line_label *label;
- 	FOR_EACH_VEC_ELT (labels, i, label)
- 	  {
- 	    if (label_line > label->m_label_line)
- 	      /* We've printed all the labels for this label line.  */
- 	      break;
- 
- 	    if (label_line == label->m_label_line)
- 	      {
- 		gcc_assert (column <= label->m_column);
- 
- 		if (label_line == label_line_with_in_edge)
- 		  {
- 		    /* Print a prefix showing an incoming
- 		       link from another label.
- 		       .|+----------->(10) ...to here
- 		       . ^~~~~~~~~~~~~
- 		       . this text.  */
- 		    gcc_assert (get_options ().show_event_links_p);
- 		    m_sink.colorize_text_for_cfg_edge ();
- 		    const cppchar_t right= get_theme ().get_cppchar
- 		      (text_art::theme::cell_kind::CFG_RIGHT);
- 		    while (column < label->m_column - 1)
- 		      {
- 			m_sink.add_character (right);
- 			column++;
- 		      }
- 		    if (column == label->m_column - 1)
- 		      {
- 			m_sink.add_character ('>');
- 			column++;
- 		      }
- 		    m_sink.colorize_text_ensure_normal ();
- 		    m_link_lhs_state = link_lhs_state::none;
- 		    label_line_with_in_edge = -1;
- 		  }
- 		else
- 		  move_to_column (&column, label->m_column, true);
- 		gcc_assert (column == label->m_column);
- 
- 		begin_label (label->m_state_idx, true);
- 		m_sink.add_text (label->m_text.m_buffer);
- 		end_label (label->m_state_idx, true);
- 
- 		column += label->m_display_width;
- 		if (get_options ().show_event_links_p && label->m_has_out_edge)
- 		  {
- 		    /* Print a suffix showing the start of a linkage
- 		       to another label e.g. " ->-+" which will be the
- 		       first part of e.g.
- 		       .      (9) following ‘false’ branch... ->-+ <- HERE
- 		       .                                         |
- 		       .                                         |
- 		       .  */
- 		    const cppchar_t right= get_theme ().get_cppchar
- 		      (text_art::theme::cell_kind::CFG_RIGHT);
- 		    const cppchar_t from_right_to_down= get_theme ().get_cppchar
- 		      (text_art::theme::cell_kind::CFG_FROM_RIGHT_TO_DOWN);
- 		    m_sink.colorize_text_for_cfg_edge ();
- 		    m_sink.add_space ();
- 		    m_sink.add_character (right);
- 		    m_sink.add_character ('>');
- 		    m_sink.add_character (right);
- 		    m_sink.add_character (from_right_to_down);
- 		    m_sink.colorize_text_ensure_normal ();
- 		    column += 5;
- 		    m_link_rhs_column = column - 1;
- 		  }
- 	      }
- 	    else if (label->m_has_vbar)
- 	      {
- 		gcc_assert (column <= label->m_column);
- 		move_to_column (&column, label->m_column, true);
- 		begin_label (label->m_state_idx, false);
- 		m_sink.add_character ('|');
- 		end_label (label->m_state_idx, false);
- 		column++;
- 	      }
- 	  }
- 
- 	/* If we have a vertical link line on the RHS, print the
- 	   '|' on this annotation line after the labels.  */
- 	if (m_link_rhs_column != -1 && column < m_link_rhs_column)
- 	  {
- 	    move_to_column (&column, m_link_rhs_column, true);
- 	    m_sink.colorize_text_for_cfg_edge ();
- 	    const cppchar_t down= get_theme ().get_cppchar
- 	      (text_art::theme::cell_kind::CFG_DOWN);
- 	    m_sink.add_character (down);
- 	    m_sink.colorize_text_ensure_normal ();
- 	  }
- 
- 	end_line ();
-       }
-     }
- 
-   /* If we have a vertical link line on the RHS, print a trailing
-      annotation line showing the vertical line.  */
-   if (m_link_rhs_column != -1)
-     {
-       int column = 1 + m_layout.m_x_offset_display;
-       start_annotation_line (margin_kind::normal);
-       move_to_column (&column, m_link_rhs_column, true);
-       m_sink.colorize_text_for_cfg_edge ();
-       const cppchar_t down= get_theme ().get_cppchar
- 	(text_art::theme::cell_kind::CFG_DOWN);
-       m_sink.add_character (down);
-       end_line ();
-     }
- 
-   /* Clean up.  */
-   {
-     line_label *label;
-     FOR_EACH_VEC_ELT (labels, i, label)
-       label->m_text.maybe_free ();
-   }
- }
- 
- /* If there are any fixit hints inserting new lines before source line ROW,
-    print them.
- 
-    They are printed on lines of their own, before the source line
-    itself, with a leading '+'.  */
- 
- template <typename Sink>
- void
- layout_printer<Sink>::print_leading_fixits (linenum_type row)
- {
-   for (unsigned int i = 0; i < m_layout.m_fixit_hints.length (); i++)
-     {
-       const fixit_hint *hint = m_layout.m_fixit_hints[i];
- 
-       if (!hint->ends_with_newline_p ())
- 	/* Not a newline fixit; print it in print_trailing_fixits.  */
- 	continue;
- 
-       gcc_assert (hint->insertion_p ());
- 
-       if (hint->affects_line_p (m_layout.m_line_table,
- 				m_layout.m_exploc.file,
- 				row))
- 	{
- 	  /* Printing the '+' with normal colorization
- 	     and the inserted line with "insert" colorization
- 	     helps them stand out from each other, and from
- 	     the surrounding text.  */
- 	  m_sink.colorize_text_ensure_normal ();
- 	  start_annotation_line (margin_kind::insertion);
- 	  m_sink.colorize_text_for_fixit_insert ();
- 	  /* Print all but the trailing newline of the fix-it hint.
- 	     We have to print the newline separately to avoid
- 	     getting additional pp prefixes printed.  */
- 	  for (size_t i = 0; i < hint->get_length () - 1; i++)
- 	    m_sink.add_character (hint->get_string ()[i]);
- 	  end_line ();
- 	}
-     }
- }
- 
- /* Subroutine of layout::print_trailing_fixits.
- 
-    Determine if the annotation line printed for LINE contained
-    the exact range from START_COLUMN to FINISH_COLUMN (in display units).  */
- 
- bool
- layout::annotation_line_showed_range_p (linenum_type line, int start_column,
- 					int finish_column) const
- {
-   layout_range *range;
-   int i;
-   FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
-     if (range->m_start.m_line == line
- 	&& range->m_start.m_columns[CU_DISPLAY_COLS] == start_column
- 	&& range->m_finish.m_line == line
- 	&& range->m_finish.m_columns[CU_DISPLAY_COLS] == finish_column)
-       return true;
-   return false;
- }
- 
- /* Classes for printing trailing fix-it hints i.e. those that
-    don't add new lines.
- 
-    For insertion, these can look like:
- 
-      new_text
- 
-    For replacement, these can look like:
- 
-      ------------- : underline showing affected range
-      new_text
- 
-    For deletion, these can look like:
- 
-      ------------- : underline showing affected range
- 
-    This can become confusing if they overlap, and so we need
-    to do some preprocessing to decide what to print.
-    We use the list of fixit_hint instances affecting the line
-    to build a list of "correction" instances, and print the
-    latter.
- 
-    For example, consider a set of fix-its for converting
-    a C-style cast to a C++ const_cast.
- 
-    Given:
- 
-    ..000000000111111111122222222223333333333.
-    ..123456789012345678901234567890123456789.
-      foo *f = (foo *)ptr->field;
-                           ^~~~~
- 
-    and the fix-it hints:
-      - replace col 10 (the open paren) with "const_cast<"
-      - replace col 16 (the close paren) with "> ("
-      - insert ")" before col 27
- 
-    then we would get odd-looking output:
- 
-      foo *f = (foo *)ptr->field;
-                           ^~~~~
-               -
-               const_cast<
-                     -
-                     > (        )
- 
-    It would be better to detect when fixit hints are going to
-    overlap (those that require new lines), and to consolidate
-    the printing of such fixits, giving something like:
- 
-      foo *f = (foo *)ptr->field;
-                           ^~~~~
-               -----------------
-               const_cast<foo *> (ptr->field)
- 
-    This works by detecting when the printing would overlap, and
-    effectively injecting no-op replace hints into the gaps between
-    such fix-its, so that the printing joins up.
- 
-    In the above example, the overlap of:
-      - replace col 10 (the open paren) with "const_cast<"
-    and:
-      - replace col 16 (the close paren) with "> ("
-    is fixed by injecting a no-op:
-      - replace cols 11-15 with themselves ("foo *")
-    and consolidating these, making:
-      - replace cols 10-16 with "const_cast<" + "foo *" + "> ("
-    i.e.:
-      - replace cols 10-16 with "const_cast<foo *> ("
- 
-    This overlaps with the final fix-it hint:
-      - insert ")" before col 27
-    and so we repeat the consolidation process, by injecting
-    a no-op:
-      - replace cols 17-26 with themselves ("ptr->field")
-    giving:
-      - replace cols 10-26 with "const_cast<foo *> (" + "ptr->field" + ")"
-    i.e.:
-      - replace cols 10-26 with "const_cast<foo *> (ptr->field)"
- 
-    and is thus printed as desired.  */
- 
- /* A range of (byte or display) columns within a line.  */
- 
- class column_range
- {
- public:
-   column_range (int start_, int finish_) : start (start_), finish (finish_)
-   {
-     gcc_assert (valid_p (start, finish));
-   }
- 
-   bool operator== (const column_range &other) const
-   {
-     return start == other.start && finish == other.finish;
-   }
- 
-   static bool valid_p (int start, int finish)
-   {
-     /* We must have either a range, or an insertion.  */
-     return (start <= finish || finish == start - 1);
-   }
- 
-   int start;
-   int finish;
- };
- 
- /* Get the range of bytes or display columns that HINT would affect.  */
- static column_range
- get_affected_range (file_cache &fc,
- 		    const cpp_char_column_policy &policy,
- 		    const fixit_hint *hint, enum column_unit col_unit)
- {
-   expanded_location exploc_start = expand_location (hint->get_start_loc ());
-   expanded_location exploc_finish = expand_location (hint->get_next_loc ());
-   --exploc_finish.column;
- 
-   int start_column;
-   int finish_column;
-   if (col_unit == CU_DISPLAY_COLS)
-     {
-       start_column = location_compute_display_column (fc, exploc_start, policy);
-       if (hint->insertion_p ())
- 	finish_column = start_column - 1;
-       else
- 	finish_column
- 	  = location_compute_display_column (fc, exploc_finish, policy);
-     }
-   else
-     {
-       start_column = exploc_start.column;
-       finish_column = exploc_finish.column;
-     }
-   return column_range (start_column, finish_column);
- }
- 
- /* Get the range of display columns that would be printed for HINT.  */
- 
- static column_range
- get_printed_columns (file_cache &fc,
- 		     const cpp_char_column_policy &policy,
- 		     const fixit_hint *hint)
- {
-   expanded_location exploc = expand_location (hint->get_start_loc ());
-   int start_column = location_compute_display_column (fc, exploc, policy);
-   int hint_width = cpp_display_width (hint->get_string (), hint->get_length (),
- 				      policy);
-   int final_hint_column = start_column + hint_width - 1;
-   if (hint->insertion_p ())
-     {
-       return column_range (start_column, final_hint_column);
-     }
-   else
-     {
-       exploc = expand_location (hint->get_next_loc ());
-       --exploc.column;
-       int finish_column = location_compute_display_column (fc, exploc, policy);
-       return column_range (start_column,
- 			   MAX (finish_column, final_hint_column));
-     }
- }
- 
- /* A correction on a particular line.
-    This describes a plan for how to print one or more fixit_hint
-    instances that affected the line, potentially consolidating hints
-    into corrections to make the result easier for the user to read.  */
- 
- class correction
- {
- public:
-   correction (column_range affected_bytes,
- 	      column_range affected_columns,
- 	      column_range printed_columns,
- 	      const char *new_text, size_t new_text_len,
- 	      const cpp_char_column_policy &policy)
-   : m_affected_bytes (affected_bytes),
-     m_affected_columns (affected_columns),
-     m_printed_columns (printed_columns),
-     m_text (xstrdup (new_text)),
-     m_byte_length (new_text_len),
-     m_policy (policy),
-     m_alloc_sz (new_text_len + 1)
-   {
-     compute_display_cols ();
-   }
- 
-   ~correction () { free (m_text); }
- 
-   bool insertion_p () const
-   {
-     return m_affected_bytes.start == m_affected_bytes.finish + 1;
-   }
- 
-   void ensure_capacity (size_t len);
-   void ensure_terminated ();
- 
-   void compute_display_cols ()
-   {
-     m_display_cols = cpp_display_width (m_text, m_byte_length, m_policy);
-   }
- 
-   void overwrite (int dst_offset, const char_span &src_span)
-   {
-     gcc_assert (dst_offset >= 0);
-     gcc_assert (dst_offset + src_span.length () < m_alloc_sz);
-     memcpy (m_text + dst_offset, src_span.get_buffer (),
- 	    src_span.length ());
-   }
- 
-   /* If insert, then start: the column before which the text
-      is to be inserted, and finish is offset by the length of
-      the replacement.
-      If replace, then the range of columns affected.  */
-   column_range m_affected_bytes;
-   column_range m_affected_columns;
- 
-   /* If insert, then start: the column before which the text
-      is to be inserted, and finish is offset by the length of
-      the replacement.
-      If replace, then the range of columns affected.  */
-   column_range m_printed_columns;
- 
-   /* The text to be inserted/used as replacement.  */
-   char *m_text;
-   size_t m_byte_length; /* Not including null-terminator.  */
-   int m_display_cols;
-   const cpp_char_column_policy &m_policy;
-   size_t m_alloc_sz;
- };
- 
- /* Ensure that m_text can hold a string of length LEN
-    (plus 1 for 0-termination).  */
- 
- void
- correction::ensure_capacity (size_t len)
- {
-   /* Allow 1 extra byte for 0-termination.  */
-   if (m_alloc_sz < (len + 1))
-     {
-       size_t new_alloc_sz = (len + 1) * 2;
-       m_text = (char *)xrealloc (m_text, new_alloc_sz);
-       m_alloc_sz = new_alloc_sz;
-     }
- }
- 
- /* Ensure that m_text is 0-terminated.  */
- 
- void
- correction::ensure_terminated ()
- {
-   /* 0-terminate the buffer.  */
-   gcc_assert (m_byte_length < m_alloc_sz);
-   m_text[m_byte_length] = '\0';
- }
- 
- /* A list of corrections affecting a particular line.
-    This is used by layout::print_trailing_fixits for planning
-    how to print the fix-it hints affecting the line.  */
- 
- class line_corrections
- {
- public:
-   line_corrections (file_cache &fc,
- 		    const char_display_policy &policy,
- 		    const char *filename,
- 		    linenum_type row)
-   : m_file_cache (fc),
-     m_policy (policy), m_filename (filename), m_row (row)
-   {}
-   ~line_corrections ();
- 
-   void add_hint (const fixit_hint *hint);
- 
-   file_cache &m_file_cache;
-   const char_display_policy &m_policy;
-   const char *m_filename;
-   linenum_type m_row;
-   auto_vec <correction *> m_corrections;
- };
- 
- /* struct line_corrections.  */
- 
- line_corrections::~line_corrections ()
- {
-   unsigned i;
-   correction *c;
-   FOR_EACH_VEC_ELT (m_corrections, i, c)
-     delete c;
- }
- 
- /* A struct wrapping a particular source line, allowing
-    run-time bounds-checking of accesses in a checked build.  */
- 
- class source_line
- {
- public:
-   source_line (file_cache &fc, const char *filename, int line);
- 
-   char_span as_span () { return char_span (chars, width); }
- 
-   const char *chars;
-   int width;
- };
- 
- /* source_line's ctor.  */
- 
- source_line::source_line (file_cache &fc, const char *filename, int line)
- {
-   char_span span = fc.get_source_line (filename, line);
-   chars = span.get_buffer ();
-   width = span.length ();
- }
- 
- /* Add HINT to the corrections for this line.
-    Attempt to consolidate nearby hints so that they will not
-    overlap with printed.  */
- 
- void
- line_corrections::add_hint (const fixit_hint *hint)
- {
-   column_range affected_bytes
-     = get_affected_range (m_file_cache, m_policy, hint, CU_BYTES);
-   column_range affected_columns
-     = get_affected_range (m_file_cache, m_policy, hint, CU_DISPLAY_COLS);
-   column_range printed_columns
-     = get_printed_columns (m_file_cache, m_policy, hint);
- 
-   /* Potentially consolidate.  */
-   if (!m_corrections.is_empty ())
-     {
-       correction *last_correction
- 	= m_corrections[m_corrections.length () - 1];
- 
-       /* The following consolidation code assumes that the fix-it hints
- 	 have been sorted by start (done within layout's ctor).  */
-       gcc_assert (affected_bytes.start
- 		  >= last_correction->m_affected_bytes.start);
-       gcc_assert (printed_columns.start
- 		  >= last_correction->m_printed_columns.start);
- 
-       if (printed_columns.start <= last_correction->m_printed_columns.finish
- 	  && column_range::valid_p (last_correction->m_affected_bytes.finish + 1,
- 				    affected_bytes.start - 1))
- 	{
- 	  /* We have two hints for which the printed forms of the hints
- 	     would touch or overlap, so we need to consolidate them to avoid
- 	     confusing the user.
- 	     Attempt to inject a "replace" correction from immediately
- 	     after the end of the last hint to immediately before the start
- 	     of the next hint.  */
- 	  column_range between (last_correction->m_affected_bytes.finish + 1,
- 				affected_bytes.start - 1);
- 
- 	  /* Try to read the source.  */
- 	  source_line line (m_file_cache, m_filename, m_row);
- 	  if (line.chars && between.finish < line.width)
- 	    {
- 	      /* Consolidate into the last correction:
- 		 add a no-op "replace" of the "between" text, and
- 		 add the text from the new hint.  */
- 	      int old_byte_len = last_correction->m_byte_length;
- 	      gcc_assert (old_byte_len >= 0);
- 	      int between_byte_len = between.finish + 1 - between.start;
- 	      gcc_assert (between_byte_len >= 0);
- 	      int new_byte_len
- 		= old_byte_len + between_byte_len + hint->get_length ();
- 	      gcc_assert (new_byte_len >= 0);
- 	      last_correction->ensure_capacity (new_byte_len);
- 	      last_correction->overwrite
- 		(old_byte_len,
- 		 line.as_span ().subspan (between.start - 1,
- 					  between.finish + 1 - between.start));
- 	      last_correction->overwrite (old_byte_len + between_byte_len,
- 					  char_span (hint->get_string (),
- 						     hint->get_length ()));
- 	      last_correction->m_byte_length = new_byte_len;
- 	      last_correction->ensure_terminated ();
- 	      last_correction->m_affected_bytes.finish
- 		= affected_bytes.finish;
- 	      last_correction->m_affected_columns.finish
- 		= affected_columns.finish;
- 	      int prev_display_cols = last_correction->m_display_cols;
- 	      last_correction->compute_display_cols ();
- 	      last_correction->m_printed_columns.finish
- 		+= last_correction->m_display_cols - prev_display_cols;
- 	      return;
- 	    }
- 	}
-     }
- 
-   /* If no consolidation happened, add a new correction instance.  */
-   m_corrections.safe_push (new correction (affected_bytes,
- 					   affected_columns,
- 					   printed_columns,
- 					   hint->get_string (),
- 					   hint->get_length (),
- 					   m_policy));
- }
- 
- /* If there are any fixit hints on source line ROW, print them.
-    They are printed in order, attempting to combine them onto lines, but
-    starting new lines if necessary.
-    Fix-it hints that insert new lines are handled separately,
-    in layout::print_leading_fixits.  */
- 
- template<typename Sink>
- void
- layout_printer<Sink>::print_trailing_fixits (linenum_type row)
- {
-   typename Sink::auto_check_tag_nesting sentinel (m_sink);
- 
-   /* Build a list of correction instances for the line,
-      potentially consolidating hints (for the sake of readability).  */
-   line_corrections corrections (m_layout.m_file_cache, m_layout.m_char_policy,
- 				m_layout.m_exploc.file, row);
-   for (unsigned int i = 0; i < m_layout.m_fixit_hints.length (); i++)
-     {
-       const fixit_hint *hint = m_layout.m_fixit_hints[i];
- 
-       /* Newline fixits are handled by layout::print_leading_fixits.  */
-       if (hint->ends_with_newline_p ())
- 	continue;
- 
-       if (hint->affects_line_p (m_layout.m_line_table,
- 				m_layout.m_exploc.file,
- 				row))
- 	corrections.add_hint (hint);
-     }
- 
-   /* Now print the corrections.  */
-   unsigned i;
-   correction *c;
-   int column = 1 + m_layout.m_x_offset_display;
- 
-   if (!corrections.m_corrections.is_empty ())
-     start_annotation_line (margin_kind::normal);
- 
-   FOR_EACH_VEC_ELT (corrections.m_corrections, i, c)
-     {
-       /* For now we assume each fixit hint can only touch one line.  */
-       if (c->insertion_p ())
- 	{
- 	  /* This assumes the insertion just affects one line.  */
- 	  int start_column = c->m_printed_columns.start;
- 	  move_to_column (&column, start_column, true);
- 	  m_sink.colorize_text_for_fixit_insert ();
- 	  m_sink.add_text (c->m_text);
- 	  m_sink.colorize_text_ensure_normal ();
- 	  column += c->m_display_cols;
- 	}
-       else
- 	{
- 	  /* If the range of the replacement wasn't printed in the
- 	     annotation line, then print an extra underline to
- 	     indicate exactly what is being replaced.
- 	     Always show it for removals.  */
- 	  int start_column = c->m_affected_columns.start;
- 	  int finish_column = c->m_affected_columns.finish;
- 	  if (!m_layout.annotation_line_showed_range_p (row, start_column,
- 							finish_column)
- 	      || c->m_byte_length == 0)
- 	    {
- 	      move_to_column (&column, start_column, true);
- 	      m_sink.colorize_text_for_fixit_delete ();
- 	      for (; column <= finish_column; column++)
- 		m_sink.add_character ('-');
- 	      m_sink.colorize_text_ensure_normal ();
- 	    }
- 	  /* Print the replacement text.  REPLACE also covers
- 	     removals, so only do this extra work (potentially starting
- 	     a new line) if we have actual replacement text.  */
- 	  if (c->m_byte_length > 0)
- 	    {
- 	      move_to_column (&column, start_column, true);
- 	      m_sink.colorize_text_for_fixit_insert ();
- 	      m_sink.add_text (c->m_text);
- 	      m_sink.colorize_text_ensure_normal ();
- 	      column += c->m_display_cols;
- 	    }
- 	}
-     }
- 
-   /* Add a trailing newline, if necessary.  */
-   move_to_column (&column, 1 + m_layout.m_x_offset_display, false);
- }
- 
- /* Return true if (ROW/COLUMN) is within a range of the layout.
-    If it returns true, OUT_STATE is written to, with the
-    range index, and whether we should draw the caret at
-    (ROW/COLUMN) (as opposed to an underline).  COL_UNIT controls
-    whether all inputs and outputs are in bytes or display column units.  */
- 
- bool
- layout::get_state_at_point (/* Inputs.  */
- 			    linenum_type row, int column,
- 			    int first_non_ws, int last_non_ws,
- 			    enum column_unit col_unit,
- 			    /* Outputs.  */
- 			    point_state *out_state) const
- {
-   layout_range *range;
-   int i;
-   FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
-     {
-       if (range->m_range_display_kind == SHOW_LINES_WITHOUT_RANGE)
- 	/* Bail out early, so that such ranges don't affect underlining or
- 	   source colorization.  */
- 	continue;
- 
-       if (range->contains_point (row, column, col_unit))
- 	{
- 	  out_state->range_idx = i;
- 
- 	  /* Are we at the range's caret?  is it visible? */
- 	  out_state->draw_caret_p = false;
- 	  if (range->m_range_display_kind == SHOW_RANGE_WITH_CARET
- 	      && row == range->m_caret.m_line
- 	      && column == range->m_caret.m_columns[col_unit])
- 	    out_state->draw_caret_p = true;
- 
- 	  /* Within a multiline range, don't display any underline
- 	     in any leading or trailing whitespace on a line.
- 	     We do display carets, however.  */
- 	  if (!out_state->draw_caret_p)
- 	    if (column < first_non_ws || column > last_non_ws)
- 	      return false;
- 
- 	  /* We are within a range.  */
- 	  return true;
- 	}
-     }
- 
-   return false;
- }
- 
- /* Helper function for use by layout::print_line when printing the
-    annotation line under the source line.
-    Get the display column beyond the rightmost one that could contain a caret
-    or range marker, given that we stop rendering at trailing whitespace.
-    ROW is the source line within the given file.
-    CARET_COLUMN is the display column of range 0's caret.
-    LAST_NON_WS_COLUMN is the last display column containing a non-whitespace
-    character of source (as determined when printing the source line).  */
- 
- int
- layout::get_x_bound_for_row (linenum_type row, int caret_column,
- 			     int last_non_ws_column) const
- {
-   int result = caret_column + 1;
- 
-   layout_range *range;
-   int i;
-   FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
-     {
-       if (row >= range->m_start.m_line)
- 	{
- 	  if (range->m_finish.m_line == row)
- 	    {
- 	      /* On the final line within a range; ensure that
- 		 we render up to the end of the range.  */
- 	      const int disp_col = range->m_finish.m_columns[CU_DISPLAY_COLS];
- 	      if (result <= disp_col)
- 		result = disp_col + 1;
- 	    }
- 	  else if (row < range->m_finish.m_line)
- 	    {
- 	      /* Within a multiline range; ensure that we render up to the
- 		 last non-whitespace column.  */
- 	      if (result <= last_non_ws_column)
- 		result = last_non_ws_column + 1;
- 	    }
- 	}
-     }
- 
-   return result;
- }
- 
- /* Given *COLUMN as an x-coordinate, print spaces to position
-    successive output at DEST_COLUMN, printing a newline if necessary,
-    and updating *COLUMN.  If ADD_LEFT_MARGIN, then print the (empty)
-    left margin after any newline.  */
- 
- template<typename Sink>
- void
- layout_printer<Sink>::move_to_column (int *column,
- 				      int dest_column,
- 				      bool add_left_margin)
- {
-   /* Start a new line if we need to.  */
-   if (*column > dest_column)
-     {
-       end_line ();
-       if (add_left_margin)
- 	start_annotation_line (margin_kind::normal);
-       *column = 1 + m_layout.m_x_offset_display;
-     }
- 
-   while (*column < dest_column)
-     {
-       /* For debugging column issues, it can be helpful to replace this
- 	 add_space call with
- 	   m_sink.add_character ('0' + (*column % 10));
- 	 to visualize the changing value of "*column".  */
-       m_sink.add_space ();
-       (*column)++;
-     }
- }
- 
- /* For debugging layout issues, render a ruler giving column numbers
-    (after the 1-column indent).  */
- 
- template<typename Sink>
- void
- layout_printer<Sink>::show_ruler (int max_column)
- {
-   m_sink.push_html_tag_with_class("thead", "ruler", false);
- 
-   /* Hundreds.  */
-   if (max_column > 99)
-     {
-       start_annotation_line (margin_kind::ruler);
-       for (int column = 1 + m_layout.m_x_offset_display;
- 	   column <= max_column;
- 	   ++column)
- 	if (column % 10 == 0)
- 	  m_sink.add_character ('0' + (column / 100) % 10);
- 	else
- 	  m_sink.add_space ();
-       end_line ();
-     }
- 
-   /* Tens.  */
-   start_annotation_line (margin_kind::ruler);
-   for (int column = 1 + m_layout.m_x_offset_display;
-        column <= max_column;
-        ++column)
-     if (column % 10 == 0)
-       m_sink.add_character ('0' + (column / 10) % 10);
-     else
-       m_sink.add_space ();
-   end_line ();
- 
-   /* Units.  */
-   start_annotation_line (margin_kind::ruler);
-   for (int column = 1 + m_layout.m_x_offset_display;
-        column <= max_column;
-        ++column)
-     m_sink.add_character ('0' + (column % 10));
-   end_line ();
- 
-   m_sink.pop_html_tag("thead"); // thead
- }
- 
- /* Print leading fix-its (for new lines inserted before the source line)
-    then the source line, followed by an annotation line
-    consisting of any caret/underlines, then any fixits.
-    If the source line can't be read, print nothing.  */
- template<typename Sink>
- void
- layout_printer<Sink>::print_line (linenum_type row)
- {
-   typename Sink::auto_check_tag_nesting sentinel (m_sink);
- 
-   char_span line
-     = m_layout.m_file_cache.get_source_line (m_layout.m_exploc.file, row);
-   if (!line)
-     return;
- 
-   print_any_right_to_left_edge_lines ();
-   print_leading_fixits (row);
-   const line_bounds lbounds
-     = print_source_line (row, line.get_buffer (), line.length ());
-   if (m_layout.should_print_annotation_line_p (row))
-     print_annotation_line (row, lbounds);
-   if (get_options ().show_labels_p)
-     print_any_labels (row);
-   print_trailing_fixits (row);
- }
- 
- /* If there's a link column in the RHS, print something like this:
-    "                                           │\n"
-    "┌──────────────────────────────────────────┘\n"
-    showing the link entering at the top right and emerging
-    at the bottom left.  */
- 
- template<typename Sink>
- void
- layout_printer<Sink>::print_any_right_to_left_edge_lines ()
- {
-   if (m_link_rhs_column == -1)
-     /* Can also happen if the out-edge had UNKNOWN_LOCATION.  */
-     return;
- 
-   gcc_assert (get_options ().show_event_links_p);
- 
-   /* Print the line with "|".  */
-   start_annotation_line (margin_kind::normal);
- 
-   int column = 1 + m_layout.m_x_offset_display;
-   move_to_column (&column, m_link_rhs_column, true);
-   m_sink.colorize_text_for_cfg_edge ();
-   const cppchar_t down= get_theme ().get_cppchar
-     (text_art::theme::cell_kind::CFG_DOWN);
-   m_sink.add_character (down);
-   end_line ();
- 
-   /* Print the line with "┌──────────────────────────────────────────┘".  */
-   m_link_lhs_state = link_lhs_state::rewinding_to_lhs;
-   start_annotation_line (margin_kind::normal);
-   m_sink.colorize_text_for_cfg_edge ();
-   const cppchar_t left= get_theme ().get_cppchar
-     (text_art::theme::cell_kind::CFG_LEFT);
-   for (int column = 1 + m_layout.m_x_offset_display;
-        column < m_link_rhs_column;
-        ++column)
-     m_sink.add_character (left);
-   const cppchar_t from_down_to_left = get_theme ().get_cppchar
-     (text_art::theme::cell_kind::CFG_FROM_DOWN_TO_LEFT);
-   m_sink.add_character (from_down_to_left);
-   end_line ();
- 
-   /* We now have a link line on the LHS,
-      and no longer have one on the RHS.  */
-   m_link_lhs_state = link_lhs_state::at_lhs;
-   m_link_rhs_column = -1;
- }
- 
- template<typename Sink>
- layout_printer<Sink>::layout_printer (Sink &sink,
- 				      const layout &layout,
- 				      bool is_diagnostic_path)
- : m_sink (sink),
-   m_layout (layout),
-   m_is_diagnostic_path (is_diagnostic_path),
-   m_was_in_range_p (false),
-   m_last_range_idx (0),
-   m_link_lhs_state (link_lhs_state::none),
-   m_link_rhs_column (-1)
- {
-   if (get_options ().show_event_links_p)
-     if (auto effect_info = m_layout.m_effect_info)
-       if (effect_info->m_leading_in_edge_column)
- 	m_link_rhs_column = effect_info->m_leading_in_edge_column;
- }
- 
- } /* End of anonymous namespace.  */
- 
- /* If LOC is within the spans of lines that will already be printed for
-    this gcc_rich_location, then add it as a secondary location and return true.
- 
-    Otherwise return false.
- 
-    Use POLICY for determining how spans of lines would be printed.  */
- 
- bool
- gcc_rich_location::
- add_location_if_nearby (const diagnostic_source_print_policy &policy,
- 			location_t loc,
- 			bool restrict_to_current_line_spans,
- 			const range_label *label)
- {
-   /* Use the layout location-handling logic to sanitize LOC,
-      filtering it to the current line spans within a temporary
-      layout instance.  */
- 
-   layout layout (policy, *this);
-   location_range loc_range;
-   loc_range.m_loc = loc;
-   loc_range.m_range_display_kind = SHOW_RANGE_WITHOUT_CARET;
-   loc_range.m_label = nullptr;
-   if (!layout.maybe_add_location_range (&loc_range, 0,
- 					restrict_to_current_line_spans))
-     return false;
- 
-   add_range (loc, SHOW_RANGE_WITHOUT_CARET, label);
-   return true;
- }
- 
- bool
- gcc_rich_location::
- add_location_if_nearby (const diagnostic_context &dc,
- 			location_t loc,
- 			bool restrict_to_current_line_spans,
- 			const range_label *label)
- {
-   diagnostic_source_print_policy source_policy (dc,
- 						dc.m_source_printing);
-   return add_location_if_nearby (source_policy, loc,
- 				 restrict_to_current_line_spans, label);
- }
- 
- 
- /* As per diagnostic_source_print_policy::print, but don't print anything
-    if source printing is disabled, or if the location hasn't changed.  */
- 
- void
- diagnostic_context::maybe_show_locus (const rich_location &richloc,
- 				      const diagnostic_source_printing_options &opts,
- 				      diagnostic_t diagnostic_kind,
- 				      pretty_printer &pp,
- 				      diagnostic_source_effect_info *effects)
- {
-   const location_t loc = richloc.get_loc ();
-   /* Do nothing if source-printing has been disabled.  */
-   if (!opts.enabled)
-     return;
- 
-   /* Don't attempt to print source for UNKNOWN_LOCATION and for builtins.  */
-   if (loc <= BUILTINS_LOCATION)
-     return;
- 
-   /* Don't print the same source location twice in a row, unless we have
-      fix-it hints, or multiple locations, or a label.  */
-   if (loc == m_last_location
-       && richloc.get_num_fixit_hints () == 0
-       && richloc.get_num_locations () == 1
-       && richloc.get_range (0)->m_label == nullptr)
-     return;
- 
-   m_last_location = loc;
- 
-   diagnostic_source_print_policy source_policy (*this, opts);
-   source_policy.print (pp, richloc, diagnostic_kind, effects);
- }
- 
- /* As above, but print in HTML form to XP.
-    If non-null, use LABEL_WRITER when writing labelled ranges.  */
- 
- void
- diagnostic_context::maybe_show_locus_as_html (const rich_location &richloc,
- 					      const diagnostic_source_printing_options &opts,
- 					      diagnostic_t diagnostic_kind,
- 					      xml::printer &xp,
- 					      diagnostic_source_effect_info *effects,
- 					      html_label_writer *label_writer)
- {
-   const location_t loc = richloc.get_loc ();
-   /* Do nothing if source-printing has been disabled.  */
-   if (!opts.enabled)
-     return;
- 
-   /* Don't attempt to print source for UNKNOWN_LOCATION and for builtins.  */
-   if (loc <= BUILTINS_LOCATION)
-     return;
- 
-   /* Don't print the same source location twice in a row, unless we have
-      fix-it hints, or multiple locations, or a label.  */
-   if (loc == m_last_location
-       && richloc.get_num_fixit_hints () == 0
-       && richloc.get_num_locations () == 1
-       && richloc.get_range (0)->m_label == nullptr)
-     return;
- 
-   m_last_location = loc;
- 
-   diagnostic_source_print_policy source_policy (*this, opts);
-   source_policy.print_as_html (xp, richloc, diagnostic_kind, effects,
- 			       label_writer);
- }
- 
- diagnostic_source_print_policy::
- diagnostic_source_print_policy (const diagnostic_context &dc)
- : m_options (dc.m_source_printing),
-   m_location_policy (dc),
-   m_text_start_span_cb (dc.m_text_callbacks.m_text_start_span),
-   m_html_start_span_cb (dc.m_text_callbacks.m_html_start_span),
-   m_file_cache (dc.get_file_cache ()),
-   m_diagram_theme (dc.get_diagram_theme ()),
-   m_escape_format (dc.get_escape_format ())
- {
- }
- 
- diagnostic_source_print_policy::
- diagnostic_source_print_policy (const diagnostic_context &dc,
- 				const diagnostic_source_printing_options &opts)
- : m_options (opts),
-   m_location_policy (dc),
-   m_text_start_span_cb (dc.m_text_callbacks.m_text_start_span),
-   m_html_start_span_cb (dc.m_text_callbacks.m_html_start_span),
-   m_file_cache (dc.get_file_cache ()),
-   m_diagram_theme (dc.get_diagram_theme ()),
-   m_escape_format (dc.get_escape_format ())
- {
- }
- 
- /* Print to PP the physical source code corresponding to the location(s)
-    in RICHLOC, with additional annotations, as if for a diagnostic of the
-    given DIAGNOSTIC_KIND.
-    If EFFECTS is non-null, then use and update it.  */
- 
- void
- diagnostic_source_print_policy::print (pretty_printer &pp,
- 				       const rich_location &richloc,
- 				       diagnostic_t diagnostic_kind,
- 				       diagnostic_source_effect_info *effects)
-   const
- {
-   layout layout (*this, richloc, effects);
-   colorizer col (pp, richloc, diagnostic_kind);
-   to_text sink (pp, col);
-   layout_printer<to_text> lp (sink, layout,
- 			      diagnostic_kind == DK_DIAGNOSTIC_PATH);
-   lp.print (*this);
- }
- 
- /* As above, but print in HTML form to XP.
-    If non-null, use LABEL_WRITER when writing labelled ranges.  */
- 
- void
- diagnostic_source_print_policy::print_as_html (xml::printer &xp,
- 					       const rich_location &richloc,
- 					       diagnostic_t diagnostic_kind,
- 					       diagnostic_source_effect_info *effects,
- 					       html_label_writer *label_writer)
-   const
- {
-   layout layout (*this, richloc, effects);
-   to_html sink (xp, &richloc, label_writer);
-   layout_printer<to_html> lp (sink, layout,
- 			      diagnostic_kind == DK_DIAGNOSTIC_PATH);
-   xml::auto_check_tag_nesting sentinel (xp);
-   lp.print (*this);
- }
- 
- template <typename Sink>
- void
- layout_printer<Sink>::print (const diagnostic_source_print_policy &source_policy)
- {
-   typename Sink::auto_check_tag_nesting sentinel (m_sink);
- 
-   m_sink.push_html_tag_with_class ("table", "locus", false);
- 
-   if (get_options ().show_ruler_p)
-     show_ruler (m_layout.m_x_offset_display + get_options ().max_width);
- 
-   for (int line_span_idx = 0; line_span_idx < m_layout.get_num_line_spans ();
-        line_span_idx++)
-     {
-       const line_span *line_span = m_layout.get_line_span (line_span_idx);
-       if (get_options ().show_line_numbers_p)
- 	{
- 	  /* With line numbers, we should show whenever the line-numbering
- 	     "jumps".  */
- 	  if (line_span_idx > 0)
- 	    print_gap_in_line_numbering ();
- 	}
-       else
- 	{
- 	  /* Without line numbers, we print headings for some line spans.  */
- 	  if (m_layout.print_heading_for_line_span_index_p (line_span_idx))
- 	    {
- 	      expanded_location exploc
- 		= m_layout.get_expanded_location (line_span);
- 	      const diagnostic_location_print_policy &
- 		loc_policy = source_policy.get_location_policy ();
- 	      m_sink.invoke_start_span_fn (source_policy, loc_policy, exploc);
- 	    }
- 	}
- 
-       m_sink.push_html_tag_with_class ("tbody", "line-span", false);
- 
-       /* Iterate over the lines within this span (using linenum_arith_t to
- 	 avoid overflow with 0xffffffff causing an infinite loop).  */
-       linenum_arith_t last_line = line_span->get_last_line ();
-       for (linenum_arith_t row = line_span->get_first_line ();
- 	   row <= last_line; row++)
- 	print_line (row);
- 
-       m_sink.pop_html_tag ("tbody");
-     }
- 
-   if (auto effect_info = m_layout.m_effect_info)
-     effect_info->m_trailing_out_edge_column = m_link_rhs_column;
- 
-   m_sink.pop_html_tag ("table");
- }
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- static std::unique_ptr<xml::node>
- make_element_for_locus (const rich_location &rich_loc,
- 			diagnostic_t kind,
- 			diagnostic_context &dc)
- {
-   dc.m_last_location = UNKNOWN_LOCATION;
- 
-   xml::element wrapper ("wrapper", false);
-   xml::printer xp (wrapper);
-   dc.maybe_show_locus_as_html (rich_loc,
- 			       dc.m_source_printing,
- 			       kind,
- 			       xp,
- 			       nullptr,
- 			       nullptr); // label_writer
-   if (wrapper.m_children.size () > 0)
-     return std::move (wrapper.m_children[0]);
-   else
-     return nullptr;
- }
- 
- static label_text
- make_raw_html_for_locus (const rich_location &rich_loc,
- 			 diagnostic_t kind,
- 			 diagnostic_context &dc)
- {
-   auto node = make_element_for_locus (rich_loc, kind, dc);
-   pretty_printer pp;
-   if (node)
-     node->write_as_xml (&pp, 0, true);
-   return label_text::take (xstrdup (pp_formatted_text (&pp)));
- }
- 
- /* Selftests for diagnostic_show_locus.  */
- 
- diagnostic_show_locus_fixture::
- diagnostic_show_locus_fixture (const line_table_case &case_,
- 			       const char *content)
- : m_content (content),
-   m_tmp_source_file (SELFTEST_LOCATION, ".c", content),
-   m_ltt (case_),
-   m_fc ()
- {
-   linemap_add (line_table, LC_ENTER, false,
- 	       m_tmp_source_file.get_filename (), 1);
- }
- 
- /* Populate a char_display_policy based on DC and RICHLOC.  */
- 
- static char_display_policy
- make_char_policy (const diagnostic_context &dc,
- 		  const rich_location &richloc)
- {
-   diagnostic_source_print_policy source_policy (dc);
-   return ::make_char_policy (source_policy, richloc);
- }
- 
- /* Verify that cpp_display_width correctly handles escaping.  */
- 
- static void
- test_display_widths ()
- {
-   gcc_rich_location richloc (UNKNOWN_LOCATION);
- 
-   /* U+03C0 "GREEK SMALL LETTER PI".  */
-   const char *pi = "\xCF\x80";
-   /* U+1F642 "SLIGHTLY SMILING FACE".  */
-   const char *emoji = "\xF0\x9F\x99\x82";
-   /* Stray trailing byte of a UTF-8 character.  */
-   const char *stray = "\xBF";
-   /* U+10FFFF.  */
-   const char *max_codepoint = "\xF4\x8F\xBF\xBF";
- 
-   /* No escaping.  */
-   {
-     test_diagnostic_context dc;
-     char_display_policy policy (make_char_policy (dc, richloc));
-     ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 1);
-     ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 2);
-     ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 1);
-     /* Don't check width of U+10FFFF; it's in a private use plane.  */
-   }
- 
-   richloc.set_escape_on_output (true);
- 
-   {
-     test_diagnostic_context dc;
-     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
-     char_display_policy policy (make_char_policy (dc, richloc));
-     ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
-     ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 9);
-     ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 4);
-     ASSERT_EQ (cpp_display_width (max_codepoint, strlen (max_codepoint),
- 				  policy),
- 	       strlen ("<U+10FFFF>"));
-   }
- 
-   {
-     test_diagnostic_context dc;
-     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
-     char_display_policy policy (make_char_policy (dc, richloc));
-     ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
-     ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 16);
-     ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 4);
-     ASSERT_EQ (cpp_display_width (max_codepoint, strlen (max_codepoint),
- 				  policy),
- 	       16);
-   }
- }
- 
- /* For precise tests of the layout, make clear where the source line will
-    start.  test_left_margin sets the total byte count from the left side of the
-    screen to the start of source lines, after the line number and the separator,
-    which consists of the three characters " | ".  */
- static const int test_linenum_sep = 3;
- static const int test_left_margin = 7;
- 
- /* Helper function for test_layout_x_offset_display_utf8().  */
- static void
- test_offset_impl (int caret_byte_col, int max_width,
- 		  int expected_x_offset_display,
- 		  int left_margin = test_left_margin)
- {
-   test_diagnostic_context dc;
-   dc.m_source_printing.max_width = max_width;
-   /* diagnostic_context::min_margin_width sets the minimum space reserved for
-      the line number plus one space after.  */
-   dc.m_source_printing.min_margin_width = left_margin - test_linenum_sep + 1;
-   dc.m_source_printing.show_line_numbers_p = true;
-   diagnostic_source_print_policy source_policy (dc);
-   rich_location richloc (line_table,
- 			 linemap_position_for_column (line_table,
- 						      caret_byte_col));
-   layout test_layout (source_policy, richloc, nullptr);
-   ASSERT_EQ (left_margin - test_linenum_sep,
- 	     test_layout.get_linenum_width ());
-   ASSERT_EQ (expected_x_offset_display,
- 	     test_layout.get_x_offset_display ());
- }
- 
- /* Test that layout::calculate_x_offset_display() works.  */
- static void
- test_layout_x_offset_display_utf8 (const line_table_case &case_)
- {
- 
-   const char *content
-     = "This line is very long, so that we can use it to test the logic for "
-       "clipping long lines.  Also this: \xf0\x9f\x98\x82\xf0\x9f\x98\x82 is a "
-       "pair of emojis that occupies 8 bytes and 4 display columns, starting at "
-       "column #102.\n";
- 
-   /* Number of bytes in the line, subtracting one to remove the newline.  */
-   const int line_bytes = strlen (content) - 1;
- 
-   /* Number of display columns occupied by the line; each of the 2 emojis
-      takes up 2 fewer display columns than it does bytes.  */
-   const int line_display_cols = line_bytes - 2*2;
- 
-   /* The column of the first emoji.  Byte or display is the same as there are
-      no multibyte characters earlier on the line.  */
-   const int emoji_col = 102;
- 
-   diagnostic_show_locus_fixture f (case_, content);
- 
-   linemap_add (line_table, LC_ENTER, false, f.get_filename (), 1);
- 
-   location_t line_end = linemap_position_for_column (line_table, line_bytes);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   ASSERT_STREQ (f.get_filename (), LOCATION_FILE (line_end));
-   ASSERT_EQ (1, LOCATION_LINE (line_end));
-   ASSERT_EQ (line_bytes, LOCATION_COLUMN (line_end));
- 
-   char_span lspan = f.m_fc.get_source_line (f.get_filename (), 1);
-   ASSERT_EQ (line_display_cols,
- 	     cpp_display_width (lspan.get_buffer (), lspan.length (),
- 				def_policy ()));
-   ASSERT_EQ (line_display_cols,
- 	     location_compute_display_column (f.m_fc,
- 					      expand_location (line_end),
- 					      def_policy ()));
-   ASSERT_EQ (0, memcmp (lspan.get_buffer () + (emoji_col - 1),
- 			"\xf0\x9f\x98\x82\xf0\x9f\x98\x82", 8));
- 
-   /* (caret_byte, max_width, expected_x_offset_display, [left_margin])  */
- 
-   /* No constraint on the width -> no offset.  */
-   test_offset_impl (emoji_col, 0, 0);
- 
-   /* Caret is before the beginning -> no offset.  */
-   test_offset_impl (0, 100, 0);
- 
-   /* Caret is past the end of the line -> no offset.  */
-   test_offset_impl (line_bytes+1, 100, 0);
- 
-   /* Line fits in the display -> no offset.  */
-   test_offset_impl (line_bytes, line_display_cols + test_left_margin, 0);
-   test_offset_impl (emoji_col, line_display_cols + test_left_margin, 0);
- 
-   /* Line is too long for the display but caret location is OK
-      anyway -> no offset.  */
-   static const int small_width = 24;
-   test_offset_impl (1, small_width, 0);
- 
-   /* Width constraint is very small -> no offset.  */
-   test_offset_impl (emoji_col, CARET_LINE_MARGIN, 0);
- 
-   /* Line would be offset, but due to large line numbers, offsetting
-      would remove the whole line -> no offset.  */
-   static const int huge_left_margin = 100;
-   test_offset_impl (emoji_col, huge_left_margin, 0, huge_left_margin);
- 
-   /* Line is the same length as the display, but the line number makes it too
-      long, so offset is required.  Caret is at the end so padding on the right
-      is not in effect.  */
-   for (int excess = 1; excess <= 3; ++excess)
-     test_offset_impl (line_bytes, line_display_cols + test_left_margin - excess,
- 		      excess);
- 
-   /* Line is much too long for the display, caret is near the end ->
-      offset should be such that the line fits in the display and caret
-      remains the same distance from the end that it was.  */
-   for (int caret_offset = 0, max_offset = MIN (CARET_LINE_MARGIN, 10);
-        caret_offset <= max_offset; ++caret_offset)
-     test_offset_impl (line_bytes - caret_offset, small_width,
- 		      line_display_cols + test_left_margin - small_width);
- 
-   /* As previous case but caret is closer to the middle; now we want it to end
-      up CARET_LINE_MARGIN bytes from the end.  */
-   ASSERT_GT (line_display_cols - emoji_col, CARET_LINE_MARGIN);
-   test_offset_impl (emoji_col, small_width,
- 		    emoji_col + test_left_margin
- 		    - (small_width - CARET_LINE_MARGIN));
- 
-   /* Test that the source line is offset as expected when printed.  */
-   {
-     test_diagnostic_context dc;
-     dc.m_source_printing.max_width = small_width - 6;
-     dc.m_source_printing.min_margin_width
-       = test_left_margin - test_linenum_sep + 1;
-     dc.m_source_printing.show_line_numbers_p = true;
-     dc.m_source_printing.show_ruler_p = true;
-     diagnostic_source_print_policy policy (dc);
-     rich_location richloc (line_table,
- 			   linemap_position_for_column (line_table,
- 							emoji_col));
-     layout test_layout (policy, richloc, nullptr);
-     colorizer col (*dc.get_reference_printer (),
- 		   richloc, DK_ERROR);
-     to_text sink (*dc.get_reference_printer (), col);
-     layout_printer<to_text> lp (sink, test_layout, false);
-     lp.print (policy);
-     ASSERT_STREQ ("     |         1         \n"
- 		  "     |         1         \n"
- 		  "     | 234567890123456789\n"
- 		  "   1 | \xf0\x9f\x98\x82\xf0\x9f\x98\x82 is a pair of emojis "
- 		  "that occupies 8 bytes and 4 display columns, starting at "
- 		  "column #102.\n"
- 		  "     | ^\n",
- 		  pp_formatted_text (dc.get_reference_printer ()));
-   }
- 
-   /* Similar to the previous example, but now the offset called for would split
-      the first emoji in the middle of the UTF-8 sequence.  Check that we replace
-      it with a padding space in this case.  */
-   {
-     test_diagnostic_context dc;
-     dc.m_source_printing.max_width = small_width - 5;
-     dc.m_source_printing.min_margin_width
-       = test_left_margin - test_linenum_sep + 1;
-     dc.m_source_printing.show_line_numbers_p = true;
-     dc.m_source_printing.show_ruler_p = true;
-     diagnostic_source_print_policy policy (dc);
-     rich_location richloc (line_table,
- 			   linemap_position_for_column (line_table,
- 							emoji_col + 2));
-     layout test_layout (dc, richloc, nullptr);
-     colorizer col (*dc.get_reference_printer (),
- 		   richloc, DK_ERROR);
-     to_text sink (*dc.get_reference_printer (), col);
-     layout_printer<to_text> lp (sink, test_layout, false);
-     lp.print (policy);
-     ASSERT_STREQ ("     |        1         1 \n"
- 		  "     |        1         2 \n"
- 		  "     | 3456789012345678901\n"
- 		  "   1 |  \xf0\x9f\x98\x82 is a pair of emojis "
- 		  "that occupies 8 bytes and 4 display columns, starting at "
- 		  "column #102.\n"
- 		  "     |  ^\n",
- 		  pp_formatted_text (dc.get_reference_printer ()));
-   }
- 
- }
- 
- static void
- test_layout_x_offset_display_tab (const line_table_case &case_)
- {
-   const char *content
-     = "This line is very long, so that we can use it to test the logic for "
-       "clipping long lines.  Also this: `\t' is a tab that occupies 1 byte and "
-       "a variable number of display columns, starting at column #103.\n";
- 
-   /* Number of bytes in the line, subtracting one to remove the newline.  */
-   const int line_bytes = strlen (content) - 1;
- 
-  /* The column where the tab begins.  Byte or display is the same as there are
-     no multibyte characters earlier on the line.  */
-   const int tab_col = 103;
- 
-   /* Effective extra size of the tab beyond what a single space would have taken
-      up, indexed by tabstop.  */
-   static const int num_tabstops = 11;
-   int extra_width[num_tabstops];
-   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
-     {
-       const int this_tab_size = tabstop - (tab_col - 1) % tabstop;
-       extra_width[tabstop] = this_tab_size - 1;
-     }
-   /* Example of this calculation: if tabstop is 10, the tab starting at column
-      #103 has to expand into 8 spaces, covering columns 103-110, so that the
-      next character is at column #111.  So it takes up 7 more columns than
-      a space would have taken up.  */
-   ASSERT_EQ (7, extra_width[10]);
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-   file_cache fc;
-   line_table_test ltt (case_);
- 
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
- 
-   location_t line_end = linemap_position_for_column (line_table, line_bytes);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Check that cpp_display_width handles the tabs as expected.  */
-   char_span lspan = fc.get_source_line (tmp.get_filename (), 1);
-   ASSERT_EQ ('\t', *(lspan.get_buffer () + (tab_col - 1)));
-   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
-     {
-       cpp_char_column_policy policy (tabstop, cpp_wcwidth);
-       ASSERT_EQ (line_bytes + extra_width[tabstop],
- 		 cpp_display_width (lspan.get_buffer (), lspan.length (),
- 				    policy));
-       ASSERT_EQ (line_bytes + extra_width[tabstop],
- 		 location_compute_display_column (fc,
- 						  expand_location (line_end),
- 						  policy));
-     }
- 
-   /* Check that the tab is expanded to the expected number of spaces.  */
-   rich_location richloc (line_table,
- 			 linemap_position_for_column (line_table,
- 						      tab_col + 1));
-   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
-     {
-       test_diagnostic_context dc;
-       dc.m_tabstop = tabstop;
-       diagnostic_source_print_policy policy (dc);
-       layout test_layout (policy, richloc, nullptr);
-       colorizer col (*dc.get_reference_printer (),
- 		     richloc, DK_ERROR);
-       to_text sink (*dc.get_reference_printer (), col);
-       layout_printer<to_text> lp (sink, test_layout, false);
-       lp.print (policy);
-       const char *out = pp_formatted_text (dc.get_reference_printer ());
-       ASSERT_EQ (nullptr, strchr (out, '\t'));
-       const char *left_quote = strchr (out, '`');
-       const char *right_quote = strchr (out, '\'');
-       ASSERT_NE (nullptr, left_quote);
-       ASSERT_NE (nullptr, right_quote);
-       ASSERT_EQ (right_quote - left_quote, extra_width[tabstop] + 2);
-     }
- 
-   /* Check that the line is offset properly and that the tab is broken up
-      into the expected number of spaces when it is the last character skipped
-      over.  */
-   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
-     {
-       test_diagnostic_context dc;
-       dc.m_tabstop = tabstop;
-       static const int small_width = 24;
-       dc.m_source_printing.max_width = small_width - 4;
-       dc.m_source_printing.min_margin_width
- 	= test_left_margin - test_linenum_sep + 1;
-       dc.m_source_printing.show_line_numbers_p = true;
-       diagnostic_source_print_policy policy (dc);
-       layout test_layout (policy, richloc, nullptr);
-       colorizer col (*dc.get_reference_printer (),
- 		     richloc, DK_ERROR);
-       to_text sink (*dc.get_reference_printer (), col);
-       layout_printer<to_text> lp (sink, test_layout, false);
-       lp.print (policy);
- 
-       /* We have arranged things so that two columns will be printed before
- 	 the caret.  If the tab results in more than one space, this should
- 	 produce two spaces in the output; otherwise, it will be a single space
- 	 preceded by the opening quote before the tab character.  */
-       const char *output1
- 	= "   1 |   ' is a tab that occupies 1 byte and a variable number of "
- 	  "display columns, starting at column #103.\n"
- 	  "     |   ^\n";
-       const char *output2
- 	= "   1 | ` ' is a tab that occupies 1 byte and a variable number of "
- 	  "display columns, starting at column #103.\n"
- 	  "     |   ^\n";
-       const char *expected_output = (extra_width[tabstop] ? output1 : output2);
-       ASSERT_STREQ (expected_output, pp_formatted_text (dc.get_reference_printer ()));
-     }
- }
- 
- 
- /* Verify that diagnostic_show_locus works sanely on UNKNOWN_LOCATION.  */
- 
- static void
- test_diagnostic_show_locus_unknown_location ()
- {
-   test_diagnostic_context dc;
-   rich_location richloc (line_table, UNKNOWN_LOCATION);
-   ASSERT_STREQ ("", dc.test_show_locus (richloc));
- }
- 
- /* Verify that diagnostic_show_locus works sanely for various
-    single-line cases.
- 
-    All of these work on the following 1-line source file:
-      .0000000001111111
-      .1234567890123456
-      "foo = bar.field;\n"
-    which is set up by test_diagnostic_show_locus_one_liner and calls
-    them.  */
- 
- /* Just a caret.  */
- 
- static void
- test_one_liner_simple_caret ()
- {
-   test_diagnostic_context dc;
-   location_t caret = linemap_position_for_column (line_table, 10);
-   rich_location richloc (line_table, caret);
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		"          ^\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* No column information (column == 0).
-    No annotation line should be printed.  */
- 
- static void
- test_one_liner_no_column ()
- {
-   test_diagnostic_context dc;
-   location_t caret = linemap_position_for_column (line_table, 0);
-   rich_location richloc (line_table, caret);
-   ASSERT_STREQ (" foo = bar.field;\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Caret and range.  */
- 
- static void
- test_one_liner_caret_and_range ()
- {
-   test_diagnostic_context dc;
-   location_t caret = linemap_position_for_column (line_table, 10);
-   location_t start = linemap_position_for_column (line_table, 7);
-   location_t finish = linemap_position_for_column (line_table, 15);
-   location_t loc = make_location (caret, start, finish);
-   rich_location richloc (line_table, loc);
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		"       ~~~^~~~~~\n",
- 		dc.test_show_locus (richloc));
- 
-   {
-     test_diagnostic_context dc;
-     auto out = make_raw_html_for_locus (richloc, DK_ERROR, dc);
-      ASSERT_STREQ
-        ("<table class=\"locus\">\n"
- 	"  <tbody class=\"line-span\">\n"
- 	"    <tr><td class=\"left-margin\"> </td><td class=\"source\">foo = bar.field;</td></tr>\n"
- 	"    <tr><td class=\"left-margin\"> </td><td class=\"annotation\">      ~~~^~~~~~</td></tr>\n"
- 	"  </tbody>\n"
- 	"</table>\n",
- 	out.get ());
-   }
-   {
-     test_diagnostic_context dc;
-     dc.m_source_printing.show_line_numbers_p = true;
-     auto out = make_raw_html_for_locus (richloc, DK_ERROR, dc);
-      ASSERT_STREQ
-        ("<table class=\"locus\">\n"
- 	"  <tbody class=\"line-span\">\n"
- 	"    <tr><td class=\"linenum\">    1</td><td class=\"left-margin\"> </td><td class=\"source\">foo = bar.field;</td></tr>\n"
- 	"    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">      ~~~^~~~~~</td></tr>\n"
- 	"  </tbody>\n"
- 	"</table>\n",
- 	out.get ());
-   }
- }
- 
- /* Multiple ranges and carets.  */
- 
- static void
- test_one_liner_multiple_carets_and_ranges ()
- {
-   test_diagnostic_context dc;
-   location_t foo
-     = make_location (linemap_position_for_column (line_table, 2),
- 		     linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 3));
-   dc.m_source_printing.caret_chars[0] = 'A';
- 
-   location_t bar
-     = make_location (linemap_position_for_column (line_table, 8),
- 		     linemap_position_for_column (line_table, 7),
- 		     linemap_position_for_column (line_table, 9));
-   dc.m_source_printing.caret_chars[1] = 'B';
- 
-   location_t field
-     = make_location (linemap_position_for_column (line_table, 13),
- 		     linemap_position_for_column (line_table, 11),
- 		     linemap_position_for_column (line_table, 15));
-   dc.m_source_printing.caret_chars[2] = 'C';
- 
-   rich_location richloc (line_table, foo);
-   richloc.add_range (bar, SHOW_RANGE_WITH_CARET);
-   richloc.add_range (field, SHOW_RANGE_WITH_CARET);
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		" ~A~   ~B~ ~~C~~\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Insertion fix-it hint: adding an "&" to the front of "bar.field". */
- 
- static void
- test_one_liner_fixit_insert_before ()
- {
-   test_diagnostic_context dc;
-   location_t caret = linemap_position_for_column (line_table, 7);
-   rich_location richloc (line_table, caret);
-   richloc.add_fixit_insert_before ("&");
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		"       ^\n"
- 		"       &\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Insertion fix-it hint: adding a "[0]" after "foo". */
- 
- static void
- test_one_liner_fixit_insert_after ()
- {
-   test_diagnostic_context dc;
-   location_t start = linemap_position_for_column (line_table, 1);
-   location_t finish = linemap_position_for_column (line_table, 3);
-   location_t foo = make_location (start, start, finish);
-   rich_location richloc (line_table, foo);
-   richloc.add_fixit_insert_after ("[0]");
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		" ^~~\n"
- 		"    [0]\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Removal fix-it hint: removal of the ".field".
-    Also verify the interaction of pp_set_prefix with rulers and
-    fix-it hints.  */
- 
- static void
- test_one_liner_fixit_remove ()
- {
-   location_t start = linemap_position_for_column (line_table, 10);
-   location_t finish = linemap_position_for_column (line_table, 15);
-   location_t dot = make_location (start, start, finish);
-   rich_location richloc (line_table, dot);
-   richloc.add_fixit_remove ();
- 
-   /* Normal.  */
-   {
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  "          ^~~~~~\n"
- 		  "          ------\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Test of adding a prefix.  */
-   {
-     test_diagnostic_context dc;
-     pp_prefixing_rule (dc.get_reference_printer ()) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
-     pp_set_prefix (dc.get_reference_printer (), xstrdup ("TEST PREFIX:"));
-     ASSERT_STREQ ("TEST PREFIX: foo = bar.field;\n"
- 		  "TEST PREFIX:          ^~~~~~\n"
- 		  "TEST PREFIX:          ------\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Normal, with ruler.  */
-   {
-     test_diagnostic_context dc;
-     dc.m_source_printing.show_ruler_p = true;
-     dc.m_source_printing.max_width = 104;
-     ASSERT_STREQ ("          0         0         0         0         0         0         0         0         0         1    \n"
- 		  "          1         2         3         4         5         6         7         8         9         0    \n"
- 		  " 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234\n"
- 		  " foo = bar.field;\n"
- 		  "          ^~~~~~\n"
- 		  "          ------\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Test of adding a prefix, with ruler.  */
-   {
-     test_diagnostic_context dc;
-     dc.m_source_printing.show_ruler_p = true;
-     dc.m_source_printing.max_width = 50;
-     pp_prefixing_rule (dc.get_reference_printer ()) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
-     pp_set_prefix (dc.get_reference_printer (), xstrdup ("TEST PREFIX:"));
-     ASSERT_STREQ ("TEST PREFIX:          1         2         3         4         5\n"
- 		  "TEST PREFIX: 12345678901234567890123456789012345678901234567890\n"
- 		  "TEST PREFIX: foo = bar.field;\n"
- 		  "TEST PREFIX:          ^~~~~~\n"
- 		  "TEST PREFIX:          ------\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Test of adding a prefix, with ruler and line numbers.  */
-   {
-     test_diagnostic_context dc;
-     dc.m_source_printing.show_ruler_p = true;
-     dc.m_source_printing.max_width = 50;
-     dc.m_source_printing.show_line_numbers_p = true;
-     pp_prefixing_rule (dc.get_reference_printer ()) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
-     pp_set_prefix (dc.get_reference_printer (), xstrdup ("TEST PREFIX:"));
-     ASSERT_STREQ ("TEST PREFIX:      |          1         2         3         4         5\n"
- 		  "TEST PREFIX:      | 12345678901234567890123456789012345678901234567890\n"
- 		  "TEST PREFIX:    1 | foo = bar.field;\n"
- 		  "TEST PREFIX:      |          ^~~~~~\n"
- 		  "TEST PREFIX:      |          ------\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* Replace fix-it hint: replacing "field" with "m_field". */
- 
- static void
- test_one_liner_fixit_replace ()
- {
-   test_diagnostic_context dc;
-   location_t start = linemap_position_for_column (line_table, 11);
-   location_t finish = linemap_position_for_column (line_table, 15);
-   location_t field = make_location (start, start, finish);
-   rich_location richloc (line_table, field);
-   richloc.add_fixit_replace ("m_field");
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		"           ^~~~~\n"
- 		"           m_field\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Replace fix-it hint: replacing "field" with "m_field",
-    but where the caret was elsewhere.  */
- 
- static void
- test_one_liner_fixit_replace_non_equal_range ()
- {
-   test_diagnostic_context dc;
-   location_t equals = linemap_position_for_column (line_table, 5);
-   location_t start = linemap_position_for_column (line_table, 11);
-   location_t finish = linemap_position_for_column (line_table, 15);
-   rich_location richloc (line_table, equals);
-   source_range range;
-   range.m_start = start;
-   range.m_finish = finish;
-   richloc.add_fixit_replace (range, "m_field");
-   /* The replacement range is not indicated in the annotation line, so
-      it should be indicated via an additional underline.  */
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		"     ^\n"
- 		"           -----\n"
- 		"           m_field\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Replace fix-it hint: replacing "field" with "m_field",
-    where the caret was elsewhere, but where a secondary range
-    exactly covers "field".  */
- 
- static void
- test_one_liner_fixit_replace_equal_secondary_range ()
- {
-   test_diagnostic_context dc;
-   location_t equals = linemap_position_for_column (line_table, 5);
-   location_t start = linemap_position_for_column (line_table, 11);
-   location_t finish = linemap_position_for_column (line_table, 15);
-   rich_location richloc (line_table, equals);
-   location_t field = make_location (start, start, finish);
-   richloc.add_range (field);
-   richloc.add_fixit_replace (field, "m_field");
-   /* The replacement range is indicated in the annotation line,
-      so it shouldn't be indicated via an additional underline.  */
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		"     ^     ~~~~~\n"
- 		"           m_field\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Verify that we can use ad-hoc locations when adding fixits to a
-    rich_location.  */
- 
- static void
- test_one_liner_fixit_validation_adhoc_locations ()
- {
-   /* Generate a range that's too long to be packed, so must
-      be stored as an ad-hoc location (given the defaults
-      of 5 or 7 bits or 0 bits of packed range); 150 columns > 2**7.  */
-   const location_t c7 = linemap_position_for_column (line_table, 7);
-   const location_t c157 = linemap_position_for_column (line_table, 157);
-   const location_t loc = make_location (c7, c7, c157);
- 
-   if (c157 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   ASSERT_TRUE (IS_ADHOC_LOC (loc));
- 
-   /* Insert.  */
-   {
-     rich_location richloc (line_table, loc);
-     richloc.add_fixit_insert_before (loc, "test");
-     /* It should not have been discarded by the validator.  */
-     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  "       ^~~~~~~~~~                               "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          \n"
- 		  "       test\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Remove.  */
-   {
-     rich_location richloc (line_table, loc);
-     source_range range = source_range::from_locations (loc, c157);
-     richloc.add_fixit_remove (range);
-     /* It should not have been discarded by the validator.  */
-     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  "       ^~~~~~~~~~                               "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          \n"
- 		  "       -----------------------------------------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Replace.  */
-   {
-     rich_location richloc (line_table, loc);
-     source_range range = source_range::from_locations (loc, c157);
-     richloc.add_fixit_replace (range, "test");
-     /* It should not have been discarded by the validator.  */
-     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  "       ^~~~~~~~~~                               "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          \n"
- 		  "       test\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* Test of consolidating insertions at the same location.  */
- 
- static void
- test_one_liner_many_fixits_1 ()
- {
-   test_diagnostic_context dc;
-   location_t equals = linemap_position_for_column (line_table, 5);
-   rich_location richloc (line_table, equals);
-   for (int i = 0; i < 19; i++)
-     richloc.add_fixit_insert_before ("a");
-   ASSERT_EQ (1, richloc.get_num_fixit_hints ());
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		"     ^\n"
- 		"     aaaaaaaaaaaaaaaaaaa\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Ensure that we can add an arbitrary number of fix-it hints to a
-    rich_location, even if they are not consolidated.  */
- 
- static void
- test_one_liner_many_fixits_2 ()
- {
-   test_diagnostic_context dc;
-   location_t equals = linemap_position_for_column (line_table, 5);
-   rich_location richloc (line_table, equals);
-   for (int i = 0; i < 19; i++)
-     {
-       location_t loc = linemap_position_for_column (line_table, (i * 2) + 1);
-       richloc.add_fixit_insert_before (loc, "a");
-     }
-   ASSERT_EQ (19, richloc.get_num_fixit_hints ());
-   ASSERT_STREQ (" foo = bar.field;\n"
- 		"     ^\n"
- 		" a a a a a a a a a a a a a a a a a a a\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Test of labeling the ranges within a rich_location.  */
- 
- static void
- test_one_liner_labels ()
- {
-   location_t foo
-     = make_location (linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 3));
-   location_t bar
-     = make_location (linemap_position_for_column (line_table, 7),
- 		     linemap_position_for_column (line_table, 7),
- 		     linemap_position_for_column (line_table, 9));
-   location_t field
-     = make_location (linemap_position_for_column (line_table, 11),
- 		     linemap_position_for_column (line_table, 11),
- 		     linemap_position_for_column (line_table, 15));
- 
-   /* Example where all the labels fit on one line.  */
-   {
-     text_range_label label0 ("0");
-     text_range_label label1 ("1");
-     text_range_label label2 ("2");
-     gcc_rich_location richloc (foo, &label0, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
- 
-     {
-       test_diagnostic_context dc;
-       ASSERT_STREQ (" foo = bar.field;\n"
- 		    " ^~~   ~~~ ~~~~~\n"
- 		    " |     |   |\n"
- 		    " 0     1   2\n",
- 		    dc.test_show_locus (richloc));
-     }
- 
-     /* Verify that we can disable label-printing.  */
-     {
-       test_diagnostic_context dc;
-       dc.m_source_printing.show_labels_p = false;
-       ASSERT_STREQ (" foo = bar.field;\n"
- 		    " ^~~   ~~~ ~~~~~\n",
- 		    dc.test_show_locus (richloc));
-     }
-   }
- 
-   /* Example where the labels need extra lines.  */
-   {
-     text_range_label label0 ("label 0");
-     text_range_label label1 ("label 1");
-     text_range_label label2 ("label 2");
-     gcc_rich_location richloc (foo, &label0, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  " ^~~   ~~~ ~~~~~\n"
- 		  " |     |   |\n"
- 		  " |     |   label 2\n"
- 		  " |     label 1\n"
- 		  " label 0\n",
- 		  dc.test_show_locus (richloc));
- 
-     {
-       test_diagnostic_context dc;
-       dc.m_source_printing.show_line_numbers_p = true;
-       auto out = make_raw_html_for_locus (richloc, DK_ERROR, dc);
-       ASSERT_STREQ
- 	("<table class=\"locus\">\n"
- 	 "  <tbody class=\"line-span\">\n"
- 	 "    <tr><td class=\"linenum\">    1</td><td class=\"left-margin\"> </td><td class=\"source\">foo = bar.field;</td></tr>\n"
- 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">^~~   ~~~ ~~~~~</td></tr>\n"
- 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">|     |   |</td></tr>\n"
- 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">|     |   label 2</td></tr>\n"
- 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">|     label 1</td></tr>\n"
- 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">label 0</td></tr>\n"
- 	 "  </tbody>\n"
- 	 "</table>\n",
- 	 out.get ());
-     }
-   }
- 
-   /* Example of boundary conditions: label 0 and 1 have just enough clearance,
-      but label 1 just touches label 2.  */
-   {
-     text_range_label label0 ("aaaaa");
-     text_range_label label1 ("bbbb");
-     text_range_label label2 ("c");
-     gcc_rich_location richloc (foo, &label0, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  " ^~~   ~~~ ~~~~~\n"
- 		  " |     |   |\n"
- 		  " |     |   c\n"
- 		  " aaaaa bbbb\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of out-of-order ranges (thus requiring a sort).  */
-   {
-     text_range_label label0 ("0");
-     text_range_label label1 ("1");
-     text_range_label label2 ("2");
-     gcc_rich_location richloc (field, &label0, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-     richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label2);
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  " ~~~   ~~~ ^~~~~\n"
- 		  " |     |   |\n"
- 		  " 2     1   0\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Ensure we don't ICE if multiple ranges with labels are on
-      the same point.  */
-   {
-     text_range_label label0 ("label 0");
-     text_range_label label1 ("label 1");
-     text_range_label label2 ("label 2");
-     gcc_rich_location richloc (bar, &label0, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label2);
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  "       ^~~\n"
- 		  "       |\n"
- 		  "       label 0\n"
- 		  "       label 1\n"
- 		  "       label 2\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of out-of-order ranges (thus requiring a sort), where
-      they overlap, and there are multiple ranges on the same point.  */
-   {
-     text_range_label label_0a ("label 0a");
-     text_range_label label_1a ("label 1a");
-     text_range_label label_2a ("label 2a");
-     text_range_label label_0b ("label 0b");
-     text_range_label label_1b ("label 1b");
-     text_range_label label_2b ("label 2b");
-     text_range_label label_0c ("label 0c");
-     text_range_label label_1c ("label 1c");
-     text_range_label label_2c ("label 2c");
-     gcc_rich_location richloc (field, &label_0a, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1a);
-     richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2a);
- 
-     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label_0b);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1b);
-     richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2b);
- 
-     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label_0c);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1c);
-     richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2c);
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  " ~~~   ~~~ ^~~~~\n"
- 		  " |     |   |\n"
- 		  " |     |   label 0a\n"
- 		  " |     |   label 0b\n"
- 		  " |     |   label 0c\n"
- 		  " |     label 1a\n"
- 		  " |     label 1b\n"
- 		  " |     label 1c\n"
- 		  " label 2a\n"
- 		  " label 2b\n"
- 		  " label 2c\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Verify that a nullptr result from range_label::get_text is
-      handled gracefully.  */
-   {
-     text_range_label label (nullptr);
-     gcc_rich_location richloc (bar, &label, nullptr);
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" foo = bar.field;\n"
- 		  "       ^~~\n",
- 		  dc.test_show_locus (richloc));
-    }
- 
-   /* TODO: example of formatted printing (needs to be in
-      gcc-rich-location.cc due to Makefile.in issues).  */
- }
- 
- /* Run the various one-liner tests.  */
- 
- static void
- test_diagnostic_show_locus_one_liner (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      ....................0000000001111111.
-      ....................1234567890123456.  */
-   const char *content = "foo = bar.field;\n";
- 
-   diagnostic_show_locus_fixture f (case_, content);
- 
-   location_t line_end = linemap_position_for_column (line_table, 16);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   ASSERT_STREQ (f.get_filename (), LOCATION_FILE (line_end));
-   ASSERT_EQ (1, LOCATION_LINE (line_end));
-   ASSERT_EQ (16, LOCATION_COLUMN (line_end));
- 
-   test_one_liner_simple_caret ();
-   test_one_liner_no_column ();
-   test_one_liner_caret_and_range ();
-   test_one_liner_multiple_carets_and_ranges ();
-   test_one_liner_fixit_insert_before ();
-   test_one_liner_fixit_insert_after ();
-   test_one_liner_fixit_remove ();
-   test_one_liner_fixit_replace ();
-   test_one_liner_fixit_replace_non_equal_range ();
-   test_one_liner_fixit_replace_equal_secondary_range ();
-   test_one_liner_fixit_validation_adhoc_locations ();
-   test_one_liner_many_fixits_1 ();
-   test_one_liner_many_fixits_2 ();
-   test_one_liner_labels ();
- }
- 
- /* Version of all one-liner tests exercising multibyte awareness.
-    These are all called from test_diagnostic_show_locus_one_liner,
-    which uses diagnostic_show_locus_fixture_one_liner_utf8 to create
-    the test file; see the notes in diagnostic-show-locus-selftest.h.
- 
-    Note: all of the below asserts would be easier to read if we used UTF-8
-    directly in the string constants, but it seems better not to demand the
-    host compiler support this, when it isn't otherwise necessary.  Instead,
-    whenever an extended character appears in a string, we put a line break
-    after it so that all succeeding characters can appear visually at the
-    correct display column.  */
- 
- /* Just a caret.  */
- 
- static void
- test_one_liner_simple_caret_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t caret = linemap_position_for_column (line_table, 18);
-   rich_location richloc (line_table, caret);
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		"               ^\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Caret and range.  */
- static void
- test_one_liner_caret_and_range_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t caret = linemap_position_for_column (line_table, 18);
-   location_t start = linemap_position_for_column (line_table, 12);
-   location_t finish = linemap_position_for_column (line_table, 30);
-   location_t loc = make_location (caret, start, finish);
-   rich_location richloc (line_table, loc);
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		"          ~~~~~^~~~~~~~~~\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Multiple ranges and carets.  */
- 
- static void
- test_one_liner_multiple_carets_and_ranges_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t foo
-     = make_location (linemap_position_for_column (line_table, 7),
- 		     linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 8));
-   dc.m_source_printing.caret_chars[0] = 'A';
- 
-   location_t bar
-     = make_location (linemap_position_for_column (line_table, 16),
- 		     linemap_position_for_column (line_table, 12),
- 		     linemap_position_for_column (line_table, 17));
-   dc.m_source_printing.caret_chars[1] = 'B';
- 
-   location_t field
-     = make_location (linemap_position_for_column (line_table, 26),
- 		     linemap_position_for_column (line_table, 19),
- 		     linemap_position_for_column (line_table, 30));
-   dc.m_source_printing.caret_chars[2] = 'C';
-   rich_location richloc (line_table, foo);
-   richloc.add_range (bar, SHOW_RANGE_WITH_CARET);
-   richloc.add_range (field, SHOW_RANGE_WITH_CARET);
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		" ~~~~A~   ~~~B~ ~~~~~C~~~\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Insertion fix-it hint: adding an "&" to the front of "P_bar.field". */
- 
- static void
- test_one_liner_fixit_insert_before_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t caret = linemap_position_for_column (line_table, 12);
-   rich_location richloc (line_table, caret);
-   richloc.add_fixit_insert_before ("&");
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		"          ^\n"
- 		"          &\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Insertion fix-it hint: adding a "[0]" after "SS_foo". */
- 
- static void
- test_one_liner_fixit_insert_after_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t start = linemap_position_for_column (line_table, 1);
-   location_t finish = linemap_position_for_column (line_table, 8);
-   location_t foo = make_location (start, start, finish);
-   rich_location richloc (line_table, foo);
-   richloc.add_fixit_insert_after ("[0]");
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		" ^~~~~~\n"
- 		"       [0]\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Removal fix-it hint: removal of the ".SS_fieldP". */
- 
- static void
- test_one_liner_fixit_remove_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t start = linemap_position_for_column (line_table, 18);
-   location_t finish = linemap_position_for_column (line_table, 30);
-   location_t dot = make_location (start, start, finish);
-   rich_location richloc (line_table, dot);
-   richloc.add_fixit_remove ();
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		"               ^~~~~~~~~~\n"
- 		"               ----------\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Replace fix-it hint: replacing "SS_fieldP" with "m_SSfieldP". */
- 
- static void
- test_one_liner_fixit_replace_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t start = linemap_position_for_column (line_table, 19);
-   location_t finish = linemap_position_for_column (line_table, 30);
-   location_t field = make_location (start, start, finish);
-   rich_location richloc (line_table, field);
-   richloc.add_fixit_replace ("m_\xf0\x9f\x98\x82_field\xcf\x80");
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		"                ^~~~~~~~~\n"
- 		"                m_\xf0\x9f\x98\x82"
- 				    "_field\xcf\x80\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Replace fix-it hint: replacing "SS_fieldP" with "m_SSfieldP",
-    but where the caret was elsewhere.  */
- 
- static void
- test_one_liner_fixit_replace_non_equal_range_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t equals = linemap_position_for_column (line_table, 10);
-   location_t start = linemap_position_for_column (line_table, 19);
-   location_t finish = linemap_position_for_column (line_table, 30);
-   rich_location richloc (line_table, equals);
-   source_range range;
-   range.m_start = start;
-   range.m_finish = finish;
-   richloc.add_fixit_replace (range, "m_\xf0\x9f\x98\x82_field\xcf\x80");
-   /* The replacement range is not indicated in the annotation line, so
-      it should be indicated via an additional underline.  */
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		"        ^\n"
- 		"                ---------\n"
- 		"                m_\xf0\x9f\x98\x82"
- 				    "_field\xcf\x80\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Replace fix-it hint: replacing "SS_fieldP" with "m_SSfieldP",
-    where the caret was elsewhere, but where a secondary range
-    exactly covers "field".  */
- 
- static void
- test_one_liner_fixit_replace_equal_secondary_range_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t equals = linemap_position_for_column (line_table, 10);
-   location_t start = linemap_position_for_column (line_table, 19);
-   location_t finish = linemap_position_for_column (line_table, 30);
-   rich_location richloc (line_table, equals);
-   location_t field = make_location (start, start, finish);
-   richloc.add_range (field);
-   richloc.add_fixit_replace (field, "m_\xf0\x9f\x98\x82_field\xcf\x80");
-   /* The replacement range is indicated in the annotation line,
-      so it shouldn't be indicated via an additional underline.  */
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		"        ^       ~~~~~~~~~\n"
- 		"                m_\xf0\x9f\x98\x82"
- 				    "_field\xcf\x80\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Verify that we can use ad-hoc locations when adding fixits to a
-    rich_location.  */
- 
- static void
- test_one_liner_fixit_validation_adhoc_locations_utf8 ()
- {
-   /* Generate a range that's too long to be packed, so must
-      be stored as an ad-hoc location (given the defaults
-      of 5 bits or 7 bits or 0 bits of packed range); 150 columns > 2**7.  */
-   const location_t c12 = linemap_position_for_column (line_table, 12);
-   const location_t c162 = linemap_position_for_column (line_table, 162);
-   const location_t loc = make_location (c12, c12, c162);
- 
-   if (c162 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   ASSERT_TRUE (IS_ADHOC_LOC (loc));
- 
-   /* Insert.  */
-   {
-     rich_location richloc (line_table, loc);
-     richloc.add_fixit_insert_before (loc, "test");
-     /* It should not have been discarded by the validator.  */
-     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		     "_foo = \xcf\x80"
- 			     "_bar.\xf0\x9f\x98\x82"
- 				    "_field\xcf\x80"
- 					   ";\n"
- 		  "          ^~~~~~~~~~~~~~~~                     "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          \n"
- 		  "          test\n",
- 		dc.test_show_locus (richloc));
-   }
- 
-   /* Remove.  */
-   {
-     rich_location richloc (line_table, loc);
-     source_range range = source_range::from_locations (loc, c162);
-     richloc.add_fixit_remove (range);
-     /* It should not have been discarded by the validator.  */
-     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		     "_foo = \xcf\x80"
- 			     "_bar.\xf0\x9f\x98\x82"
- 				    "_field\xcf\x80"
- 					   ";\n"
- 		  "          ^~~~~~~~~~~~~~~~                     "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          \n"
- 		  "          -------------------------------------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------"
- 		  "----------\n",
- 		dc.test_show_locus (richloc));
-   }
- 
-   /* Replace.  */
-   {
-     rich_location richloc (line_table, loc);
-     source_range range = source_range::from_locations (loc, c162);
-     richloc.add_fixit_replace (range, "test");
-     /* It should not have been discarded by the validator.  */
-     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		     "_foo = \xcf\x80"
- 			     "_bar.\xf0\x9f\x98\x82"
- 				    "_field\xcf\x80"
- 					   ";\n"
- 		  "          ^~~~~~~~~~~~~~~~                     "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          "
- 		  "          \n"
- 		  "          test\n",
- 		dc.test_show_locus (richloc));
-   }
- }
- 
- /* Test of consolidating insertions at the same location.  */
- 
- static void
- test_one_liner_many_fixits_1_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t equals = linemap_position_for_column (line_table, 10);
-   rich_location richloc (line_table, equals);
-   for (int i = 0; i < 19; i++)
-     richloc.add_fixit_insert_before (i & 1 ? "@" : "\xcf\x80");
-   ASSERT_EQ (1, richloc.get_num_fixit_hints ());
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		"        ^\n"
- 		"        \xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80@"
- 		"\xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Ensure that we can add an arbitrary number of fix-it hints to a
-    rich_location, even if they are not consolidated.  */
- 
- static void
- test_one_liner_many_fixits_2_utf8 ()
- {
-   test_diagnostic_context dc;
-   location_t equals = linemap_position_for_column (line_table, 10);
-   rich_location richloc (line_table, equals);
-   const int nlocs = 19;
-   int locs[nlocs] = {1, 5, 7, 9, 11, 14, 16, 18, 23, 25, 27, 29, 32,
- 		     34, 36, 38, 40, 42, 44};
-   for (int i = 0; i != nlocs; ++i)
-     {
-       location_t loc = linemap_position_for_column (line_table, locs[i]);
-       richloc.add_fixit_insert_before (loc, i & 1 ? "@" : "\xcf\x80");
-     }
- 
-   ASSERT_EQ (nlocs, richloc.get_num_fixit_hints ());
-   ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		   "_foo = \xcf\x80"
- 			   "_bar.\xf0\x9f\x98\x82"
- 				  "_field\xcf\x80"
- 					 ";\n"
- 		"        ^\n"
- 		" \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80 @  \xcf\x80 @"
- 		" \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Test of labeling the ranges within a rich_location.  */
- 
- static void
- test_one_liner_labels_utf8 ()
- {
-   location_t foo
-     = make_location (linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 1),
- 		     linemap_position_for_column (line_table, 8));
-   location_t bar
-     = make_location (linemap_position_for_column (line_table, 12),
- 		     linemap_position_for_column (line_table, 12),
- 		     linemap_position_for_column (line_table, 17));
-   location_t field
-     = make_location (linemap_position_for_column (line_table, 19),
- 		     linemap_position_for_column (line_table, 19),
- 		     linemap_position_for_column (line_table, 30));
- 
-   /* Example where all the labels fit on one line.  */
-   {
-     /* These three labels contain multibyte characters such that their byte
-        lengths are respectively (12, 10, 18), but their display widths are only
-        (6, 5, 9).  All three fit on the line when considering the display
-        widths, but not when considering the byte widths, so verify that we do
-        indeed put them all on one line.  */
-     text_range_label label0
-       ("\xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80");
-     text_range_label label1
-       ("\xf0\x9f\x98\x82\xf0\x9f\x98\x82\xcf\x80");
-     text_range_label label2
-       ("\xf0\x9f\x98\x82\xcf\x80\xf0\x9f\x98\x82\xf0\x9f\x98\x82\xcf\x80"
-        "\xcf\x80");
-     gcc_rich_location richloc (foo, &label0, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
- 
-     {
-       test_diagnostic_context dc;
-       ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		       "_foo = \xcf\x80"
- 			       "_bar.\xf0\x9f\x98\x82"
- 				      "_field\xcf\x80"
- 					     ";\n"
- 		    " ^~~~~~   ~~~~~ ~~~~~~~~~\n"
- 		    " |        |     |\n"
- 		    " \xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80"
- 			   "   \xf0\x9f\x98\x82\xf0\x9f\x98\x82\xcf\x80"
- 				   " \xf0\x9f\x98\x82\xcf\x80\xf0\x9f\x98\x82"
- 					 "\xf0\x9f\x98\x82\xcf\x80\xcf\x80\n",
- 		    dc.test_show_locus (richloc));
-     }
- 
-   }
- 
-   /* Example where the labels need extra lines.  */
-   {
-     text_range_label label0 ("label 0\xf0\x9f\x98\x82");
-     text_range_label label1 ("label 1\xcf\x80");
-     text_range_label label2 ("label 2\xcf\x80");
-     gcc_rich_location richloc (foo, &label0, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		     "_foo = \xcf\x80"
- 			     "_bar.\xf0\x9f\x98\x82"
- 				    "_field\xcf\x80"
- 					   ";\n"
- 		  " ^~~~~~   ~~~~~ ~~~~~~~~~\n"
- 		  " |        |     |\n"
- 		  " |        |     label 2\xcf\x80\n"
- 		  " |        label 1\xcf\x80\n"
- 		  " label 0\xf0\x9f\x98\x82\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of boundary conditions: label 0 and 1 have just enough clearance,
-      but label 1 just touches label 2.  */
-   {
-     text_range_label label0 ("aaaaa\xf0\x9f\x98\x82\xcf\x80");
-     text_range_label label1 ("bb\xf0\x9f\x98\x82\xf0\x9f\x98\x82");
-     text_range_label label2 ("c");
-     gcc_rich_location richloc (foo, &label0, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
- 
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" \xf0\x9f\x98\x82"
- 		     "_foo = \xcf\x80"
- 			     "_bar.\xf0\x9f\x98\x82"
- 				    "_field\xcf\x80"
- 					   ";\n"
- 		  " ^~~~~~   ~~~~~ ~~~~~~~~~\n"
- 		  " |        |     |\n"
- 		  " |        |     c\n"
- 		  " aaaaa\xf0\x9f\x98\x82\xcf\x80"
- 			   " bb\xf0\x9f\x98\x82\xf0\x9f\x98\x82\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of escaping the source lines.  */
-   {
-     text_range_label label0 ("label 0\xf0\x9f\x98\x82");
-     text_range_label label1 ("label 1\xcf\x80");
-     text_range_label label2 ("label 2\xcf\x80");
-     gcc_rich_location richloc (foo, &label0, nullptr);
-     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
-     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
-     richloc.set_escape_on_output (true);
- 
-     {
-       test_diagnostic_context dc;
-       dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
-       ASSERT_STREQ (" <U+1F602>_foo = <U+03C0>_bar.<U+1F602>_field<U+03C0>;\n"
- 		    " ^~~~~~~~~~~~~   ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~\n"
- 		    " |               |            |\n"
- 		    " label 0\xf0\x9f\x98\x82"
- 		    /* ... */ "       label 1\xcf\x80"
- 		    /* ...................*/ "     label 2\xcf\x80\n",
- 		    dc.test_show_locus (richloc));
-     }
-     {
-       test_diagnostic_context dc;
-       dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
-       ASSERT_STREQ
- 	(" <f0><9f><98><82>_foo = <cf><80>_bar.<f0><9f><98><82>_field<cf><80>;\n"
- 	 " ^~~~~~~~~~~~~~~~~~~~   ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
- 	 " |                      |            |\n"
- 	 " label 0\xf0\x9f\x98\x82"
- 	 /* ... */ "              label 1\xcf\x80"
- 	 /* ..........................*/ "     label 2\xcf\x80\n",
- 	 dc.test_show_locus (richloc));
-     }
-   }
- }
- 
- /* Make sure that colorization codes don't interrupt a multibyte
-    sequence, which would corrupt it.  */
- static void
- test_one_liner_colorized_utf8 ()
- {
-   test_diagnostic_context dc;
-   dc.m_source_printing.colorize_source_p = true;
-   diagnostic_color_init (&dc, DIAGNOSTICS_COLOR_YES);
-   const location_t pi = linemap_position_for_column (line_table, 12);
-   rich_location richloc (line_table, pi);
- 
-   /* In order to avoid having the test depend on exactly how the colorization
-      was effected, just confirm there are two pi characters in the output.  */
-   const char *result = dc.test_show_locus (richloc);
-   const char *null_term = result + strlen (result);
-   const char *first_pi = strstr (result, "\xcf\x80");
-   ASSERT_TRUE (first_pi && first_pi <= null_term - 2);
-   ASSERT_STR_CONTAINS (first_pi + 2, "\xcf\x80");
- }
- 
- static const char * const one_liner_utf8_content
-   /* Display columns.
-      0000000000000000000000011111111111111111111111111111112222222222222
-      1111111122222222345678900000000123456666666677777777890123444444445  */
-   = "\xf0\x9f\x98\x82_foo = \xcf\x80_bar.\xf0\x9f\x98\x82_field\xcf\x80;\n";
-   /* 0000000000000000000001111111111111111111222222222222222222222233333
-      1111222233334444567890122223333456789999000011112222345678999900001
-      Byte columns.  */
- 
- diagnostic_show_locus_fixture_one_liner_utf8::
- diagnostic_show_locus_fixture_one_liner_utf8 (const line_table_case &case_)
- : diagnostic_show_locus_fixture (case_, one_liner_utf8_content)
- {
- }
- 
- /* Run the various one-liner tests.  */
- 
- static void
- test_diagnostic_show_locus_one_liner_utf8 (const line_table_case &case_)
- {
-   diagnostic_show_locus_fixture_one_liner_utf8 f (case_);
- 
-   location_t line_end = linemap_position_for_column (line_table, 31);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   ASSERT_STREQ (f.get_filename (), LOCATION_FILE (line_end));
-   ASSERT_EQ (1, LOCATION_LINE (line_end));
-   ASSERT_EQ (31, LOCATION_COLUMN (line_end));
- 
-   char_span lspan = f.m_fc.get_source_line (f.get_filename (), 1);
-   ASSERT_EQ (25, cpp_display_width (lspan.get_buffer (), lspan.length (),
- 				    def_policy ()));
-   ASSERT_EQ (25, location_compute_display_column (f.m_fc,
- 						  expand_location (line_end),
- 						  def_policy ()));
- 
-   test_one_liner_simple_caret_utf8 ();
-   test_one_liner_caret_and_range_utf8 ();
-   test_one_liner_multiple_carets_and_ranges_utf8 ();
-   test_one_liner_fixit_insert_before_utf8 ();
-   test_one_liner_fixit_insert_after_utf8 ();
-   test_one_liner_fixit_remove_utf8 ();
-   test_one_liner_fixit_replace_utf8 ();
-   test_one_liner_fixit_replace_non_equal_range_utf8 ();
-   test_one_liner_fixit_replace_equal_secondary_range_utf8 ();
-   test_one_liner_fixit_validation_adhoc_locations_utf8 ();
-   test_one_liner_many_fixits_1_utf8 ();
-   test_one_liner_many_fixits_2_utf8 ();
-   test_one_liner_labels_utf8 ();
-   test_one_liner_colorized_utf8 ();
- }
- 
- /* Verify that gcc_rich_location::add_location_if_nearby works.  */
- 
- static void
- test_add_location_if_nearby (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      ...000000000111111111122222222223333333333.
-      ...123456789012345678901234567890123456789.  */
-   const char *content
-     = ("struct same_line { double x; double y; ;\n" /* line 1.  */
-        "struct different_line\n"                    /* line 2.  */
-        "{\n"                                        /* line 3.  */
-        "  double x;\n"                              /* line 4.  */
-        "  double y;\n"                              /* line 5.  */
-        ";\n");                                      /* line 6.  */
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", content, nullptr);
-   line_table_test ltt (case_);
- 
-   const line_map_ordinary *ord_map
-     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
- 					   tmp.get_filename (), 0));
- 
-   linemap_line_start (line_table, 1, 100);
- 
-   const location_t final_line_end
-     = linemap_position_for_line_and_column (line_table, ord_map, 6, 7);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Test of add_location_if_nearby on the same line as the
-      primary location.  */
-   {
-     test_diagnostic_context dc;
-     const location_t missing_close_brace_1_39
-       = linemap_position_for_line_and_column (line_table, ord_map, 1, 39);
-     const location_t matching_open_brace_1_18
-       = linemap_position_for_line_and_column (line_table, ord_map, 1, 18);
-     gcc_rich_location richloc (missing_close_brace_1_39);
-     bool added = richloc.add_location_if_nearby (dc,
- 						 matching_open_brace_1_18);
-     ASSERT_TRUE (added);
-     ASSERT_EQ (2, richloc.get_num_locations ());
-     ASSERT_STREQ (" struct same_line { double x; double y; ;\n"
- 		  "                  ~                    ^\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Test of add_location_if_nearby on a different line to the
-      primary location.  */
-   {
-     test_diagnostic_context dc;
-     const location_t missing_close_brace_6_1
-       = linemap_position_for_line_and_column (line_table, ord_map, 6, 1);
-     const location_t matching_open_brace_3_1
-       = linemap_position_for_line_and_column (line_table, ord_map, 3, 1);
-     gcc_rich_location richloc (missing_close_brace_6_1);
-     bool added = richloc.add_location_if_nearby (dc,
- 						 matching_open_brace_3_1);
-     ASSERT_FALSE (added);
-     ASSERT_EQ (1, richloc.get_num_locations ());
-   }
- }
- 
- /* Verify that we print fixits even if they only affect lines
-    outside those covered by the ranges in the rich_location.  */
- 
- static void
- test_diagnostic_show_locus_fixit_lines (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      ...000000000111111111122222222223333333333.
-      ...123456789012345678901234567890123456789.  */
-   const char *content
-     = ("struct point { double x; double y; };\n" /* line 1.  */
-        "struct point origin = {x: 0.0,\n"        /* line 2.  */
-        "                       y\n"              /* line 3.  */
-        "\n"                                      /* line 4.  */
-        "\n"                                      /* line 5.  */
-        "                        : 0.0};\n");     /* line 6.  */
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-   line_table_test ltt (case_);
- 
-   const line_map_ordinary *ord_map
-     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
- 					   tmp.get_filename (), 0));
- 
-   linemap_line_start (line_table, 1, 100);
- 
-   const location_t final_line_end
-     = linemap_position_for_line_and_column (line_table, ord_map, 6, 36);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* A pair of tests for modernizing the initializers to C99-style.  */
- 
-   /* The one-liner case (line 2).  */
-   {
-     test_diagnostic_context dc;
-     const location_t x
-       = linemap_position_for_line_and_column (line_table, ord_map, 2, 24);
-     const location_t colon
-       = linemap_position_for_line_and_column (line_table, ord_map, 2, 25);
-     rich_location richloc (line_table, colon);
-     richloc.add_fixit_insert_before (x, ".");
-     richloc.add_fixit_replace (colon, "=");
-     ASSERT_STREQ (" struct point origin = {x: 0.0,\n"
- 		  "                         ^\n"
- 		  "                        .=\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* The multiline case.  The caret for the rich_location is on line 6;
-      verify that insertion fixit on line 3 is still printed (and that
-      span starts are printed due to the gap between the span at line 3
-      and that at line 6).  */
-   {
-     test_diagnostic_context dc;
-     const location_t y
-       = linemap_position_for_line_and_column (line_table, ord_map, 3, 24);
-     const location_t colon
-       = linemap_position_for_line_and_column (line_table, ord_map, 6, 25);
-     rich_location richloc (line_table, colon);
-     richloc.add_fixit_insert_before (y, ".");
-     richloc.add_fixit_replace (colon, "=");
-     ASSERT_STREQ ("FILENAME:3:24:\n"
- 		  "                        y\n"
- 		  "                        .\n"
- 		  "FILENAME:6:25:\n"
- 		  "                         : 0.0};\n"
- 		  "                         ^\n"
- 		  "                         =\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* As above, but verify the behavior of multiple line spans
-      with line-numbering enabled.  */
-   {
-     const location_t y
-       = linemap_position_for_line_and_column (line_table, ord_map, 3, 24);
-     const location_t colon
-       = linemap_position_for_line_and_column (line_table, ord_map, 6, 25);
-     rich_location richloc (line_table, colon);
-     richloc.add_fixit_insert_before (y, ".");
-     richloc.add_fixit_replace (colon, "=");
-     test_diagnostic_context dc;
-     dc.m_source_printing.show_line_numbers_p = true;
-     ASSERT_STREQ ("    3 |                        y\n"
- 		  "      |                        .\n"
- 		  "......\n"
- 		  "    6 |                         : 0.0};\n"
- 		  "      |                         ^\n"
- 		  "      |                         =\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- 
- /* Verify that fix-it hints are appropriately consolidated.
- 
-    If any fix-it hints in a rich_location involve locations beyond
-    LINE_MAP_MAX_LOCATION_WITH_COLS, then we can't reliably apply
-    the fix-it as a whole, so there should be none.
- 
-    Otherwise, verify that consecutive "replace" and "remove" fix-its
-    are merged, and that other fix-its remain separate.   */
- 
- static void
- test_fixit_consolidation (const line_table_case &case_)
- {
-   line_table_test ltt (case_);
- 
-   linemap_add (line_table, LC_ENTER, false, "test.c", 1);
- 
-   const location_t c10 = linemap_position_for_column (line_table, 10);
-   const location_t c15 = linemap_position_for_column (line_table, 15);
-   const location_t c16 = linemap_position_for_column (line_table, 16);
-   const location_t c17 = linemap_position_for_column (line_table, 17);
-   const location_t c20 = linemap_position_for_column (line_table, 20);
-   const location_t c21 = linemap_position_for_column (line_table, 21);
-   const location_t caret = c10;
- 
-   /* Insert + insert. */
-   {
-     rich_location richloc (line_table, caret);
-     richloc.add_fixit_insert_before (c10, "foo");
-     richloc.add_fixit_insert_before (c15, "bar");
- 
-     if (c15 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-       /* Bogus column info for 2nd fixit, so no fixits.  */
-       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
-     else
-       /* They should not have been merged.  */
-       ASSERT_EQ (2, richloc.get_num_fixit_hints ());
-   }
- 
-   /* Insert + replace. */
-   {
-     rich_location richloc (line_table, caret);
-     richloc.add_fixit_insert_before (c10, "foo");
-     richloc.add_fixit_replace (source_range::from_locations (c15, c17),
- 			       "bar");
- 
-     if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-       /* Bogus column info for 2nd fixit, so no fixits.  */
-       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
-     else
-       /* They should not have been merged.  */
-       ASSERT_EQ (2, richloc.get_num_fixit_hints ());
-   }
- 
-   /* Replace + non-consecutive insert. */
-   {
-     rich_location richloc (line_table, caret);
-     richloc.add_fixit_replace (source_range::from_locations (c10, c15),
- 			       "bar");
-     richloc.add_fixit_insert_before (c17, "foo");
- 
-     if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-       /* Bogus column info for 2nd fixit, so no fixits.  */
-       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
-     else
-       /* They should not have been merged.  */
-       ASSERT_EQ (2, richloc.get_num_fixit_hints ());
-   }
- 
-   /* Replace + non-consecutive replace. */
-   {
-     rich_location richloc (line_table, caret);
-     richloc.add_fixit_replace (source_range::from_locations (c10, c15),
- 			       "foo");
-     richloc.add_fixit_replace (source_range::from_locations (c17, c20),
- 			       "bar");
- 
-     if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-       /* Bogus column info for 2nd fixit, so no fixits.  */
-       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
-     else
-       /* They should not have been merged.  */
-       ASSERT_EQ (2, richloc.get_num_fixit_hints ());
-   }
- 
-   /* Replace + consecutive replace. */
-   {
-     rich_location richloc (line_table, caret);
-     richloc.add_fixit_replace (source_range::from_locations (c10, c15),
- 			       "foo");
-     richloc.add_fixit_replace (source_range::from_locations (c16, c20),
- 			       "bar");
- 
-     if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-       /* Bogus column info for 2nd fixit, so no fixits.  */
-       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
-     else
-       {
- 	/* They should have been merged into a single "replace".  */
- 	ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 	const fixit_hint *hint = richloc.get_fixit_hint (0);
- 	ASSERT_STREQ ("foobar", hint->get_string ());
- 	ASSERT_EQ (c10, hint->get_start_loc ());
- 	ASSERT_EQ (c21, hint->get_next_loc ());
-       }
-   }
- 
-   /* Replace + consecutive removal. */
-   {
-     rich_location richloc (line_table, caret);
-     richloc.add_fixit_replace (source_range::from_locations (c10, c15),
- 			       "foo");
-     richloc.add_fixit_remove (source_range::from_locations (c16, c20));
- 
-     if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-       /* Bogus column info for 2nd fixit, so no fixits.  */
-       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
-     else
-       {
- 	/* They should have been merged into a single replace, with the
- 	   range extended to cover that of the removal.  */
- 	ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 	const fixit_hint *hint = richloc.get_fixit_hint (0);
- 	ASSERT_STREQ ("foo", hint->get_string ());
- 	ASSERT_EQ (c10, hint->get_start_loc ());
- 	ASSERT_EQ (c21, hint->get_next_loc ());
-       }
-   }
- 
-   /* Consecutive removals. */
-   {
-     rich_location richloc (line_table, caret);
-     richloc.add_fixit_remove (source_range::from_locations (c10, c15));
-     richloc.add_fixit_remove (source_range::from_locations (c16, c20));
- 
-     if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-       /* Bogus column info for 2nd fixit, so no fixits.  */
-       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
-     else
-       {
- 	/* They should have been merged into a single "replace-with-empty".  */
- 	ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 	const fixit_hint *hint = richloc.get_fixit_hint (0);
- 	ASSERT_STREQ ("", hint->get_string ());
- 	ASSERT_EQ (c10, hint->get_start_loc ());
- 	ASSERT_EQ (c21, hint->get_next_loc ());
-       }
-   }
- }
- 
- /* Verify that the line_corrections machinery correctly prints
-    overlapping fixit-hints.  */
- 
- static void
- test_overlapped_fixit_printing (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      ...000000000111111111122222222223333333333.
-      ...123456789012345678901234567890123456789.  */
-   const char *content
-     = ("  foo *f = (foo *)ptr->field;\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
-   file_cache fc;
-   line_table_test ltt (case_);
- 
-   const line_map_ordinary *ord_map
-     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
- 					   tmp.get_filename (), 0));
- 
-   linemap_line_start (line_table, 1, 100);
- 
-   const location_t final_line_end
-     = linemap_position_for_line_and_column (line_table, ord_map, 6, 36);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* A test for converting a C-style cast to a C++-style cast.  */
-   const location_t open_paren
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 12);
-   const location_t close_paren
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 18);
-   const location_t expr_start
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 19);
-   const location_t expr_finish
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 28);
-   const location_t expr = make_location (expr_start, expr_start, expr_finish);
- 
-   /* Various examples of fix-it hints that aren't themselves consolidated,
-      but for which the *printing* may need consolidation.  */
- 
-   /* Example where 3 fix-it hints are printed as one.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_replace (open_paren, "const_cast<");
-     richloc.add_fixit_replace (close_paren, "> (");
-     richloc.add_fixit_insert_after (")");
- 
-     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
- 		  "                   ^~~~~~~~~~\n"
- 		  "            -----------------\n"
- 		  "            const_cast<foo *> (ptr->field)\n",
- 		  dc.test_show_locus (richloc));
- 
-     /* Unit-test the line_corrections machinery.  */
-     char_display_policy policy (make_char_policy (dc, richloc));
-     ASSERT_EQ (3, richloc.get_num_fixit_hints ());
-     const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
-     ASSERT_EQ (column_range (12, 12),
- 	       get_affected_range (fc, policy, hint_0, CU_BYTES));
-     ASSERT_EQ (column_range (12, 12),
- 	       get_affected_range (fc, policy, hint_0, CU_DISPLAY_COLS));
-     ASSERT_EQ (column_range (12, 22), get_printed_columns (fc, policy, hint_0));
-     const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
-     ASSERT_EQ (column_range (18, 18),
- 	       get_affected_range (fc, policy, hint_1, CU_BYTES));
-     ASSERT_EQ (column_range (18, 18),
- 	       get_affected_range (fc, policy, hint_1, CU_DISPLAY_COLS));
-     ASSERT_EQ (column_range (18, 20), get_printed_columns (fc, policy, hint_1));
-     const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
-     ASSERT_EQ (column_range (29, 28),
- 	       get_affected_range (fc, policy, hint_2, CU_BYTES));
-     ASSERT_EQ (column_range (29, 28),
- 	       get_affected_range (fc, policy, hint_2, CU_DISPLAY_COLS));
-     ASSERT_EQ (column_range (29, 29), get_printed_columns (fc, policy, hint_2));
- 
-     /* Add each hint in turn to a line_corrections instance,
-        and verify that they are consolidated into one correction instance
-        as expected.  */
-     line_corrections lc (fc, policy, tmp.get_filename (), 1);
- 
-     /* The first replace hint by itself.  */
-     lc.add_hint (hint_0);
-     ASSERT_EQ (1, lc.m_corrections.length ());
-     ASSERT_EQ (column_range (12, 12), lc.m_corrections[0]->m_affected_bytes);
-     ASSERT_EQ (column_range (12, 12), lc.m_corrections[0]->m_affected_columns);
-     ASSERT_EQ (column_range (12, 22), lc.m_corrections[0]->m_printed_columns);
-     ASSERT_STREQ ("const_cast<", lc.m_corrections[0]->m_text);
- 
-     /* After the second replacement hint, they are printed together
-        as a replacement (along with the text between them).  */
-     lc.add_hint (hint_1);
-     ASSERT_EQ (1, lc.m_corrections.length ());
-     ASSERT_STREQ ("const_cast<foo *> (", lc.m_corrections[0]->m_text);
-     ASSERT_EQ (column_range (12, 18), lc.m_corrections[0]->m_affected_bytes);
-     ASSERT_EQ (column_range (12, 18), lc.m_corrections[0]->m_affected_columns);
-     ASSERT_EQ (column_range (12, 30), lc.m_corrections[0]->m_printed_columns);
- 
-     /* After the final insertion hint, they are all printed together
-        as a replacement (along with the text between them).  */
-     lc.add_hint (hint_2);
-     ASSERT_STREQ ("const_cast<foo *> (ptr->field)",
- 		  lc.m_corrections[0]->m_text);
-     ASSERT_EQ (1, lc.m_corrections.length ());
-     ASSERT_EQ (column_range (12, 28), lc.m_corrections[0]->m_affected_bytes);
-     ASSERT_EQ (column_range (12, 28), lc.m_corrections[0]->m_affected_columns);
-     ASSERT_EQ (column_range (12, 41), lc.m_corrections[0]->m_printed_columns);
-   }
- 
-   /* Example where two are consolidated during printing.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_replace (open_paren, "CAST (");
-     richloc.add_fixit_replace (close_paren, ") (");
-     richloc.add_fixit_insert_after (")");
- 
-     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
- 		  "                   ^~~~~~~~~~\n"
- 		  "            -\n"
- 		  "            CAST (-\n"
- 		  "                  ) (        )\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example where none are consolidated during printing.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_replace (open_paren, "CST (");
-     richloc.add_fixit_replace (close_paren, ") (");
-     richloc.add_fixit_insert_after (")");
- 
-     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
- 		  "                   ^~~~~~~~~~\n"
- 		  "            -\n"
- 		  "            CST ( -\n"
- 		  "                  ) (        )\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of deletion fix-it hints.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_insert_before (open_paren, "(bar *)");
-     source_range victim = {open_paren, close_paren};
-     richloc.add_fixit_remove (victim);
- 
-     /* This case is actually handled by fixit-consolidation,
-        rather than by line_corrections.  */
-     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 
-     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
- 		  "                   ^~~~~~~~~~\n"
- 		  "            -------\n"
- 		  "            (bar *)\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of deletion fix-it hints that would overlap.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_insert_before (open_paren, "(longer *)");
-     source_range victim = {expr_start, expr_finish};
-     richloc.add_fixit_remove (victim);
- 
-     /* These fixits are not consolidated.  */
-     ASSERT_EQ (2, richloc.get_num_fixit_hints ());
- 
-     /* But the corrections are.  */
-     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
- 		  "                   ^~~~~~~~~~\n"
- 		  "            -----------------\n"
- 		  "            (longer *)(foo *)\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of insertion fix-it hints that would overlap.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_insert_before (open_paren, "LONGER THAN THE CAST");
-     richloc.add_fixit_insert_after (close_paren, "TEST");
- 
-     /* The first insertion is long enough that if printed naively,
-        it would overlap with the second.
-        Verify that they are printed as a single replacement.  */
-     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
- 		  "                   ^~~~~~~~~~\n"
- 		  "            -------\n"
- 		  "            LONGER THAN THE CAST(foo *)TEST\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* Multibyte-aware version of preceding tests.  See comments above
-    test_one_liner_simple_caret_utf8() too, we use the same two multibyte
-    characters here.  */
- 
- static void
- test_overlapped_fixit_printing_utf8 (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.  */
- 
-   const char *content
-     /* Display columns.
-        00000000000000000000000111111111111111111111111222222222222222223
-        12344444444555555556789012344444444555555556789012345678999999990  */
-     = "  f\xf0\x9f\x98\x82 *f = (f\xf0\x9f\x98\x82 *)ptr->field\xcf\x80;\n";
-     /* 00000000000000000000011111111111111111111112222222222333333333333
-        12344445555666677778901234566667777888899990123456789012333344445
-        Byte columns.  */
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
-   line_table_test ltt (case_);
- 
-   const line_map_ordinary *ord_map
-     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
- 					   tmp.get_filename (), 0));
- 
-   linemap_line_start (line_table, 1, 100);
- 
-   const location_t final_line_end
-     = linemap_position_for_line_and_column (line_table, ord_map, 6, 50);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* A test for converting a C-style cast to a C++-style cast.  */
-   const location_t open_paren
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 14);
-   const location_t close_paren
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 22);
-   const location_t expr_start
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 23);
-   const location_t expr_finish
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 34);
-   const location_t expr = make_location (expr_start, expr_start, expr_finish);
- 
-   /* Various examples of fix-it hints that aren't themselves consolidated,
-      but for which the *printing* may need consolidation.  */
- 
-   /* Example where 3 fix-it hints are printed as one.  */
-   {
-     test_diagnostic_context dc;
-     file_cache &fc = dc.get_file_cache ();
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_replace (open_paren, "const_cast<");
-     richloc.add_fixit_replace (close_paren, "> (");
-     richloc.add_fixit_insert_after (")");
- 
-     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
- 			" *f = (f\xf0\x9f\x98\x82"
- 				  " *)ptr->field\xcf\x80"
- 						";\n"
- 		  "                   ^~~~~~~~~~~\n"
- 		  "            ------------------\n"
- 		  "            const_cast<f\xf0\x9f\x98\x82"
- 					    " *> (ptr->field\xcf\x80"
- 							    ")\n",
- 		  dc.test_show_locus (richloc));
- 
-     /* Unit-test the line_corrections machinery.  */
-     char_display_policy policy (make_char_policy (dc, richloc));
-     ASSERT_EQ (3, richloc.get_num_fixit_hints ());
-     const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
-     ASSERT_EQ (column_range (14, 14),
- 	       get_affected_range (fc, policy, hint_0, CU_BYTES));
-     ASSERT_EQ (column_range (12, 12),
- 	       get_affected_range (fc, policy, hint_0, CU_DISPLAY_COLS));
-     ASSERT_EQ (column_range (12, 22), get_printed_columns (fc, policy, hint_0));
-     const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
-     ASSERT_EQ (column_range (22, 22),
- 	       get_affected_range (fc, policy, hint_1, CU_BYTES));
-     ASSERT_EQ (column_range (18, 18),
- 	       get_affected_range (fc, policy, hint_1, CU_DISPLAY_COLS));
-     ASSERT_EQ (column_range (18, 20), get_printed_columns (fc, policy, hint_1));
-     const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
-     ASSERT_EQ (column_range (35, 34),
- 	       get_affected_range (fc, policy, hint_2, CU_BYTES));
-     ASSERT_EQ (column_range (30, 29),
- 	       get_affected_range (fc, policy, hint_2, CU_DISPLAY_COLS));
-     ASSERT_EQ (column_range (30, 30), get_printed_columns (fc, policy, hint_2));
- 
-     /* Add each hint in turn to a line_corrections instance,
-        and verify that they are consolidated into one correction instance
-        as expected.  */
-     line_corrections lc (fc, policy, tmp.get_filename (), 1);
- 
-     /* The first replace hint by itself.  */
-     lc.add_hint (hint_0);
-     ASSERT_EQ (1, lc.m_corrections.length ());
-     ASSERT_EQ (column_range (14, 14), lc.m_corrections[0]->m_affected_bytes);
-     ASSERT_EQ (column_range (12, 12), lc.m_corrections[0]->m_affected_columns);
-     ASSERT_EQ (column_range (12, 22), lc.m_corrections[0]->m_printed_columns);
-     ASSERT_STREQ ("const_cast<", lc.m_corrections[0]->m_text);
- 
-     /* After the second replacement hint, they are printed together
-        as a replacement (along with the text between them).  */
-     lc.add_hint (hint_1);
-     ASSERT_EQ (1, lc.m_corrections.length ());
-     ASSERT_STREQ ("const_cast<f\xf0\x9f\x98\x82 *> (",
- 		  lc.m_corrections[0]->m_text);
-     ASSERT_EQ (column_range (14, 22), lc.m_corrections[0]->m_affected_bytes);
-     ASSERT_EQ (column_range (12, 18), lc.m_corrections[0]->m_affected_columns);
-     ASSERT_EQ (column_range (12, 30), lc.m_corrections[0]->m_printed_columns);
- 
-     /* After the final insertion hint, they are all printed together
-        as a replacement (along with the text between them).  */
-     lc.add_hint (hint_2);
-     ASSERT_STREQ ("const_cast<f\xf0\x9f\x98\x82 *> (ptr->field\xcf\x80)",
- 		  lc.m_corrections[0]->m_text);
-     ASSERT_EQ (1, lc.m_corrections.length ());
-     ASSERT_EQ (column_range (14, 34), lc.m_corrections[0]->m_affected_bytes);
-     ASSERT_EQ (column_range (12, 29), lc.m_corrections[0]->m_affected_columns);
-     ASSERT_EQ (column_range (12, 42), lc.m_corrections[0]->m_printed_columns);
-   }
- 
-   /* Example where two are consolidated during printing.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_replace (open_paren, "CAST (");
-     richloc.add_fixit_replace (close_paren, ") (");
-     richloc.add_fixit_insert_after (")");
- 
-     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
- 			" *f = (f\xf0\x9f\x98\x82"
- 				  " *)ptr->field\xcf\x80"
- 						";\n"
- 		  "                   ^~~~~~~~~~~\n"
- 		  "            -\n"
- 		  "            CAST (-\n"
- 		  "                  ) (         )\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example where none are consolidated during printing.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_replace (open_paren, "CST (");
-     richloc.add_fixit_replace (close_paren, ") (");
-     richloc.add_fixit_insert_after (")");
- 
-     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
- 			" *f = (f\xf0\x9f\x98\x82"
- 				  " *)ptr->field\xcf\x80"
- 						";\n"
- 		  "                   ^~~~~~~~~~~\n"
- 		  "            -\n"
- 		  "            CST ( -\n"
- 		  "                  ) (         )\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of deletion fix-it hints.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_insert_before (open_paren, "(bar\xf0\x9f\x98\x82 *)");
-     source_range victim = {open_paren, close_paren};
-     richloc.add_fixit_remove (victim);
- 
-     /* This case is actually handled by fixit-consolidation,
-        rather than by line_corrections.  */
-     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
- 
-     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
- 			" *f = (f\xf0\x9f\x98\x82"
- 				  " *)ptr->field\xcf\x80"
- 						";\n"
- 		  "                   ^~~~~~~~~~~\n"
- 		  "            -------\n"
- 		  "            (bar\xf0\x9f\x98\x82"
- 				    " *)\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of deletion fix-it hints that would overlap.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_insert_before (open_paren, "(long\xf0\x9f\x98\x82 *)");
-     source_range victim = {expr_start, expr_finish};
-     richloc.add_fixit_remove (victim);
- 
-     /* These fixits are not consolidated.  */
-     ASSERT_EQ (2, richloc.get_num_fixit_hints ());
- 
-     /* But the corrections are.  */
-     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
- 			" *f = (f\xf0\x9f\x98\x82"
- 				  " *)ptr->field\xcf\x80"
- 						";\n"
- 		  "                   ^~~~~~~~~~~\n"
- 		  "            ------------------\n"
- 		  "            (long\xf0\x9f\x98\x82"
- 				     " *)(f\xf0\x9f\x98\x82"
- 					    " *)\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Example of insertion fix-it hints that would overlap.  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, expr);
-     richloc.add_fixit_insert_before
-       (open_paren, "L\xf0\x9f\x98\x82NGER THAN THE CAST");
-     richloc.add_fixit_insert_after (close_paren, "TEST");
- 
-     /* The first insertion is long enough that if printed naively,
-        it would overlap with the second.
-        Verify that they are printed as a single replacement.  */
-     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
- 			" *f = (f\xf0\x9f\x98\x82"
- 				  " *)ptr->field\xcf\x80"
- 						";\n"
- 		  "                   ^~~~~~~~~~~\n"
- 		  "            -------\n"
- 		  "            L\xf0\x9f\x98\x82"
- 				 "NGER THAN THE CAST(f\xf0\x9f\x98\x82"
- 						       " *)TEST\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* Verify that the line_corrections machinery correctly prints
-    overlapping fixit-hints that have been added in the wrong
-    order.
-    Adapted from PR c/81405 seen on gcc.dg/init-excess-1.c*/
- 
- static void
- test_overlapped_fixit_printing_2 (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      ...000000000111111111122222222223333333333.
-      ...123456789012345678901234567890123456789.  */
-   const char *content
-     = ("int a5[][0][0] = { 1, 2 };\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-   line_table_test ltt (case_);
- 
-   const line_map_ordinary *ord_map
-     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
- 					   tmp.get_filename (), 0));
- 
-   linemap_line_start (line_table, 1, 100);
- 
-   const location_t final_line_end
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 100);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   const location_t col_1
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 1);
-   const location_t col_20
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 20);
-   const location_t col_21
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 21);
-   const location_t col_23
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 23);
-   const location_t col_25
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 25);
- 
-   /* Two insertions, in the wrong order.  */
-   {
-     test_diagnostic_context dc;
-     file_cache &fc = dc.get_file_cache ();
- 
-     rich_location richloc (line_table, col_20);
-     richloc.add_fixit_insert_before (col_23, "{");
-     richloc.add_fixit_insert_before (col_21, "}");
- 
-     /* These fixits should be accepted; they can't be consolidated.  */
-     char_display_policy policy (make_char_policy (dc, richloc));
-     ASSERT_EQ (2, richloc.get_num_fixit_hints ());
-     const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
-     ASSERT_EQ (column_range (23, 22),
- 	       get_affected_range (fc, policy, hint_0, CU_BYTES));
-     ASSERT_EQ (column_range (23, 23), get_printed_columns (fc, policy, hint_0));
-     const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
-     ASSERT_EQ (column_range (21, 20),
- 	       get_affected_range (fc, policy, hint_1, CU_BYTES));
-     ASSERT_EQ (column_range (21, 21), get_printed_columns (fc, policy, hint_1));
- 
-     /* Verify that they're printed correctly.  */
-     ASSERT_STREQ (" int a5[][0][0] = { 1, 2 };\n"
- 		  "                    ^\n"
- 		  "                     } {\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Various overlapping insertions, some occurring "out of order"
-      (reproducing the fix-it hints from PR c/81405).  */
-   {
-     test_diagnostic_context dc;
-     rich_location richloc (line_table, col_20);
- 
-     richloc.add_fixit_insert_before (col_20, "{{");
-     richloc.add_fixit_insert_before (col_21, "}}");
-     richloc.add_fixit_insert_before (col_23, "{");
-     richloc.add_fixit_insert_before (col_21, "}");
-     richloc.add_fixit_insert_before (col_23, "{{");
-     richloc.add_fixit_insert_before (col_25, "}");
-     richloc.add_fixit_insert_before (col_21, "}");
-     richloc.add_fixit_insert_before (col_1, "{");
-     richloc.add_fixit_insert_before (col_25, "}");
- 
-     ASSERT_STREQ (" int a5[][0][0] = { 1, 2 };\n"
- 		  "                    ^\n"
- 		  " {                  -----\n"
- 		  "                    {{1}}}}, {{{2 }}\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* Insertion fix-it hint: adding a "break;" on a line by itself.  */
- 
- static void
- test_fixit_insert_containing_newline (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................0000000001111111.
-      .........................1234567890123456.  */
-   const char *old_content = ("    case 'a':\n" /* line 1. */
- 			     "      x = a;\n"  /* line 2. */
- 			     "    case 'b':\n" /* line 3. */
- 			     "      x = b;\n");/* line 4. */
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
- 
-   location_t case_start = linemap_position_for_column (line_table, 5);
-   location_t case_finish = linemap_position_for_column (line_table, 13);
-   location_t case_loc = make_location (case_start, case_start, case_finish);
-   location_t line_start = linemap_position_for_column (line_table, 1);
- 
-   if (case_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Add a "break;" on a line by itself before line 3 i.e. before
-      column 1 of line 3. */
-   {
-     rich_location richloc (line_table, case_loc);
-     richloc.add_fixit_insert_before (line_start, "      break;\n");
- 
-     /* Without line numbers.  */
-     {
-       test_diagnostic_context dc;
-       ASSERT_STREQ ("       x = a;\n"
- 		    "+      break;\n"
- 		    "     case 'b':\n"
- 		    "     ^~~~~~~~~\n",
- 		    dc.test_show_locus (richloc));
-     }
- 
-     /* With line numbers.  */
-     {
-       test_diagnostic_context dc;
-       dc.m_source_printing.show_line_numbers_p = true;
-       ASSERT_STREQ ("    2 |       x = a;\n"
- 		    "  +++ |+      break;\n"
- 		    "    3 |     case 'b':\n"
- 		    "      |     ^~~~~~~~~\n",
- 		    dc.test_show_locus (richloc));
-     }
-   }
- 
-   /* Verify that attempts to add text with a newline fail when the
-      insertion point is *not* at the start of a line.  */
-   {
-     rich_location richloc (line_table, case_loc);
-     richloc.add_fixit_insert_before (case_start, "break;\n");
-     ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
-     test_diagnostic_context dc;
-     ASSERT_STREQ ("     case 'b':\n"
- 		  "     ^~~~~~~~~\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* Insertion fix-it hint: adding a "#include <stdio.h>\n" to the top
-    of the file, where the fix-it is printed in a different line-span
-    to the primary range of the diagnostic.  */
- 
- static void
- test_fixit_insert_containing_newline_2 (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................0000000001111111.
-      .........................1234567890123456.  */
-   const char *old_content = ("test (int ch)\n"  /* line 1. */
- 			     "{\n"              /* line 2. */
- 			     " putchar (ch);\n" /* line 3. */
- 			     "}\n");            /* line 4. */
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   line_table_test ltt (case_);
- 
-   const line_map_ordinary *ord_map = linemap_check_ordinary
-     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
-   linemap_line_start (line_table, 1, 100);
- 
-   /* The primary range is the "putchar" token.  */
-   location_t putchar_start
-     = linemap_position_for_line_and_column (line_table, ord_map, 3, 2);
-   location_t putchar_finish
-     = linemap_position_for_line_and_column (line_table, ord_map, 3, 8);
-   location_t putchar_loc
-     = make_location (putchar_start, putchar_start, putchar_finish);
-   rich_location richloc (line_table, putchar_loc);
- 
-   /* Add a "#include <stdio.h>" on a line by itself at the top of the file.  */
-   location_t file_start
-      = linemap_position_for_line_and_column (line_table, ord_map,  1, 1);
-   richloc.add_fixit_insert_before (file_start, "#include <stdio.h>\n");
- 
-   if (putchar_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   {
-     test_diagnostic_context dc;
-     ASSERT_STREQ ("FILENAME:1:1:\n"
- 		  "+#include <stdio.h>\n"
- 		  " test (int ch)\n"
- 		  "FILENAME:3:2:\n"
- 		  "  putchar (ch);\n"
- 		  "  ^~~~~~~\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* With line-numbering, the line spans are close enough to be
-      consolidated, since it makes little sense to skip line 2.  */
-   {
-     test_diagnostic_context dc;
-     dc.m_source_printing.show_line_numbers_p = true;
-     ASSERT_STREQ ("  +++ |+#include <stdio.h>\n"
- 		  "    1 | test (int ch)\n"
- 		  "    2 | {\n"
- 		  "    3 |  putchar (ch);\n"
- 		  "      |  ^~~~~~~\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* Replacement fix-it hint containing a newline.
-    This will fail, as newlines are only supported when inserting at the
-    beginning of a line.  */
- 
- static void
- test_fixit_replace_containing_newline (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-     .........................0000000001111.
-     .........................1234567890123.  */
-   const char *old_content = "foo = bar ();\n";
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
- 
-   /* Replace the " = " with "\n  = ", as if we were reformatting an
-      overly long line.  */
-   location_t start = linemap_position_for_column (line_table, 4);
-   location_t finish = linemap_position_for_column (line_table, 6);
-   location_t loc = linemap_position_for_column (line_table, 13);
-   rich_location richloc (line_table, loc);
-   source_range range = source_range::from_locations (start, finish);
-   richloc.add_fixit_replace (range, "\n =");
- 
-   /* Arbitrary newlines are not yet supported within fix-it hints, so
-      the fix-it should not be displayed.  */
-   ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
- 
-   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   test_diagnostic_context dc;
-   ASSERT_STREQ (" foo = bar ();\n"
- 		"             ^\n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Fix-it hint, attempting to delete a newline.
-    This will fail, as we currently only support fix-it hints that
-    affect one line at a time.  */
- 
- static void
- test_fixit_deletion_affecting_newline (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-     ..........................0000000001111.
-     ..........................1234567890123.  */
-   const char *old_content = ("foo = bar (\n"
- 			     "      );\n");
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   line_table_test ltt (case_);
-   const line_map_ordinary *ord_map = linemap_check_ordinary
-     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
-   linemap_line_start (line_table, 1, 100);
- 
-   /* Attempt to delete the " (\n...)".  */
-   location_t start
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 10);
-   location_t caret
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 11);
-   location_t finish
-     = linemap_position_for_line_and_column (line_table, ord_map, 2, 7);
-   location_t loc = make_location (caret, start, finish);
-   rich_location richloc (line_table, loc);
-   richloc. add_fixit_remove ();
- 
-   /* Fix-it hints that affect more than one line are not yet supported, so
-      the fix-it should not be displayed.  */
-   ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
- 
-   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   test_diagnostic_context dc;
-   ASSERT_STREQ (" foo = bar (\n"
- 		"          ~^\n"
- 		"       );\n"
- 		"       ~    \n",
- 		dc.test_show_locus (richloc));
- }
- 
- static void
- test_tab_expansion (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.  This example uses a tabstop
-      of 8, as the column numbers attempt to indicate:
- 
-     .....................000.01111111111.22222333333  display
-     .....................123.90123456789.56789012345  columns  */
-   const char *content = "  \t   This: `\t' is a tab.\n";
-   /* ....................000 00000011111 11111222222  byte
-      ....................123 45678901234 56789012345  columns  */
- 
-   const int tabstop = 8;
-   cpp_char_column_policy policy (tabstop, cpp_wcwidth);
-   const int first_non_ws_byte_col = 7;
-   const int right_quote_byte_col = 15;
-   const int last_byte_col = 25;
-   ASSERT_EQ (35, cpp_display_width (content, last_byte_col, policy));
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
- 
-   /* Don't attempt to run the tests if column data might be unavailable.  */
-   location_t line_end = linemap_position_for_column (line_table, last_byte_col);
-   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Check that the leading whitespace with mixed tabs and spaces is expanded
-      into 11 spaces.  Recall that print_line() also puts one space before
-      everything too.  */
-   {
-     test_diagnostic_context dc;
-     dc.m_tabstop = tabstop;
-     rich_location richloc (line_table,
- 			   linemap_position_for_column (line_table,
- 							first_non_ws_byte_col));
-     ASSERT_STREQ ("            This: `      ' is a tab.\n"
- 		  "            ^\n",
- 		  dc.test_show_locus (richloc));
-   }
- 
-   /* Confirm the display width was tracked correctly across the internal tab
-      as well.  */
-   {
-     test_diagnostic_context dc;
-     dc.m_tabstop = tabstop;
-     rich_location richloc (line_table,
- 			   linemap_position_for_column (line_table,
- 							right_quote_byte_col));
-     ASSERT_STREQ ("            This: `      ' is a tab.\n"
- 		  "                         ^\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* Verify that the escaping machinery can cope with a variety of different
-    invalid bytes.  */
- 
- static void
- test_escaping_bytes_1 (const line_table_case &case_)
- {
-   const char content[] = "before\0\1\2\3\v\x80\xff""after\n";
-   const size_t sz = sizeof (content);
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz);
-   line_table_test ltt (case_);
-   const line_map_ordinary *ord_map = linemap_check_ordinary
-     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
-   linemap_line_start (line_table, 1, 100);
- 
-   location_t finish
-     = linemap_position_for_line_and_column (line_table, ord_map, 1,
- 					    strlen (content));
- 
-   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Locations of the NUL and \v bytes.  */
-   location_t nul_loc
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 7);
-   location_t v_loc
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 11);
-   gcc_rich_location richloc (nul_loc);
-   richloc.add_range (v_loc);
- 
-   {
-     test_diagnostic_context dc;
-     ASSERT_STREQ (" before \1\2\3\v\x80\xff""after\n"
- 		  "       ^   ~\n",
- 		  dc.test_show_locus (richloc));
-   }
-   richloc.set_escape_on_output (true);
-   {
-     test_diagnostic_context dc;
-     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
-     ASSERT_STREQ
-       (" before<U+0000><U+0001><U+0002><U+0003><U+000B><80><ff>after\n"
-        "       ^~~~~~~~                        ~~~~~~~~\n",
-        dc.test_show_locus (richloc));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
-     ASSERT_STREQ (" before<00><01><02><03><0b><80><ff>after\n"
- 		  "       ^~~~            ~~~~\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* As above, but verify that we handle the initial byte of a line
-    correctly.  */
- 
- static void
- test_escaping_bytes_2 (const line_table_case &case_)
- {
-   const char content[]  = "\0after\n";
-   const size_t sz = sizeof (content);
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz);
-   line_table_test ltt (case_);
-   const line_map_ordinary *ord_map = linemap_check_ordinary
-     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
-   linemap_line_start (line_table, 1, 100);
- 
-   location_t finish
-     = linemap_position_for_line_and_column (line_table, ord_map, 1,
- 					    strlen (content));
- 
-   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Location of the NUL byte.  */
-   location_t nul_loc
-     = linemap_position_for_line_and_column (line_table, ord_map, 1, 1);
-   gcc_rich_location richloc (nul_loc);
- 
-   {
-     test_diagnostic_context dc;
-     ASSERT_STREQ ("  after\n"
- 		  " ^\n",
- 		  dc.test_show_locus (richloc));
-   }
-   richloc.set_escape_on_output (true);
-   {
-     test_diagnostic_context dc;
-     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
-     ASSERT_STREQ (" <U+0000>after\n"
- 		  " ^~~~~~~~\n",
- 		  dc.test_show_locus (richloc));
-   }
-   {
-     test_diagnostic_context dc;
-     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
-     ASSERT_STREQ (" <00>after\n"
- 		  " ^~~~\n",
- 		  dc.test_show_locus (richloc));
-   }
- }
- 
- /* Verify that line numbers are correctly printed for the case of
-    a multiline range in which the width of the line numbers changes
-    (e.g. from "9" to "10").  */
- 
- static void
- test_line_numbers_multiline_range ()
- {
-   /* Create a tempfile and write some text to it.  */
-   pretty_printer pp;
-   for (int i = 0; i < 20; i++)
-     /* .........0000000001111111.
-    .............1234567890123456.  */
-     pp_printf (&pp, "this is line %i\n", i + 1);
-   temp_source_file tmp (SELFTEST_LOCATION, ".txt", pp_formatted_text (&pp));
-   line_table_test ltt;
- 
-   const line_map_ordinary *ord_map = linemap_check_ordinary
-     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
-   linemap_line_start (line_table, 1, 100);
- 
-   /* Create a multi-line location, starting at the "line" of line 9, with
-      a caret on the "is" of line 10, finishing on the "this" line 11.  */
- 
-   location_t start
-     = linemap_position_for_line_and_column (line_table, ord_map, 9, 9);
-   location_t caret
-     = linemap_position_for_line_and_column (line_table, ord_map, 10, 6);
-   location_t finish
-     = linemap_position_for_line_and_column (line_table, ord_map, 11, 4);
-   location_t loc = make_location (caret, start, finish);
- 
-   test_diagnostic_context dc;
-   dc.m_source_printing.show_line_numbers_p = true;
-   dc.m_source_printing.min_margin_width = 0;
-   gcc_rich_location richloc (loc);
-   ASSERT_STREQ (" 9 | this is line 9\n"
- 		"   |         ~~~~~~\n"
- 		"10 | this is line 10\n"
- 		"   | ~~~~~^~~~~~~~~~\n"
- 		"11 | this is line 11\n"
- 		"   | ~~~~  \n",
- 		dc.test_show_locus (richloc));
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- diagnostic_show_locus_cc_tests ()
- {
-   test_line_span ();
- 
-   test_layout_range_for_single_point ();
-   test_layout_range_for_single_line ();
-   test_layout_range_for_multiple_lines ();
- 
-   test_display_widths ();
- 
-   for_each_line_table_case (test_layout_x_offset_display_utf8);
-   for_each_line_table_case (test_layout_x_offset_display_tab);
- 
-   test_get_line_bytes_without_trailing_whitespace ();
- 
-   test_diagnostic_show_locus_unknown_location ();
- 
-   for_each_line_table_case (test_diagnostic_show_locus_one_liner);
-   for_each_line_table_case (test_diagnostic_show_locus_one_liner_utf8);
-   for_each_line_table_case (test_add_location_if_nearby);
-   for_each_line_table_case (test_diagnostic_show_locus_fixit_lines);
-   for_each_line_table_case (test_fixit_consolidation);
-   for_each_line_table_case (test_overlapped_fixit_printing);
-   for_each_line_table_case (test_overlapped_fixit_printing_utf8);
-   for_each_line_table_case (test_overlapped_fixit_printing_2);
-   for_each_line_table_case (test_fixit_insert_containing_newline);
-   for_each_line_table_case (test_fixit_insert_containing_newline_2);
-   for_each_line_table_case (test_fixit_replace_containing_newline);
-   for_each_line_table_case (test_fixit_deletion_affecting_newline);
-   for_each_line_table_case (test_tab_expansion);
-   for_each_line_table_case (test_escaping_bytes_1);
-   for_each_line_table_case (test_escaping_bytes_2);
- 
-   test_line_numbers_multiline_range ();
- }
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
- 
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic pop
- #endif
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-spec.cc gcc-16-20250727/gcc/diagnostic-spec.cc
*** gcc-16-20250720/gcc/diagnostic-spec.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-spec.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,230 ****
- /* Functions to enable and disable individual warnings on an expression
-    and statement basis.
-    Copyright (C) 2021-2025 Free Software Foundation, Inc.
-    Contributed by Martin Sebor <msebor@redhat.com>
- 
-    This file is part of GCC.
- 
-    GCC is free software; you can redistribute it and/or modify it under
-    the terms of the GNU General Public License as published by the Free
-    Software Foundation; either version 3, or (at your option) any later
-    version.
- 
-    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-    WARRANTY; without even the implied warranty of MERCHANTABILITY or
-    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-    for more details.
- 
-    You should have received a copy of the GNU General Public License
-    along with GCC; see the file COPYING3.  If not see
-    <http://www.gnu.org/licenses/>.  */
- 
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "backend.h"
- #include "bitmap.h"
- #include "tree.h"
- #include "cgraph.h"
- #include "hash-map.h"
- #include "diagnostic-spec.h"
- #include "pretty-print.h"
- #include "options.h"
- 
- /* Initialize *THIS from warning option OPT.  */
- 
- nowarn_spec_t::nowarn_spec_t (opt_code opt)
- {
-   /* Create a very simple mapping based on testing and experience.
-      It should become more refined with time. */
-   switch (opt)
-     {
-     case no_warning:
-       m_bits = 0;
-       break;
- 
-     case all_warnings:
-       m_bits = -1;
-       break;
- 
-       /* Flow-sensitive warnings about pointer problems issued by both
- 	 front ends and the middle end.  */
-     case OPT_Waddress:
-     case OPT_Wnonnull:
-       m_bits = NW_NONNULL;
-       break;
- 
-       /* Flow-sensitive warnings about arithmetic overflow issued by both
- 	 front ends and the middle end.  */
-     case OPT_Woverflow:
-     case OPT_Wshift_count_negative:
-     case OPT_Wshift_count_overflow:
-     case OPT_Wstrict_overflow:
-       m_bits = NW_VFLOW;
-       break;
- 
-       /* Lexical warnings issued by front ends.  */
-     case OPT_Wabi:
-     case OPT_Wlogical_op:
-     case OPT_Wparentheses:
-     case OPT_Wreturn_type:
-     case OPT_Wsizeof_array_div:
-     case OPT_Wstrict_aliasing:
-     case OPT_Wunused:
-     case OPT_Wunused_function:
-     case OPT_Wunused_but_set_variable_:
-     case OPT_Wunused_variable:
-     case OPT_Wunused_but_set_parameter_:
-       m_bits = NW_LEXICAL;
-       break;
- 
-       /* Access warning group.  */
-     case OPT_Warray_bounds_:
-     case OPT_Wformat_overflow_:
-     case OPT_Wformat_truncation_:
-     case OPT_Wrestrict:
-     case OPT_Wsizeof_pointer_memaccess:
-     case OPT_Wstrict_aliasing_:
-     case OPT_Wstringop_overflow_:
-     case OPT_Wstringop_overread:
-     case OPT_Wstringop_truncation:
-       m_bits = NW_ACCESS;
-       break;
- 
-       /* Initialization warning group.  */
-     case OPT_Winit_self:
-     case OPT_Wuninitialized:
-     case OPT_Wmaybe_uninitialized:
-       m_bits = NW_UNINIT;
-       break;
- 
-     case OPT_Wdangling_pointer_:
-     case OPT_Wreturn_local_addr:
-     case OPT_Wuse_after_free_:
-       m_bits = NW_DANGLING;
-       break;
- 
-     case OPT_Wpessimizing_move:
-     case OPT_Wredundant_move:
-       m_bits = NW_REDUNDANT;
-       break;
- 
-     default:
-       /* A catchall group for everything else.  */
-       m_bits = NW_OTHER;
-     }
- }
- 
- /* A mapping from a 'location_t' to the warning spec set for it.  */
- 
- GTY(()) nowarn_map_t *nowarn_map;
- 
- /* Return the no-warning disposition for location LOC and option OPT
-    or for all/any otions by default.  */
- 
- bool
- warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
- {
-   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
- 
-   if (!nowarn_map)
-     return false;
- 
-   if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
-     {
-       const nowarn_spec_t optspec (opt);
-       return *pspec & optspec;
-     }
- 
-   return false;
- }
- 
-  /* Change the supression of warnings for location LOC.
-     OPT controls which warnings are affected.
-     The wildcard OPT of -1 controls all warnings.
-     If SUPP is true (the default), enable the suppression of the warnings.
-     If SUPP is false, disable the suppression of the warnings.  */
- 
- bool
- suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
- 		     bool supp /* = true */)
- {
-   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
- 
-   const nowarn_spec_t optspec (supp ? opt : opt_code ());
- 
-   if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : nullptr)
-     {
-       if (supp)
- 	{
- 	  *pspec |= optspec;
- 	  return true;
- 	}
- 
-       *pspec &= optspec;
-       if (*pspec)
- 	return true;
- 
-       nowarn_map->remove (loc);
-       return false;
-     }
- 
-   if (!supp || opt == no_warning)
-     return false;
- 
-   if (!nowarn_map)
-     nowarn_map = nowarn_map_t::create_ggc (32);
- 
-   nowarn_map->put (loc, optspec);
-   return true;
- }
- 
- /* Change the warning disposition for LOC to match OPTSPEC.  */
- 
- void
- put_warning_spec_at (location_t loc, unsigned bits)
- {
-   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
- 
-   nowarn_spec_t optspec = nowarn_spec_t::from_bits (bits);
-   if (!optspec)
-     {
-       if (nowarn_map)
- 	nowarn_map->remove (loc);
-     }
-   else
-     {
-       if (!nowarn_map)
- 	nowarn_map = nowarn_map_t::create_ggc (32);
-       nowarn_map->put (loc, optspec);
-     }
- }
- 
- /* Copy the no-warning disposition from one location to another.  */
- 
- void
- copy_warning (location_t to, location_t from)
- {
-   if (!nowarn_map)
-     return;
- 
-   nowarn_spec_t *from_spec;
-   if (RESERVED_LOCATION_P (from))
-     from_spec = nullptr;
-   else
-     from_spec = nowarn_map->get (from);
-   if (RESERVED_LOCATION_P (to))
-     /* We cannot set no-warning dispositions for 'to', so we have no chance but
-        lose those potentially set for 'from'.  */
-     ;
-   else
-     {
-       if (from_spec)
- 	{
- 	  nowarn_spec_t tem = *from_spec;
- 	  nowarn_map->put (to, tem);
- 	}
-       else
- 	nowarn_map->remove (to);
-     }
- }
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-spec.h gcc-16-20250727/gcc/diagnostic-spec.h
*** gcc-16-20250720/gcc/diagnostic-spec.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-spec.h	Thu Jan  1 00:00:00 1970
***************
*** 1,149 ****
- /* Language-independent APIs to enable/disable per-location warnings.
- 
-    Copyright (C) 2021-2025 Free Software Foundation, Inc.
-    Contributed by Martin Sebor <msebor@redhat.com>
- 
-    This file is part of GCC.
- 
-    GCC is free software; you can redistribute it and/or modify it under
-    the terms of the GNU General Public License as published by the Free
-    Software Foundation; either version 3, or (at your option) any later
-    version.
- 
-    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-    WARRANTY; without even the implied warranty of MERCHANTABILITY or
-    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-    for more details.
- 
-    You should have received a copy of the GNU General Public License
-    along with GCC; see the file COPYING3.  If not see
-    <http://www.gnu.org/licenses/>.  */
- 
- #ifndef DIAGNOSTIC_SPEC_H_INCLUDED
- #define DIAGNOSTIC_SPEC_H_INCLUDED
- 
- #include "hash-map.h"
- 
- /* A "bitset" of warning groups.  */
- 
- class nowarn_spec_t
- {
- public:
-   enum
-     {
-      /* Middle end warnings about invalid accesses.  */
-      NW_ACCESS = 1 << 0,
-      /* Front end/lexical warnings.  */
-      NW_LEXICAL = 1 << 1,
-      /* Warnings about null pointers.  */
-      NW_NONNULL = 1 << 2,
-      /* Warnings about uninitialized reads.  */
-      NW_UNINIT = 1 << 3,
-      /* Warnings about arithmetic overflow.  */
-      NW_VFLOW = 1 << 4,
-      /* Warnings about dangling pointers.  */
-      NW_DANGLING = 1 << 5,
-      /* All other unclassified warnings.  */
-      NW_OTHER = 1 << 6,
-      /* Warnings about redundant calls.  */
-      NW_REDUNDANT = 1 << 7,
-      /* All groups of warnings.  */
-      NW_ALL = (NW_ACCESS | NW_LEXICAL | NW_NONNULL
- 	       | NW_UNINIT | NW_VFLOW | NW_DANGLING | NW_REDUNDANT | NW_OTHER)
-    };
- 
-   nowarn_spec_t (): m_bits () { }
- 
-   nowarn_spec_t (opt_code);
- 
-   static nowarn_spec_t from_bits (unsigned bits)
-   {
-     nowarn_spec_t spec;
-     spec.m_bits = bits;
-     return spec;
-   }
- 
-   /* Return the raw bitset.  */
-   operator unsigned() const
-   {
-     return m_bits;
-   }
- 
-   /* Return true if the bitset is clear.  */
-   bool operator!() const
-   {
-     return !m_bits;
-   }
- 
-   /* Return the inverse of the bitset.  */
-   nowarn_spec_t operator~() const
-   {
-     nowarn_spec_t res (*this);
-     res.m_bits &= ~NW_ALL;
-     return res;
-   }
- 
-   /* Set *THIS to the bitwise OR of *THIS and RHS.  */
-   nowarn_spec_t& operator|= (const nowarn_spec_t &rhs)
-   {
-     m_bits |= rhs.m_bits;
-     return *this;
-   }
- 
-   /* Set *THIS to the bitwise AND of *THIS and RHS.  */
-   nowarn_spec_t& operator&= (const nowarn_spec_t &rhs)
-   {
-     m_bits &= rhs.m_bits;
-     return *this;
-   }
- 
-   /* Set *THIS to the bitwise exclusive OR of *THIS and RHS.  */
-   nowarn_spec_t& operator^= (const nowarn_spec_t &rhs)
-   {
-     m_bits ^= rhs.m_bits;
-     return *this;
-   }
- 
- private:
-   /* Bitset of warning groups.  */
-   unsigned m_bits;
- };
- 
- /* Return the bitwise OR of LHS and RHS.  */
- 
- inline nowarn_spec_t
- operator| (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
- {
-   return nowarn_spec_t (lhs) |= rhs;
- }
- 
- /* Return the bitwise AND of LHS and RHS.  */
- 
- inline nowarn_spec_t
- operator& (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
- {
-   return nowarn_spec_t (lhs) &= rhs;
- }
- 
- /* Return true if LHS is equal RHS.  */
- 
- inline bool
- operator== (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
- {
-   return static_cast<unsigned>(lhs) == static_cast<unsigned>(rhs);
- }
- 
- /* Return true if LHS is not equal RHS.  */
- 
- inline bool
- operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
- {
-   return !(lhs == rhs);
- }
- 
- typedef hash_map<location_hash, nowarn_spec_t> nowarn_map_t;
- 
- /* A mapping from a 'location_t' to the warning spec set for it.  */
- extern GTY(()) nowarn_map_t *nowarn_map;
- 
- #endif // DIAGNOSTIC_SPEC_H_INCLUDED
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-state-graphs.cc gcc-16-20250727/gcc/diagnostic-state-graphs.cc
*** gcc-16-20250720/gcc/diagnostic-state-graphs.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-state-graphs.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,158 ****
- /* Extensions to diagnostics::digraphs to support state graphs.
-    Copyright (C) 2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- 
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #define INCLUDE_ALGORITHM
- #define INCLUDE_MAP
- #define INCLUDE_SET
- #define INCLUDE_STRING
- #define INCLUDE_VECTOR
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- 
- #include "diagnostic-state-graphs.h"
- #include "graphviz.h"
- #include "xml.h"
- #include "xml-printer.h"
- #include "intl.h"
- #include "selftest.h"
- 
- using namespace diagnostics::state_graphs;
- 
- const char * const node_kind_strs[] = {
-   "globals",
-   "code",
-   "function",
-   "stack",
-   "stack-frame",
-   "heap",
-   "thread-local",
-   "dynalloc-buffer",
-   "variable",
-   "field",
-   "padding",
-   "element",
-   "other",
- };
- 
- const char *
- diagnostics::state_graphs::node_kind_to_str (enum node_kind k)
- {
-   return node_kind_strs[static_cast<int> (k)];
- }
- 
- // struct state_node_ref
- 
- enum node_kind
- state_node_ref::get_node_kind () const
- {
-   const char *value = get_attr ("kind");
-   if (!value)
-     return node_kind::other;
- 
-   for (size_t i = 0; i < ARRAY_SIZE (node_kind_strs); ++i)
-     if (!strcmp (node_kind_strs[i], value))
-       return static_cast<enum node_kind> (i);
- 
-   return node_kind::other;
- }
- 
- void
- state_node_ref::set_node_kind (enum node_kind k)
- {
-   set_attr ("kind", node_kind_to_str (k));
- }
- 
- const char * const dynalloc_state_strs[] = {
-   "unknown",
-   "nonnull",
-   "unchecked",
-   "freed"
- };
- 
- enum node_dynalloc_state
- state_node_ref::get_dynalloc_state () const
- {
-   const char *value = get_attr ("dynalloc-state");
-   if (!value)
-     return node_dynalloc_state::unknown;
- 
-   for (size_t i = 0; i < ARRAY_SIZE (dynalloc_state_strs); ++i)
-     if (!strcmp (dynalloc_state_strs[i], value))
-       return static_cast<enum node_dynalloc_state> (i);
-   
-   return node_dynalloc_state::unknown;
- }
- 
- void
- state_node_ref::set_dynalloc_state (enum node_dynalloc_state s) const
- {
-   set_attr ("dynalloc-state",
- 	    dynalloc_state_strs[static_cast <size_t> (s)]);
- }
- 
- const char *
- state_node_ref::get_dynamic_extents () const
- {
-   return m_node.get_attr (STATE_NODE_PREFIX, "dynamic-extents");
- }
- 
- void
- state_node_ref::set_json_attr (const char *key,
- 			       std::unique_ptr<json::value> value) const
- {
-   m_node.set_json_attr (STATE_NODE_PREFIX, key, std::move (value));
- }
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- static void
- test_node_attrs ()
- {
-   diagnostics::digraphs::digraph g;
-   diagnostics::digraphs::node n (g, "a");
-   state_node_ref node_ref (n);
- 
-   ASSERT_EQ (node_ref.get_node_kind (), node_kind::other);
-   node_ref.set_node_kind (node_kind::stack);
-   ASSERT_EQ (node_ref.get_node_kind (), node_kind::stack);
- 
-   ASSERT_EQ (node_ref.get_dynalloc_state (), node_dynalloc_state::unknown);
-   node_ref.set_dynalloc_state (node_dynalloc_state::freed);
-   ASSERT_EQ (node_ref.get_dynalloc_state (), node_dynalloc_state::freed);
- 
-   ASSERT_EQ (node_ref.get_type (), nullptr);
-   node_ref.set_type ("const char *");
-   ASSERT_STREQ (node_ref.get_type (), "const char *");
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- diagnostic_state_graphs_cc_tests ()
- {
-   test_node_attrs ();
- }
- 
- } // namespace selftest
- 
- #endif /* CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-state-graphs.h gcc-16-20250727/gcc/diagnostic-state-graphs.h
*** gcc-16-20250720/gcc/diagnostic-state-graphs.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-state-graphs.h	Thu Jan  1 00:00:00 1970
***************
*** 1,156 ****
- /* Extensions to diagnostics::digraphs to support state graphs.
-    Copyright (C) 2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_STATE_GRAPHS_H
- #define GCC_DIAGNOSTIC_STATE_GRAPHS_H
- 
- #include "diagnostic-digraphs.h"
- #include "logical-location.h"
- 
- /* diagnostics::digraphs provides support for directed graphs.
- 
-    diagnostics::state_graphs provides a way to extend these graphs
-    for representing "state graphs" i.e. a representation of the state
-    of memory inside a program, for use e.g. by -fanalyzer.
- 
-    Specifically, nodes represent memory regions, and we use property bags
-    in these nodes to stash extra properties (e.g. what kind of memory region
-    a node is e.g. stack vs heap).  */
- 
- class sarif_graph;
- namespace dot { class graph; }
- 
- namespace diagnostics {
- namespace state_graphs {
- 
- enum class node_kind
- {
-   // Memory regions
-   globals,
-   code,
-   function, // code within a particular function
-   stack,
-   stack_frame,
-   heap_,
-   thread_local_,
- 
-   /* Dynamically-allocated buffer,
-      on heap or stack (depending on parent).  */
-   dynalloc_buffer,
- 
-   variable,
- 
-   field, // field within a struct or union
-   padding, // padding bits in a struct or union
-   element, // element within an array
- 
-   other // anything else
- };
- 
- extern const char *
- node_kind_to_str (enum node_kind);
- 
- enum class node_dynalloc_state
- {
-   unknown,
-   nonnull,
-   unchecked,
-   freed
- };
- 
- /* Prefixes to use in SARIF property bags.  */
- #define STATE_GRAPH_PREFIX "gcc/diagnostic_state_graph/"
- #define STATE_NODE_PREFIX "gcc/diagnostic_state_node/"
- #define STATE_EDGE_PREFIX "gcc/diagnostic_state_edge/"
- 
- /* A wrapper around a node that gets/sets attributes, using
-    the node's property bag for storage, so that the data roundtrips
-    through SARIF.  */
- 
- struct state_node_ref
- {
-   state_node_ref (diagnostics::digraphs::node &node)
-   : m_node (node)
-   {}
- 
-   enum node_kind
-   get_node_kind () const;
-   void
-   set_node_kind (enum node_kind);
- 
-   // For node_kind::stack_frame, this will be the function
-   logical_location
-   get_logical_loc () const
-   {
-     return m_node.get_logical_loc ();
-   }
- 
-   // For node_kind::dynalloc_buffer
-   enum node_dynalloc_state
-   get_dynalloc_state () const;
- 
-   void
-   set_dynalloc_state (enum node_dynalloc_state) const;
- 
-   const char *
-   get_dynamic_extents () const;
- 
-   const char *
-   get_name () const { return get_attr ("name"); }
-   void
-   set_name (const char *name) const { set_attr ("name", name); }
- 
-   const char *
-   get_type () const { return get_attr ("type"); }
-   void
-   set_type (const char *type) const { set_attr ("type", type); }
- 
-   const char *
-   get_value () const { return get_attr ("value"); }
- 
-   const char *
-   get_index () const { return get_attr ("index"); }
- 
-   const char *
-   get_attr (const char *key) const
-   {
-     return m_node.get_attr (STATE_NODE_PREFIX, key);
-   }
- 
-   void
-   set_attr (const char *key, const char *value) const
-   {
-     return m_node.set_attr (STATE_NODE_PREFIX, key, value);
-   }
- 
-   void
-   set_json_attr (const char *key, std::unique_ptr<json::value> value) const;
- 
-   diagnostics::digraphs::node &m_node;
- };
- 
- extern std::unique_ptr<dot::graph>
- make_dot_graph (const diagnostics::digraphs::digraph &state_graph,
- 		const logical_location_manager &logical_loc_mgr);
- 
- } // namespace state_graphs
- } // namespace diagnostics
- 
- #endif /* ! GCC_DIAGNOSTIC_STATE_GRAPHS_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-state-to-dot.cc gcc-16-20250727/gcc/diagnostic-state-to-dot.cc
*** gcc-16-20250720/gcc/diagnostic-state-to-dot.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-state-to-dot.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,550 ****
- /* Creating GraphViz .dot files from diagnostic state graphs.
-    Copyright (C) 2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- 
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #define INCLUDE_ALGORITHM
- #define INCLUDE_MAP
- #define INCLUDE_SET
- #define INCLUDE_STRING
- #define INCLUDE_VECTOR
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- 
- #include "diagnostic-state-graphs.h"
- #include "graphviz.h"
- #include "xml.h"
- #include "xml-printer.h"
- #include "intl.h"
- 
- using namespace diagnostics::state_graphs;
- 
- static int
- get_depth (const diagnostics::digraphs::node &n)
- {
-   int deepest_child = 0;
-   for (size_t i = 0; i < n.get_num_children (); ++i)
-       deepest_child = std::max (deepest_child,
- 				get_depth (n.get_child (i)));
-   return deepest_child + 1;
- }
- 
- static const char *
- get_color_for_dynalloc_state (enum node_dynalloc_state dynalloc_st)
- {
-   switch (dynalloc_st)
-     {
-     default:
-       gcc_unreachable ();
-       break;
-     case node_dynalloc_state::unknown:
-     case node_dynalloc_state::nonnull:
-       return nullptr;
- 
-     case node_dynalloc_state::unchecked:
-       return "#ec7a08"; // pf-orange-400
- 
-     case node_dynalloc_state::freed:
-       return "#cc0000"; // pf-red-100
-     }
- }
- 
- static void
- set_color_for_dynalloc_state (dot::attr_list &attrs,
- 			      enum node_dynalloc_state state)
- {
-   if (const char *color = get_color_for_dynalloc_state (state))
-     attrs.add (dot::id ("color"), dot::id (color));
- }
- 
- class state_diagram : public dot::graph
- {
- public:
-   state_diagram (const diagnostics::digraphs::digraph &input_state_graph,
- 		 const logical_location_manager &logical_loc_mgr)
-   : m_logical_loc_mgr (logical_loc_mgr)
-   {
-     // "node [shape=plaintext]\n"
-     {
-       auto attr_stmt
- 	= std::make_unique<dot::attr_stmt> (dot::attr_stmt::kind::node);
-       attr_stmt->m_attrs.add (dot::id ("shape"), dot::id ("plaintext"));
-       add_stmt (std::move (attr_stmt));
-     }
- 
-     /* Determine which nodes are involved in edges.  */
-     for (size_t i = 0; i < input_state_graph.get_num_edges (); ++i)
-       {
- 	auto &edge = input_state_graph.get_edge (i);
- 	m_src_nodes.insert (&edge.get_src_node ());
- 	m_dst_nodes.insert (&edge.get_dst_node ());
-       }
- 
-     /* Recurse down the nodes in the state graph, creating subgraphs
-        and then eventually creating nodes, and recursively
-        creating XML tables, and adding ports for the endpoints of edges
-        where needed.  */
- 
-     auto root_cluster
-       = std::make_unique<dot::subgraph> (dot::id ("cluster_memory_regions"));
-     for (size_t i = 0; i < input_state_graph.get_num_nodes (); ++i)
-       on_input_state_node (*root_cluster,
- 			   state_node_ref (input_state_graph.get_node (i)));
-     add_stmt (std::move (root_cluster));
- 
-     /* Now create dot edges for edges in input_stage_graph.  */
-     for (size_t i = 0; i < input_state_graph.get_num_edges (); ++i)
-       {
- 	auto &edge = input_state_graph.get_edge (i);
- 	auto &src_node = edge.get_src_node ();
- 	auto &dst_node = edge.get_dst_node ();
- 
- 	auto src_port_id = m_src_node_to_port_id.find (&src_node);
- 	if (src_port_id == m_src_node_to_port_id.end ())
- 	  continue;
- 	auto dst_port_id = m_dst_node_to_port_id.find (&dst_node);
- 	if (dst_port_id == m_dst_node_to_port_id.end ())
- 	  continue;
- 
- 	auto e = std::make_unique<dot::edge_stmt> (src_port_id->second,
- 						   dst_port_id->second);
- 	set_color_for_dynalloc_state
- 	  (e->m_attrs, state_node_ref (dst_node).get_dynalloc_state ());
- 
- 	add_stmt (std::move (e));
-       }
-   }
- 
- private:
-   struct pending_edge
-   {
-     dot::node_id m_src_node_id;
-     std::string m_dst_region_id;
-   };
- 
-   dot::id
-   get_id_for_region (const char *region_id)
-   {
-     gcc_assert (region_id);
-     return std::string ("cluster_region_") + region_id;
-   }
- 
-   dot::id
-   make_id (state_node_ref state_node, bool cluster)
-   {
-     std::string input_node_id = state_node.m_node.get_id ();
-     if (cluster)
-       return std::string ("cluster_") + input_node_id;
-     else
-       return input_node_id;
-   }
- 
-   bool
-   starts_node_p (state_node_ref state_node)
-   {
-     switch (state_node.get_node_kind ())
-       {
-       default:
- 	return false;
- 
-       case node_kind::stack:
- 	/* We want all frames in the stack in the same table,
- 	   so they are grouped.  */
-       case node_kind::dynalloc_buffer:
-       case node_kind::variable:
- 	return true;
-       }
-   }
- 
-   const char *
-   get_label_for_node (state_node_ref state_node)
-   {
-     switch (state_node.get_node_kind ())
-       {
-       default:
- 	return nullptr;
- 
-       case node_kind::globals:
- 	return _("Globals");
-       case node_kind::code:
- 	return _("Code");
-       case node_kind::stack:
- 	return _("Stack");
-       case node_kind::heap_:
- 	return _("Heap");
-       }
-   }
- 
-   void
-   on_input_state_node (dot::subgraph &parent_subgraph,
- 		       state_node_ref state_node)
-   {
-     dot::id sg_id = make_id (state_node, true);
- 
-     if (starts_node_p (state_node))
-       {
- 	// Create node with table
- 	xml::element table ("table", false);
- 	xml::printer xp (table);
- 	xp.set_attr ("border", "0");
- 	xp.set_attr ("cellborder", "1");
- 	xp.set_attr ("cellspacing", "0");
- 
- 	const int max_depth = get_depth (state_node.m_node);
- 	const int num_columns = max_depth + 2;
- 
- 	dot::id id_of_dot_node = make_id (state_node, false);
- 	on_node_in_table (id_of_dot_node, xp, state_node,
- 			  max_depth, 0, num_columns);
- 
- 	auto node = std::make_unique<dot::node_stmt> (std::move (id_of_dot_node));
- 	node->m_attrs.add (dot::id ("shape"),
- 			   dot::id ("plaintext"));
- 
- 	// xml must be done by now
- 
- 	node->m_attrs.add (dot::id ("label"),
- 			   dot::id (table));
- 
- 	parent_subgraph.m_stmt_list.add_stmt (std::move (node));
-       }
-     else
-       {
- 	auto child_subgraph = std::make_unique<dot::subgraph> (std::move (sg_id));
- 
- 	if (const char *label = get_label_for_node (state_node))
- 	  child_subgraph->add_attr (dot::id ("label"), dot::id (label));
- 
- 	// recurse:
- 	for (size_t i = 0; i < state_node.m_node.get_num_children (); ++i)
- 	  on_input_state_node (*child_subgraph,
- 			       state_node.m_node.get_child (i));
- 	parent_subgraph.m_stmt_list.add_stmt (std::move (child_subgraph));
-       }
-   }
- 
-   enum class style { h1, h2 };
- 
-   void
-   add_title_tr (const dot::id &id_of_dot_node,
- 		xml::printer &xp,
- 		int num_columns,
- 		state_node_ref state_node,
- 		std::string heading,
- 		enum style styl,
- 		enum node_dynalloc_state dynalloc_state)
-   {
-     xp.push_tag ("tr", true);
-     xp.push_tag ("td", false);
-     xp.set_attr ("colspan", std::to_string (num_columns));
-     xp.set_attr ("cellpadding", "5");
- 
-     const char *bgcolor;
-     const char *color;
-     if (const char *c = get_color_for_dynalloc_state (dynalloc_state))
-       {
- 	bgcolor = c;
- 	color = "white";
-       }
-     else
-       switch (styl)
- 	{
- 	default:
- 	  gcc_unreachable ();
- 	case style::h1:
- 	  // from diagnostic-format-html.cc: HTML_STYLE .linenum
- 	  bgcolor = "#0088ce";
- 	  color = "white";
- 	  break;
- 	case style::h2:
- 	  // from diagnostic-format-html.cc: HTML_STYLE .events-hdr
- 	  bgcolor = "#393f44"; // pf-black-800
- 	  color = "white";
- 	  break;
- 	}
- 
-     xp.set_attr ("bgcolor", bgcolor);
-     xp.push_tag ("font", false);
-     xp.set_attr ("color", color);
-     if (heading == "")
-       heading = " ";
-     xp.add_text (std::move (heading));
-     xp.pop_tag ("font");
- 
-     maybe_add_dst_port (id_of_dot_node, xp, state_node);
- 
-     xp.pop_tag ("td");
-     xp.pop_tag ("tr");
-   }
- 
-   /* Recursively add <TR> to XP for STATE_NODE and its descendents.  */
-   void
-   on_node_in_table (const dot::id &id_of_dot_node,
- 		    xml::printer &xp,
- 		    state_node_ref state_node,
- 		    int max_depth,
- 		    int depth,
- 		    int num_columns)
-   {
-     bool recurse = true;
-     auto input_node_kind = state_node.get_node_kind ();
- 
-     switch (input_node_kind)
-       {
-       case node_kind::padding:
-       case node_kind::other:
- 	return;
- 
-       case node_kind::stack:
- 	add_title_tr (id_of_dot_node, xp, num_columns, state_node, "Stack",
- 		      style::h1,
- 		      node_dynalloc_state::unknown);
- 	break;
-       case node_kind::stack_frame:
- 	if (auto logical_loc = state_node.get_logical_loc ())
- 	  if (const char *function
- 		= m_logical_loc_mgr.get_short_name (logical_loc))
- 	    add_title_tr (id_of_dot_node, xp, num_columns, state_node,
- 			  std::string ("Frame: ") + function,
- 			  style::h2,
- 			  node_dynalloc_state::unknown);
- 	break;
-       case node_kind::dynalloc_buffer:
- 	{
- 	  enum node_dynalloc_state dynalloc_st
- 	    = state_node.get_dynalloc_state ();
- 	  const char *extents = state_node.get_dynamic_extents ();
- 	  const char *type = state_node.get_type ();
- 	  pretty_printer pp;
- 	  switch (dynalloc_st)
- 	    {
- 	    default:
- 	      gcc_unreachable ();
- 
- 	    case node_dynalloc_state::unknown:
- 	    case node_dynalloc_state::nonnull:
- 	      if (type)
- 		{
- 		if (extents)
- 		  pp_printf (&pp, "%s (%s byte allocation)",
- 			     type, extents);
- 		else
- 		  pp_printf (&pp, "%s", type);
- 		}
- 	      else
- 		{
- 		  if (extents)
- 		    pp_printf (&pp, "%s byte allocation",
- 			       extents);
- 		}
- 	      break;
- 
- 	    case node_dynalloc_state::unchecked:
- 	      if (type)
- 		{
- 		  if (extents)
- 		    pp_printf (&pp, "%s (unchecked %s byte allocation)",
- 			       type, extents);
- 		}
- 	      else
- 		{
- 		  if (extents)
- 		    pp_printf (&pp, "Unchecked %s byte allocation",
- 			       extents);
- 		}
- 	      break;
- 
- 	    case node_dynalloc_state::freed:
- 	      // TODO: show deallocator
- 	      // TODO: show deallocation event
- 	      pp_printf (&pp, "Freed buffer");
- 	      break;
- 	    }
- 	  maybe_add_dst_port (id_of_dot_node, xp, state_node);
- 	  add_title_tr (id_of_dot_node, xp, num_columns, state_node,
- 			pp_formatted_text (&pp),
- 			style::h2,
- 			dynalloc_st);
- 	}
- 	break;
- 
-       default:
- 	{
- 	  xp.push_tag ("tr", true);
- 
- 	  maybe_add_dst_port (id_of_dot_node, xp, state_node);
- 
- 	  if (depth > 0)
- 	    {
- 	      /* Indent, by create a <td> spanning "depth" columns.  */
- 	      xp.push_tag ("td", false);
- 	      xp.set_attr ("colspan", std::to_string (depth));
- 	      xp.add_text (" "); // graphviz doesn't like <td/>
- 	      xp.pop_tag ("td");
- 	    }
- 
- 	  switch (input_node_kind)
- 	    {
- 	    default:
- 	      break;
- 	    case node_kind::variable:
- 	      {
- 		const char *name = state_node.get_name ();
- 		gcc_assert (name);
- 		xp.push_tag ("td", false);
- 		maybe_add_dst_port (id_of_dot_node, xp, state_node);
- 		push_src_text (xp);
- 		xp.add_text (name);
- 		pop_src_text (xp);
- 		xp.pop_tag ("td");
- 	      }
- 	      break;
- 	    case node_kind::element:
- 	      {
- 		const char *index = state_node.get_index ();
- 		gcc_assert (index);
- 		xp.push_tag ("td", false);
- 		maybe_add_dst_port (id_of_dot_node, xp, state_node);
- 		push_src_text (xp);
- 		xp.add_text ("[");
- 		xp.add_text (index);
- 		xp.add_text ("]");
- 		pop_src_text (xp);
- 		xp.pop_tag ("td");
- 	      }
- 	      break;
- 	    case node_kind::field:
- 	      {
- 		const char *name = state_node.get_name ();
- 		gcc_assert (name);
- 		xp.push_tag ("td", false);
- 		maybe_add_dst_port (id_of_dot_node, xp, state_node);
- 		push_src_text (xp);
- 		xp.add_text (".");
- 		xp.add_text (name);
- 		pop_src_text (xp);
- 		xp.pop_tag ("td");
- 	      }
- 	      break;
- 	    }
- 
- 	  if (const char *type = state_node.get_type ())
- 	    {
- 	      xp.push_tag ("td", false);
- 	      xp.set_attr ("align", "right");
- 	      push_src_text (xp);
- 	      xp.add_text (type);
- 	      pop_src_text (xp);
- 	      xp.pop_tag ("td");
- 	    }
- 
- 	  if (const char *value = state_node.get_value ())
- 	    {
- 	      xp.push_tag ("td", false);
- 	      xp.set_attr ("align", "left");
- 	      maybe_add_src_port (id_of_dot_node, xp, state_node);
- 	      push_src_text (xp);
- 	      xp.add_text (value);
- 	      pop_src_text (xp);
- 	      xp.pop_tag ("td");
- 	      recurse = false;
- 	    }
- 	  xp.pop_tag ("tr");
- 	}
- 	break;
-       }
- 
-     if (recurse)
-       for (size_t i = 0; i < state_node.m_node.get_num_children (); ++i)
- 	on_node_in_table (id_of_dot_node, xp,
- 			  state_node.m_node.get_child (i),
- 			  max_depth, depth + 1, num_columns);
-   }
- 
-   void
-   push_src_text (xml::printer &xp)
-   {
-     xp.push_tag ("font");
-     xp.set_attr ("color", "blue");
-   }
- 
-   void
-   pop_src_text (xml::printer &xp)
-   {
-     xp.pop_tag ("font");
-   }
- 
-   /* If STATE_NODE is in m_src_nodes, add a port to XP for possible
-      incoming edges to use.  */
- 
-   void
-   maybe_add_src_port (const dot::id &id_of_dot_node,
- 		      xml::printer &xp,
- 		      state_node_ref state_node)
-   {
-     auto iter = m_src_nodes.find (&state_node.m_node);
-     if (iter == m_src_nodes.end ())
-       return;
- 
-     dot::id src_id = make_id (state_node, false);
-     dot::node_id node_id (id_of_dot_node,
- 			  dot::port (src_id,
- 				     dot::compass_pt::e));
-     m_src_node_to_port_id.insert ({&state_node.m_node, node_id});
-     xp.set_attr ("port", src_id.m_str);
-   }
- 
-   /* If STATE_NODE is in m_dst_nodes, add a port to XP for possible
-      incoming edges to use.  */
- 
-   void
-   maybe_add_dst_port (const dot::id &id_of_dot_node,
- 		      xml::printer &xp,
- 		      state_node_ref state_node)
-   {
-     auto iter = m_dst_nodes.find (&state_node.m_node);
-     if (iter == m_dst_nodes.end ())
-       return;
- 
-     dot::id dst_id = make_id (state_node, false);
-     dot::node_id node_id (id_of_dot_node,
- 			  dot::port (dst_id/*,
- 					     dot::compass_pt::w*/));
-     m_dst_node_to_port_id.insert ({&state_node.m_node, node_id});
-     xp.set_attr ("port", dst_id.m_str);
-   }
- 
- private:
-   const logical_location_manager &m_logical_loc_mgr;
- 
-   /* All nodes involved in edges (and thus will need a port).  */
-   std::set<diagnostics::digraphs::node *> m_src_nodes;
-   std::set<diagnostics::digraphs::node *> m_dst_nodes;
- 
-   std::map<diagnostics::digraphs::node *, dot::node_id> m_src_node_to_port_id;
-   std::map<diagnostics::digraphs::node *, dot::node_id> m_dst_node_to_port_id;
- };
- 
- std::unique_ptr<dot::graph>
- diagnostics::state_graphs::
- make_dot_graph (const diagnostics::digraphs::digraph &state_graph,
- 		const logical_location_manager &logical_loc_mgr)
- {
-   return std::make_unique<state_diagram> (state_graph, logical_loc_mgr);
- }
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic-url.h gcc-16-20250727/gcc/diagnostic-url.h
*** gcc-16-20250720/gcc/diagnostic-url.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic-url.h	Thu Jan  1 00:00:00 1970
***************
*** 1,52 ****
- /* Copyright (C) 2019-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_DIAGNOSTIC_URL_H
- #define GCC_DIAGNOSTIC_URL_H
- 
- /* Whether to add URLs to diagnostics:
-    - DIAGNOSTICS_URL_NO: never
-    - DIAGNOSTICS_URL_YES: always
-    - DIAGNOSTICS_URL_AUTO: depending on the output stream.  */
- typedef enum
- {
-   DIAGNOSTICS_URL_NO       = 0,
-   DIAGNOSTICS_URL_YES      = 1,
-   DIAGNOSTICS_URL_AUTO     = 2
- } diagnostic_url_rule_t;
- 
- /* Tells whether URLs should be emitted, and, if so, how to
-    terminate strings within the escape sequence.   */
- enum diagnostic_url_format
- {
-   /* No URLs shall be emitted.  */
-   URL_FORMAT_NONE,
- 
-   /* Use ST string termination.  */
-   URL_FORMAT_ST,
- 
-   /* Use BEL string termination.  */
-   URL_FORMAT_BEL
- };
- 
- const diagnostic_url_format URL_FORMAT_DEFAULT = URL_FORMAT_BEL;
- 
- extern diagnostic_url_format determine_url_format (diagnostic_url_rule_t);
- 
- #endif /* ! GCC_DIAGNOSTIC_URL_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic.cc gcc-16-20250727/gcc/diagnostic.cc
*** gcc-16-20250720/gcc/diagnostic.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,2484 ****
- /* Language-independent diagnostic subroutines for the GNU Compiler Collection
-    Copyright (C) 1999-2025 Free Software Foundation, Inc.
-    Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- 
- /* This file implements the language independent aspect of diagnostic
-    message module.  */
- 
- #include "config.h"
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "version.h"
- #include "demangle.h"
- #include "intl.h"
- #include "backtrace.h"
- #include "diagnostic.h"
- #include "diagnostic-color.h"
- #include "diagnostic-url.h"
- #include "diagnostic-metadata.h"
- #include "diagnostic-path.h"
- #include "diagnostic-client-data-hooks.h"
- #include "diagnostic-diagram.h"
- #include "diagnostic-format.h"
- #include "diagnostic-format-sarif.h"
- #include "diagnostic-format-text.h"
- #include "edit-context.h"
- #include "selftest.h"
- #include "selftest-diagnostic.h"
- #include "opts.h"
- #include "cpplib.h"
- #include "text-art/theme.h"
- #include "pretty-print-urlifier.h"
- #include "logical-location.h"
- #include "diagnostic-buffer.h"
- 
- #ifdef HAVE_TERMIOS_H
- # include <termios.h>
- #endif
- 
- #ifdef GWINSZ_IN_SYS_IOCTL
- # include <sys/ioctl.h>
- #endif
- 
- /* Disable warnings about quoting issues in the pp_xxx calls below
-    that (intentionally) don't follow GCC diagnostic conventions.  */
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic push
- #  pragma GCC diagnostic ignored "-Wformat-diag"
- #endif
- 
- static void real_abort (void) ATTRIBUTE_NORETURN;
- 
- /* Name of program invoked, sans directories.  */
- 
- const char *progname;
- 
- 
- /* Return a malloc'd string containing MSG formatted a la printf.  The
-    caller is responsible for freeing the memory.  */
- char *
- build_message_string (const char *msg, ...)
- {
-   char *str;
-   va_list ap;
- 
-   va_start (ap, msg);
-   str = xvasprintf (msg, ap);
-   va_end (ap);
- 
-   return str;
- }
- 
- 
- /* Return the value of the getenv("COLUMNS") as an integer. If the
-    value is not set to a positive integer, use ioctl to get the
-    terminal width. If it fails, return INT_MAX.  */
- int
- get_terminal_width (void)
- {
-   const char * s = getenv ("COLUMNS");
-   if (s != nullptr) {
-     int n = atoi (s);
-     if (n > 0)
-       return n;
-   }
- 
- #ifdef TIOCGWINSZ
-   struct winsize w;
-   w.ws_col = 0;
-   if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
-     return w.ws_col;
- #endif
- 
-   return INT_MAX;
- }
- 
- /* Set caret_max_width to value.  */
- void
- diagnostic_set_caret_max_width (diagnostic_context *context, int value)
- {
-   /* One minus to account for the leading empty space.  */
-   value = value ? value - 1
-     : (isatty (fileno (pp_buffer (context->get_reference_printer ())->m_stream))
-        ? get_terminal_width () - 1 : INT_MAX);
- 
-   if (value <= 0)
-     value = INT_MAX;
- 
-   context->m_source_printing.max_width = value;
- }
- 
- void
- diagnostic_option_classifier::init (int n_opts)
- {
-   m_n_opts = n_opts;
-   m_classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
-   for (int i = 0; i < n_opts; i++)
-     m_classify_diagnostic[i] = DK_UNSPECIFIED;
-   m_push_list = vNULL;
-   m_classification_history = vNULL;
- }
- 
- void
- diagnostic_option_classifier::fini ()
- {
-   XDELETEVEC (m_classify_diagnostic);
-   m_classify_diagnostic = nullptr;
-   m_classification_history.release ();
-   m_push_list.release ();
- }
- 
- /* Save the diagnostic_option_classifier state to F for PCH
-    output.  Returns 0 on success, -1 on error.  */
- 
- int
- diagnostic_option_classifier::pch_save (FILE *f)
- {
-   unsigned int lengths[2] = { m_classification_history.length (),
- 			      m_push_list.length () };
-   if (fwrite (lengths, sizeof (lengths), 1, f) != 1
-       || (lengths[0]
- 	  && fwrite (m_classification_history.address (),
- 		     sizeof (diagnostic_classification_change_t),
- 		     lengths[0], f) != lengths[0])
-       || (lengths[1]
- 	  && fwrite (m_push_list.address (), sizeof (int),
- 		     lengths[1], f) != lengths[1]))
-     return -1;
-   return 0;
- }
- 
- /* Read the diagnostic_option_classifier state from F for PCH
-    read.  Returns 0 on success, -1 on error.  */
- 
- int
- diagnostic_option_classifier::pch_restore (FILE *f)
- {
-   unsigned int lengths[2];
-   if (fread (lengths, sizeof (lengths), 1, f) != 1)
-     return -1;
-   gcc_checking_assert (m_classification_history.is_empty ());
-   gcc_checking_assert (m_push_list.is_empty ());
-   m_classification_history.safe_grow (lengths[0]);
-   m_push_list.safe_grow (lengths[1]);
-   if ((lengths[0]
-        && fread (m_classification_history.address (),
- 		 sizeof (diagnostic_classification_change_t),
- 		 lengths[0], f) != lengths[0])
-       || (lengths[1]
- 	  && fread (m_push_list.address (), sizeof (int),
- 		    lengths[1], f) != lengths[1]))
-     return -1;
-   return 0;
- }
- 
- /* Save all diagnostic classifications in a stack.  */
- 
- void
- diagnostic_option_classifier::push ()
- {
-   m_push_list.safe_push (m_classification_history.length ());
- }
- 
- /* Restore the topmost classification set off the stack.  If the stack
-    is empty, revert to the state based on command line parameters.  */
- 
- void
- diagnostic_option_classifier::pop (location_t where)
- {
-   int jump_to;
- 
-   if (!m_push_list.is_empty ())
-     jump_to = m_push_list.pop ();
-   else
-     jump_to = 0;
- 
-   diagnostic_classification_change_t v = { where, jump_to, DK_POP };
-   m_classification_history.safe_push (v);
- }
- 
- /* Initialize the diagnostic message outputting machinery.  */
- 
- void
- diagnostic_context::initialize (int n_opts)
- {
-   /* Allocate a basic pretty-printer.  Clients will replace this a
-      much more elaborated pretty-printer if they wish.  */
-   m_reference_printer = std::make_unique<pretty_printer> ().release ();
- 
-   m_file_cache = new file_cache ();
-   m_diagnostic_counters.clear ();
-   m_warning_as_error_requested = false;
-   m_n_opts = n_opts;
-   m_option_classifier.init (n_opts);
-   m_source_printing.enabled = false;
-   diagnostic_set_caret_max_width (this, pp_line_cutoff (get_reference_printer ()));
-   for (int i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
-     m_source_printing.caret_chars[i] = '^';
-   m_show_cwe = false;
-   m_show_rules = false;
-   m_path_format = DPF_NONE;
-   m_show_path_depths = false;
-   m_show_option_requested = false;
-   m_abort_on_error = false;
-   m_show_column = false;
-   m_pedantic_errors = false;
-   m_permissive = false;
-   m_opt_permissive = 0;
-   m_fatal_errors = false;
-   m_inhibit_warnings = false;
-   m_warn_system_headers = false;
-   m_max_errors = 0;
-   m_internal_error = nullptr;
-   m_adjust_diagnostic_info = nullptr;
-   m_text_callbacks.m_begin_diagnostic = default_diagnostic_text_starter;
-   m_text_callbacks.m_text_start_span
-     = default_diagnostic_start_span_fn<to_text>;
-   m_text_callbacks.m_html_start_span
-     = default_diagnostic_start_span_fn<to_html>;
-   m_text_callbacks.m_end_diagnostic = default_diagnostic_text_finalizer;
-   m_option_mgr = nullptr;
-   m_urlifier_stack = new auto_vec<urlifier_stack_node> ();
-   m_last_location = UNKNOWN_LOCATION;
-   m_client_aux_data = nullptr;
-   m_lock = 0;
-   m_inhibit_notes_p = false;
-   m_source_printing.colorize_source_p = false;
-   m_source_printing.show_labels_p = false;
-   m_source_printing.show_line_numbers_p = false;
-   m_source_printing.min_margin_width = 0;
-   m_source_printing.show_ruler_p = false;
-   m_source_printing.show_event_links_p = false;
-   m_report_bug = false;
-   m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_none;
-   if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
-     {
-       if (!strcmp (var, "fixits-v1"))
- 	m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
-       else if (!strcmp (var, "fixits-v2"))
- 	m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
-       /* Silently ignore unrecognized values.  */
-     }
-   m_column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
-   m_column_origin = 1;
-   m_tabstop = 8;
-   m_escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
-   m_edit_context_ptr = nullptr;
-   m_diagnostic_groups.m_group_nesting_depth = 0;
-   m_diagnostic_groups.m_diagnostic_nesting_level = 0;
-   m_diagnostic_groups.m_emission_count = 0;
-   m_diagnostic_groups.m_inhibiting_notes_from = 0;
-   m_output_sinks.safe_push
-     (new diagnostic_text_output_format (*this, nullptr, true));
-   m_set_locations_cb = nullptr;
-   m_client_data_hooks = nullptr;
-   m_diagrams.m_theme = nullptr;
-   m_original_argv = nullptr;
-   m_diagnostic_buffer = nullptr;
- 
-   enum diagnostic_text_art_charset text_art_charset
-     = DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI;
-   if (const char *lang = getenv ("LANG"))
-     {
-       /* For LANG=C, don't assume the terminal supports anything
- 	 other than ASCII.  */
-       if (!strcmp (lang, "C"))
- 	text_art_charset = DIAGNOSTICS_TEXT_ART_CHARSET_ASCII;
-     }
-   set_text_art_charset (text_art_charset);
- }
- 
- /* Maybe initialize the color support. We require clients to do this
-    explicitly, since most clients don't want color.  When called
-    without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT.  */
- 
- void
- diagnostic_context::color_init (int value)
- {
-   /* value == -1 is the default value.  */
-   if (value < 0)
-     {
-       /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
- 	 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
- 	 otherwise default to -fdiagnostics-color=never, for other
- 	 values default to that
- 	 -fdiagnostics-color={never,auto,always}.  */
-       if (DIAGNOSTICS_COLOR_DEFAULT == -1)
- 	{
- 	  if (!getenv ("GCC_COLORS"))
- 	    return;
- 	  value = DIAGNOSTICS_COLOR_AUTO;
- 	}
-       else
- 	value = DIAGNOSTICS_COLOR_DEFAULT;
-     }
-   pp_show_color (m_reference_printer)
-     = colorize_init ((diagnostic_color_rule_t) value);
-   for (auto sink : m_output_sinks)
-     if (sink->follows_reference_printer_p ())
-       pp_show_color (sink->get_printer ())
- 	= pp_show_color (m_reference_printer);
- }
- 
- /* Initialize URL support within this context based on VALUE,
-    handling "auto".  */
- 
- void
- diagnostic_context::urls_init (int value)
- {
-   /* value == -1 is the default value.  */
-   if (value < 0)
-     {
-       /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
- 	 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
- 	 environment, otherwise default to -fdiagnostics-urls=never,
- 	 for other values default to that
- 	 -fdiagnostics-urls={never,auto,always}.  */
-       if (DIAGNOSTICS_URLS_DEFAULT == -1)
- 	{
- 	  if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
- 	    return;
- 	  value = DIAGNOSTICS_URL_AUTO;
- 	}
-       else
- 	value = DIAGNOSTICS_URLS_DEFAULT;
-     }
- 
-   m_reference_printer->set_url_format
-     (determine_url_format ((diagnostic_url_rule_t) value));
-   for (auto sink : m_output_sinks)
-     if (sink->follows_reference_printer_p ())
-       sink->get_printer ()->set_url_format
- 	(m_reference_printer->get_url_format ());
- }
- 
- /* Create the file_cache, if not already created, and tell it how to
-    translate files on input.  */
- void
- diagnostic_context::
- initialize_input_context (diagnostic_input_charset_callback ccb,
- 			  bool should_skip_bom)
- {
-   m_file_cache->initialize_input_context (ccb, should_skip_bom);
- }
- 
- /* Do any cleaning up required after the last diagnostic is emitted.  */
- 
- void
- diagnostic_context::finish ()
- {
-   /* We might be handling a fatal error.
-      Close any active diagnostic groups, which may trigger flushing
-      sinks.  */
-   while (m_diagnostic_groups.m_group_nesting_depth > 0)
-     end_group ();
- 
-   set_diagnostic_buffer (nullptr);
- 
-   /* Clean ups.  */
- 
-   while (!m_output_sinks.is_empty ())
-     delete m_output_sinks.pop ();
- 
-   if (m_diagrams.m_theme)
-     {
-       delete m_diagrams.m_theme;
-       m_diagrams.m_theme = nullptr;
-     }
- 
-   delete m_file_cache;
-   m_file_cache = nullptr;
- 
-   m_option_classifier.fini ();
- 
-   delete m_reference_printer;
-   m_reference_printer = nullptr;
- 
-   if (m_edit_context_ptr)
-     {
-       delete m_edit_context_ptr;
-       m_edit_context_ptr = nullptr;
-     }
- 
-   if (m_client_data_hooks)
-     {
-       delete m_client_data_hooks;
-       m_client_data_hooks = nullptr;
-     }
- 
-   delete m_option_mgr;
-   m_option_mgr = nullptr;
- 
-   if (m_urlifier_stack)
-     {
-       while (!m_urlifier_stack->is_empty ())
- 	pop_urlifier ();
-       delete m_urlifier_stack;
-       m_urlifier_stack = nullptr;
-     }
- 
-   freeargv (m_original_argv);
-   m_original_argv = nullptr;
- }
- 
- /* Dump state of this diagnostic_context to OUT, for debugging.  */
- 
- void
- diagnostic_context::dump (FILE *out) const
- {
-   fprintf (out, "diagnostic_context:\n");
-   m_diagnostic_counters.dump (out, 2);
-   fprintf (out, "  reference printer:\n");
-   m_reference_printer->dump (out, 4);
-   fprintf (out, "  output sinks:\n");
-   if (m_output_sinks.length () > 0)
-     {
-       for (unsigned i = 0; i < m_output_sinks.length (); ++i)
- 	{
- 	  fprintf (out, "  sink %i:\n", i);
- 	  m_output_sinks[i]->dump (out, 4);
- 	}
-     }
-   else
-     fprintf (out, "    (none):\n");
-   fprintf (out, "  diagnostic buffer:\n");
-   if (m_diagnostic_buffer)
-     m_diagnostic_buffer->dump (out, 4);
-   else
-     fprintf (out, "    (none):\n");
-   fprintf (out, "  file cache:\n");
-   if (m_file_cache)
-     m_file_cache->dump (out, 4);
-   else
-     fprintf (out, "    (none):\n");
- }
- 
- /* Return true if sufficiently severe diagnostics have been seen that
-    we ought to exit with a non-zero exit code.  */
- 
- bool
- diagnostic_context::execution_failed_p () const
- {
-   /* Equivalent to (seen_error () || werrorcount), but on
-      this context, rather than global_dc.  */
-   return (diagnostic_count (DK_ERROR)
- 	  || diagnostic_count (DK_SORRY)
- 	  || diagnostic_count (DK_WERROR));
- }
- 
- void
- diagnostic_context::remove_all_output_sinks ()
- {
-   while (!m_output_sinks.is_empty ())
-     delete m_output_sinks.pop ();
- }
- 
- void
- diagnostic_context::
- set_output_format (std::unique_ptr<diagnostic_output_format> output_format)
- {
-   remove_all_output_sinks ();
-   m_output_sinks.safe_push (output_format.release ());
- }
- 
- diagnostic_output_format &
- diagnostic_context::get_output_format (size_t idx) const
- {
-   gcc_assert (idx < m_output_sinks.length ());
-   gcc_assert (m_output_sinks[idx]);
-   return *m_output_sinks[idx];
- }
- 
- void
- diagnostic_context::add_sink (std::unique_ptr<diagnostic_output_format> sink)
- {
-   m_output_sinks.safe_push (sink.release ());
- }
- 
- /* Return true if there are no machine-readable formats writing to stderr.  */
- 
- bool
- diagnostic_context::supports_fnotice_on_stderr_p () const
- {
-   for (auto sink : m_output_sinks)
-     if (sink->machine_readable_stderr_p ())
-       return false;
-   return true;
- }
- 
- void
- diagnostic_context::set_main_input_filename (const char *filename)
- {
-   for (auto sink : m_output_sinks)
-     sink->set_main_input_filename (filename);
- }
- 
- void
- diagnostic_context::
- set_client_data_hooks (std::unique_ptr<diagnostic_client_data_hooks> hooks)
- {
-   delete m_client_data_hooks;
-   /* Ideally the field would be a std::unique_ptr here.  */
-   m_client_data_hooks = hooks.release ();
- }
- 
- void
- diagnostic_context::set_original_argv (unique_argv original_argv)
- {
-   /* Ideally we'd use a unique_argv for m_original_argv, but
-      diagnostic_context doesn't yet have a ctor/dtor pair.  */
- 
-   // Ensure any old value is freed
-   freeargv (m_original_argv);
- 
-   // Take ownership of the new value
-   m_original_argv = original_argv.release ();
- }
- 
- void
- diagnostic_context::
- set_option_manager (std::unique_ptr<diagnostic_option_manager> mgr,
- 		    unsigned lang_mask)
- {
-   delete m_option_mgr;
-   m_option_mgr = mgr.release ();
-   m_lang_mask = lang_mask;
- }
- 
- void
- diagnostic_context::push_owned_urlifier (std::unique_ptr<urlifier> ptr)
- {
-   gcc_assert (m_urlifier_stack);
-   const urlifier_stack_node node = { ptr.release (), true };
-   m_urlifier_stack->safe_push (node);
- }
- 
- void
- diagnostic_context::push_borrowed_urlifier (const urlifier &loan)
- {
-   gcc_assert (m_urlifier_stack);
-   const urlifier_stack_node node = { const_cast <urlifier *> (&loan), false };
-   m_urlifier_stack->safe_push (node);
- }
- 
- void
- diagnostic_context::pop_urlifier ()
- {
-   gcc_assert (m_urlifier_stack);
-   gcc_assert (m_urlifier_stack->length () > 0);
- 
-   const urlifier_stack_node node = m_urlifier_stack->pop ();
-   if (node.m_owned)
-     delete node.m_urlifier;
- }
- 
- const logical_location_manager *
- diagnostic_context::get_logical_location_manager () const
- {
-   if (!m_client_data_hooks)
-     return nullptr;
-   return m_client_data_hooks->get_logical_location_manager ();
- }
- 
- const urlifier *
- diagnostic_context::get_urlifier () const
- {
-   if (!m_urlifier_stack)
-     return nullptr;
-   if (m_urlifier_stack->is_empty ())
-     return nullptr;
-   return m_urlifier_stack->last ().m_urlifier;
- }
- 
- 
- /* Set PP as the reference printer for this context.
-    Refresh all output sinks.  */
- 
- void
- diagnostic_context::set_pretty_printer (std::unique_ptr<pretty_printer> pp)
- {
-   delete m_reference_printer;
-   m_reference_printer = pp.release ();
-   refresh_output_sinks ();
- }
- 
- /* Give all output sinks a chance to rebuild their pretty_printer.  */
- 
- void
- diagnostic_context::refresh_output_sinks ()
- {
-   for (auto sink : m_output_sinks)
-     sink->update_printer ();
- }
- 
- /* Set FORMAT_DECODER on the reference printer and on the pretty_printer
-    of all output sinks.  */
- 
- void
- diagnostic_context::set_format_decoder (printer_fn format_decoder)
- {
-   pp_format_decoder (m_reference_printer) = format_decoder;
-   for (auto sink : m_output_sinks)
-     pp_format_decoder (sink->get_printer ()) = format_decoder;
- }
- 
- void
- diagnostic_context::set_show_highlight_colors (bool val)
- {
-   pp_show_highlight_colors (m_reference_printer) = val;
-   for (auto sink : m_output_sinks)
-     if (sink->follows_reference_printer_p ())
-       pp_show_highlight_colors (sink->get_printer ()) = val;
- }
- 
- void
- diagnostic_context::set_prefixing_rule (diagnostic_prefixing_rule_t rule)
- {
-   pp_prefixing_rule (m_reference_printer) = rule;
-   for (auto sink : m_output_sinks)
-     if (sink->follows_reference_printer_p ())
-       pp_prefixing_rule (sink->get_printer ()) = rule;
- }
- 
- void
- diagnostic_context::create_edit_context ()
- {
-   delete m_edit_context_ptr;
-   gcc_assert (m_file_cache);
-   m_edit_context_ptr = new edit_context (*m_file_cache);
- }
- 
- /* Initialize DIAGNOSTIC, where the message MSG has already been
-    translated.  */
- void
- diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
- 				va_list *args, rich_location *richloc,
- 				diagnostic_t kind)
- {
-   gcc_assert (richloc);
-   diagnostic->message.m_err_no = errno;
-   diagnostic->message.m_args_ptr = args;
-   diagnostic->message.m_format_spec = msg;
-   diagnostic->message.m_richloc = richloc;
-   diagnostic->richloc = richloc;
-   diagnostic->metadata = nullptr;
-   diagnostic->kind = kind;
-   diagnostic->option_id = 0;
- }
- 
- /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
-    translated.  */
- void
- diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
- 		     va_list *args, rich_location *richloc,
- 		     diagnostic_t kind)
- {
-   gcc_assert (richloc);
-   diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
- }
- 
- static const char *const diagnostic_kind_color[] = {
- #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
- #include "diagnostic.def"
- #undef DEFINE_DIAGNOSTIC_KIND
-   nullptr
- };
- 
- /* Get a color name for diagnostics of type KIND
-    Result could be nullptr.  */
- 
- const char *
- diagnostic_get_color_for_kind (diagnostic_t kind)
- {
-   return diagnostic_kind_color[kind];
- }
- 
- /* Given an expanded_location, convert the column (which is in 1-based bytes)
-    to the requested units, without converting the origin.
-    Return -1 if the column is invalid (<= 0).  */
- 
- static int
- convert_column_unit (file_cache &fc,
- 		     enum diagnostics_column_unit column_unit,
- 		     int tabstop,
- 		     expanded_location s)
- {
-   if (s.column <= 0)
-     return -1;
- 
-   switch (column_unit)
-     {
-     default:
-       gcc_unreachable ();
- 
-     case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
-       {
- 	cpp_char_column_policy policy (tabstop, cpp_wcwidth);
- 	return location_compute_display_column (fc, s, policy);
-       }
- 
-     case DIAGNOSTICS_COLUMN_UNIT_BYTE:
-       return s.column;
-     }
- }
- 
- diagnostic_column_policy::
- diagnostic_column_policy (const diagnostic_context &dc)
- : m_file_cache (dc.get_file_cache ()),
-   m_column_unit (dc.m_column_unit),
-   m_column_origin (dc.m_column_origin),
-   m_tabstop (dc.m_tabstop)
- {
- }
- 
- /* Given an expanded_location, convert the column (which is in 1-based bytes)
-    to the requested units and origin.  Return -1 if the column is
-    invalid (<= 0).  */
- int
- diagnostic_column_policy::converted_column (expanded_location s) const
- {
-   int one_based_col = convert_column_unit (m_file_cache,
- 					   m_column_unit, m_tabstop, s);
-   if (one_based_col <= 0)
-     return -1;
-   return one_based_col + (m_column_origin - 1);
- }
- 
- /* Return a string describing a location e.g. "foo.c:42:10".  */
- 
- label_text
- diagnostic_column_policy::get_location_text (const expanded_location &s,
- 					     bool show_column,
- 					     bool colorize) const
- {
-   const char *locus_cs = colorize_start (colorize, "locus");
-   const char *locus_ce = colorize_stop (colorize);
-   const char *file = s.file ? s.file : progname;
-   int line = 0;
-   int col = -1;
-   if (strcmp (file, special_fname_builtin ()))
-     {
-       line = s.line;
-       if (show_column)
- 	col = converted_column (s);
-     }
- 
-   const char *line_col = maybe_line_and_column (line, col);
-   return label_text::take (build_message_string ("%s%s%s:%s", locus_cs, file,
- 						 line_col, locus_ce));
- }
- 
- diagnostic_location_print_policy::
- diagnostic_location_print_policy (const diagnostic_context &dc)
- : m_column_policy (dc),
-   m_show_column (dc.m_show_column)
- {
- }
- 
- diagnostic_location_print_policy::
- diagnostic_location_print_policy (const diagnostic_text_output_format &text_output)
- :
-   m_column_policy (text_output.get_context ()),
-   m_show_column (text_output.get_context ().m_show_column)
- {
- }
- 
- static const char *const diagnostic_kind_text[] = {
- #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
- #include "diagnostic.def"
- #undef DEFINE_DIAGNOSTIC_KIND
-   "must-not-happen"
- };
- 
- /* Get unlocalized string describing KIND.  */
- 
- const char *
- get_diagnostic_kind_text (diagnostic_t kind)
- {
-   return diagnostic_kind_text[kind];
- }
- 
- /* Functions at which to stop the backtrace print.  It's not
-    particularly helpful to print the callers of these functions.  */
- 
- static const char * const bt_stop[] =
- {
-   "main",
-   "toplev::main",
-   "execute_one_pass",
-   "compile_file",
- };
- 
- /* A callback function passed to the backtrace_full function.  */
- 
- static int
- bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
- 	     const char *function)
- {
-   int *pcount = (int *) data;
- 
-   /* If we don't have any useful information, don't print
-      anything.  */
-   if (filename == nullptr && function == nullptr)
-     return 0;
- 
-   /* Skip functions in diagnostic.cc.  */
-   if (*pcount == 0
-       && filename != nullptr
-       && strcmp (lbasename (filename), "diagnostic.cc") == 0)
-     return 0;
- 
-   /* Print up to 20 functions.  We could make this a --param, but
-      since this is only for debugging just use a constant for now.  */
-   if (*pcount >= 20)
-     {
-       /* Returning a non-zero value stops the backtrace.  */
-       return 1;
-     }
-   ++*pcount;
- 
-   char *alc = nullptr;
-   if (function != nullptr)
-     {
-       char *str = cplus_demangle_v3 (function,
- 				     (DMGL_VERBOSE | DMGL_ANSI
- 				      | DMGL_GNU_V3 | DMGL_PARAMS));
-       if (str != nullptr)
- 	{
- 	  alc = str;
- 	  function = str;
- 	}
- 
-       for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
- 	{
- 	  size_t len = strlen (bt_stop[i]);
- 	  if (strncmp (function, bt_stop[i], len) == 0
- 	      && (function[len] == '\0' || function[len] == '('))
- 	    {
- 	      if (alc != nullptr)
- 		free (alc);
- 	      /* Returning a non-zero value stops the backtrace.  */
- 	      return 1;
- 	    }
- 	}
-     }
- 
-   fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
- 	   (unsigned long) pc,
- 	   function == nullptr ? "???" : function,
- 	   filename == nullptr ? "???" : filename,
- 	   lineno);
- 
-   if (alc != nullptr)
-     free (alc);
- 
-   return 0;
- }
- 
- /* A callback function passed to the backtrace_full function.  This is
-    called if backtrace_full has an error.  */
- 
- static void
- bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
- {
-   if (errnum < 0)
-     {
-       /* This means that no debug info was available.  Just quietly
- 	 skip printing backtrace info.  */
-       return;
-     }
-   fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
- 	   errnum == 0 ? "" : xstrerror (errnum));
- }
- 
- /* Check if we've met the maximum error limit, and if so fatally exit
-    with a message.
-    FLUSH indicates whether a diagnostic_context::finish call is needed.  */
- 
- void
- diagnostic_context::check_max_errors (bool flush)
- {
-   if (!m_max_errors)
-     return;
- 
-   int count = (diagnostic_count (DK_ERROR)
- 	       + diagnostic_count (DK_SORRY)
- 	       + diagnostic_count (DK_WERROR));
- 
-   if (count >= m_max_errors)
-     {
-       fnotice (stderr,
- 	       "compilation terminated due to -fmax-errors=%u.\n",
- 	       m_max_errors);
-       if (flush)
- 	finish ();
-       exit (FATAL_EXIT_CODE);
-     }
- }
- 
- /* Take any action which is expected to happen after the diagnostic
-    is written out.  This function does not always return.  */
- 
- void
- diagnostic_context::action_after_output (diagnostic_t diag_kind)
- {
-   switch (diag_kind)
-     {
-     case DK_DEBUG:
-     case DK_NOTE:
-     case DK_ANACHRONISM:
-     case DK_WARNING:
-       break;
- 
-     case DK_ERROR:
-     case DK_SORRY:
-       if (m_abort_on_error)
- 	real_abort ();
-       if (m_fatal_errors)
- 	{
- 	  fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
- 	  finish ();
- 	  exit (FATAL_EXIT_CODE);
- 	}
-       break;
- 
-     case DK_ICE:
-     case DK_ICE_NOBT:
-       {
- 	/* Attempt to ensure that any outputs are flushed e.g. that .sarif
- 	   files are written out.
- 	   Only do it once.  */
- 	static bool finishing_due_to_ice = false;
- 	if (!finishing_due_to_ice)
- 	  {
- 	    finishing_due_to_ice = true;
- 	    finish ();
- 	  }
- 
- 	struct backtrace_state *state = nullptr;
- 	if (diag_kind == DK_ICE)
- 	  state = backtrace_create_state (nullptr, 0, bt_err_callback, nullptr);
- 	int count = 0;
- 	if (state != nullptr)
- 	  backtrace_full (state, 2, bt_callback, bt_err_callback,
- 			  (void *) &count);
- 
- 	if (m_abort_on_error)
- 	  real_abort ();
- 
- 	if (m_report_bug)
- 	  fnotice (stderr, "Please submit a full bug report, "
- 		   "with preprocessed source.\n");
- 	else
- 	  fnotice (stderr, "Please submit a full bug report, "
- 		   "with preprocessed source (by using -freport-bug).\n");
- 
- 	if (count > 0)
- 	  fnotice (stderr, "Please include the complete backtrace "
- 		   "with any bug report.\n");
- 	fnotice (stderr, "See %s for instructions.\n", bug_report_url);
- 
- 	exit (ICE_EXIT_CODE);
-       }
- 
-     case DK_FATAL:
-       if (m_abort_on_error)
- 	real_abort ();
-       fnotice (stderr, "compilation terminated.\n");
-       finish ();
-       exit (FATAL_EXIT_CODE);
- 
-     default:
-       gcc_unreachable ();
-     }
- }
- 
- /* State whether we should inhibit notes in the current diagnostic_group and
-    its future children if any.  */
- 
- void
- diagnostic_context::inhibit_notes_in_group (bool inhibit)
- {
-   int curr_depth = (m_diagnostic_groups.m_group_nesting_depth
- 		    + m_diagnostic_groups.m_diagnostic_nesting_level);
- 
-   if (inhibit)
-     {
-       /* If we're already inhibiting, there's nothing to do.  */
-       if (m_diagnostic_groups.m_inhibiting_notes_from)
- 	return;
- 
-       /* Since we're called via warning/error/... that all have their own
- 	 diagnostic_group, we must consider that we started inhibiting in their
- 	 parent.  */
-       gcc_assert (m_diagnostic_groups.m_group_nesting_depth > 0);
-       m_diagnostic_groups.m_inhibiting_notes_from = curr_depth - 1;
-     }
-   else if (m_diagnostic_groups.m_inhibiting_notes_from)
-     {
-       /* Only cancel inhibition at the depth that set it up.  */
-       if (curr_depth >= m_diagnostic_groups.m_inhibiting_notes_from)
- 	return;
- 
-       m_diagnostic_groups.m_inhibiting_notes_from = 0;
-     }
- }
- 
- /* Return whether notes must be inhibited in the current diagnostic_group.  */
- 
- bool
- diagnostic_context::notes_inhibited_in_group () const
- {
-   if (m_diagnostic_groups.m_inhibiting_notes_from
-       && (m_diagnostic_groups.m_group_nesting_depth
- 	  + m_diagnostic_groups.m_diagnostic_nesting_level
- 	  >= m_diagnostic_groups.m_inhibiting_notes_from))
-     return true;
-   return false;
- }
- 
- /* class logical_location_manager.  */
- 
- /* Return true iff this is a function or method.  */
- 
- bool
- logical_location_manager::function_p (key k) const
- {
-   switch (get_kind (k))
-     {
-     default:
-       gcc_unreachable ();
-     case logical_location_kind::unknown:
-     case logical_location_kind::module_:
-     case logical_location_kind::namespace_:
-     case logical_location_kind::type:
-     case logical_location_kind::return_type:
-     case logical_location_kind::parameter:
-     case logical_location_kind::variable:
-       return false;
- 
-     case logical_location_kind::function:
-     case logical_location_kind::member:
-       return true;
-     }
- }
- 
- /* Interface to specify diagnostic kind overrides.  Returns the
-    previous setting, or DK_UNSPECIFIED if the parameters are out of
-    range.  If OPTION_ID is zero, the new setting is for all the
-    diagnostics.  */
- diagnostic_t
- diagnostic_option_classifier::
- classify_diagnostic (const diagnostic_context *context,
- 		     diagnostic_option_id option_id,
- 		     diagnostic_t new_kind,
- 		     location_t where)
- {
-   diagnostic_t old_kind;
- 
-   if (option_id.m_idx < 0
-       || option_id.m_idx >= m_n_opts
-       || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
-     return DK_UNSPECIFIED;
- 
-   old_kind = m_classify_diagnostic[option_id.m_idx];
- 
-   /* Handle pragmas separately, since we need to keep track of *where*
-      the pragmas were.  */
-   if (where != UNKNOWN_LOCATION)
-     {
-       unsigned i;
- 
-       /* Record the command-line status, so we can reset it back on DK_POP. */
-       if (old_kind == DK_UNSPECIFIED)
- 	{
- 	  old_kind = (!context->option_enabled_p (option_id)
- 		      ? DK_IGNORED : DK_ANY);
- 	  m_classify_diagnostic[option_id.m_idx] = old_kind;
- 	}
- 
-       diagnostic_classification_change_t *p;
-       FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
- 	if (p->option == option_id.m_idx)
- 	  {
- 	    old_kind = p->kind;
- 	    break;
- 	  }
- 
-       diagnostic_classification_change_t v
- 	= { where, option_id.m_idx, new_kind };
-       m_classification_history.safe_push (v);
-     }
-   else
-     m_classify_diagnostic[option_id.m_idx] = new_kind;
- 
-   return old_kind;
- }
- 
- /* Helper function for print_parseable_fixits.  Print TEXT to PP, obeying the
-    escaping rules for -fdiagnostics-parseable-fixits.  */
- 
- static void
- print_escaped_string (pretty_printer *pp, const char *text)
- {
-   gcc_assert (pp);
-   gcc_assert (text);
- 
-   pp_character (pp, '"');
-   for (const char *ch = text; *ch; ch++)
-     {
-       switch (*ch)
- 	{
- 	case '\\':
- 	  /* Escape backslash as two backslashes.  */
- 	  pp_string (pp, "\\\\");
- 	  break;
- 	case '\t':
- 	  /* Escape tab as "\t".  */
- 	  pp_string (pp, "\\t");
- 	  break;
- 	case '\n':
- 	  /* Escape newline as "\n".  */
- 	  pp_string (pp, "\\n");
- 	  break;
- 	case '"':
- 	  /* Escape doublequotes as \".  */
- 	  pp_string (pp, "\\\"");
- 	  break;
- 	default:
- 	  if (ISPRINT (*ch))
- 	    pp_character (pp, *ch);
- 	  else
- 	    /* Use octal for non-printable chars.  */
- 	    {
- 	      unsigned char c = (*ch & 0xff);
- 	      pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
- 	    }
- 	  break;
- 	}
-     }
-   pp_character (pp, '"');
- }
- 
- /* Implementation of -fdiagnostics-parseable-fixits and
-    GCC_EXTRA_DIAGNOSTIC_OUTPUT.
-    Print a machine-parseable version of all fixits in RICHLOC to PP,
-    using COLUMN_UNIT to express columns.
-    Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY.  */
- 
- static void
- print_parseable_fixits (file_cache &fc,
- 			pretty_printer *pp, rich_location *richloc,
- 			enum diagnostics_column_unit column_unit,
- 			int tabstop)
- {
-   gcc_assert (pp);
-   gcc_assert (richloc);
- 
-   char *saved_prefix = pp_take_prefix (pp);
-   pp_set_prefix (pp, nullptr);
- 
-   for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
-     {
-       const fixit_hint *hint = richloc->get_fixit_hint (i);
-       location_t start_loc = hint->get_start_loc ();
-       expanded_location start_exploc = expand_location (start_loc);
-       pp_string (pp, "fix-it:");
-       print_escaped_string (pp, start_exploc.file);
-       /* For compatibility with clang, print as a half-open range.  */
-       location_t next_loc = hint->get_next_loc ();
-       expanded_location next_exploc = expand_location (next_loc);
-       int start_col
- 	= convert_column_unit (fc, column_unit, tabstop, start_exploc);
-       int next_col
- 	= convert_column_unit (fc, column_unit, tabstop, next_exploc);
-       pp_printf (pp, ":{%i:%i-%i:%i}:",
- 		 start_exploc.line, start_col,
- 		 next_exploc.line, next_col);
-       print_escaped_string (pp, hint->get_string ());
-       pp_newline (pp);
-     }
- 
-   pp_set_prefix (pp, saved_prefix);
- }
- 
- /* Update the inlining info in this context for a DIAGNOSTIC.  */
- 
- void
- diagnostic_context::get_any_inlining_info (diagnostic_info *diagnostic)
- {
-   auto &ilocs = diagnostic->m_iinfo.m_ilocs;
- 
-   if (m_set_locations_cb)
-     /* Retrieve the locations into which the expression about to be
-        diagnosed has been inlined, including those of all the callers
-        all the way down the inlining stack.  */
-     m_set_locations_cb (this, diagnostic);
-   else
-     {
-       /* When there's no callback use just the one location provided
- 	 by the caller of the diagnostic function.  */
-       location_t loc = diagnostic_location (diagnostic);
-       ilocs.safe_push (loc);
-       diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
-     }
- }
- 
- /* Update the kind of DIAGNOSTIC based on its location(s), including
-    any of those in its inlining stack, relative to any
-      #pragma GCC diagnostic
-    directives recorded within this object.
- 
-    Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
-    otherwise.  */
- 
- diagnostic_t
- diagnostic_option_classifier::
- update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
- {
-   if (m_classification_history.is_empty ())
-     return DK_UNSPECIFIED;
- 
-   /* Iterate over the locations, checking the diagnostic disposition
-      for the diagnostic at each.  If it's explicitly set as opposed
-      to unspecified, update the disposition for this instance of
-      the diagnostic and return it.  */
-   for (location_t loc: diagnostic->m_iinfo.m_ilocs)
-     {
-       /* FIXME: Stupid search.  Optimize later. */
-       unsigned int i;
-       diagnostic_classification_change_t *p;
-       FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
- 	{
- 	  location_t pragloc = p->location;
- 	  if (!linemap_location_before_p (line_table, pragloc, loc))
- 	    continue;
- 
- 	  if (p->kind == (int) DK_POP)
- 	    {
- 	      /* Move on to the next region.  */
- 	      i = p->option;
- 	      continue;
- 	    }
- 
- 	  diagnostic_option_id option = p->option;
- 	  /* The option 0 is for all the diagnostics.  */
- 	  if (option == 0 || option == diagnostic->option_id)
- 	    {
- 	      diagnostic_t kind = p->kind;
- 	      if (kind != DK_UNSPECIFIED)
- 		diagnostic->kind = kind;
- 	      return kind;
- 	    }
- 	}
-     }
- 
-   return DK_UNSPECIFIED;
- }
- 
- /* Generate a URL string describing CWE.  The caller is responsible for
-    freeing the string.  */
- 
- char *
- get_cwe_url (int cwe)
- {
-   return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
- }
- 
- /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
-    as appropriate for #pragma GCC diagnostic and -Werror=foo.  */
- 
- bool
- diagnostic_context::diagnostic_enabled (diagnostic_info *diagnostic)
- {
-   /* Update the inlining stack for this diagnostic.  */
-   get_any_inlining_info (diagnostic);
- 
-   /* Diagnostics with no option or -fpermissive are always enabled.  */
-   if (!diagnostic->option_id.m_idx
-       || diagnostic->option_id == m_opt_permissive)
-     return true;
- 
-   /* This tests if the user provided the appropriate -Wfoo or
-      -Wno-foo option.  */
-   if (!option_enabled_p (diagnostic->option_id))
-     return false;
- 
-   /* This tests for #pragma diagnostic changes.  */
-   diagnostic_t diag_class
-     = m_option_classifier.update_effective_level_from_pragmas (diagnostic);
- 
-   /* This tests if the user provided the appropriate -Werror=foo
-      option.  */
-   if (diag_class == DK_UNSPECIFIED
-       && !option_unspecified_p (diagnostic->option_id))
-     {
-       const diagnostic_t new_kind
- 	= m_option_classifier.get_current_override (diagnostic->option_id);
-       if (new_kind != DK_ANY)
- 	/* DK_ANY means the diagnostic is not to be ignored, but we don't want
- 	   to change it specifically to DK_ERROR or DK_WARNING; we want to
- 	   preserve whatever the caller has specified.  */
- 	diagnostic->kind = new_kind;
-     }
- 
-   /* This allows for future extensions, like temporarily disabling
-      warnings for ranges of source code.  */
-   if (diagnostic->kind == DK_IGNORED)
-     return false;
- 
-   return true;
- }
- 
- /* Returns whether warning OPTION_ID is enabled at LOC.  */
- 
- bool
- diagnostic_context::warning_enabled_at (location_t loc,
- 					diagnostic_option_id option_id)
- {
-   if (!diagnostic_report_warnings_p (this, loc))
-     return false;
- 
-   rich_location richloc (line_table, loc);
-   diagnostic_info diagnostic = {};
-   diagnostic.option_id = option_id;
-   diagnostic.richloc = &richloc;
-   diagnostic.message.m_richloc = &richloc;
-   diagnostic.kind = DK_WARNING;
-   return diagnostic_enabled (&diagnostic);
- }
- 
- /* Emit a diagnostic within a diagnostic group on this context.  */
- 
- bool
- diagnostic_context::
- emit_diagnostic_with_group (diagnostic_t kind,
- 			    rich_location &richloc,
- 			    const diagnostic_metadata *metadata,
- 			    diagnostic_option_id option_id,
- 			    const char *gmsgid, ...)
- {
-   begin_group ();
- 
-   va_list ap;
-   va_start (ap, gmsgid);
-   bool ret = emit_diagnostic_with_group_va (kind, richloc, metadata, option_id,
- 					    gmsgid, &ap);
-   va_end (ap);
- 
-   end_group ();
- 
-   return ret;
- }
- 
- /* As above, but taking a va_list *.  */
- 
- bool
- diagnostic_context::
- emit_diagnostic_with_group_va (diagnostic_t kind,
- 			       rich_location &richloc,
- 			       const diagnostic_metadata *metadata,
- 			       diagnostic_option_id option_id,
- 			       const char *gmsgid, va_list *ap)
- {
-   begin_group ();
- 
-   bool ret = diagnostic_impl (&richloc, metadata, option_id,
- 			      gmsgid, ap, kind);
- 
-   end_group ();
- 
-   return ret;
- }
- 
- /* Report a diagnostic message (an error or a warning) as specified by
-    this diagnostic_context.
-    front-end independent format specifiers are exactly those described
-    in the documentation of output_format.
-    Return true if a diagnostic was printed, false otherwise.  */
- 
- bool
- diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
- {
-   diagnostic_t orig_diag_kind = diagnostic->kind;
- 
-   /* Every call to report_diagnostic should be within a
-      begin_group/end_group pair so that output formats can reliably
-      flush diagnostics with on_end_group when the topmost group is ended.  */
-   gcc_assert (m_diagnostic_groups.m_group_nesting_depth > 0);
- 
-   /* Give preference to being able to inhibit warnings, before they
-      get reclassified to something else.  */
-   bool was_warning = (diagnostic->kind == DK_WARNING
- 		      || diagnostic->kind == DK_PEDWARN);
-   if (was_warning && m_inhibit_warnings)
-     {
-       inhibit_notes_in_group ();
-       return false;
-     }
- 
-   if (m_adjust_diagnostic_info)
-     m_adjust_diagnostic_info (this, diagnostic);
- 
-   if (diagnostic->kind == DK_PEDWARN)
-     {
-       diagnostic->kind = m_pedantic_errors ? DK_ERROR : DK_WARNING;
- 
-       /* We do this to avoid giving the message for -pedantic-errors.  */
-       orig_diag_kind = diagnostic->kind;
-     }
- 
-   if (diagnostic->kind == DK_NOTE && m_inhibit_notes_p)
-     return false;
- 
-   /* If the user requested that warnings be treated as errors, so be
-      it.  Note that we do this before the next block so that
-      individual warnings can be overridden back to warnings with
-      -Wno-error=*.  */
-   if (m_warning_as_error_requested
-       && diagnostic->kind == DK_WARNING)
-     diagnostic->kind = DK_ERROR;
- 
-   diagnostic->message.m_data = &diagnostic->x_data;
- 
-   /* Check to see if the diagnostic is enabled at the location and
-      not disabled by #pragma GCC diagnostic anywhere along the inlining
-      stack.  .  */
-   if (!diagnostic_enabled (diagnostic))
-     {
-       inhibit_notes_in_group ();
-       return false;
-     }
- 
-   if ((was_warning || diagnostic->kind == DK_WARNING)
-       && ((!m_warn_system_headers
- 	   && diagnostic->m_iinfo.m_allsyslocs)
- 	  || m_inhibit_warnings))
-     /* Bail if the warning is not to be reported because all locations in the
-        inlining stack (if there is one) are in system headers.  */
-     return false;
- 
-   if (diagnostic->kind == DK_NOTE && notes_inhibited_in_group ())
-     /* Bail for all the notes in the diagnostic_group that started to inhibit notes.  */
-     return false;
- 
-   if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
-     check_max_errors (false);
- 
-   if (m_lock > 0)
-     {
-       /* If we're reporting an ICE in the middle of some other error,
- 	 try to flush out the previous error, then let this one
- 	 through.  Don't do this more than once.  */
-       if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
- 	  && m_lock == 1)
- 	pp_newline_and_flush (m_reference_printer);
-       else
- 	error_recursion ();
-     }
- 
-   /* We are accepting the diagnostic, so should stop inhibiting notes.  */
-   inhibit_notes_in_group (/*inhibit=*/false);
- 
-   m_lock++;
- 
-   if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
-     {
-       /* When not checking, ICEs are converted to fatal errors when an
- 	 error has already occurred.  This is counteracted by
- 	 abort_on_error.  */
-       if (!CHECKING_P
- 	  && (diagnostic_count (DK_ERROR) > 0
- 	      || diagnostic_count (DK_SORRY) > 0)
- 	  && !m_abort_on_error)
- 	{
- 	  expanded_location s
- 	    = expand_location (diagnostic_location (diagnostic));
- 	  fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
- 		   s.file, s.line);
- 	  exit (ICE_EXIT_CODE);
- 	}
-       if (m_internal_error)
- 	(*m_internal_error) (this,
- 			     diagnostic->message.m_format_spec,
- 			     diagnostic->message.m_args_ptr);
-     }
- 
-   /* Increment the counter for the appropriate diagnostic kind, either
-      within this context, or within the diagnostic_buffer.  */
-   {
-     const diagnostic_t kind_for_count =
-       ((diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
-        ? DK_WERROR
-        : diagnostic->kind);
-     diagnostic_counters &counters
-       = (m_diagnostic_buffer
- 	 ? m_diagnostic_buffer->m_diagnostic_counters
- 	 : m_diagnostic_counters);
-     ++counters.m_count_for_kind[kind_for_count];
-   }
- 
-   /* Is this the initial diagnostic within the stack of groups?  */
-   if (m_diagnostic_groups.m_emission_count == 0)
-     for (auto sink : m_output_sinks)
-       sink->on_begin_group ();
-   m_diagnostic_groups.m_emission_count++;
- 
-   va_list *orig_args = diagnostic->message.m_args_ptr;
-   for (auto sink : m_output_sinks)
-     {
-       /* Formatting the message is done per-output-format,
- 	 so that each output format gets its own set of pp_token_lists
- 	 to work with.
- 
- 	 Run phases 1 and 2 of formatting the message before calling
- 	 the format's on_report_diagnostic.
- 	 In particular, some format codes may have side-effects here which
- 	 need to happen before sending the diagnostic to the output format.
- 	 For example, Fortran's %C and %L formatting codes populate the
- 	 rich_location.
- 	 Such side-effects must be idempotent, since they are run per
- 	 output-format.
- 
- 	 Make a duplicate of the varargs for each call to pp_format,
- 	 so that each has its own set to consume.  */
-       va_list copied_args;
-       va_copy (copied_args, *orig_args);
-       diagnostic->message.m_args_ptr = &copied_args;
-       pp_format (sink->get_printer (), &diagnostic->message);
-       va_end (copied_args);
- 
-       /* Call vfunc in the output format.  This is responsible for
- 	 phase 3 of formatting, and for printing the result.  */
-       sink->on_report_diagnostic (*diagnostic, orig_diag_kind);
-     }
- 
-   switch (m_extra_output_kind)
-     {
-     default:
-       break;
-     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
-       print_parseable_fixits (get_file_cache (),
- 			      m_reference_printer, diagnostic->richloc,
- 			      DIAGNOSTICS_COLUMN_UNIT_BYTE,
- 			      m_tabstop);
-       pp_flush (m_reference_printer);
-       break;
-     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
-       print_parseable_fixits (get_file_cache (),
- 			      m_reference_printer, diagnostic->richloc,
- 			      DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
- 			      m_tabstop);
-       pp_flush (m_reference_printer);
-       break;
-     }
-   if (m_diagnostic_buffer == nullptr
-       || diagnostic->kind == DK_ICE
-       || diagnostic->kind == DK_ICE_NOBT)
-     action_after_output (diagnostic->kind);
-   diagnostic->x_data = nullptr;
- 
-   if (m_edit_context_ptr)
-     if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
-       if (!m_diagnostic_buffer)
- 	m_edit_context_ptr->add_fixits (diagnostic->richloc);
- 
-   m_lock--;
- 
-   if (!m_diagnostic_buffer)
-     for (auto sink : m_output_sinks)
-       sink->after_diagnostic (*diagnostic);
- 
-   return true;
- }
- 
- void
- diagnostic_context::report_verbatim (text_info &text)
- {
-   va_list *orig_args = text.m_args_ptr;
-   for (auto sink : m_output_sinks)
-     {
-       va_list copied_args;
-       va_copy (copied_args, *orig_args);
-       text.m_args_ptr = &copied_args;
-       sink->on_report_verbatim (text);
-       va_end (copied_args);
-     }
- }
- 
- void
- diagnostic_context::
- report_global_digraph (const diagnostics::digraphs::lazy_digraph &ldg)
- {
-   for (auto sink : m_output_sinks)
-     sink->report_global_digraph (ldg);
- }
- 
- /* Get the number of digits in the decimal representation of VALUE.  */
- 
- int
- num_digits (int value)
- {
-   /* Perhaps simpler to use log10 for this, but doing it this way avoids
-      using floating point.  */
-   gcc_assert (value >= 0);
- 
-   if (value == 0)
-     return 1;
- 
-   int digits = 0;
-   while (value > 0)
-     {
-       digits++;
-       value /= 10;
-     }
-   return digits;
- }
- 
- /* Given a partial pathname as input, return another pathname that
-    shares no directory elements with the pathname of __FILE__.  This
-    is used by fancy_abort() to print `internal compiler error in expr.cc'
-    instead of `internal compiler error in ../../GCC/gcc/expr.cc'.  */
- 
- const char *
- trim_filename (const char *name)
- {
-   static const char this_file[] = __FILE__;
-   const char *p = name, *q = this_file;
- 
-   /* First skip any "../" in each filename.  This allows us to give a proper
-      reference to a file in a subdirectory.  */
-   while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
-     p += 3;
- 
-   while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
-     q += 3;
- 
-   /* Now skip any parts the two filenames have in common.  */
-   while (*p == *q && *p != 0 && *q != 0)
-     p++, q++;
- 
-   /* Now go backwards until the previous directory separator.  */
-   while (p > name && !IS_DIR_SEPARATOR (p[-1]))
-     p--;
- 
-   return p;
- }
- 
- /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
-    permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
-    and internal_error_no_backtrace, as documented and defined below.  */
- bool
- diagnostic_context::diagnostic_impl (rich_location *richloc,
- 				     const diagnostic_metadata *metadata,
- 				     diagnostic_option_id option_id,
- 				     const char *gmsgid,
- 				     va_list *ap, diagnostic_t kind)
- {
-   diagnostic_info diagnostic;
-   if (kind == DK_PERMERROR)
-     {
-       diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
- 			   m_permissive ? DK_WARNING : DK_ERROR);
-       diagnostic.option_id = (option_id.m_idx != -1 ? option_id : m_opt_permissive);
-     }
-   else
-     {
-       diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
-       if (kind == DK_WARNING || kind == DK_PEDWARN)
- 	diagnostic.option_id = option_id;
-     }
-   diagnostic.metadata = metadata;
-   return report_diagnostic (&diagnostic);
- }
- 
- /* Implement inform_n, warning_n, and error_n, as documented and
-    defined below.  */
- bool
- diagnostic_context::diagnostic_n_impl (rich_location *richloc,
- 				       const diagnostic_metadata *metadata,
- 				       diagnostic_option_id option_id,
- 				       unsigned HOST_WIDE_INT n,
- 				       const char *singular_gmsgid,
- 				       const char *plural_gmsgid,
- 				       va_list *ap, diagnostic_t kind)
- {
-   diagnostic_info diagnostic;
-   unsigned long gtn;
- 
-   if (sizeof n <= sizeof gtn)
-     gtn = n;
-   else
-     /* Use the largest number ngettext can handle, otherwise
-        preserve the six least significant decimal digits for
-        languages where the plural form depends on them.  */
-     gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
- 
-   const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
-   diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
-   if (kind == DK_WARNING)
-     diagnostic.option_id = option_id;
-   diagnostic.metadata = metadata;
-   return report_diagnostic (&diagnostic);
- }
- 
- 
- /* Emit DIAGRAM to this context, respecting the output format.  */
- 
- void
- diagnostic_context::emit_diagram (const diagnostic_diagram &diagram)
- {
-   if (m_diagrams.m_theme == nullptr)
-     return;
- 
-   for (auto sink : m_output_sinks)
-     sink->on_diagram (diagram);
- }
- 
- /* Inform the user that an error occurred while trying to report some
-    other error.  This indicates catastrophic internal inconsistencies,
-    so give up now.  But do try to flush out the previous error.
-    This mustn't use internal_error, that will cause infinite recursion.  */
- 
- void
- diagnostic_context::error_recursion ()
- {
-   if (m_lock < 3)
-     pp_newline_and_flush (m_reference_printer);
- 
-   fnotice (stderr,
- 	   "internal compiler error: error reporting routines re-entered.\n");
- 
-   /* Call action_after_output to get the "please submit a bug report"
-      message.  */
-   action_after_output (DK_ICE);
- 
-   /* Do not use gcc_unreachable here; that goes through internal_error
-      and therefore would cause infinite recursion.  */
-   real_abort ();
- }
- 
- /* Report an internal compiler error in a friendly manner.  This is
-    the function that gets called upon use of abort() in the source
-    code generally, thanks to a special macro.  */
- 
- void
- fancy_abort (const char *file, int line, const char *function)
- {
-   /* If fancy_abort is called before the diagnostic subsystem is initialized,
-      internal_error will crash internally in a way that prevents a
-      useful message reaching the user.
-      This can happen with libgccjit in the case of gcc_assert failures
-      that occur outside of the libgccjit mutex that guards the rest of
-      gcc's state, including global_dc (when global_dc may not be
-      initialized yet, or might be in use by another thread).
-      Handle such cases as gracefully as possible by falling back to a
-      minimal abort handler that only relies on i18n.  */
-   if (global_dc->get_reference_printer () == nullptr)
-     {
-       /* Print the error message.  */
-       fnotice (stderr, diagnostic_kind_text[DK_ICE]);
-       fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
-       fputc ('\n', stderr);
- 
-       /* Attempt to print a backtrace.  */
-       struct backtrace_state *state
- 	= backtrace_create_state (nullptr, 0, bt_err_callback, nullptr);
-       int count = 0;
-       if (state != nullptr)
- 	backtrace_full (state, 2, bt_callback, bt_err_callback,
- 			(void *) &count);
- 
-       /* We can't call warn_if_plugins or emergency_dump_function as these
- 	 rely on GCC state that might not be initialized, or might be in
- 	 use by another thread.  */
- 
-       /* Abort the process.  */
-       real_abort ();
-     }
- 
-   internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
- }
- 
- /* class diagnostic_context.  */
- 
- void
- diagnostic_context::begin_group ()
- {
-   m_diagnostic_groups.m_group_nesting_depth++;
- }
- 
- void
- diagnostic_context::end_group ()
- {
-   if (--m_diagnostic_groups.m_group_nesting_depth == 0)
-     {
-       /* Handle the case where we've popped the final diagnostic group.
- 	 If any diagnostics were emitted, give the context a chance
- 	 to do something.  */
-       if (m_diagnostic_groups.m_emission_count > 0)
- 	for (auto sink : m_output_sinks)
- 	  sink->on_end_group ();
-       m_diagnostic_groups.m_emission_count = 0;
-     }
-   /* We're popping one level, so might need to stop inhibiting notes.  */
-   inhibit_notes_in_group (/*inhibit=*/false);
- }
- 
- void
- diagnostic_context::push_nesting_level ()
- {
-   ++m_diagnostic_groups.m_diagnostic_nesting_level;
- }
- 
- void
- diagnostic_context::pop_nesting_level ()
- {
-   --m_diagnostic_groups.m_diagnostic_nesting_level;
-   /* We're popping one level, so might need to stop inhibiting notes.  */
-   inhibit_notes_in_group (/*inhibit=*/false);
- }
- 
- void
- diagnostic_output_format::dump (FILE *out, int indent) const
- {
-   fprintf (out, "%*sprinter:\n", indent, "");
-   m_printer->dump (out, indent + 2);
- }
- 
- void
- diagnostic_output_format::on_report_verbatim (text_info &)
- {
-   /* No-op.  */
- }
- 
- /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
-    file-based output formats.  */
- 
- void
- diagnostic_output_format_init (diagnostic_context &context,
- 			       const char *main_input_filename_,
- 			       const char *base_file_name,
- 			       enum diagnostics_output_format format,
- 			       bool json_formatting)
- {
-   diagnostic_output_format *new_sink = nullptr;
-   switch (format)
-     {
-     default:
-       gcc_unreachable ();
-     case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
-       /* The default; do nothing.  */
-       break;
- 
-     case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
-       new_sink = &diagnostic_output_format_init_sarif_stderr (context,
- 							      line_table,
- 							      json_formatting);
-       break;
- 
-     case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
-       new_sink = &diagnostic_output_format_init_sarif_file (context,
- 							line_table,
- 							    json_formatting,
- 							    base_file_name);
-       break;
-     }
-   if (new_sink)
-     new_sink->set_main_input_filename (main_input_filename_);
- }
- 
- /* Initialize this context's m_diagrams based on CHARSET.
-    Specifically, make a text_art::theme object for m_diagrams.m_theme,
-    (or nullptr for "no diagrams").  */
- 
- void
- diagnostic_context::
- set_text_art_charset (enum diagnostic_text_art_charset charset)
- {
-   delete m_diagrams.m_theme;
-   switch (charset)
-     {
-     default:
-       gcc_unreachable ();
- 
-     case DIAGNOSTICS_TEXT_ART_CHARSET_NONE:
-       m_diagrams.m_theme = nullptr;
-       break;
- 
-     case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII:
-       m_diagrams.m_theme = new text_art::ascii_theme ();
-       break;
- 
-     case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE:
-       m_diagrams.m_theme = new text_art::unicode_theme ();
-       break;
- 
-     case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI:
-       m_diagrams.m_theme = new text_art::emoji_theme ();
-       break;
-     }
- }
- 
- /* If BUFFER is non-null, use BUFFER as the active diagnostic_buffer on
-    this context.  BUFFER is borrowed.
- 
-    If BUFFER is null, stop any buffering on this context until the next call
-    to this function.  */
- 
- void
- diagnostic_context::set_diagnostic_buffer (diagnostic_buffer *buffer)
- {
-   /* We don't allow changing buffering within a diagnostic group
-      (to simplify handling of buffered diagnostics within the
-      diagnostic_format implementations).  */
-   gcc_assert (m_diagnostic_groups.m_group_nesting_depth == 0);
- 
-   /* Likewise, for simplicity, we only allow changing buffers
-      at nesting level 0.  */
-   gcc_assert (m_diagnostic_groups.m_diagnostic_nesting_level == 0);
- 
-   m_diagnostic_buffer = buffer;
- 
-   if (buffer)
-     {
-       buffer->ensure_per_format_buffers ();
-       gcc_assert (buffer->m_per_format_buffers);
-       gcc_assert (buffer->m_per_format_buffers->length ()
- 		  == m_output_sinks.length ());
-       for (unsigned idx = 0; idx < m_output_sinks.length (); ++idx)
- 	{
- 	  auto sink = m_output_sinks[idx];
- 	  auto per_format_buffer = (*buffer->m_per_format_buffers)[idx];
- 	  sink->set_buffer (per_format_buffer);
- 	}
-     }
-   else
-     for (auto sink : m_output_sinks)
-       sink->set_buffer (nullptr);
- }
- 
- /* Clear BUFFER without flushing it.  */
- 
- void
- diagnostic_context::clear_diagnostic_buffer (diagnostic_buffer &buffer)
- {
-   if (buffer.m_per_format_buffers)
-     for (auto per_format_buffer : *buffer.m_per_format_buffers)
-       per_format_buffer->clear ();
- 
-   buffer.m_diagnostic_counters.clear ();
- 
-   /* We need to reset last_location, otherwise we may skip caret lines
-      when we actually give a diagnostic.  */
-   m_last_location = UNKNOWN_LOCATION;
- }
- 
- /* Flush the diagnostics in BUFFER to this context, clearing BUFFER.  */
- 
- void
- diagnostic_context::flush_diagnostic_buffer (diagnostic_buffer &buffer)
- {
-   bool had_errors
-     = (buffer.m_diagnostic_counters.m_count_for_kind[DK_ERROR] > 0
-        || buffer.m_diagnostic_counters.m_count_for_kind[DK_WERROR] > 0);
-   if (buffer.m_per_format_buffers)
-     for (auto per_format_buffer : *buffer.m_per_format_buffers)
-       per_format_buffer->flush ();
-   buffer.m_diagnostic_counters.move_to (m_diagnostic_counters);
- 
-   action_after_output (had_errors ? DK_ERROR : DK_WARNING);
-   check_max_errors (true);
- }
- 
- /* struct diagnostic_counters.  */
- 
- diagnostic_counters::diagnostic_counters ()
- {
-   clear ();
- }
- 
- void
- diagnostic_counters::dump (FILE *out, int indent) const
- {
-   fprintf (out, "%*scounts:\n", indent, "");
-   bool none = true;
-   for (int i = 0; i < DK_LAST_DIAGNOSTIC_KIND; i++)
-     if (m_count_for_kind[i] > 0)
-       {
- 	fprintf (out, "%*s%s%i\n",
- 		 indent + 2, "",
- 		 get_diagnostic_kind_text (static_cast<diagnostic_t> (i)),
- 		 m_count_for_kind[i]);
- 	none = false;
-       }
-   if (none)
-     fprintf (out, "%*s(none)\n", indent + 2, "");
- }
- 
- void
- diagnostic_counters::move_to (diagnostic_counters &dest)
- {
-   for (int i = 0; i < DK_LAST_DIAGNOSTIC_KIND; i++)
-     dest.m_count_for_kind[i] += m_count_for_kind[i];
-   clear ();
- }
- 
- void
- diagnostic_counters::clear ()
- {
-   memset (&m_count_for_kind, 0, sizeof m_count_for_kind);
- }
- 
- /* class diagnostic_buffer.  */
- 
- diagnostic_buffer::diagnostic_buffer (diagnostic_context &ctxt)
- : m_ctxt (ctxt),
-   m_per_format_buffers (nullptr)
- {
- }
- 
- diagnostic_buffer::~diagnostic_buffer ()
- {
-   if (m_per_format_buffers)
-     {
-       for (auto iter : *m_per_format_buffers)
- 	delete iter;
-       delete m_per_format_buffers;
-     }
- }
- 
- void
- diagnostic_buffer::dump (FILE *out, int indent) const
- {
-   m_diagnostic_counters.dump (out, indent + 2);
-   fprintf (out, "%*sm_per_format_buffers:\n", indent, "");
-   if (m_per_format_buffers)
-     for (auto per_format_buffer : *m_per_format_buffers)
-       per_format_buffer->dump (out, indent + 2);
-   else
-     fprintf (out, "%*s(none)\n", indent + 2, "");
- }
- 
- bool
- diagnostic_buffer::empty_p () const
- {
-   if (m_per_format_buffers)
-     for (auto per_format_buffer : *m_per_format_buffers)
-       /* Query initial buffer.  */
-       return per_format_buffer->empty_p ();
-   return true;
- }
- 
- void
- diagnostic_buffer::move_to (diagnostic_buffer &dest)
- {
-   /* Bail if there's nothing to move.  */
-   if (!m_per_format_buffers)
-     return;
- 
-   m_diagnostic_counters.move_to (dest.m_diagnostic_counters);
- 
-   if (!dest.m_per_format_buffers)
-     {
-       /* Optimization for the "move to empty" case:
- 	 simply move the vec to the dest.  */
-       dest.m_per_format_buffers = m_per_format_buffers;
-       m_per_format_buffers = nullptr;
-       return;
-     }
- 
-   dest.ensure_per_format_buffers ();
-   gcc_assert (m_per_format_buffers);
-   gcc_assert (m_per_format_buffers->length ()
- 	      == m_ctxt.m_output_sinks.length ());
-   gcc_assert (dest.m_per_format_buffers);
-   gcc_assert (dest.m_per_format_buffers->length ()
- 	      == m_ctxt.m_output_sinks.length ());
-   for (unsigned idx = 0; idx < m_ctxt.m_output_sinks.length (); ++idx)
-     {
-       auto per_format_buffer_src = (*m_per_format_buffers)[idx];
-       auto per_format_buffer_dest = (*dest.m_per_format_buffers)[idx];
-       per_format_buffer_src->move_to (*per_format_buffer_dest);
-     }
- }
- 
- /* Lazily get the output formats to create their own kind of buffers.
-    We can't change the output sinks on a context once this has been called
-    on any diagnostic_buffer instances for that context, since there's no
-    way to update all diagnostic_buffer instances for that context.  */
- 
- void
- diagnostic_buffer::ensure_per_format_buffers ()
- {
-   if (!m_per_format_buffers)
-     {
-       m_per_format_buffers = new auto_vec<diagnostic_per_format_buffer *> ();
-       for (unsigned idx = 0; idx < m_ctxt.m_output_sinks.length (); ++idx)
- 	{
- 	  auto sink = m_ctxt.m_output_sinks[idx];
- 	  auto per_format_buffer = sink->make_per_format_buffer ();
- 	  m_per_format_buffers->safe_push (per_format_buffer.release ());
- 	}
-     }
-   gcc_assert (m_per_format_buffers);
-   gcc_assert (m_per_format_buffers->length ()
- 	      == m_ctxt.m_output_sinks.length ());
- }
- 
- /* Really call the system 'abort'.  This has to go right at the end of
-    this file, so that there are no functions after it that call abort
-    and get the system abort instead of our macro.  */
- #undef abort
- static void
- real_abort (void)
- {
-   abort ();
- }
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* Helper function for test_print_escaped_string.  */
- 
- static void
- assert_print_escaped_string (const location &loc, const char *expected_output,
- 			     const char *input)
- {
-   pretty_printer pp;
-   print_escaped_string (&pp, input);
-   ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
- }
- 
- #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
-     assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
- 
- /* Tests of print_escaped_string.  */
- 
- static void
- test_print_escaped_string ()
- {
-   /* Empty string.  */
-   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
- 
-   /* Non-empty string.  */
-   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
- 
-   /* Various things that need to be escaped:  */
-   /* Backslash.  */
-   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
- 				     "before\\after");
-   /* Tab.  */
-   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
- 				     "before\tafter");
-   /* Newline.  */
-   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
- 				     "before\nafter");
-   /* Double quote.  */
-   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
- 				     "before\"after");
- 
-   /* Non-printable characters: BEL: '\a': 0x07 */
-   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
- 				     "before\aafter");
-   /* Non-printable characters: vertical tab: '\v': 0x0b */
-   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
- 				     "before\vafter");
- }
- 
- /* Tests of print_parseable_fixits.  */
- 
- /* Verify that print_parseable_fixits emits the empty string if there
-    are no fixits.  */
- 
- static void
- test_print_parseable_fixits_none ()
- {
-   pretty_printer pp;
-   file_cache fc;
-   rich_location richloc (line_table, UNKNOWN_LOCATION);
- 
-   print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
-   ASSERT_STREQ ("", pp_formatted_text (&pp));
- }
- 
- /* Verify that print_parseable_fixits does the right thing if there
-    is an insertion fixit hint.  */
- 
- static void
- test_print_parseable_fixits_insert ()
- {
-   pretty_printer pp;
-   file_cache fc;
-   rich_location richloc (line_table, UNKNOWN_LOCATION);
- 
-   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
-   linemap_line_start (line_table, 5, 100);
-   linemap_add (line_table, LC_LEAVE, false, nullptr, 0);
-   location_t where = linemap_position_for_column (line_table, 10);
-   richloc.add_fixit_insert_before (where, "added content");
- 
-   print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
-   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
- 		pp_formatted_text (&pp));
- }
- 
- /* Verify that print_parseable_fixits does the right thing if there
-    is an removal fixit hint.  */
- 
- static void
- test_print_parseable_fixits_remove ()
- {
-   pretty_printer pp;
-   file_cache fc;
-   rich_location richloc (line_table, UNKNOWN_LOCATION);
- 
-   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
-   linemap_line_start (line_table, 5, 100);
-   linemap_add (line_table, LC_LEAVE, false, nullptr, 0);
-   source_range where;
-   where.m_start = linemap_position_for_column (line_table, 10);
-   where.m_finish = linemap_position_for_column (line_table, 20);
-   richloc.add_fixit_remove (where);
- 
-   print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
-   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
- 		pp_formatted_text (&pp));
- }
- 
- /* Verify that print_parseable_fixits does the right thing if there
-    is an replacement fixit hint.  */
- 
- static void
- test_print_parseable_fixits_replace ()
- {
-   pretty_printer pp;
-   file_cache fc;
-   rich_location richloc (line_table, UNKNOWN_LOCATION);
- 
-   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
-   linemap_line_start (line_table, 5, 100);
-   linemap_add (line_table, LC_LEAVE, false, nullptr, 0);
-   source_range where;
-   where.m_start = linemap_position_for_column (line_table, 10);
-   where.m_finish = linemap_position_for_column (line_table, 20);
-   richloc.add_fixit_replace (where, "replacement");
- 
-   print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
-   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
- 		pp_formatted_text (&pp));
- }
- 
- /* Verify that print_parseable_fixits correctly handles
-    DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN.  */
- 
- static void
- test_print_parseable_fixits_bytes_vs_display_columns ()
- {
-   line_table_test ltt;
-   rich_location richloc (line_table, UNKNOWN_LOCATION);
- 
-   /* 1-based byte offsets:     12345677778888999900001234567.  */
-   const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
-   /* 1-based display cols:     123456[......7-8.....]9012345.  */
-   const int tabstop = 8;
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-   file_cache fc;
-   const char *const fname = tmp.get_filename ();
- 
-   linemap_add (line_table, LC_ENTER, false, fname, 0);
-   linemap_line_start (line_table, 1, 100);
-   linemap_add (line_table, LC_LEAVE, false, nullptr, 0);
-   source_range where;
-   where.m_start = linemap_position_for_column (line_table, 12);
-   where.m_finish = linemap_position_for_column (line_table, 17);
-   richloc.add_fixit_replace (where, "color");
- 
-   /* Escape fname.  */
-   pretty_printer tmp_pp;
-   print_escaped_string (&tmp_pp, fname);
-   char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
- 
-   const int buf_len = strlen (escaped_fname) + 100;
-   char *const expected = XNEWVEC (char, buf_len);
- 
-   {
-     pretty_printer pp;
-     print_parseable_fixits (fc, &pp, &richloc,
- 			    DIAGNOSTICS_COLUMN_UNIT_BYTE,
- 			    tabstop);
-     snprintf (expected, buf_len,
- 	      "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
-     ASSERT_STREQ (expected, pp_formatted_text (&pp));
-   }
-   {
-     pretty_printer pp;
-     print_parseable_fixits (fc, &pp, &richloc,
- 			    DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
- 			    tabstop);
-     snprintf (expected, buf_len,
- 	      "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
-     ASSERT_STREQ (expected, pp_formatted_text (&pp));
-   }
- 
-   XDELETEVEC (expected);
-   free (escaped_fname);
- }
- 
- /* Verify that
-      diagnostic_column_policy::get_location_text (..., SHOW_COLUMN, ...)
-    generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
-    colorization disabled.  */
- 
- static void
- assert_location_text (const char *expected_loc_text,
- 		      const char *filename, int line, int column,
- 		      bool show_column,
- 		      int origin = 1,
- 		      enum diagnostics_column_unit column_unit
- 			= DIAGNOSTICS_COLUMN_UNIT_BYTE)
- {
-   test_diagnostic_context dc;
-   dc.m_column_unit = column_unit;
-   dc.m_column_origin = origin;
- 
-   expanded_location xloc;
-   xloc.file = filename;
-   xloc.line = line;
-   xloc.column = column;
-   xloc.data = nullptr;
-   xloc.sysp = false;
- 
-   diagnostic_column_policy column_policy (dc);
-   label_text actual_loc_text
-     = column_policy.get_location_text (xloc, show_column, false);
-   ASSERT_STREQ (expected_loc_text, actual_loc_text.get ());
- }
- 
- /* Verify that get_location_text works as expected.  */
- 
- static void
- test_get_location_text ()
- {
-   const char *old_progname = progname;
-   progname = "PROGNAME";
-   assert_location_text ("PROGNAME:", nullptr, 0, 0, true);
-   char *built_in_colon = concat (special_fname_builtin (), ":", (char *) 0);
-   assert_location_text (built_in_colon, special_fname_builtin (),
- 			42, 10, true);
-   free (built_in_colon);
-   assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
-   assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
-   assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
-   for (int origin = 0; origin != 2; ++origin)
-     assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
-   assert_location_text ("foo.c:", "foo.c", 0, 10, true);
-   assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
-   assert_location_text ("foo.c:", "foo.c", 0, 10, false);
- 
-   maybe_line_and_column (INT_MAX, INT_MAX);
-   maybe_line_and_column (INT_MIN, INT_MIN);
- 
-   {
-     /* In order to test display columns vs byte columns, we need to create a
-        file for location_get_source_line() to read.  */
- 
-     const char *const content = "smile \xf0\x9f\x98\x82\n";
-     const int line_bytes = strlen (content) - 1;
-     const int def_tabstop = 8;
-     const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
-     const int display_width = cpp_display_width (content, line_bytes, policy);
-     ASSERT_EQ (line_bytes - 2, display_width);
-     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-     const char *const fname = tmp.get_filename ();
-     const int buf_len = strlen (fname) + 16;
-     char *const expected = XNEWVEC (char, buf_len);
- 
-     snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
-     assert_location_text (expected, fname, 1, line_bytes, true,
- 			  1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
- 
-     snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
-     assert_location_text (expected, fname, 1, line_bytes, true,
- 			  0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
- 
-     snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
-     assert_location_text (expected, fname, 1, line_bytes, true,
- 			  1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
- 
-     snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
-     assert_location_text (expected, fname, 1, line_bytes, true,
- 			  0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
- 
-     XDELETEVEC (expected);
-   }
- 
- 
-   progname = old_progname;
- }
- 
- /* Selftest for num_digits.  */
- 
- static void
- test_num_digits ()
- {
-   ASSERT_EQ (1, num_digits (0));
-   ASSERT_EQ (1, num_digits (9));
-   ASSERT_EQ (2, num_digits (10));
-   ASSERT_EQ (2, num_digits (99));
-   ASSERT_EQ (3, num_digits (100));
-   ASSERT_EQ (3, num_digits (999));
-   ASSERT_EQ (4, num_digits (1000));
-   ASSERT_EQ (4, num_digits (9999));
-   ASSERT_EQ (5, num_digits (10000));
-   ASSERT_EQ (5, num_digits (99999));
-   ASSERT_EQ (6, num_digits (100000));
-   ASSERT_EQ (6, num_digits (999999));
-   ASSERT_EQ (7, num_digits (1000000));
-   ASSERT_EQ (7, num_digits (9999999));
-   ASSERT_EQ (8, num_digits (10000000));
-   ASSERT_EQ (8, num_digits (99999999));
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- c_diagnostic_cc_tests ()
- {
-   test_print_escaped_string ();
-   test_print_parseable_fixits_none ();
-   test_print_parseable_fixits_insert ();
-   test_print_parseable_fixits_remove ();
-   test_print_parseable_fixits_replace ();
-   test_print_parseable_fixits_bytes_vs_display_columns ();
-   test_get_location_text ();
-   test_num_digits ();
- }
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
- 
- #if __GNUC__ >= 10
- #  pragma GCC diagnostic pop
- #endif
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic.def gcc-16-20250727/gcc/diagnostic.def
*** gcc-16-20250720/gcc/diagnostic.def	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic.def	Thu Jan  1 00:00:00 1970
***************
*** 1,55 ****
- /* Copyright (C) 2001-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- /* DK_UNSPECIFIED must be first so it has a value of zero.  We never
-    assign this kind to an actual diagnostic, we only use this in
-    variables that can hold a kind, to mean they have yet to have a
-    kind specified.  I.e. they're uninitialized.  Within the diagnostic
-    machinery, this kind also means "don't change the existing kind",
-    meaning "no change is specified".  */
- DEFINE_DIAGNOSTIC_KIND (DK_UNSPECIFIED, "", NULL)
- 
- /* If a diagnostic is set to DK_IGNORED, it won't get reported at all.
-    This is used by the diagnostic machinery when it wants to disable a
-    diagnostic without disabling the option which causes it.  */
- DEFINE_DIAGNOSTIC_KIND (DK_IGNORED, "", NULL)
- 
- /* The remainder are real diagnostic types.  */
- DEFINE_DIAGNOSTIC_KIND (DK_FATAL, "fatal error: ", "error")
- DEFINE_DIAGNOSTIC_KIND (DK_ICE, "internal compiler error: ", "error")
- DEFINE_DIAGNOSTIC_KIND (DK_ERROR, "error: ", "error")
- DEFINE_DIAGNOSTIC_KIND (DK_SORRY, "sorry, unimplemented: ", "error")
- DEFINE_DIAGNOSTIC_KIND (DK_WARNING, "warning: ", "warning")
- DEFINE_DIAGNOSTIC_KIND (DK_ANACHRONISM, "anachronism: ", "warning")
- DEFINE_DIAGNOSTIC_KIND (DK_NOTE, "note: ", "note")
- DEFINE_DIAGNOSTIC_KIND (DK_DEBUG, "debug: ", "note")
- 
- /* For use when using the diagnostic_show_locus machinery to show
-    a range of events within a path.  */
- DEFINE_DIAGNOSTIC_KIND (DK_DIAGNOSTIC_PATH, "path: ", "path")
- 
- /* These two would be re-classified as DK_WARNING or DK_ERROR, so the
- prefix does not matter.  */
- DEFINE_DIAGNOSTIC_KIND (DK_PEDWARN, "pedwarn: ", NULL)
- DEFINE_DIAGNOSTIC_KIND (DK_PERMERROR, "permerror: ", NULL)
- /* This one is just for counting DK_WARNING promoted to DK_ERROR
-    due to -Werror and -Werror=warning.  */
- DEFINE_DIAGNOSTIC_KIND (DK_WERROR, "error: ", NULL)
- /* This is like DK_ICE, but backtrace is not printed.  Used in the driver
-    when reporting fatal signal in the compiler.  */
- DEFINE_DIAGNOSTIC_KIND (DK_ICE_NOBT, "internal compiler error: ", "error")
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/diagnostic.h gcc-16-20250727/gcc/diagnostic.h
*** gcc-16-20250720/gcc/diagnostic.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/diagnostic.h	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 21,1166 ****
  #ifndef GCC_DIAGNOSTIC_H
  #define GCC_DIAGNOSTIC_H
  
- #include "unique-argv.h"
  #include "rich-location.h"
  #include "pretty-print.h"
  #include "diagnostic-core.h"
  
! namespace diagnostics {
!   namespace digraphs {
!     class lazy_digraph;
!   } // namespace digraphs
! } // namespace diagnostics
! 
! namespace text_art
! {
!   class theme;
! } // namespace text_art
! 
! namespace xml
! {
!   class printer;
! } // namespace xml
! 
! /* An enum for controlling what units to use for the column number
!    when diagnostics are output, used by the -fdiagnostics-column-unit option.
!    Tabs will be expanded or not according to the value of -ftabstop.  The origin
!    (default 1) is controlled by -fdiagnostics-column-origin.  */
! 
! enum diagnostics_column_unit
! {
!   /* The default from GCC 11 onwards: display columns.  */
!   DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
! 
!   /* The behavior in GCC 10 and earlier: simple bytes.  */
!   DIAGNOSTICS_COLUMN_UNIT_BYTE
! };
! 
! /* An enum for controlling how to print non-ASCII characters/bytes when
!    a diagnostic suggests escaping the source code on output.  */
! 
! enum diagnostics_escape_format
! {
!   /* Escape non-ASCII Unicode characters in the form <U+XXXX> and
!      non-UTF-8 bytes in the form <XX>.  */
!   DIAGNOSTICS_ESCAPE_FORMAT_UNICODE,
! 
!   /* Escape non-ASCII bytes in the form <XX> (thus showing the underlying
!      encoding of non-ASCII Unicode characters).  */
!   DIAGNOSTICS_ESCAPE_FORMAT_BYTES
! };
! 
! /* Enum for overriding the standard output format.  */
! 
! enum diagnostics_output_format
! {
!   /* The default: textual output.  */
!   DIAGNOSTICS_OUTPUT_FORMAT_TEXT,
! 
!   /* SARIF-based output, as JSON to stderr.  */
!   DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR,
! 
!   /* SARIF-based output, to a JSON file.  */
!   DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE
! };
! 
! /* An enum for controlling how diagnostic_paths should be printed.  */
! enum diagnostic_path_format
! {
!   /* Don't print diagnostic_paths.  */
!   DPF_NONE,
! 
!   /* Print diagnostic_paths by emitting a separate "note" for every event
!      in the path.  */
!   DPF_SEPARATE_EVENTS,
! 
!   /* Print diagnostic_paths by consolidating events together where they
!      are close enough, and printing such runs of events with multiple
!      calls to diagnostic_show_locus, showing the individual events in
!      each run via labels in the source.  */
!   DPF_INLINE_EVENTS
! };
! 
! /* An enum for capturing values of GCC_EXTRA_DIAGNOSTIC_OUTPUT,
!    and for -fdiagnostics-parseable-fixits.  */
! 
! enum diagnostics_extra_output_kind
! {
!   /* No extra output, or an unrecognized value.  */
!   EXTRA_DIAGNOSTIC_OUTPUT_none,
! 
!   /* Emit fix-it hints using the "fixits-v1" format, equivalent to
!      -fdiagnostics-parseable-fixits.  */
!   EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1,
! 
!   /* Emit fix-it hints using the "fixits-v2" format.  */
!   EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
! };
! 
! /* Values for -fdiagnostics-text-art-charset=.  */
! 
! enum diagnostic_text_art_charset
! {
!   /* No text art diagrams shall be emitted.  */
!   DIAGNOSTICS_TEXT_ART_CHARSET_NONE,
! 
!   /* Use pure ASCII for text art diagrams.  */
!   DIAGNOSTICS_TEXT_ART_CHARSET_ASCII,
! 
!   /* Use ASCII + conservative use of other unicode characters
!      in text art diagrams.  */
!   DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE,
! 
!   /* Use Emoji.  */
!   DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI
! };
! 
! /* A diagnostic is described by the MESSAGE to send, the FILE and LINE of
!    its context and its KIND (ice, error, warning, note, ...)  See complete
!    list in diagnostic.def.  */
! struct diagnostic_info
! {
!   diagnostic_info ()
!     : message (), richloc (), metadata (), x_data (), kind (), option_id (),
!       m_iinfo ()
!   { }
! 
!   /* Text to be formatted.  */
!   text_info message;
! 
!   /* The location at which the diagnostic is to be reported.  */
!   rich_location *richloc;
! 
!   /* An optional bundle of metadata associated with the diagnostic
!      (or NULL).  */
!   const diagnostic_metadata *metadata;
! 
!   /* Auxiliary data for client.  */
!   void *x_data;
!   /* The kind of diagnostic it is about.  */
!   diagnostic_t kind;
!   /* Which OPT_* directly controls this diagnostic.  */
!   diagnostic_option_id option_id;
! 
!   /* Inlining context containing locations for each call site along
!      the inlining stack.  */
!   struct inlining_info
!   {
!     /* Locations along the inlining stack.  */
!     auto_vec<location_t, 8> m_ilocs;
!     /* The abstract origin of the location.  */
!     void *m_ao;
!     /* Set if every M_ILOCS element is in a system header.  */
!     bool m_allsyslocs;
!   } m_iinfo;
! };
! 
! /*  Forward declarations.  */
! class diagnostic_location_print_policy;
! class diagnostic_source_print_policy;
! 
! typedef void (*diagnostic_text_starter_fn) (diagnostic_text_output_format &,
! 					    const diagnostic_info *);
! 
! struct to_text;
! struct to_html;
! 
! extern pretty_printer *get_printer (to_text &);
! 
! template <typename Sink>
! using diagnostic_start_span_fn = void (*) (const diagnostic_location_print_policy &,
! 					   Sink &sink,
! 					   expanded_location);
! 
! typedef void (*diagnostic_text_finalizer_fn) (diagnostic_text_output_format &,
! 					      const diagnostic_info *,
! 					      diagnostic_t);
! 
! /* Abstract base class for the diagnostic subsystem to make queries
!    about command-line options.  */
! 
! class diagnostic_option_manager
! {
! public:
!   virtual ~diagnostic_option_manager () {}
! 
!   /* Return 1 if option OPTION_ID is enabled, 0 if it is disabled,
!      or -1 if it isn't a simple on-off switch
!      (or if the value is unknown, typically set later in target).  */
!   virtual int option_enabled_p (diagnostic_option_id option_id) const = 0;
! 
!   /* Return malloced memory for the name of the option OPTION_ID
!      which enabled a diagnostic, originally of type ORIG_DIAG_KIND but
!      possibly converted to DIAG_KIND by options such as -Werror.
!      May return NULL if no name is to be printed.
!      May be passed 0 as well as the index of a particular option.  */
!   virtual char *make_option_name (diagnostic_option_id option_id,
! 				  diagnostic_t orig_diag_kind,
! 				  diagnostic_t diag_kind) const = 0;
! 
!   /* Return malloced memory for a URL describing the option that controls
!      a diagnostic.
!      May return NULL if no URL is available.
!      May be passed 0 as well as the index of a particular option.  */
!   virtual char *make_option_url (diagnostic_option_id option_id) const = 0;
! };
! 
! class edit_context;
! class diagnostic_client_data_hooks;
! class logical_location_manager;
! class diagnostic_diagram;
! class diagnostic_source_effect_info;
! class diagnostic_output_format;
!   class diagnostic_text_output_format;
! class diagnostic_buffer;
! 
! /* A stack of sets of classifications: each entry in the stack is
!    a mapping from option index to diagnostic severity that can be changed
!    via pragmas.  The stack can be pushed and popped.  */
! 
! class diagnostic_option_classifier
! {
! public:
!   void init (int n_opts);
!   void fini ();
! 
!   /* Save all diagnostic classifications in a stack.  */
!   void push ();
! 
!   /* Restore the topmost classification set off the stack.  If the stack
!      is empty, revert to the state based on command line parameters.  */
!   void pop (location_t where);
! 
!   bool option_unspecified_p (diagnostic_option_id option_id) const
!   {
!     return get_current_override (option_id) == DK_UNSPECIFIED;
!   }
! 
!   diagnostic_t get_current_override (diagnostic_option_id option_id) const
!   {
!     gcc_assert (option_id.m_idx < m_n_opts);
!     return m_classify_diagnostic[option_id.m_idx];
!   }
! 
!   diagnostic_t
!   classify_diagnostic (const diagnostic_context *context,
! 		       diagnostic_option_id option_id,
! 		       diagnostic_t new_kind,
! 		       location_t where);
! 
!   diagnostic_t
!   update_effective_level_from_pragmas (diagnostic_info *diagnostic) const;
! 
!   int pch_save (FILE *);
!   int pch_restore (FILE *);
! 
! private:
!   /* Each time a diagnostic's classification is changed with a pragma,
!      we record the change and the location of the change in an array of
!      these structs.  */
!   struct diagnostic_classification_change_t
!   {
!     location_t location;
! 
!     /* For DK_POP, this is the index of the corresponding push (as stored
!        in m_push_list).
!        Otherwise, this is an option index.  */
!     int option;
! 
!     diagnostic_t kind;
!   };
! 
!   int m_n_opts;
! 
!   /* For each option index that can be passed to warning() et al
!      (OPT_* from options.h when using this code with the core GCC
!      options), this array may contain a new kind that the diagnostic
!      should be changed to before reporting, or DK_UNSPECIFIED to leave
!      it as the reported kind, or DK_IGNORED to not report it at
!      all.  */
!   diagnostic_t *m_classify_diagnostic;
! 
!   /* History of all changes to the classifications above.  This list
!      is stored in location-order, so we can search it, either
!      binary-wise or end-to-front, to find the most recent
!      classification for a given diagnostic, given the location of the
!      diagnostic.  */
!   vec<diagnostic_classification_change_t> m_classification_history;
! 
!   /* For diagnostic_context::get_classification_history, declared later.  */
!   friend class diagnostic_context;
! 
!   /* For pragma push/pop.  */
!   vec<int> m_push_list;
! };
! 
! /* A bundle of options relating to printing the user's source code
!    (potentially with a margin, underlining, labels, etc).  */
! 
! struct diagnostic_source_printing_options
! {
!   /* True if we should print the source line with a caret indicating
!      the location.
!      Corresponds to -fdiagnostics-show-caret.  */
!   bool enabled;
! 
!   /* Maximum width of the source line printed.  */
!   int max_width;
! 
!   /* Character used at the caret when printing source locations.  */
!   char caret_chars[rich_location::STATICALLY_ALLOCATED_RANGES];
! 
!   /* When printing source code, should the characters at carets and ranges
!      be colorized? (assuming colorization is on at all).
!      This should be true for frontends that generate range information
!      (so that the ranges of code are colorized),
!      and false for frontends that merely specify points within the
!      source code (to avoid e.g. colorizing just the first character in
!      a token, which would look strange).  */
!   bool colorize_source_p;
! 
!   /* When printing source code, should labelled ranges be printed?
!      Corresponds to -fdiagnostics-show-labels.  */
!   bool show_labels_p;
! 
!   /* When printing source code, should there be a left-hand margin
!      showing line numbers?
!      Corresponds to -fdiagnostics-show-line-numbers.  */
!   bool show_line_numbers_p;
! 
!   /* If printing source code, what should the minimum width of the margin
!      be?  Line numbers will be right-aligned, and padded to this width.
!      Corresponds to -fdiagnostics-minimum-margin-width=VALUE.  */
!   int min_margin_width;
! 
!   /* Usable by plugins; if true, print a debugging ruler above the
!      source output.  */
!   bool show_ruler_p;
! 
!   /* When printing events in an inline path, should we print lines
!      visualizing links between related events (e.g. for CFG paths)?
!      Corresponds to -fdiagnostics-show-event-links.  */
!   bool show_event_links_p;
! };
! 
! /* A bundle of state for determining column numbers in diagnostics
!    (tab stops, whether to start at 0 or 1, etc).
!    Uses a file_cache to handle tabs.  */
! 
! class diagnostic_column_policy
! {
! public:
!   diagnostic_column_policy (const diagnostic_context &dc);
! 
!   int converted_column (expanded_location s) const;
! 
!   label_text get_location_text (const expanded_location &s,
! 				bool show_column,
! 				bool colorize) const;
! 
!   int get_tabstop () const { return m_tabstop; }
! 
! private:
!   file_cache &m_file_cache;
!   enum diagnostics_column_unit m_column_unit;
!   int m_column_origin;
!   int m_tabstop;
! };
! 
! /* A bundle of state for printing locations within diagnostics
!    (e.g. "FILENAME:LINE:COLUMN"), to isolate the interactions between
!    diagnostic_context and the start_span callbacks.  */
! 
! class diagnostic_location_print_policy
! {
! public:
!   diagnostic_location_print_policy (const diagnostic_context &dc);
!   diagnostic_location_print_policy (const diagnostic_text_output_format &);
! 
!   bool show_column_p () const { return m_show_column; }
! 
!   const diagnostic_column_policy &
!   get_column_policy () const { return m_column_policy; }
! 
!   void
!   print_text_span_start (const diagnostic_context &dc,
! 			 pretty_printer &pp,
! 			 const expanded_location &exploc);
! 
!   void
!   print_html_span_start (const diagnostic_context &dc,
! 			 xml::printer &xp,
! 			 const expanded_location &exploc);
! 
! private:
!   diagnostic_column_policy m_column_policy;
!   bool m_show_column;
! };
! 
! /* Abstract base class for optionally supplying extra tags when writing
!    out annotation labels in HTML output.  */
! 
! class html_label_writer
! {
! public:
!   virtual ~html_label_writer () {}
!   virtual void begin_label () = 0;
!   virtual void end_label () = 0;
! };
! 
! /* A bundle of state for printing source within a diagnostic,
!    to isolate the interactions between diagnostic_context and the
!    implementation of diagnostic_show_locus.  */
! 
! class diagnostic_source_print_policy
! {
! public:
!   diagnostic_source_print_policy (const diagnostic_context &);
!   diagnostic_source_print_policy (const diagnostic_context &,
! 				  const diagnostic_source_printing_options &);
! 
!   void
!   print (pretty_printer &pp,
! 	 const rich_location &richloc,
! 	 diagnostic_t diagnostic_kind,
! 	 diagnostic_source_effect_info *effect_info) const;
! 
!   void
!   print_as_html (xml::printer &xp,
! 		 const rich_location &richloc,
! 		 diagnostic_t diagnostic_kind,
! 		 diagnostic_source_effect_info *effect_info,
! 		 html_label_writer *label_writer) const;
! 
!   const diagnostic_source_printing_options &
!   get_options () const { return m_options; }
! 
!   diagnostic_start_span_fn<to_text>
!   get_text_start_span_fn () const { return m_text_start_span_cb; }
! 
!   diagnostic_start_span_fn<to_html>
!   get_html_start_span_fn () const { return m_html_start_span_cb; }
! 
!   file_cache &
!   get_file_cache () const { return m_file_cache; }
! 
!   enum diagnostics_escape_format
!   get_escape_format () const
!   {
!     return m_escape_format;
!   }
! 
!   text_art::theme *
!   get_diagram_theme () const { return m_diagram_theme; }
! 
!   const diagnostic_column_policy &get_column_policy () const
!   {
!     return m_location_policy.get_column_policy ();
!   }
! 
!   const diagnostic_location_print_policy &get_location_policy () const
!   {
!     return m_location_policy;
!   }
! 
! private:
!   const diagnostic_source_printing_options &m_options;
!   class diagnostic_location_print_policy m_location_policy;
!   diagnostic_start_span_fn<to_text> m_text_start_span_cb;
!   diagnostic_start_span_fn<to_html> m_html_start_span_cb;
!   file_cache &m_file_cache;
! 
!   /* Other data copied from diagnostic_context.  */
!   text_art::theme *m_diagram_theme;
!   enum diagnostics_escape_format m_escape_format;
! };
! 
! /* A collection of counters of diagnostics, per-kind
!    (e.g. "3 errors and 1 warning"), for use by both diagnostic_context
!    and by diagnostic_buffer.  */
! 
! struct diagnostic_counters
! {
!   diagnostic_counters ();
! 
!   void dump (FILE *out, int indent) const;
!   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
! 
!   int get_count (diagnostic_t kind) const { return m_count_for_kind[kind]; }
! 
!   void move_to (diagnostic_counters &dest);
!   void clear ();
! 
!   int m_count_for_kind[DK_LAST_DIAGNOSTIC_KIND];
! };
! 
! /* This class encapsulates the state of the diagnostics subsystem
!    as a whole (either directly, or via owned objects of other classes, to
!    avoid global variables).
! 
!    It has responsibility for:
!    - being a central place for clients to report diagnostics
!    - reporting those diagnostics to zero or more output sinks
!      (e.g. text vs SARIF)
!    - providing a "dump" member function for a debug dump of the state of
!      the diagnostics subsytem
!    - direct vs buffered diagnostics (see class diagnostic_buffer)
!    - tracking the original argv of the program (for SARIF output)
!    - crash-handling
! 
!    It delegates responsibility to various other classes:
!    - the various output sinks (instances of diagnostic_output_format
!      subclasses)
!    - formatting of messages (class pretty_printer)
!    - an optional urlifier to inject URLs into formatted messages
!    - counting the number of diagnostics reported of each kind
!      (class diagnostic_counters)
!    - calling out to a diagnostic_option_manager to determine if
!      a particular warning is enabled or disabled
!    - tracking pragmas that enable/disable warnings in a range of
!      source code
!    - a cache for use when quoting the user's source code (class file_cache)
!    - a text_art::theme
!    - an edit_context for generating patches from fix-it hints
!    - diagnostic_client_data_hooks for metadata.
! 
!    Try to avoid adding new responsibilities to this class itself, to avoid
!    the "blob" anti-pattern.  */
! 
! class diagnostic_context
! {
! public:
!   /* Give access to m_text_callbacks.  */
!   friend diagnostic_text_starter_fn &
!   diagnostic_text_starter (diagnostic_context *context);
!   friend diagnostic_start_span_fn<to_text> &
!   diagnostic_start_span (diagnostic_context *context);
!   friend diagnostic_text_finalizer_fn &
!   diagnostic_text_finalizer (diagnostic_context *context);
! 
!   friend class diagnostic_source_print_policy;
!   friend class diagnostic_text_output_format;
!   friend class diagnostic_buffer;
! 
!   typedef void (*set_locations_callback_t) (diagnostic_context *,
! 					    diagnostic_info *);
! 
!   void initialize (int n_opts);
!   void color_init (int value);
!   void urls_init (int value);
!   void set_pretty_printer (std::unique_ptr<pretty_printer> pp);
!   void refresh_output_sinks ();
! 
!   void finish ();
! 
!   void dump (FILE *out) const;
!   void DEBUG_FUNCTION dump () const { dump (stderr); }
! 
!   bool execution_failed_p () const;
! 
!   void set_original_argv (unique_argv original_argv);
!   const char * const *get_original_argv ()
!   {
!     return const_cast<const char * const *> (m_original_argv);
!   }
! 
!   void set_set_locations_callback (set_locations_callback_t cb)
!   {
!     m_set_locations_cb = cb;
!   }
! 
!   void
!   initialize_input_context (diagnostic_input_charset_callback ccb,
! 			    bool should_skip_bom);
! 
!   void begin_group ();
!   void end_group ();
! 
!   void push_nesting_level ();
!   void pop_nesting_level ();
! 
!   bool warning_enabled_at (location_t loc, diagnostic_option_id option_id);
! 
!   bool option_unspecified_p (diagnostic_option_id option_id) const
!   {
!     return m_option_classifier.option_unspecified_p (option_id);
!   }
! 
!   bool emit_diagnostic_with_group (diagnostic_t kind,
! 				   rich_location &richloc,
! 				   const diagnostic_metadata *metadata,
! 				   diagnostic_option_id option_id,
! 				   const char *gmsgid, ...)
!     ATTRIBUTE_GCC_DIAG(6,7);
!   bool emit_diagnostic_with_group_va (diagnostic_t kind,
! 				      rich_location &richloc,
! 				      const diagnostic_metadata *metadata,
! 				      diagnostic_option_id option_id,
! 				      const char *gmsgid, va_list *ap)
!     ATTRIBUTE_GCC_DIAG(6,0);
! 
!   bool report_diagnostic (diagnostic_info *);
!   void report_verbatim (text_info &);
! 
!   /* Report a directed graph associated with the run as a whole
!      to any sinks that support directed graphs.  */
!   void
!   report_global_digraph (const diagnostics::digraphs::lazy_digraph &);
! 
!   diagnostic_t
!   classify_diagnostic (diagnostic_option_id option_id,
! 		       diagnostic_t new_kind,
! 		       location_t where)
!   {
!     return m_option_classifier.classify_diagnostic (this,
! 						    option_id,
! 						    new_kind,
! 						    where);
!   }
! 
!   void push_diagnostics (location_t where ATTRIBUTE_UNUSED)
!   {
!     m_option_classifier.push ();
!   }
!   void pop_diagnostics (location_t where)
!   {
!     m_option_classifier.pop (where);
!   }
! 
!   void maybe_show_locus (const rich_location &richloc,
! 			 const diagnostic_source_printing_options &opts,
! 			 diagnostic_t diagnostic_kind,
! 			 pretty_printer &pp,
! 			 diagnostic_source_effect_info *effect_info);
!   void maybe_show_locus_as_html (const rich_location &richloc,
! 				 const diagnostic_source_printing_options &opts,
! 				 diagnostic_t diagnostic_kind,
! 				 xml::printer &xp,
! 				 diagnostic_source_effect_info *effect_info,
! 				 html_label_writer *label_writer);
! 
!   void emit_diagram (const diagnostic_diagram &diagram);
! 
!   /* Various setters for use by option-handling logic.  */
!   void set_output_format (std::unique_ptr<diagnostic_output_format> output_format);
!   void set_text_art_charset (enum diagnostic_text_art_charset charset);
!   void set_client_data_hooks (std::unique_ptr<diagnostic_client_data_hooks> hooks);
! 
!   void push_owned_urlifier (std::unique_ptr<urlifier>);
!   void push_borrowed_urlifier (const urlifier &);
!   void pop_urlifier ();
! 
!   void create_edit_context ();
!   void set_warning_as_error_requested (bool val)
!   {
!     m_warning_as_error_requested = val;
!   }
!   void set_report_bug (bool val) { m_report_bug = val; }
!   void set_extra_output_kind (enum diagnostics_extra_output_kind kind)
!   {
!     m_extra_output_kind = kind;
!   }
!   void set_show_cwe (bool val) { m_show_cwe = val;  }
!   void set_show_rules (bool val) { m_show_rules = val; }
!   void set_show_highlight_colors (bool val);
!   void set_path_format (enum diagnostic_path_format val)
!   {
!     m_path_format = val;
!   }
!   void set_show_path_depths (bool val) { m_show_path_depths = val; }
!   void set_show_option_requested (bool val) { m_show_option_requested = val; }
!   void set_max_errors (int val) { m_max_errors = val; }
!   void set_escape_format (enum diagnostics_escape_format val)
!   {
!     m_escape_format = val;
!   }
! 
!   void set_format_decoder (printer_fn format_decoder);
!   void set_prefixing_rule (diagnostic_prefixing_rule_t rule);
! 
!   /* Various accessors.  */
!   bool warning_as_error_requested_p () const
!   {
!     return m_warning_as_error_requested;
!   }
!   bool show_path_depths_p () const { return m_show_path_depths; }
!   diagnostic_output_format &get_output_format (size_t idx) const;
!   enum diagnostic_path_format get_path_format () const { return m_path_format; }
!   enum diagnostics_escape_format get_escape_format () const
!   {
!     return m_escape_format;
!   }
! 
!   file_cache &
!   get_file_cache () const
!   {
!     gcc_assert (m_file_cache);
!     return *m_file_cache;
!   }
! 
!   edit_context *get_edit_context () const
!   {
!     return m_edit_context_ptr;
!   }
!   const diagnostic_client_data_hooks *get_client_data_hooks () const
!   {
!     return m_client_data_hooks;
!   }
! 
!   const logical_location_manager *
!   get_logical_location_manager () const;
! 
!   const urlifier *get_urlifier () const;
! 
!   text_art::theme *get_diagram_theme () const { return m_diagrams.m_theme; }
! 
!   int &diagnostic_count (diagnostic_t kind)
!   {
!     return m_diagnostic_counters.m_count_for_kind[kind];
!   }
!   int diagnostic_count (diagnostic_t kind) const
!   {
!     return m_diagnostic_counters.get_count (kind);
!   }
! 
!   /* Option-related member functions.  */
!   inline bool option_enabled_p (diagnostic_option_id option_id) const
!   {
!     if (!m_option_mgr)
!       return true;
!     return m_option_mgr->option_enabled_p (option_id);
!   }
! 
!   inline char *make_option_name (diagnostic_option_id option_id,
! 				 diagnostic_t orig_diag_kind,
! 				 diagnostic_t diag_kind) const
!   {
!     if (!m_option_mgr)
!       return nullptr;
!     return m_option_mgr->make_option_name (option_id,
! 					   orig_diag_kind,
! 					   diag_kind);
!   }
! 
!   inline char *make_option_url (diagnostic_option_id option_id) const
!   {
!     if (!m_option_mgr)
!       return nullptr;
!     return m_option_mgr->make_option_url (option_id);
!   }
! 
!   void
!   set_option_manager (std::unique_ptr<diagnostic_option_manager> mgr,
! 		      unsigned lang_mask);
! 
!   unsigned get_lang_mask () const
!   {
!     return m_lang_mask;
!   }
! 
!   bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
! 			diagnostic_option_id, const char *,
! 			va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(5,0);
!   bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
! 			  diagnostic_option_id, unsigned HOST_WIDE_INT,
! 			  const char *, const char *, va_list *,
! 			  diagnostic_t) ATTRIBUTE_GCC_DIAG(7,0);
! 
!   int get_diagnostic_nesting_level () const
!   {
!     return m_diagnostic_groups.m_diagnostic_nesting_level;
!   }
! 
!   char *build_indent_prefix () const;
! 
!   int
!   pch_save (FILE *f)
!   {
!     return m_option_classifier.pch_save (f);
!   }
! 
!   int
!   pch_restore (FILE *f)
!   {
!     return m_option_classifier.pch_restore (f);
!   }
! 
! 
!   void set_diagnostic_buffer (diagnostic_buffer *);
!   diagnostic_buffer *get_diagnostic_buffer () const
!   {
!     return m_diagnostic_buffer;
!   }
!   void clear_diagnostic_buffer (diagnostic_buffer &);
!   void flush_diagnostic_buffer (diagnostic_buffer &);
! 
!   std::unique_ptr<pretty_printer> clone_printer () const
!   {
!     return m_reference_printer->clone ();
!   }
! 
!   pretty_printer *get_reference_printer () const
!   {
!     return m_reference_printer;
!   }
! 
!   void
!   add_sink (std::unique_ptr<diagnostic_output_format>);
! 
!   void remove_all_output_sinks ();
! 
!   bool supports_fnotice_on_stderr_p () const;
! 
!   /* Raise SIGABRT on any diagnostic of severity DK_ERROR or higher.  */
!   void
!   set_abort_on_error (bool val)
!   {
!     m_abort_on_error = val;
!   }
! 
!   /* Accessor for use in serialization, e.g. by C++ modules.  */
!   auto &
!   get_classification_history ()
!   {
!     return m_option_classifier.m_classification_history;
!   }
! 
!   void set_main_input_filename (const char *filename);
! 
!   void
!   set_permissive_option (diagnostic_option_id opt_permissive)
!   {
!     m_opt_permissive = opt_permissive;
!   }
! 
!   void
!   set_fatal_errors (bool fatal_errors)
!   {
!     m_fatal_errors = fatal_errors;
!   }
! 
!   void
!   set_internal_error_callback (void (*cb) (diagnostic_context *,
! 					   const char *,
! 					   va_list *))
!   {
!     m_internal_error = cb;
!   }
! 
!   void
!   set_adjust_diagnostic_info_callback (void (*cb) (diagnostic_context *,
! 						   diagnostic_info *))
!   {
!     m_adjust_diagnostic_info = cb;
!   }
! 
!   void
!   inhibit_notes () { m_inhibit_notes_p = true; }
! 
! private:
!   void error_recursion () ATTRIBUTE_NORETURN;
! 
!   bool diagnostic_enabled (diagnostic_info *diagnostic);
! 
!   void get_any_inlining_info (diagnostic_info *diagnostic);
! 
!   void check_max_errors (bool flush);
!   void action_after_output (diagnostic_t diag_kind);
! 
!   /* Data members.
!      Ideally, all of these would be private.  */
! 
! private:
!   /* A reference instance of pretty_printer created by the client
!      and owned by the context.  Used for cloning when creating/adding
!      output formats.
!      Owned by the context; this would be a std::unique_ptr if
!      diagnostic_context had a proper ctor.  */
!   pretty_printer *m_reference_printer;
! 
!   /* Cache of source code.
!      Owned by the context; this would be a std::unique_ptr if
!      diagnostic_context had a proper ctor.  */
!   file_cache *m_file_cache;
! 
!   /* The number of times we have issued diagnostics.  */
!   diagnostic_counters m_diagnostic_counters;
! 
!   /* True if it has been requested that warnings be treated as errors.  */
!   bool m_warning_as_error_requested;
! 
!   /* The number of option indexes that can be passed to warning() et
!      al.  */
!   int m_n_opts;
! 
!   /* The stack of sets of overridden diagnostic option severities.  */
!   diagnostic_option_classifier m_option_classifier;
! 
!   /* True if we should print any CWE identifiers associated with
!      diagnostics.  */
!   bool m_show_cwe;
! 
!   /* True if we should print any rules associated with diagnostics.  */
!   bool m_show_rules;
! 
!   /* How should diagnostic_path objects be printed.  */
!   enum diagnostic_path_format m_path_format;
! 
!   /* True if we should print stack depths when printing diagnostic paths.  */
!   bool m_show_path_depths;
! 
!   /* True if we should print the command line option which controls
!      each diagnostic, if known.  */
!   bool m_show_option_requested;
! 
!   /* True if we should raise a SIGABRT on errors.  */
!   bool m_abort_on_error;
! 
! public:
!   /* True if we should show the column number on diagnostics.  */
!   bool m_show_column;
! 
!   /* True if pedwarns are errors.  */
!   bool m_pedantic_errors;
! 
!   /* True if permerrors are warnings.  */
!   bool m_permissive;
! 
! private:
!   /* The option to associate with turning permerrors into warnings,
!      if any.  */
!   diagnostic_option_id m_opt_permissive;
! 
!   /* True if errors are fatal.  */
!   bool m_fatal_errors;
! 
! public:
!   /* True if all warnings should be disabled.  */
!   bool m_inhibit_warnings;
! 
!   /* True if warnings should be given in system headers.  */
!   bool m_warn_system_headers;
! 
! private:
!   /* Maximum number of errors to report.  */
!   int m_max_errors;
! 
!   /* Client-supplied callbacks for use in text output.  */
!   struct {
!     /* This function is called before any message is printed out.  It is
!        responsible for preparing message prefix and such.  For example, it
!        might say:
!        In file included from "/usr/local/include/curses.h:5:
!        from "/home/gdr/src/nifty_printer.h:56:
!        ...
!     */
!     diagnostic_text_starter_fn m_begin_diagnostic;
! 
!     /* This function is called by diagnostic_show_locus in between
!        disjoint spans of source code, so that the context can print
!        something to indicate that a new span of source code has begun.  */
!     diagnostic_start_span_fn<to_text> m_text_start_span;
!     diagnostic_start_span_fn<to_html> m_html_start_span;
! 
!     /* This function is called after the diagnostic message is printed.  */
!     diagnostic_text_finalizer_fn m_end_diagnostic;
!   } m_text_callbacks;
! 
!   /* Client hook to report an internal error.  */
!   void (*m_internal_error) (diagnostic_context *, const char *, va_list *);
! 
!   /* Client hook to adjust properties of the given diagnostic that we're
!      about to issue, such as its kind.  */
!   void (*m_adjust_diagnostic_info)(diagnostic_context *, diagnostic_info *);
! 
!   /* Owned by the context; this would be a std::unique_ptr if
!      diagnostic_context had a proper ctor.  */
!   diagnostic_option_manager *m_option_mgr;
!   unsigned m_lang_mask;
! 
!   /* A stack of optional hooks for adding URLs to quoted text strings in
!      diagnostics.  Only used for the main diagnostic message.
!      Typically a single one owner by the context, but can be temporarily
!      overridden by a borrowed urlifier (e.g. on-stack).  */
!   struct urlifier_stack_node
!   {
!     urlifier *m_urlifier;
!     bool m_owned;
!   };
!   auto_vec<urlifier_stack_node> *m_urlifier_stack;
! 
! public:
!   /* Auxiliary data for client.  */
!   void *m_client_aux_data;
! 
!   /* Used to detect that the last caret was printed at the same location.  */
!   location_t m_last_location;
! 
! private:
!   int m_lock;
! 
!   bool m_inhibit_notes_p;
! 
! public:
!   diagnostic_source_printing_options m_source_printing;
! 
! private:
!   /* True if -freport-bug option is used.  */
!   bool m_report_bug;
! 
!   /* Used to specify additional diagnostic output to be emitted after the
!      rest of the diagnostic.  This is for implementing
!      -fdiagnostics-parseable-fixits and GCC_EXTRA_DIAGNOSTIC_OUTPUT.  */
!   enum diagnostics_extra_output_kind m_extra_output_kind;
! 
! public:
!   /* What units to use when outputting the column number.  */
!   enum diagnostics_column_unit m_column_unit;
! 
!   /* The origin for the column number (1-based or 0-based typically).  */
!   int m_column_origin;
! 
!   /* The size of the tabstop for tab expansion.  */
!   int m_tabstop;
! 
! private:
!   /* How should non-ASCII/non-printable bytes be escaped when
!      a diagnostic suggests escaping the source code on output.  */
!   enum diagnostics_escape_format m_escape_format;
! 
!   /* If non-NULL, an edit_context to which fix-it hints should be
!      applied, for generating patches.
!      Owned by the context; this would be a std::unique_ptr if
!      diagnostic_context had a proper ctor.  */
!   edit_context *m_edit_context_ptr;
! 
!   /* Fields relating to diagnostic groups.  */
!   struct {
!     /* How many diagnostic_group instances are currently alive.  */
!     int m_group_nesting_depth;
! 
!     /* How many nesting levels have been pushed within this group.  */
!     int m_diagnostic_nesting_level;
! 
!     /* How many diagnostics have been emitted since the bottommost
!        diagnostic_group was pushed.  */
!     int m_emission_count;
! 
!     /* The "group+diagnostic" nesting depth from which to inhibit notes.  */
!     int m_inhibiting_notes_from;
!   } m_diagnostic_groups;
! 
!   void inhibit_notes_in_group (bool inhibit = true);
!   bool notes_inhibited_in_group () const;
! 
!   /* The various sinks to which diagnostics are to be outputted
!      (text vs structured formats such as SARIF).
!      The sinks are owned by the context; this would be a
!      std::vector<std::unique_ptr> if diagnostic_context had a
!      proper ctor.  */
!   auto_vec<diagnostic_output_format *> m_output_sinks;
! 
!   /* Callback to set the locations of call sites along the inlining
!      stack corresponding to a diagnostic location.  Needed to traverse
!      the BLOCK_SUPERCONTEXT() chain hanging off the LOCATION_BLOCK()
!      of a diagnostic's location.  */
!   set_locations_callback_t m_set_locations_cb;
! 
!   /* A bundle of hooks for providing data to the context about its client
!      e.g. version information, plugins, etc.
!      Used by SARIF output to give metadata about the client that's
!      producing diagnostics.
!      Owned by the context; this would be a std::unique_ptr if
!      diagnostic_context had a proper ctor.  */
!   diagnostic_client_data_hooks *m_client_data_hooks;
! 
!   /* Support for diagrams.  */
!   struct
!   {
!     /* Theme to use when generating diagrams.
!        Can be NULL (if text art is disabled).
!        Owned by the context; this would be a std::unique_ptr if
!        diagnostic_context had a proper ctor.  */
!     text_art::theme *m_theme;
! 
!   } m_diagrams;
! 
!   /* Owned by the context.  */
!   char **m_original_argv;
! 
!   /* Borrowed pointer to the active diagnostic_buffer, if any.
!      If null (the default), then diagnostics that are reported to the
!      context are immediately issued to the output format.
!      If non-null, then diagnostics that are reported to the context
!      are buffered in the buffer, and may be issued to the output format
!      later (if the buffer is flushed), moved to other buffers, or
!      discarded (if the buffer is cleared).  */
!   diagnostic_buffer *m_diagnostic_buffer;
! };
! 
! /* Client supplied function to announce a diagnostic
!    (for text-based diagnostic output).  */
! inline diagnostic_text_starter_fn &
! diagnostic_text_starter (diagnostic_context *context)
! {
!   return context->m_text_callbacks.m_begin_diagnostic;
! }
! 
! /* Client supplied function called between disjoint spans of source code,
!    so that the context can print
!    something to indicate that a new span of source code has begun.  */
! inline diagnostic_start_span_fn<to_text> &
! diagnostic_start_span (diagnostic_context *context)
! {
!   return context->m_text_callbacks.m_text_start_span;
! }
! 
! /* Client supplied function called after a diagnostic message is
!    displayed (for text-based diagnostic output).  */
! inline diagnostic_text_finalizer_fn &
! diagnostic_text_finalizer (diagnostic_context *context)
! {
!   return context->m_text_callbacks.m_end_diagnostic;
! }
  
  /* Extension hooks for client.  */
  #define diagnostic_context_auxiliary_data(DC) (DC)->m_client_aux_data
! #define diagnostic_info_auxiliary_data(DI) (DI)->x_data
  
! /* This diagnostic_context is used by front-ends that directly output
     diagnostic messages without going through `error', `warning',
     and similar functions.  */
! extern diagnostic_context *global_dc;
  
  /* The number of errors that have been issued so far.  Ideally, these
!    would take a diagnostic_context as an argument.  */
! #define errorcount global_dc->diagnostic_count (DK_ERROR)
  /* Similarly, but for warnings.  */
! #define warningcount global_dc->diagnostic_count (DK_WARNING)
  /* Similarly, but for warnings promoted to errors.  */
! #define werrorcount global_dc->diagnostic_count (DK_WERROR)
  /* Similarly, but for sorrys.  */
! #define sorrycount global_dc->diagnostic_count (DK_SORRY)
  
  /* Returns nonzero if warnings should be emitted.  */
  #define diagnostic_report_warnings_p(DC, LOC)				\
--- 21,51 ----
  #ifndef GCC_DIAGNOSTIC_H
  #define GCC_DIAGNOSTIC_H
  
  #include "rich-location.h"
  #include "pretty-print.h"
  #include "diagnostic-core.h"
  
! #include "diagnostics/diagnostic-info.h"
! #include "diagnostics/context.h"
  
  /* Extension hooks for client.  */
  #define diagnostic_context_auxiliary_data(DC) (DC)->m_client_aux_data
! #define diagnostic_info_auxiliary_data(DI) (DI)->m_x_data
  
! /* This diagnostics::context is used by front-ends that directly output
     diagnostic messages without going through `error', `warning',
     and similar functions.  */
! extern diagnostics::context *global_dc;
  
  /* The number of errors that have been issued so far.  Ideally, these
!    would take a diagnostics::context as an argument.  */
! #define errorcount global_dc->diagnostic_count (diagnostics::kind::error)
  /* Similarly, but for warnings.  */
! #define warningcount global_dc->diagnostic_count (diagnostics::kind::warning)
  /* Similarly, but for warnings promoted to errors.  */
! #define werrorcount global_dc->diagnostic_count (diagnostics::kind::werror)
  /* Similarly, but for sorrys.  */
! #define sorrycount global_dc->diagnostic_count (diagnostics::kind::sorry)
  
  /* Returns nonzero if warnings should be emitted.  */
  #define diagnostic_report_warnings_p(DC, LOC)				\
*************** extern diagnostic_context *global_dc;
*** 1171,1215 ****
     diagnostic.  */
  
  inline void
! diagnostic_set_option_id (diagnostic_info *info,
! 			  diagnostic_option_id option_id)
  {
!   info->option_id = option_id;
  }
  
  /* Diagnostic related functions.  */
  
  inline void
! diagnostic_initialize (diagnostic_context *context, int n_opts)
  {
    context->initialize (n_opts);
  }
  
  inline void
! diagnostic_color_init (diagnostic_context *context, int value = -1)
  {
    context->color_init (value);
  }
  
  inline void
! diagnostic_urls_init (diagnostic_context *context, int value = -1)
  {
    context->urls_init (value);
  }
  
  inline void
! diagnostic_finish (diagnostic_context *context)
  {
    context->finish ();
  }
  
  inline void
! diagnostic_show_locus (diagnostic_context *context,
! 		       const diagnostic_source_printing_options &opts,
  		       rich_location *richloc,
! 		       diagnostic_t diagnostic_kind,
  		       pretty_printer *pp,
! 		       diagnostic_source_effect_info *effect_info = nullptr)
  {
    gcc_assert (context);
    gcc_assert (richloc);
--- 56,100 ----
     diagnostic.  */
  
  inline void
! diagnostic_set_option_id (diagnostics::diagnostic_info *info,
! 			  diagnostics::option_id opt_id)
  {
!   info->m_option_id = opt_id;
  }
  
  /* Diagnostic related functions.  */
  
  inline void
! diagnostic_initialize (diagnostics::context *context, int n_opts)
  {
    context->initialize (n_opts);
  }
  
  inline void
! diagnostic_color_init (diagnostics::context *context, int value = -1)
  {
    context->color_init (value);
  }
  
  inline void
! diagnostic_urls_init (diagnostics::context *context, int value = -1)
  {
    context->urls_init (value);
  }
  
  inline void
! diagnostic_finish (diagnostics::context *context)
  {
    context->finish ();
  }
  
  inline void
! diagnostic_show_locus (diagnostics::context *context,
! 		       const diagnostics::source_printing_options &opts,
  		       rich_location *richloc,
! 		       enum diagnostics::kind diagnostic_kind,
  		       pretty_printer *pp,
! 		       diagnostics::source_effect_info *effect_info = nullptr)
  {
    gcc_assert (context);
    gcc_assert (richloc);
*************** diagnostic_show_locus (diagnostic_contex
*** 1218,1230 ****
  }
  
  inline void
! diagnostic_show_locus_as_html (diagnostic_context *context,
! 			       const diagnostic_source_printing_options &opts,
  			       rich_location *richloc,
! 			       diagnostic_t diagnostic_kind,
  			       xml::printer &xp,
! 			       diagnostic_source_effect_info *effect_info = nullptr,
! 			       html_label_writer *label_writer = nullptr)
  {
    gcc_assert (context);
    gcc_assert (richloc);
--- 103,115 ----
  }
  
  inline void
! diagnostic_show_locus_as_html (diagnostics::context *context,
! 			       const diagnostics::source_printing_options &opts,
  			       rich_location *richloc,
! 			       enum diagnostics::kind diagnostic_kind,
  			       xml::printer &xp,
! 			       diagnostics::source_effect_info *effect_info = nullptr,
! 			       diagnostics::html_label_writer *label_writer = nullptr)
  {
    gcc_assert (context);
    gcc_assert (richloc);
*************** diagnostic_show_locus_as_html (diagnosti
*** 1248,1254 ****
     rather skipped as part of the conversion process.)  */
  
  inline void
! diagnostic_initialize_input_context (diagnostic_context *context,
  				     diagnostic_input_charset_callback ccb,
  				     bool should_skip_bom)
  {
--- 133,139 ----
     rather skipped as part of the conversion process.)  */
  
  inline void
! diagnostic_initialize_input_context (diagnostics::context *context,
  				     diagnostic_input_charset_callback ccb,
  				     bool should_skip_bom)
  {
*************** diagnostic_initialize_input_context (dia
*** 1256,1278 ****
  }
  
  /* Force diagnostics controlled by OPTIDX to be kind KIND.  */
! inline diagnostic_t
! diagnostic_classify_diagnostic (diagnostic_context *context,
! 				diagnostic_option_id option_id,
! 				diagnostic_t kind,
  				location_t where)
  {
!   return context->classify_diagnostic (option_id, kind, where);
  }
  
  inline void
! diagnostic_push_diagnostics (diagnostic_context *context,
  			     location_t where)
  {
    context->push_diagnostics (where);
  }
  inline void
! diagnostic_pop_diagnostics (diagnostic_context *context,
  			    location_t where)
  {
    context->pop_diagnostics (where);
--- 141,163 ----
  }
  
  /* Force diagnostics controlled by OPTIDX to be kind KIND.  */
! inline diagnostics::kind
! diagnostic_classify_diagnostic (diagnostics::context *context,
! 				diagnostics::option_id opt_id,
! 				enum diagnostics::kind kind,
  				location_t where)
  {
!   return context->classify_diagnostic (opt_id, kind, where);
  }
  
  inline void
! diagnostic_push_diagnostics (diagnostics::context *context,
  			     location_t where)
  {
    context->push_diagnostics (where);
  }
  inline void
! diagnostic_pop_diagnostics (diagnostics::context *context,
  			    location_t where)
  {
    context->pop_diagnostics (where);
*************** diagnostic_pop_diagnostics (diagnostic_c
*** 1286,1293 ****
     Return true if a diagnostic was printed, false otherwise.  */
  
  inline bool
! diagnostic_report_diagnostic (diagnostic_context *context,
! 			      diagnostic_info *diagnostic)
  {
    context->begin_group ();
    bool warned = context->report_diagnostic (diagnostic);
--- 171,178 ----
     Return true if a diagnostic was printed, false otherwise.  */
  
  inline bool
! diagnostic_report_diagnostic (diagnostics::context *context,
! 			      diagnostics::diagnostic_info *diagnostic)
  {
    context->begin_group ();
    bool warned = context->report_diagnostic (diagnostic);
*************** diagnostic_report_diagnostic (diagnostic
*** 1296,1318 ****
  }
  
  #ifdef ATTRIBUTE_GCC_DIAG
! extern void diagnostic_set_info (diagnostic_info *, const char *, va_list *,
! 				 rich_location *, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
! extern void diagnostic_set_info_translated (diagnostic_info *, const char *,
! 					    va_list *, rich_location *,
! 					    diagnostic_t)
       ATTRIBUTE_GCC_DIAG(2,0);
  #endif
! void default_diagnostic_text_starter (diagnostic_text_output_format &,
! 				      const diagnostic_info *);
! template <typename Sink>
! void default_diagnostic_start_span_fn (const diagnostic_location_print_policy &,
! 				       Sink &sink,
! 				       expanded_location);
! void default_diagnostic_text_finalizer (diagnostic_text_output_format &,
! 					const diagnostic_info *,
! 					diagnostic_t);
! void diagnostic_set_caret_max_width (diagnostic_context *context, int value);
  
  int get_terminal_width (void);
  
--- 181,210 ----
  }
  
  #ifdef ATTRIBUTE_GCC_DIAG
! extern void diagnostic_set_info (diagnostics::diagnostic_info *,
! 				 const char *, va_list *,
! 				 rich_location *,
! 				 enum diagnostics::kind)
!   ATTRIBUTE_GCC_DIAG(2,0);
! extern void diagnostic_set_info_translated (diagnostics::diagnostic_info *,
! 					    const char *, va_list *,
! 					    rich_location *,
! 					    enum diagnostics::kind)
       ATTRIBUTE_GCC_DIAG(2,0);
  #endif
! 
! namespace diagnostics {
! 
! void default_text_starter (diagnostics::text_sink &,
! 			   const diagnostics::diagnostic_info *);
! template <typename TextOrHtml>
! void default_start_span_fn (const diagnostics::location_print_policy &,
! 			    TextOrHtml &text_or_html,
! 			    expanded_location);
! void default_text_finalizer (diagnostics::text_sink &,
! 			     const diagnostics::diagnostic_info *,
! 			     enum diagnostics::kind);
! } // namespace diagnostics
  
  int get_terminal_width (void);
  
*************** int get_terminal_width (void);
*** 1320,1336 ****
     specifies which location. By default, expand the first one.  */
  
  inline location_t
! diagnostic_location (const diagnostic_info * diagnostic, int which = 0)
  {
!   return diagnostic->message.get_location (which);
  }
  
  /* Return the number of locations to be printed in DIAGNOSTIC.  */
  
  inline unsigned int
! diagnostic_num_locations (const diagnostic_info * diagnostic)
  {
!   return diagnostic->message.m_richloc->get_num_locations ();
  }
  
  /* Expand the location of this diagnostic. Use this function for
--- 212,229 ----
     specifies which location. By default, expand the first one.  */
  
  inline location_t
! diagnostic_location (const diagnostics::diagnostic_info *diagnostic,
! 		     int which = 0)
  {
!   return diagnostic->m_message.get_location (which);
  }
  
  /* Return the number of locations to be printed in DIAGNOSTIC.  */
  
  inline unsigned int
! diagnostic_num_locations (const diagnostics::diagnostic_info *diagnostic)
  {
!   return diagnostic->m_message.m_richloc->get_num_locations ();
  }
  
  /* Expand the location of this diagnostic. Use this function for
*************** diagnostic_num_locations (const diagnost
*** 1338,1346 ****
     expand the first one.  */
  
  inline expanded_location
! diagnostic_expand_location (const diagnostic_info * diagnostic, int which = 0)
  {
!   return diagnostic->richloc->get_expanded_location (which);
  }
  
  /* This is somehow the right-side margin of a caret line, that is, we
--- 231,240 ----
     expand the first one.  */
  
  inline expanded_location
! diagnostic_expand_location (const diagnostics::diagnostic_info *diagnostic,
! 			    int which = 0)
  {
!   return diagnostic->m_richloc->get_expanded_location (which);
  }
  
  /* This is somehow the right-side margin of a caret line, that is, we
*************** const int CARET_LINE_MARGIN = 10;
*** 1353,1391 ****
     whether to print one or two caret lines.  */
  
  inline bool
! diagnostic_same_line (const diagnostic_context *context,
! 		       expanded_location s1, expanded_location s2)
  {
    return (s2.column && s1.line == s2.line
! 	  && (context->m_source_printing.max_width - CARET_LINE_MARGIN
  	      > abs (s1.column - s2.column)));
  }
  
- extern const char *diagnostic_get_color_for_kind (diagnostic_t kind);
- 
  /* Pure text formatting support functions.  */
  
  extern char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1;
  
- /* Compute the number of digits in the decimal representation of an integer.  */
- extern int num_digits (int);
- 
  inline bool
! warning_enabled_at (location_t loc, diagnostic_option_id option_id)
  {
!   return global_dc->warning_enabled_at (loc, option_id);
  }
  
  inline bool
! option_unspecified_p (diagnostic_option_id option_id)
  {
!   return global_dc->option_unspecified_p (option_id);
  }
  
! extern char *get_cwe_url (int cwe);
  
! extern const char *get_diagnostic_kind_text (diagnostic_t kind);
  
! const char *maybe_line_and_column (int line, int col);
  
  #endif /* ! GCC_DIAGNOSTIC_H */
--- 247,285 ----
     whether to print one or two caret lines.  */
  
  inline bool
! diagnostic_same_line (const diagnostics::context *context,
! 		      expanded_location s1, expanded_location s2)
  {
    return (s2.column && s1.line == s2.line
! 	  && ((context->get_source_printing_options ().max_width
! 	       - CARET_LINE_MARGIN)
  	      > abs (s1.column - s2.column)));
  }
  
  /* Pure text formatting support functions.  */
  
  extern char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1;
  
  inline bool
! warning_enabled_at (location_t loc, diagnostics::option_id opt_id)
  {
!   return global_dc->warning_enabled_at (loc, opt_id);
  }
  
  inline bool
! option_unspecified_p (diagnostics::option_id opt_id)
  {
!   return global_dc->option_unspecified_p (opt_id);
  }
  
! namespace diagnostics {
  
! /* Compute the number of digits in the decimal representation of an integer.  */
! extern int num_digits (int);
  
! extern char *get_cwe_url (int cwe);
! extern const char *maybe_line_and_column (int line, int col);
! 
! } // namespace diagnostics
  
  #endif /* ! GCC_DIAGNOSTIC_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/buffering.cc gcc-16-20250727/gcc/diagnostics/buffering.cc
*** gcc-16-20250720/gcc/diagnostics/buffering.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/buffering.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,199 ----
+ /* Support for buffering diagnostics before flushing them to output sinks.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "diagnostic.h"
+ #include "diagnostics/buffering.h"
+ #include "diagnostics/sink.h"
+ 
+ namespace diagnostics {
+ 
+ /* Methods fns of diagnostics::context relating to buffering.  */
+ 
+ /* If BUFFER_ is non-null, use BUFFER as the active diagnostics::buffer on
+    this context.  BUFFER is borrowed.
+ 
+    If BUFFER_ is null, stop any buffering on this context until the next call
+    to this function.  */
+ 
+ void
+ context::set_diagnostic_buffer (buffer *buffer_)
+ {
+   /* We don't allow changing buffering within a diagnostic group
+      (to simplify handling of buffered diagnostics within the
+      diagnostic_format implementations).  */
+   gcc_assert (m_diagnostic_groups.m_group_nesting_depth == 0);
+ 
+   /* Likewise, for simplicity, we only allow changing buffers
+      at nesting level 0.  */
+   gcc_assert (m_diagnostic_groups.m_diagnostic_nesting_level == 0);
+ 
+   m_diagnostic_buffer = buffer_;
+ 
+   if (buffer_)
+     {
+       buffer_->ensure_per_sink_buffers ();
+       gcc_assert (buffer_->m_per_sink_buffers);
+       gcc_assert (buffer_->m_per_sink_buffers->length ()
+ 		  == m_sinks.length ());
+       for (unsigned idx = 0; idx < m_sinks.length (); ++idx)
+ 	{
+ 	  auto sink_ = m_sinks[idx];
+ 	  auto per_sink_buffer = (*buffer_->m_per_sink_buffers)[idx];
+ 	  sink_->set_buffer (per_sink_buffer);
+ 	}
+     }
+   else
+     for (auto sink_ : m_sinks)
+       sink_->set_buffer (nullptr);
+ }
+ 
+ /* Clear BUFFER_ without flushing it.  */
+ 
+ void
+ context::clear_diagnostic_buffer (buffer &buffer_)
+ {
+   if (buffer_.m_per_sink_buffers)
+     for (auto per_sink_buffer_ : *buffer_.m_per_sink_buffers)
+       per_sink_buffer_->clear ();
+ 
+   buffer_.m_diagnostic_counters.clear ();
+ 
+   /* We need to reset last_location, otherwise we may skip caret lines
+      when we actually give a diagnostic.  */
+   m_last_location = UNKNOWN_LOCATION;
+ }
+ 
+ /* Flush the diagnostics in BUFFER_ to this context, clearing BUFFER_.  */
+ 
+ void
+ context::flush_diagnostic_buffer (buffer &buffer_)
+ {
+   bool had_errors
+     = (buffer_.diagnostic_count (kind::error) > 0
+        || buffer_.diagnostic_count (kind::werror) > 0);
+   if (buffer_.m_per_sink_buffers)
+     for (auto per_sink_buffer_ : *buffer_.m_per_sink_buffers)
+       per_sink_buffer_->flush ();
+   buffer_.m_diagnostic_counters.move_to (m_diagnostic_counters);
+ 
+   action_after_output (had_errors ? kind::error : kind::warning);
+   check_max_errors (true);
+ }
+ 
+ /* class diagnostics::buffer.  */
+ 
+ buffer::buffer (context &ctxt)
+ : m_ctxt (ctxt),
+   m_per_sink_buffers (nullptr)
+ {
+ }
+ 
+ buffer::~buffer ()
+ {
+   if (m_per_sink_buffers)
+     {
+       for (auto iter : *m_per_sink_buffers)
+ 	delete iter;
+       delete m_per_sink_buffers;
+     }
+ }
+ 
+ void
+ buffer::dump (FILE *out, int indent) const
+ {
+   m_diagnostic_counters.dump (out, indent + 2);
+   fprintf (out, "%*sm_per_sink_buffers:\n", indent, "");
+   if (m_per_sink_buffers)
+     for (auto per_sink_buffer_ : *m_per_sink_buffers)
+       per_sink_buffer_->dump (out, indent + 2);
+   else
+     fprintf (out, "%*s(none)\n", indent + 2, "");
+ }
+ 
+ bool
+ buffer::empty_p () const
+ {
+   if (m_per_sink_buffers)
+     for (auto per_sink_buffer_ : *m_per_sink_buffers)
+       /* Query initial buffer.  */
+       return per_sink_buffer_->empty_p ();
+   return true;
+ }
+ 
+ void
+ buffer::move_to (buffer &dest)
+ {
+   /* Bail if there's nothing to move.  */
+   if (!m_per_sink_buffers)
+     return;
+ 
+   m_diagnostic_counters.move_to (dest.m_diagnostic_counters);
+ 
+   if (!dest.m_per_sink_buffers)
+     {
+       /* Optimization for the "move to empty" case:
+ 	 simply move the vec to the dest.  */
+       dest.m_per_sink_buffers = m_per_sink_buffers;
+       m_per_sink_buffers = nullptr;
+       return;
+     }
+ 
+   dest.ensure_per_sink_buffers ();
+   gcc_assert (m_per_sink_buffers);
+   gcc_assert (m_per_sink_buffers->length ()
+ 	      == m_ctxt.m_sinks.length ());
+   gcc_assert (dest.m_per_sink_buffers);
+   gcc_assert (dest.m_per_sink_buffers->length ()
+ 	      == m_ctxt.m_sinks.length ());
+   for (unsigned idx = 0; idx < m_ctxt.m_sinks.length (); ++idx)
+     {
+       auto per_sink_buffer_src = (*m_per_sink_buffers)[idx];
+       auto per_sink_buffer_dest = (*dest.m_per_sink_buffers)[idx];
+       per_sink_buffer_src->move_to (*per_sink_buffer_dest);
+     }
+ }
+ 
+ /* Lazily get the output formats to create their own kind of buffers.
+    We can't change the output sinks on a context once this has been called
+    on any diagnostics::buffer instances for that context, since there's no
+    way to update all diagnostics::buffer instances for that context.  */
+ 
+ void
+ buffer::ensure_per_sink_buffers ()
+ {
+   if (!m_per_sink_buffers)
+     {
+       m_per_sink_buffers = new auto_vec<per_sink_buffer *> ();
+       for (unsigned idx = 0; idx < m_ctxt.m_sinks.length (); ++idx)
+ 	{
+ 	  auto sink_ = m_ctxt.m_sinks[idx];
+ 	  auto per_sink_buffer = sink_->make_per_sink_buffer ();
+ 	  m_per_sink_buffers->safe_push (per_sink_buffer.release ());
+ 	}
+     }
+   gcc_assert (m_per_sink_buffers);
+   gcc_assert (m_per_sink_buffers->length ()
+ 	      == m_ctxt.m_sinks.length ());
+ }
+ 
+ } // namespace diagnostics
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/buffering.h gcc-16-20250727/gcc/diagnostics/buffering.h
*** gcc-16-20250720/gcc/diagnostics/buffering.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/buffering.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,113 ----
+ /* Support for buffering diagnostics before flushing them to output sinks.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_BUFFERING_H
+ #define GCC_DIAGNOSTICS_BUFFERING_H
+ 
+ #include "diagnostic.h"
+ 
+ namespace diagnostics {
+ 
+ class per_sink_buffer;
+ class sink;
+   class text_sink;
+ 
+ /* Class representing a buffer of zero or more diagnostics that
+    have been reported to a diagnostics::context, but which haven't
+    yet been flushed.
+ 
+    A diagnostics::buffer can be:
+ 
+    * flushed to the diagnostics::context, which issues
+    the diagnostics within the buffer to the output format
+    and checks for limits such as -fmax-errors=, or
+ 
+    * moved to another diagnostics::buffer, which moves the diagnostics
+    within the first buffer to the other buffer, appending them after any
+    existing diagnostics within the destination buffer, emptying the
+    source buffer, or
+ 
+    * cleared, which discards any diagnostics within the buffer
+    without issuing them to the output format.
+ 
+    Since a buffer needs to contain output-format-specific data,
+    it's not possible to change the output format of the
+    diagnostics::context once any buffers are non-empty.
+ 
+    To simplify implementing output formats, it's not possible
+    to change buffering on a diagnostics::context whilst within a
+    diagnostic group.  */
+ 
+ class buffer
+ {
+  public:
+   friend class context;
+ 
+   buffer (context &ctxt);
+   ~buffer ();
+ 
+   void dump (FILE *out, int indent) const;
+   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
+ 
+   int diagnostic_count (enum kind kind) const
+   {
+     return m_diagnostic_counters.get_count (kind);
+   }
+ 
+   bool empty_p () const;
+ 
+   void move_to (buffer &dest);
+ 
+  private:
+   void ensure_per_sink_buffers ();
+ 
+   context &m_ctxt;
+   auto_vec<per_sink_buffer *> *m_per_sink_buffers;
+ 
+   /* The number of buffered diagnostics of each kind.  */
+   counters m_diagnostic_counters;
+ };
+ 
+ /* Implementation detail of diagnostics::buffer.
+ 
+    Abstract base class describing how to represent zero of more
+    buffered diagnostics for a particular diagnostics::sink
+    (e.g. text vs SARIF).
+ 
+    Each diagnostics::sink subclass should implement its own
+    subclass for handling diagnostics::buffer.  */
+ 
+ class per_sink_buffer
+ {
+ public:
+   virtual ~per_sink_buffer () {}
+ 
+   virtual void dump (FILE *out, int indent) const = 0;
+   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
+ 
+   virtual bool empty_p () const = 0;
+   virtual void move_to (per_sink_buffer &dest) = 0;
+   virtual void clear () = 0;
+   virtual void flush () = 0;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_BUFFERING_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/changes.cc gcc-16-20250727/gcc/diagnostics/changes.cc
*** gcc-16-20250720/gcc/diagnostics/changes.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/changes.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,1868 ----
+ /* Determining the results of applying fix-it hints.
+    Copyright (C) 2016-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "line-map.h"
+ #include "diagnostics/changes.h"
+ #include "pretty-print.h"
+ #include "diagnostics/color.h"
+ #include "diagnostics/file-cache.h"
+ #include "selftest.h"
+ 
+ namespace diagnostics {
+ namespace changes {
+ 
+ /* This file implements a way to track the effect of fix-its,
+    via a class change_set; the other classes are support classes for
+    change_set.
+ 
+    A complication here is that fix-its are expressed relative to coordinates
+    in the file when it was parsed, before any changes have been made, and
+    so if there's more that one fix-it to be applied, we have to adjust
+    later fix-its to allow for the changes made by earlier ones.  This
+    is done by the various "get_effective_column" methods.
+ 
+    The "filename" params are required to outlive the change_set (no
+    copy of the underlying str is taken, just the ptr).  */
+ 
+ /* Forward decls.  class change_set is declared within changes.h.
+    The other types are declared here.  */
+ class change_set;
+ class changed_file;
+ class changed_line;
+ class line_event;
+ 
+ /* A struct to hold the params of a print_diff call.  */
+ 
+ class diff
+ {
+ public:
+   diff (pretty_printer *pp, bool show_filenames)
+   : m_pp (pp), m_show_filenames (show_filenames) {}
+ 
+   pretty_printer *m_pp;
+   bool m_show_filenames;
+ };
+ 
+ /* The state of one named file within an change_set: the filename,
+    and the lines that have been edited so far.  */
+ 
+ class changed_file
+ {
+  public:
+   changed_file (change_set &ec, const char *filename);
+   static void delete_cb (changed_file *file);
+ 
+   const char *get_filename () const { return m_filename; }
+   char *get_content ();
+ 
+   bool apply_fixit (int line, int start_column,
+ 		    int next_column,
+ 		    const char *replacement_str,
+ 		    int replacement_len);
+   int get_effective_column (int line, int column);
+ 
+   static int call_print_diff (const char *, changed_file *file,
+ 			      void *user_data)
+   {
+     diff *d = (diff *)user_data;
+     file->print_diff (d->m_pp, d->m_show_filenames);
+     return 0;
+   }
+ 
+   file_cache &get_file_cache () const
+   {
+     return m_change_set.get_file_cache ();
+   }
+ 
+  private:
+   bool print_content (pretty_printer *pp);
+   void print_diff (pretty_printer *pp, bool show_filenames);
+   int print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
+ 		       int old_end_of_hunk, int new_start_of_hunk);
+   changed_line *get_line (int line);
+   changed_line *get_or_insert_line (int line);
+   int get_num_lines (bool *missing_trailing_newline);
+ 
+   int get_effective_line_count (int old_start_of_hunk,
+ 				int old_end_of_hunk);
+ 
+   void print_run_of_changed_lines (pretty_printer *pp,
+ 				   int start_of_run,
+ 				   int end_of_run);
+ 
+   change_set &m_change_set;
+   const char *m_filename;
+   typed_splay_tree<int, changed_line *> m_changed_lines;
+   int m_num_lines;
+ };
+ 
+ /* A line added before an changed_line.  */
+ 
+ class added_line
+ {
+  public:
+   added_line (const char *content, int len)
+   : m_content (xstrndup (content, len)), m_len (len) {}
+   ~added_line () { free (m_content); }
+ 
+   const char *get_content () const { return m_content; }
+   int get_len () const { return m_len; }
+ 
+  private:
+   char *m_content;
+   int m_len;
+ };
+ 
+ /* Class for representing edit events that have occurred on one line of
+    one file: the replacement of some text between some columns
+    on the line.
+ 
+    Subsequent events will need their columns adjusting if they're
+    are on this line and their column is >= the start point.  */
+ 
+ class line_event
+ {
+  public:
+   line_event (int start, int next, int len) : m_start (start),
+     m_delta (len - (next - start)) {}
+ 
+   int get_effective_column (int orig_column) const
+   {
+     if (orig_column >= m_start)
+       return orig_column += m_delta;
+     else
+       return orig_column;
+   }
+ 
+  private:
+   int m_start;
+   int m_delta;
+ };
+ 
+ /* The state of one edited line within an changed_file.
+    As well as the current content of the line, it contains a record of
+    the changes, so that further changes can be applied in the correct
+    place.
+ 
+    When handling fix-it hints containing newlines, new lines are added
+    as added_line predecessors to an changed_line.  Hence it's possible
+    for an "changed_line" to not actually have been changed, but to merely
+    be a placeholder for the lines added before it.  This can be tested
+    for with actuall_edited_p, and has a slight effect on how diff hunks
+    are generated.  */
+ 
+ class changed_line
+ {
+  public:
+   changed_line (file_cache &fc, const char *filename, int line_num);
+   ~changed_line ();
+   static void delete_cb (changed_line *el);
+ 
+   int get_line_num () const { return m_line_num; }
+   const char *get_content () const { return m_content; }
+   int get_len () const { return m_len; }
+ 
+   int get_effective_column (int orig_column) const;
+   bool apply_fixit (int start_column,
+ 		    int next_column,
+ 		    const char *replacement_str,
+ 		    int replacement_len);
+ 
+   int get_effective_line_count () const;
+ 
+   /* Has the content of this line actually changed, or are we merely
+      recording predecessor added_lines?  */
+   bool actually_edited_p () const { return m_line_events.length () > 0; }
+ 
+   void print_content (pretty_printer *pp) const;
+   void print_diff_lines (pretty_printer *pp) const;
+ 
+  private:
+   void ensure_capacity (int len);
+   void ensure_terminated ();
+ 
+   int m_line_num;
+   char *m_content;
+   int m_len;
+   int m_alloc_sz;
+   auto_vec <line_event> m_line_events;
+   auto_vec <added_line *> m_predecessors;
+ };
+ 
+ /* Forward decls.  */
+ 
+ static void
+ print_diff_line (pretty_printer *pp, char prefix_char,
+ 		 const char *line, int line_size);
+ 
+ /* Implementation of class change_set.  */
+ 
+ /* change_set's ctor.  */
+ 
+ change_set::change_set (file_cache &fc)
+ : m_file_cache (fc),
+   m_valid (true),
+   m_files (strcmp, NULL, changed_file::delete_cb)
+ {}
+ 
+ /* Add any fixits within RICHLOC to this context, recording the
+    changes that they make.  */
+ 
+ void
+ change_set::add_fixits (rich_location *richloc)
+ {
+   if (!m_valid)
+     return;
+   if (richloc->seen_impossible_fixit_p ())
+     {
+       m_valid = false;
+       return;
+     }
+   for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
+     {
+       const fixit_hint *hint = richloc->get_fixit_hint (i);
+       if (!apply_fixit (hint))
+ 	m_valid = false;
+     }
+ }
+ 
+ /* Get the content of the given file, with fix-its applied.
+    If any errors occurred in this change_set, return NULL.
+    The ptr should be freed by the caller.  */
+ 
+ char *
+ change_set::get_content (const char *filename)
+ {
+   if (!m_valid)
+     return NULL;
+   changed_file &file = get_or_insert_file (filename);
+   return file.get_content ();
+ }
+ 
+ /* Map a location before the edits to a column number after the edits.
+    This method is for the selftests.  */
+ 
+ int
+ change_set::get_effective_column (const char *filename, int line,
+ 				    int column)
+ {
+   changed_file *file = get_file (filename);
+   if (!file)
+     return column;
+   return file->get_effective_column (line, column);
+ }
+ 
+ /* Generate a unified diff.  The resulting string should be freed by the
+    caller.  Primarily for selftests.
+    If any errors occurred in this change_set, return NULL.  */
+ 
+ char *
+ change_set::generate_diff (bool show_filenames)
+ {
+   if (!m_valid)
+     return NULL;
+ 
+   pretty_printer pp;
+   print_diff (&pp, show_filenames);
+   return xstrdup (pp_formatted_text (&pp));
+ }
+ 
+ /* Print a unified diff to PP, showing the changes made within the
+    context.  */
+ 
+ void
+ change_set::print_diff (pretty_printer *pp, bool show_filenames)
+ {
+   if (!m_valid)
+     return;
+   diff d (pp, show_filenames);
+   m_files.foreach (changed_file::call_print_diff, &d);
+ }
+ 
+ /* Attempt to apply the given fixit.  Return true if it can be
+    applied, or false otherwise.  */
+ 
+ bool
+ change_set::apply_fixit (const fixit_hint *hint)
+ {
+   expanded_location start = expand_location (hint->get_start_loc ());
+   expanded_location next_loc = expand_location (hint->get_next_loc ());
+   if (start.file != next_loc.file)
+     return false;
+   if (start.line != next_loc.line)
+     return false;
+   if (start.column == 0)
+     return false;
+   if (next_loc.column == 0)
+     return false;
+ 
+   changed_file &file = get_or_insert_file (start.file);
+   if (!m_valid)
+     return false;
+   return file.apply_fixit (start.line, start.column, next_loc.column,
+ 			   hint->get_string (),
+ 			   hint->get_length ());
+ }
+ 
+ /* Locate the changed_file * for FILENAME, if any
+    Return NULL if there isn't one.  */
+ 
+ changed_file *
+ change_set::get_file (const char *filename)
+ {
+   gcc_assert (filename);
+   return m_files.lookup (filename);
+ }
+ 
+ /* Locate the changed_file for FILENAME, adding one if there isn't one.  */
+ 
+ changed_file &
+ change_set::get_or_insert_file (const char *filename)
+ {
+   gcc_assert (filename);
+ 
+   changed_file *file = get_file (filename);
+   if (file)
+     return *file;
+ 
+   /* Not found.  */
+   file = new changed_file (*this, filename);
+   m_files.insert (filename, file);
+   return *file;
+ }
+ 
+ /* Implementation of class changed_file.  */
+ 
+ /* Callback for m_changed_lines, for comparing line numbers.  */
+ 
+ static int line_comparator (int a, int b)
+ {
+   return a - b;
+ }
+ 
+ /* changed_file's constructor.  */
+ 
+ changed_file::changed_file (change_set &ec, const char *filename)
+ : m_change_set (ec),
+   m_filename (filename),
+   m_changed_lines (line_comparator, NULL, changed_line::delete_cb),
+   m_num_lines (-1)
+ {
+ }
+ 
+ /* A callback for deleting changed_file *, for use as a
+    delete_value_fn for change_set::m_files.  */
+ 
+ void
+ changed_file::delete_cb (changed_file *file)
+ {
+   delete file;
+ }
+ 
+ /* Get the content of the file, with fix-its applied.
+    The ptr should be freed by the caller.  */
+ 
+ char *
+ changed_file::get_content ()
+ {
+   pretty_printer pp;
+   if (!print_content (&pp))
+     return NULL;
+   return xstrdup (pp_formatted_text (&pp));
+ }
+ 
+ /* Attempt to replace columns START_COLUMN up to but not including NEXT_COLUMN
+    of LINE with the string REPLACEMENT_STR of length REPLACEMENT_LEN,
+    updating the in-memory copy of the line, and the record of edits to
+    the line.  */
+ 
+ bool
+ changed_file::apply_fixit (int line, int start_column, int next_column,
+ 			  const char *replacement_str,
+ 			  int replacement_len)
+ {
+   changed_line *el = get_or_insert_line (line);
+   if (!el)
+     return false;
+   return el->apply_fixit (start_column, next_column, replacement_str,
+ 			  replacement_len);
+ }
+ 
+ /* Given line LINE, map from COLUMN in the input file to its current
+    column after edits have been applied.  */
+ 
+ int
+ changed_file::get_effective_column (int line, int column)
+ {
+   const changed_line *el = get_line (line);
+   if (!el)
+     return column;
+   return el->get_effective_column (column);
+ }
+ 
+ /* Attempt to print the content of the file to PP, with edits applied.
+    Return true if successful, false otherwise.  */
+ 
+ bool
+ changed_file::print_content (pretty_printer *pp)
+ {
+   bool missing_trailing_newline;
+   int line_count = get_num_lines (&missing_trailing_newline);
+   for (int line_num = 1; line_num <= line_count; line_num++)
+     {
+       changed_line *el = get_line (line_num);
+       if (el)
+ 	el->print_content (pp);
+       else
+ 	{
+ 	  char_span line
+ 	    = get_file_cache ().get_source_line (m_filename, line_num);
+ 	  if (!line)
+ 	    return false;
+ 	  for (size_t i = 0; i < line.length (); i++)
+ 	    pp_character (pp, line[i]);
+ 	}
+       if (line_num < line_count)
+ 	pp_character (pp, '\n');
+     }
+ 
+   if (!missing_trailing_newline)
+     pp_character (pp, '\n');
+ 
+   return true;
+ }
+ 
+ /* Print a unified diff to PP, showing any changes that have occurred
+    to this file.  */
+ 
+ void
+ changed_file::print_diff (pretty_printer *pp, bool show_filenames)
+ {
+   if (show_filenames)
+     {
+       pp_string (pp, colorize_start (pp_show_color (pp), "diff-filename"));
+       /* Avoid -Wformat-diag in non-diagnostic output.  */
+       pp_string (pp, "--- ");
+       pp_string (pp, m_filename);
+       pp_newline (pp);
+       pp_string (pp, "+++ ");
+       pp_string (pp, m_filename);
+       pp_newline (pp);
+       pp_string (pp, colorize_stop (pp_show_color (pp)));
+     }
+ 
+   changed_line *el = m_changed_lines.min ();
+ 
+   bool missing_trailing_newline;
+   int line_count = get_num_lines (&missing_trailing_newline);
+ 
+   const int context_lines = 3;
+ 
+   /* Track new line numbers minus old line numbers.  */
+ 
+   int line_delta = 0;
+ 
+   while (el)
+     {
+       int start_of_hunk = el->get_line_num ();
+       start_of_hunk -= context_lines;
+       if (start_of_hunk < 1)
+ 	start_of_hunk = 1;
+ 
+       /* Locate end of hunk, merging in changed lines
+ 	 that are sufficiently close.  */
+       while (true)
+ 	{
+ 	  changed_line *next_el
+ 	    = m_changed_lines.successor (el->get_line_num ());
+ 	  if (!next_el)
+ 	    break;
+ 
+ 	  int end_of_printed_hunk = el->get_line_num () + context_lines;
+ 	  if (!el->actually_edited_p ())
+ 	    end_of_printed_hunk--;
+ 
+ 	  if (end_of_printed_hunk
+ 	      >= next_el->get_line_num () - context_lines)
+ 	    el = next_el;
+ 	  else
+ 	    break;
+ 	}
+ 
+       int end_of_hunk = el->get_line_num ();
+       end_of_hunk += context_lines;
+       if (!el->actually_edited_p ())
+ 	end_of_hunk--;
+       if (end_of_hunk > line_count)
+ 	end_of_hunk = line_count;
+ 
+       int new_start_of_hunk = start_of_hunk + line_delta;
+       line_delta += print_diff_hunk (pp, start_of_hunk, end_of_hunk,
+ 				     new_start_of_hunk);
+       el = m_changed_lines.successor (el->get_line_num ());
+     }
+ }
+ 
+ /* Print one hunk within a unified diff to PP, covering the
+    given range of lines.  OLD_START_OF_HUNK and OLD_END_OF_HUNK are
+    line numbers in the unedited version of the file.
+    NEW_START_OF_HUNK is a line number in the edited version of the file.
+    Return the change in the line count within the hunk.  */
+ 
+ int
+ changed_file::print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
+ 			      int old_end_of_hunk, int new_start_of_hunk)
+ {
+   int old_num_lines = old_end_of_hunk - old_start_of_hunk + 1;
+   int new_num_lines
+     = get_effective_line_count (old_start_of_hunk, old_end_of_hunk);
+ 
+   pp_string (pp, colorize_start (pp_show_color (pp), "diff-hunk"));
+   pp_printf (pp, "%s -%i,%i +%i,%i %s",
+ 	     "@@", old_start_of_hunk, old_num_lines,
+ 	     new_start_of_hunk, new_num_lines, "@@\n");
+   pp_string (pp, colorize_stop (pp_show_color (pp)));
+ 
+   int line_num = old_start_of_hunk;
+   while (line_num <= old_end_of_hunk)
+     {
+       changed_line *el = get_line (line_num);
+       if (el)
+ 	{
+ 	  /* We have an edited line.
+ 	     Consolidate into runs of changed lines.  */
+ 	  const int first_changed_line_in_run = line_num;
+ 	  while (get_line (line_num))
+ 	    line_num++;
+ 	  const int last_changed_line_in_run = line_num - 1;
+ 	  print_run_of_changed_lines (pp, first_changed_line_in_run,
+ 				      last_changed_line_in_run);
+ 	}
+       else
+ 	{
+ 	  /* Unchanged line.  */
+ 	  char_span old_line
+ 	    = get_file_cache ().get_source_line (m_filename, line_num);
+ 	  print_diff_line (pp, ' ', old_line.get_buffer (), old_line.length ());
+ 	  line_num++;
+ 	}
+     }
+ 
+   return new_num_lines - old_num_lines;
+ }
+ 
+ /* Subroutine of changed_file::print_diff_hunk: given a run of lines
+    from START_OF_RUN to END_OF_RUN that all have changed_line instances,
+    print the diff to PP.  */
+ 
+ void
+ changed_file::print_run_of_changed_lines (pretty_printer *pp,
+ 					 int start_of_run,
+ 					 int end_of_run)
+ {
+   /* Show old version of lines.  */
+   pp_string (pp, colorize_start (pp_show_color (pp),
+ 				 "diff-delete"));
+   for (int line_num = start_of_run;
+        line_num <= end_of_run;
+        line_num++)
+     {
+       changed_line *el_in_run = get_line (line_num);
+       gcc_assert (el_in_run);
+       if (el_in_run->actually_edited_p ())
+ 	{
+ 	  char_span old_line
+ 	    = get_file_cache ().get_source_line (m_filename, line_num);
+ 	  print_diff_line (pp, '-', old_line.get_buffer (),
+ 			   old_line.length ());
+ 	}
+     }
+   pp_string (pp, colorize_stop (pp_show_color (pp)));
+ 
+   /* Show new version of lines.  */
+   pp_string (pp, colorize_start (pp_show_color (pp),
+ 				 "diff-insert"));
+   for (int line_num = start_of_run;
+        line_num <= end_of_run;
+        line_num++)
+     {
+       changed_line *el_in_run = get_line (line_num);
+       gcc_assert (el_in_run);
+       el_in_run->print_diff_lines (pp);
+     }
+   pp_string (pp, colorize_stop (pp_show_color (pp)));
+ }
+ 
+ /* Print one line within a diff, starting with PREFIX_CHAR,
+    followed by the LINE of content, of length LEN.  LINE is
+    not necessarily 0-terminated.  Print a trailing newline.  */
+ 
+ static void
+ print_diff_line (pretty_printer *pp, char prefix_char,
+ 		 const char *line, int len)
+ {
+   pp_character (pp, prefix_char);
+   for (int i = 0; i < len; i++)
+     pp_character (pp, line[i]);
+   pp_character (pp, '\n');
+ }
+ 
+ /* Determine the number of lines that will be present after
+    editing for the range of lines from OLD_START_OF_HUNK to
+    OLD_END_OF_HUNK inclusive.  */
+ 
+ int
+ changed_file::get_effective_line_count (int old_start_of_hunk,
+ 				       int old_end_of_hunk)
+ {
+   int line_count = 0;
+   for (int old_line_num = old_start_of_hunk; old_line_num <= old_end_of_hunk;
+        old_line_num++)
+     {
+       changed_line *el = get_line (old_line_num);
+       if (el)
+ 	line_count += el->get_effective_line_count ();
+       else
+ 	line_count++;
+     }
+   return line_count;
+ }
+ 
+ /* Get the state of LINE within the file, or NULL if it is untouched.  */
+ 
+ changed_line *
+ changed_file::get_line (int line)
+ {
+   return m_changed_lines.lookup (line);
+ }
+ 
+ /* Get the state of LINE within the file, creating a state for it
+    if necessary.  Return NULL if an error occurs.  */
+ 
+ changed_line *
+ changed_file::get_or_insert_line (int line)
+ {
+   changed_line *el = get_line (line);
+   if (el)
+     return el;
+   el = new changed_line (get_file_cache (), m_filename, line);
+   if (el->get_content () == NULL)
+     {
+       delete el;
+       return NULL;
+     }
+   m_changed_lines.insert (line, el);
+   return el;
+ }
+ 
+ /* Get the total number of lines in m_content, writing
+    true to *MISSING_TRAILING_NEWLINE if the final line
+    if missing a newline, false otherwise.  */
+ 
+ int
+ changed_file::get_num_lines (bool *missing_trailing_newline)
+ {
+   gcc_assert (missing_trailing_newline);
+   if (m_num_lines == -1)
+     {
+       m_num_lines = 0;
+       while (true)
+ 	{
+ 	  char_span line
+ 	    = get_file_cache ().get_source_line (m_filename, m_num_lines + 1);
+ 	  if (line)
+ 	    m_num_lines++;
+ 	  else
+ 	    break;
+ 	}
+     }
+   *missing_trailing_newline
+     = get_file_cache ().missing_trailing_newline_p (m_filename);
+   return m_num_lines;
+ }
+ 
+ /* Implementation of class changed_line.  */
+ 
+ /* changed_line's ctor.  */
+ 
+ changed_line::changed_line (file_cache &fc, const char *filename, int line_num)
+ : m_line_num (line_num),
+   m_content (NULL), m_len (0), m_alloc_sz (0),
+   m_line_events (),
+   m_predecessors ()
+ {
+   char_span line = fc.get_source_line (filename, line_num);
+   if (!line)
+     return;
+   m_len = line.length ();
+   ensure_capacity (m_len);
+   memcpy (m_content, line.get_buffer (), m_len);
+   ensure_terminated ();
+ }
+ 
+ /* changed_line's dtor.  */
+ 
+ changed_line::~changed_line ()
+ {
+   unsigned i;
+   added_line *pred;
+ 
+   free (m_content);
+   FOR_EACH_VEC_ELT (m_predecessors, i, pred)
+     delete pred;
+ }
+ 
+ /* A callback for deleting changed_line *, for use as a
+    delete_value_fn for changed_file::m_changed_lines.  */
+ 
+ void
+ changed_line::delete_cb (changed_line *el)
+ {
+   delete el;
+ }
+ 
+ /* Map a location before the edits to a column number after the edits,
+    within a specific line.  */
+ 
+ int
+ changed_line::get_effective_column (int orig_column) const
+ {
+   int i;
+   line_event *event;
+   FOR_EACH_VEC_ELT (m_line_events, i, event)
+     orig_column = event->get_effective_column (orig_column);
+   return orig_column;
+ }
+ 
+ /* Attempt to replace columns START_COLUMN up to but not including
+    NEXT_COLUMN of the line with the string REPLACEMENT_STR of
+    length REPLACEMENT_LEN, updating the in-memory copy of the line,
+    and the record of edits to the line.
+    Return true if successful; false if an error occurred.  */
+ 
+ bool
+ changed_line::apply_fixit (int start_column,
+ 			  int next_column,
+ 			  const char *replacement_str,
+ 			  int replacement_len)
+ {
+   /* Handle newlines.  They will only ever be at the end of the
+      replacement text, thanks to the filtering in rich_location.  */
+   if (replacement_len > 1)
+     if (replacement_str[replacement_len - 1] == '\n')
+       {
+ 	/* Stash in m_predecessors, stripping off newline.  */
+ 	m_predecessors.safe_push (new added_line (replacement_str,
+ 						  replacement_len - 1));
+ 	return true;
+       }
+ 
+   start_column = get_effective_column (start_column);
+   next_column = get_effective_column (next_column);
+ 
+   int start_offset = start_column - 1;
+   int next_offset = next_column - 1;
+ 
+   gcc_assert (start_offset >= 0);
+   gcc_assert (next_offset >= 0);
+ 
+   if (start_column > next_column)
+     return false;
+   if (start_offset >= (m_len + 1))
+     return false;
+   if (next_offset >= (m_len + 1))
+     return false;
+ 
+   size_t victim_len = next_offset - start_offset;
+ 
+   /* Ensure buffer is big enough.  */
+   size_t new_len = m_len + replacement_len - victim_len;
+   ensure_capacity (new_len);
+ 
+   char *suffix = m_content + next_offset;
+   gcc_assert (suffix <= m_content + m_len);
+   size_t len_suffix = (m_content + m_len) - suffix;
+ 
+   /* Move successor content into position.  They overlap, so use memmove.  */
+   memmove (m_content + start_offset + replacement_len,
+ 	   suffix, len_suffix);
+ 
+   /* Replace target content.  They don't overlap, so use memcpy.  */
+   memcpy (m_content + start_offset,
+ 	  replacement_str,
+ 	  replacement_len);
+ 
+   m_len = new_len;
+ 
+   ensure_terminated ();
+ 
+   /* Record the replacement, so that future changes to the line can have
+      their column information adjusted accordingly.  */
+   m_line_events.safe_push (line_event (start_column, next_column,
+ 				       replacement_len));
+   return true;
+ }
+ 
+ /* Determine the number of lines that will be present after
+    editing for this line.  Typically this is just 1, but
+    if newlines have been added before this line, they will
+    also be counted.  */
+ 
+ int
+ changed_line::get_effective_line_count () const
+ {
+   return m_predecessors.length () + 1;
+ }
+ 
+ /* Subroutine of changed_file::print_content.
+    Print this line and any new lines added before it, to PP.  */
+ 
+ void
+ changed_line::print_content (pretty_printer *pp) const
+ {
+   unsigned i;
+   added_line *pred;
+   FOR_EACH_VEC_ELT (m_predecessors, i, pred)
+     {
+       pp_string (pp, pred->get_content ());
+       pp_newline (pp);
+     }
+   pp_string (pp, m_content);
+ }
+ 
+ /* Subroutine of changed_file::print_run_of_changed_lines for
+    printing diff hunks to PP.
+    Print the '+' line for this line, and any newlines added
+    before it.
+    Note that if this changed_line was actually edited, the '-'
+    line has already been printed.  If it wasn't, then we merely
+    have a placeholder changed_line for adding newlines to, and
+    we need to print a ' ' line for the changed_line as we haven't
+    printed it yet.  */
+ 
+ void
+ changed_line::print_diff_lines (pretty_printer *pp) const
+ {
+   unsigned i;
+   added_line *pred;
+   FOR_EACH_VEC_ELT (m_predecessors, i, pred)
+     print_diff_line (pp, '+', pred->get_content (),
+ 		     pred->get_len ());
+   if (actually_edited_p ())
+     print_diff_line (pp, '+', m_content, m_len);
+   else
+     print_diff_line (pp, ' ', m_content, m_len);
+ }
+ 
+ /* Ensure that the buffer for m_content is at least large enough to hold
+    a string of length LEN and its 0-terminator, doubling on repeated
+    allocations.  */
+ 
+ void
+ changed_line::ensure_capacity (int len)
+ {
+   /* Allow 1 extra byte for 0-termination.  */
+   if (m_alloc_sz < (len + 1))
+     {
+       size_t new_alloc_sz = (len + 1) * 2;
+       m_content = (char *)xrealloc (m_content, new_alloc_sz);
+       m_alloc_sz = new_alloc_sz;
+     }
+ }
+ 
+ /* Ensure that m_content is 0-terminated.  */
+ 
+ void
+ changed_line::ensure_terminated ()
+ {
+   /* 0-terminate the buffer.  */
+   gcc_assert (m_len < m_alloc_sz);
+   m_content[m_len] = '\0';
+ }
+ 
+ #if CHECKING_P
+ 
+ /* Selftests of code-editing.  */
+ 
+ namespace selftest {
+ 
+ using line_table_case = ::selftest::line_table_case;
+ using line_table_test = ::selftest::line_table_test;
+ using temp_source_file = ::selftest::temp_source_file;
+ using named_temp_file = ::selftest::named_temp_file;
+ 
+ /* A wrapper class for ensuring that the underlying pointer is freed.  */
+ 
+ template <typename POINTER_T>
+ class auto_free
+ {
+  public:
+   auto_free (POINTER_T p) : m_ptr (p) {}
+   ~auto_free () { free (m_ptr); }
+ 
+   operator POINTER_T () { return m_ptr; }
+ 
+  private:
+   POINTER_T m_ptr;
+ };
+ 
+ /* Verify that change_set::get_content works for unedited files.  */
+ 
+ static void
+ test_get_content ()
+ {
+   /* Test of empty file.  */
+   {
+     const char *content = ("");
+     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+     file_cache fc;
+     change_set edit (fc);
+     auto_free <char *> result = edit.get_content (tmp.get_filename ());
+     ASSERT_STREQ ("", result);
+   }
+ 
+   /* Test of simple content.  */
+   {
+     const char *content = ("/* before */\n"
+ 			   "foo = bar.field;\n"
+ 			   "/* after */\n");
+     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+     file_cache fc;
+     change_set edit (fc);
+     auto_free <char *> result = edit.get_content (tmp.get_filename ());
+     ASSERT_STREQ ("/* before */\n"
+ 		  "foo = bar.field;\n"
+ 		  "/* after */\n", result);
+   }
+ 
+   /* Test of omitting the trailing newline on the final line.  */
+   {
+     const char *content = ("/* before */\n"
+ 			   "foo = bar.field;\n"
+ 			   "/* after */");
+     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+     file_cache fc;
+     change_set edit (fc);
+     auto_free <char *> result = edit.get_content (tmp.get_filename ());
+     /* We should respect the omitted trailing newline.  */
+     ASSERT_STREQ ("/* before */\n"
+ 		  "foo = bar.field;\n"
+ 		  "/* after */", result);
+   }
+ }
+ 
+ /* Test applying an "insert" fixit, using insert_before.  */
+ 
+ static void
+ test_applying_fixits_insert_before (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................0000000001111111.
+      .........................1234567890123456.  */
+   const char *old_content = ("/* before */\n"
+ 			     "foo = bar.field;\n"
+ 			     "/* after */\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
+ 
+   /* Add a comment in front of "bar.field".  */
+   location_t start = linemap_position_for_column (line_table, 7);
+   rich_location richloc (line_table, start);
+   richloc.add_fixit_insert_before ("/* inserted */");
+ 
+   if (start > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&richloc);
+   auto_free <char *> new_content = edit.get_content (filename);
+   if (start <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+     ASSERT_STREQ ("/* before */\n"
+ 		  "foo = /* inserted */bar.field;\n"
+ 		  "/* after */\n", new_content);
+ 
+   /* Verify that locations on other lines aren't affected by the change.  */
+   ASSERT_EQ (100, edit.get_effective_column (filename, 1, 100));
+   ASSERT_EQ (100, edit.get_effective_column (filename, 3, 100));
+ 
+   /* Verify locations on the line before the change.  */
+   ASSERT_EQ (1, edit.get_effective_column (filename, 2, 1));
+   ASSERT_EQ (6, edit.get_effective_column (filename, 2, 6));
+ 
+   /* Verify locations on the line at and after the change.  */
+   ASSERT_EQ (21, edit.get_effective_column (filename, 2, 7));
+   ASSERT_EQ (22, edit.get_effective_column (filename, 2, 8));
+ 
+   /* Verify diff.  */
+   auto_free <char *> diff = edit.generate_diff (false);
+   ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ 		" /* before */\n"
+ 		"-foo = bar.field;\n"
+ 		"+foo = /* inserted */bar.field;\n"
+ 		" /* after */\n", diff);
+ }
+ 
+ /* Test applying an "insert" fixit, using insert_after, with
+    a range of length > 1 (to ensure that the end-point of
+    the input range is used).  */
+ 
+ static void
+ test_applying_fixits_insert_after (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................0000000001111111.
+      .........................1234567890123456.  */
+   const char *old_content = ("/* before */\n"
+ 			     "foo = bar.field;\n"
+ 			     "/* after */\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
+ 
+   /* Add a comment after "field".  */
+   location_t start = linemap_position_for_column (line_table, 11);
+   location_t finish = linemap_position_for_column (line_table, 15);
+   location_t field = make_location (start, start, finish);
+   rich_location richloc (line_table, field);
+   richloc.add_fixit_insert_after ("/* inserted */");
+ 
+   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Verify that the text was inserted after the end of "field". */
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&richloc);
+   auto_free <char *> new_content = edit.get_content (filename);
+   ASSERT_STREQ ("/* before */\n"
+ 		"foo = bar.field/* inserted */;\n"
+ 		"/* after */\n", new_content);
+ 
+   /* Verify diff.  */
+   auto_free <char *> diff = edit.generate_diff (false);
+   ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ 		" /* before */\n"
+ 		"-foo = bar.field;\n"
+ 		"+foo = bar.field/* inserted */;\n"
+ 		" /* after */\n", diff);
+ }
+ 
+ /* Test applying an "insert" fixit, using insert_after at the end of
+    a line (contrast with test_applying_fixits_insert_after_failure
+    below).  */
+ 
+ static void
+ test_applying_fixits_insert_after_at_line_end (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................0000000001111111.
+      .........................1234567890123456.  */
+   const char *old_content = ("/* before */\n"
+ 			     "foo = bar.field;\n"
+ 			     "/* after */\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
+ 
+   /* Add a comment after the semicolon.  */
+   location_t loc = linemap_position_for_column (line_table, 16);
+   rich_location richloc (line_table, loc);
+   richloc.add_fixit_insert_after ("/* inserted */");
+ 
+   if (loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&richloc);
+   auto_free <char *> new_content = edit.get_content (filename);
+   ASSERT_STREQ ("/* before */\n"
+ 		"foo = bar.field;/* inserted */\n"
+ 		"/* after */\n", new_content);
+ 
+   /* Verify diff.  */
+   auto_free <char *> diff = edit.generate_diff (false);
+   ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ 		" /* before */\n"
+ 		"-foo = bar.field;\n"
+ 		"+foo = bar.field;/* inserted */\n"
+ 		" /* after */\n", diff);
+ }
+ 
+ /* Test of a failed attempt to apply an "insert" fixit, using insert_after,
+    due to the relevant linemap ending.  Contrast with
+    test_applying_fixits_insert_after_at_line_end above.  */
+ 
+ static void
+ test_applying_fixits_insert_after_failure (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................0000000001111111.
+      .........................1234567890123456.  */
+   const char *old_content = ("/* before */\n"
+ 			     "foo = bar.field;\n"
+ 			     "/* after */\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
+ 
+   /* Add a comment after the semicolon.  */
+   location_t loc = linemap_position_for_column (line_table, 16);
+   rich_location richloc (line_table, loc);
+ 
+   /* We want a failure of linemap_position_for_loc_and_offset.
+      We can do this by starting a new linemap at line 3, so that
+      there is no appropriate location value for the insertion point
+      within the linemap for line 2.  */
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
+ 
+   /* The failure fails to happen at the transition point from
+      packed ranges to unpacked ranges (where there are some "spare"
+      location_t values).  Skip the test there.  */
+   if (loc >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
+     return;
+ 
+   /* Offsetting "loc" should now fail (by returning the input loc. */
+   ASSERT_EQ (loc, linemap_position_for_loc_and_offset (line_table, loc, 1));
+ 
+   /* Hence attempting to use add_fixit_insert_after at the end of the line
+      should now fail.  */
+   richloc.add_fixit_insert_after ("/* inserted */");
+   ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+ 
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&richloc);
+   ASSERT_FALSE (edit.valid_p ());
+   ASSERT_EQ (NULL, edit.get_content (filename));
+   ASSERT_EQ (NULL, edit.generate_diff (false));
+ }
+ 
+ /* Test applying an "insert" fixit that adds a newline.  */
+ 
+ static void
+ test_applying_fixits_insert_containing_newline (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................0000000001111111.
+      .........................1234567890123456.  */
+   const char *old_content = ("    case 'a':\n" /* line 1. */
+ 			     "      x = a;\n"  /* line 2. */
+ 			     "    case 'b':\n" /* line 3. */
+ 			     "      x = b;\n");/* line 4. */
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
+ 
+   /* Add a "break;" on a line by itself before line 3 i.e. before
+      column 1 of line 3. */
+   location_t case_start = linemap_position_for_column (line_table, 5);
+   location_t case_finish = linemap_position_for_column (line_table, 13);
+   location_t case_loc = make_location (case_start, case_start, case_finish);
+   rich_location richloc (line_table, case_loc);
+   location_t line_start = linemap_position_for_column (line_table, 1);
+   richloc.add_fixit_insert_before (line_start, "      break;\n");
+ 
+   if (case_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&richloc);
+   auto_free <char *> new_content = edit.get_content (filename);
+   ASSERT_STREQ (("    case 'a':\n"
+ 		 "      x = a;\n"
+ 		 "      break;\n"
+ 		 "    case 'b':\n"
+ 		 "      x = b;\n"),
+ 		new_content);
+ 
+   /* Verify diff.  */
+   auto_free <char *> diff = edit.generate_diff (false);
+   ASSERT_STREQ (("@@ -1,4 +1,5 @@\n"
+ 		 "     case 'a':\n"
+ 		 "       x = a;\n"
+ 		 "+      break;\n"
+ 		 "     case 'b':\n"
+ 		 "       x = b;\n"),
+ 		diff);
+ }
+ 
+ /* Test applying a "replace" fixit that grows the affected line.  */
+ 
+ static void
+ test_applying_fixits_growing_replace (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................0000000001111111.
+      .........................1234567890123456.  */
+   const char *old_content = ("/* before */\n"
+ 			     "foo = bar.field;\n"
+ 			     "/* after */\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, filename, 2);
+ 
+   /* Replace "field" with "m_field".  */
+   location_t start = linemap_position_for_column (line_table, 11);
+   location_t finish = linemap_position_for_column (line_table, 15);
+   location_t field = make_location (start, start, finish);
+   rich_location richloc (line_table, field);
+   richloc.add_fixit_replace ("m_field");
+ 
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&richloc);
+   auto_free <char *> new_content = edit.get_content (filename);
+   if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+     {
+       ASSERT_STREQ ("/* before */\n"
+ 		    "foo = bar.m_field;\n"
+ 		    "/* after */\n", new_content);
+ 
+       /* Verify location of ";" after the change.  */
+       ASSERT_EQ (18, edit.get_effective_column (filename, 2, 16));
+ 
+       /* Verify diff.  */
+       auto_free <char *> diff = edit.generate_diff (false);
+       ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ 		    " /* before */\n"
+ 		    "-foo = bar.field;\n"
+ 		    "+foo = bar.m_field;\n"
+ 		    " /* after */\n", diff);
+     }
+ }
+ 
+ /* Test applying a "replace" fixit that shrinks the affected line.  */
+ 
+ static void
+ test_applying_fixits_shrinking_replace (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................000000000111111111.
+      .........................123456789012345678.  */
+   const char *old_content = ("/* before */\n"
+ 			     "foo = bar.m_field;\n"
+ 			     "/* after */\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, filename, 2);
+ 
+   /* Replace "field" with "m_field".  */
+   location_t start = linemap_position_for_column (line_table, 11);
+   location_t finish = linemap_position_for_column (line_table, 17);
+   location_t m_field = make_location (start, start, finish);
+   rich_location richloc (line_table, m_field);
+   richloc.add_fixit_replace ("field");
+ 
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&richloc);
+   auto_free <char *> new_content = edit.get_content (filename);
+   if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+     {
+       ASSERT_STREQ ("/* before */\n"
+ 		    "foo = bar.field;\n"
+ 		    "/* after */\n", new_content);
+ 
+       /* Verify location of ";" after the change.  */
+       ASSERT_EQ (16, edit.get_effective_column (filename, 2, 18));
+ 
+       /* Verify diff.  */
+       auto_free <char *> diff = edit.generate_diff (false);
+       ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ 		    " /* before */\n"
+ 		    "-foo = bar.m_field;\n"
+ 		    "+foo = bar.field;\n"
+ 		    " /* after */\n", diff);
+     }
+ }
+ 
+ /* Replacement fix-it hint containing a newline.  */
+ 
+ static void
+ test_applying_fixits_replace_containing_newline (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+     .........................0000000001111.
+     .........................1234567890123.  */
+   const char *old_content = "foo = bar ();\n";
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, filename, 1);
+ 
+   /* Replace the " = " with "\n  = ", as if we were reformatting an
+      overly long line.  */
+   location_t start = linemap_position_for_column (line_table, 4);
+   location_t finish = linemap_position_for_column (line_table, 6);
+   location_t loc = linemap_position_for_column (line_table, 13);
+   rich_location richloc (line_table, loc);
+   source_range range = source_range::from_locations (start, finish);
+   richloc.add_fixit_replace (range, "\n  = ");
+ 
+   /* Newlines are only supported within fix-it hints that
+      are at the start of lines (for entirely new lines), hence
+      this fix-it should not be displayed.  */
+   ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+ 
+   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&richloc);
+   auto_free <char *> new_content = edit.get_content (filename);
+   //ASSERT_STREQ ("foo\n  = bar ();\n", new_content);
+ }
+ 
+ /* Test applying a "remove" fixit.  */
+ 
+ static void
+ test_applying_fixits_remove (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................000000000111111111.
+      .........................123456789012345678.  */
+   const char *old_content = ("/* before */\n"
+ 			     "foo = bar.m_field;\n"
+ 			     "/* after */\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, filename, 2);
+ 
+   /* Remove ".m_field".  */
+   location_t start = linemap_position_for_column (line_table, 10);
+   location_t finish = linemap_position_for_column (line_table, 17);
+   rich_location richloc (line_table, start);
+   source_range range;
+   range.m_start = start;
+   range.m_finish = finish;
+   richloc.add_fixit_remove (range);
+ 
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&richloc);
+   auto_free <char *> new_content = edit.get_content (filename);
+   if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+     {
+       ASSERT_STREQ ("/* before */\n"
+ 		    "foo = bar;\n"
+ 		    "/* after */\n", new_content);
+ 
+       /* Verify location of ";" after the change.  */
+       ASSERT_EQ (10, edit.get_effective_column (filename, 2, 18));
+ 
+       /* Verify diff.  */
+       auto_free <char *> diff = edit.generate_diff (false);
+       ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ 		    " /* before */\n"
+ 		    "-foo = bar.m_field;\n"
+ 		    "+foo = bar;\n"
+ 		    " /* after */\n", diff);
+     }
+ }
+ 
+ /* Test applying multiple fixits to one line.  */
+ 
+ static void
+ test_applying_fixits_multiple (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................00000000011111111.
+      .........................12345678901234567.  */
+   const char *old_content = ("/* before */\n"
+ 			     "foo = bar.field;\n"
+ 			     "/* after */\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, filename, 2);
+ 
+   location_t c7 = linemap_position_for_column (line_table, 7);
+   location_t c9 = linemap_position_for_column (line_table, 9);
+   location_t c11 = linemap_position_for_column (line_table, 11);
+   location_t c15 = linemap_position_for_column (line_table, 15);
+   location_t c17 = linemap_position_for_column (line_table, 17);
+ 
+   if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Add a comment in front of "bar.field".  */
+   rich_location insert_a (line_table, c7);
+   insert_a.add_fixit_insert_before (c7, "/* alpha */");
+ 
+   /* Add a comment after "bar.field;".  */
+   rich_location insert_b (line_table, c17);
+   insert_b.add_fixit_insert_before (c17, "/* beta */");
+ 
+   /* Replace "bar" with "pub".   */
+   rich_location replace_a (line_table, c7);
+   replace_a.add_fixit_replace (source_range::from_locations (c7, c9),
+ 			       "pub");
+ 
+   /* Replace "field" with "meadow".   */
+   rich_location replace_b (line_table, c7);
+   replace_b.add_fixit_replace (source_range::from_locations (c11, c15),
+ 			       "meadow");
+ 
+   file_cache fc;
+   change_set edit (fc);
+   edit.add_fixits (&insert_a);
+   ASSERT_EQ (100, edit.get_effective_column (filename, 1, 100));
+   ASSERT_EQ (1, edit.get_effective_column (filename, 2, 1));
+   ASSERT_EQ (6, edit.get_effective_column (filename, 2, 6));
+   ASSERT_EQ (18, edit.get_effective_column (filename, 2, 7));
+   ASSERT_EQ (27, edit.get_effective_column (filename, 2, 16));
+   ASSERT_EQ (100, edit.get_effective_column (filename, 3, 100));
+ 
+   edit.add_fixits (&insert_b);
+   edit.add_fixits (&replace_a);
+   edit.add_fixits (&replace_b);
+ 
+   if (c17 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+     {
+       auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+       ASSERT_STREQ ("/* before */\n"
+ 		     "foo = /* alpha */pub.meadow;/* beta */\n"
+ 		     "/* after */\n",
+ 		    new_content);
+ 
+       /* Verify diff.  */
+       auto_free <char *> diff = edit.generate_diff (false);
+       ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ 		    " /* before */\n"
+ 		    "-foo = bar.field;\n"
+ 		    "+foo = /* alpha */pub.meadow;/* beta */\n"
+ 		    " /* after */\n", diff);
+     }
+ }
+ 
+ /* Subroutine of test_applying_fixits_multiple_lines.
+    Add the text "CHANGED: " to the front of the given line.  */
+ 
+ static location_t
+ change_line (change_set &edit, int line_num)
+ {
+   const line_map_ordinary *ord_map
+     = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+   const int column = 1;
+   location_t loc =
+     linemap_position_for_line_and_column (line_table, ord_map,
+ 					  line_num, column);
+ 
+   expanded_location exploc = expand_location (loc);
+   if (loc <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+     {
+       ASSERT_EQ (line_num, exploc.line);
+       ASSERT_EQ (column, exploc.column);
+     }
+ 
+   rich_location insert (line_table, loc);
+   insert.add_fixit_insert_before ("CHANGED: ");
+   edit.add_fixits (&insert);
+   return loc;
+ }
+ 
+ /* Subroutine of test_applying_fixits_multiple_lines.
+    Add the text "INSERTED\n" in front of the given line.  */
+ 
+ static location_t
+ insert_line (change_set &edit, int line_num)
+ {
+   const line_map_ordinary *ord_map
+     = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+   const int column = 1;
+   location_t loc =
+     linemap_position_for_line_and_column (line_table, ord_map,
+ 					  line_num, column);
+ 
+   expanded_location exploc = expand_location (loc);
+   if (loc <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+     {
+       ASSERT_EQ (line_num, exploc.line);
+       ASSERT_EQ (column, exploc.column);
+     }
+ 
+   rich_location insert (line_table, loc);
+   insert.add_fixit_insert_before ("INSERTED\n");
+   edit.add_fixits (&insert);
+   return loc;
+ }
+ 
+ /* Test of editing multiple lines within a long file,
+    to ensure that diffs are generated as expected.  */
+ 
+ static void
+ test_applying_fixits_multiple_lines (const line_table_case &case_)
+ {
+   /* Create a tempfile and write many lines of text to it.  */
+   named_temp_file tmp (".txt");
+   const char *filename = tmp.get_filename ();
+   FILE *f = fopen (filename, "w");
+   ASSERT_NE (f, NULL);
+   for (int i = 1; i <= 1000; i++)
+     fprintf (f, "line %i\n", i);
+   fclose (f);
+ 
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, filename, 1);
+   linemap_position_for_column (line_table, 127);
+ 
+   file_cache fc;
+   change_set edit (fc);
+ 
+   /* A run of consecutive lines.  */
+   change_line (edit, 2);
+   change_line (edit, 3);
+   change_line (edit, 4);
+   insert_line (edit, 5);
+ 
+   /* A run of nearby lines, within the contextual limit.  */
+   change_line (edit, 150);
+   change_line (edit, 151);
+   location_t last_loc = change_line (edit, 153);
+ 
+   if (last_loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Verify diff.  */
+   auto_free <char *> diff = edit.generate_diff (false);
+   ASSERT_STREQ ("@@ -1,7 +1,8 @@\n"
+ 		" line 1\n"
+ 		"-line 2\n"
+ 		"-line 3\n"
+ 		"-line 4\n"
+ 		"+CHANGED: line 2\n"
+ 		"+CHANGED: line 3\n"
+ 		"+CHANGED: line 4\n"
+ 		"+INSERTED\n"
+ 		" line 5\n"
+ 		" line 6\n"
+ 		" line 7\n"
+ 		"@@ -147,10 +148,10 @@\n"
+ 		" line 147\n"
+ 		" line 148\n"
+ 		" line 149\n"
+ 		"-line 150\n"
+ 		"-line 151\n"
+ 		"+CHANGED: line 150\n"
+ 		"+CHANGED: line 151\n"
+ 		" line 152\n"
+ 		"-line 153\n"
+ 		"+CHANGED: line 153\n"
+ 		" line 154\n"
+ 		" line 155\n"
+ 		" line 156\n", diff);
+ 
+   /* Ensure tmp stays alive until this point, so that the tempfile
+      persists until after the generate_diff call.  */
+   tmp.get_filename ();
+ }
+ 
+ /* Test of converting an initializer for a named field from
+    the old GCC extension to C99 syntax.
+    Exercises a shrinking replacement followed by a growing
+    replacement on the same line.  */
+ 
+ static void
+ test_applying_fixits_modernize_named_init (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................00000000011111111.
+      .........................12345678901234567.  */
+   const char *old_content = ("/* before */\n"
+ 			     "bar    : 1,\n"
+ 			     "/* after */\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, filename, 2);
+ 
+   location_t c1 = linemap_position_for_column (line_table, 1);
+   location_t c3 = linemap_position_for_column (line_table, 3);
+   location_t c8 = linemap_position_for_column (line_table, 8);
+ 
+   if (c8 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Replace "bar" with ".".  */
+   rich_location r1 (line_table, c8);
+   r1.add_fixit_replace (source_range::from_locations (c1, c3),
+ 			".");
+ 
+   /* Replace ":" with "bar =".   */
+   rich_location r2 (line_table, c8);
+   r2.add_fixit_replace (source_range::from_locations (c8, c8),
+ 			"bar =");
+ 
+   /* The order should not matter.  Do r1 then r2. */
+   {
+     file_cache fc;
+     change_set edit (fc);
+     edit.add_fixits (&r1);
+ 
+     /* Verify state after first replacement.  */
+     {
+       auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+       /* We should now have:
+ 	 ............00000000011.
+ 	 ............12345678901.  */
+       ASSERT_STREQ ("/* before */\n"
+ 		    ".    : 1,\n"
+ 		    "/* after */\n",
+ 		    new_content);
+       /* Location of the "1".  */
+       ASSERT_EQ (6, edit.get_effective_column (filename, 2, 8));
+       /* Location of the ",".  */
+       ASSERT_EQ (9, edit.get_effective_column (filename, 2, 11));
+     }
+ 
+     edit.add_fixits (&r2);
+ 
+     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+     /* Verify state after second replacement.
+        ............00000000011111111.
+        ............12345678901234567.  */
+     ASSERT_STREQ ("/* before */\n"
+ 		  ".    bar = 1,\n"
+ 		  "/* after */\n",
+ 		  new_content);
+   }
+ 
+   /* Try again, doing r2 then r1; the new_content should be the same.  */
+   {
+     file_cache fc;
+     change_set edit (fc);
+     edit.add_fixits (&r2);
+     edit.add_fixits (&r1);
+     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+     /*.............00000000011111111.
+       .............12345678901234567.  */
+     ASSERT_STREQ ("/* before */\n"
+ 		  ".    bar = 1,\n"
+ 		  "/* after */\n",
+ 		  new_content);
+   }
+ }
+ 
+ /* Test of a fixit affecting a file that can't be read.  */
+ 
+ static void
+ test_applying_fixits_unreadable_file ()
+ {
+   const char *filename = "this-does-not-exist.txt";
+   line_table_test ltt;
+   linemap_add (line_table, LC_ENTER, false, filename, 1);
+ 
+   location_t loc = linemap_position_for_column (line_table, 1);
+ 
+   rich_location insert (line_table, loc);
+   insert.add_fixit_insert_before ("change 1");
+   insert.add_fixit_insert_before ("change 2");
+ 
+   file_cache fc;
+   change_set edit (fc);
+   /* Attempting to add the fixits affecting the unreadable file
+      should transition the edit from valid to invalid.  */
+   ASSERT_TRUE (edit.valid_p ());
+   edit.add_fixits (&insert);
+   ASSERT_FALSE (edit.valid_p ());
+   ASSERT_EQ (NULL, edit.get_content (filename));
+   ASSERT_EQ (NULL, edit.generate_diff (false));
+ }
+ 
+ /* Verify that we gracefully handle an attempt to edit a line
+    that's beyond the end of the file.  */
+ 
+ static void
+ test_applying_fixits_line_out_of_range ()
+ {
+   /* Create a tempfile and write some text to it.
+      ........................00000000011111111.
+      ........................12345678901234567.  */
+   const char *old_content = "One-liner file\n";
+   temp_source_file tmp (SELFTEST_LOCATION, ".txt", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt;
+   linemap_add (line_table, LC_ENTER, false, filename, 2);
+ 
+   /* Try to insert a string in line 2.  */
+   location_t loc = linemap_position_for_column (line_table, 1);
+ 
+   rich_location insert (line_table, loc);
+   insert.add_fixit_insert_before ("change");
+ 
+   /* Verify that attempting the insertion puts an change_set
+      into an invalid state.  */
+   file_cache fc;
+   change_set edit (fc);
+   ASSERT_TRUE (edit.valid_p ());
+   edit.add_fixits (&insert);
+   ASSERT_FALSE (edit.valid_p ());
+   ASSERT_EQ (NULL, edit.get_content (filename));
+   ASSERT_EQ (NULL, edit.generate_diff (false));
+ }
+ 
+ /* Verify the boundary conditions of column values in fix-it
+    hints applied to change_set instances.  */
+ 
+ static void
+ test_applying_fixits_column_validation (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      ........................00000000011111111.
+      ........................12345678901234567.  */
+   const char *old_content = "One-liner file\n";
+   temp_source_file tmp (SELFTEST_LOCATION, ".txt", old_content);
+   const char *filename = tmp.get_filename ();
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, filename, 1);
+ 
+   location_t c11 = linemap_position_for_column (line_table, 11);
+   location_t c14 = linemap_position_for_column (line_table, 14);
+   location_t c15 = linemap_position_for_column (line_table, 15);
+   location_t c16 = linemap_position_for_column (line_table, 16);
+ 
+   /* Verify limits of valid columns in insertion fixits.  */
+ 
+   /* Verify inserting at the end of the line.  */
+   {
+     rich_location richloc (line_table, c11);
+     richloc.add_fixit_insert_before (c15, " change");
+ 
+     /* Col 15 is at the end of the line, so the insertion
+        should succeed.  */
+     file_cache fc;
+     change_set edit (fc);
+     edit.add_fixits (&richloc);
+     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+     if (c15 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+       ASSERT_STREQ ("One-liner file change\n", new_content);
+     else
+       ASSERT_EQ (NULL, new_content);
+   }
+ 
+   /* Verify inserting beyond the end of the line.  */
+   {
+     rich_location richloc (line_table, c11);
+     richloc.add_fixit_insert_before (c16, " change");
+ 
+     /* Col 16 is beyond the end of the line, so the insertion
+        should fail gracefully.  */
+     file_cache fc;
+     change_set edit (fc);
+     ASSERT_TRUE (edit.valid_p ());
+     edit.add_fixits (&richloc);
+     ASSERT_FALSE (edit.valid_p ());
+     ASSERT_EQ (NULL, edit.get_content (filename));
+     ASSERT_EQ (NULL, edit.generate_diff (false));
+   }
+ 
+   /* Verify limits of valid columns in replacement fixits.  */
+ 
+   /* Verify replacing the end of the line.  */
+   {
+     rich_location richloc (line_table, c11);
+     source_range range = source_range::from_locations (c11, c14);
+     richloc.add_fixit_replace (range, "change");
+ 
+     /* Col 14 is at the end of the line, so the replacement
+        should succeed.  */
+     file_cache fc;
+     change_set edit (fc);
+     edit.add_fixits (&richloc);
+     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+     if (c14 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+       ASSERT_STREQ ("One-liner change\n", new_content);
+     else
+       ASSERT_EQ (NULL, new_content);
+   }
+ 
+   /* Verify going beyond the end of the line.  */
+   {
+     rich_location richloc (line_table, c11);
+     source_range range = source_range::from_locations (c11, c15);
+     richloc.add_fixit_replace (range, "change");
+ 
+     /* Col 15 is after the end of the line, so the replacement
+        should fail; verify that the attempt fails gracefully.  */
+     file_cache fc;
+     change_set edit (fc);
+     ASSERT_TRUE (edit.valid_p ());
+     edit.add_fixits (&richloc);
+     ASSERT_FALSE (edit.valid_p ());
+     ASSERT_EQ (NULL, edit.get_content (filename));
+     ASSERT_EQ (NULL, edit.generate_diff (false));
+   }
+ }
+ 
+ static void
+ run_all_tests ()
+ {
+   test_get_content ();
+   for_each_line_table_case (test_applying_fixits_insert_before);
+   for_each_line_table_case (test_applying_fixits_insert_after);
+   for_each_line_table_case (test_applying_fixits_insert_after_at_line_end);
+   for_each_line_table_case (test_applying_fixits_insert_after_failure);
+   for_each_line_table_case (test_applying_fixits_insert_containing_newline);
+   for_each_line_table_case (test_applying_fixits_growing_replace);
+   for_each_line_table_case (test_applying_fixits_shrinking_replace);
+   for_each_line_table_case (test_applying_fixits_replace_containing_newline);
+   for_each_line_table_case (test_applying_fixits_remove);
+   for_each_line_table_case (test_applying_fixits_multiple);
+   for_each_line_table_case (test_applying_fixits_multiple_lines);
+   for_each_line_table_case (test_applying_fixits_modernize_named_init);
+   test_applying_fixits_unreadable_file ();
+   test_applying_fixits_line_out_of_range ();
+   for_each_line_table_case (test_applying_fixits_column_validation);
+ }
+ 
+ } // namespace diagnostics::changes::selftest
+ } // namespace diagnostics::changes
+ 
+ namespace selftest { // diagnostics::selftest
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ changes_cc_tests ()
+ {
+   diagnostics::changes::selftest::run_all_tests ();
+ }
+ 
+ } // namespace selftest
+ } // namespace diagnostics
+ 
+ #endif /* CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/changes.h gcc-16-20250727/gcc/diagnostics/changes.h
*** gcc-16-20250720/gcc/diagnostics/changes.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/changes.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,78 ----
+ /* Determining the results of applying fix-it hints.
+    Copyright (C) 2016-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_CHANGES_H
+ #define GCC_DIAGNOSTICS_CHANGES_H
+ 
+ #include "typed-splay-tree.h"
+ 
+ class fixit_hint;
+ 
+ namespace diagnostics {
+ namespace changes {
+ 
+ class change_set;
+ class changed_file;
+ 
+ /* A set of changes to the source code.
+ 
+    The changes are "atomic" - if any changes can't be applied,
+    none of them can be (tracked by the m_valid flag).
+    Similarly, attempts to add the changes from a rich_location flagged
+    as containing invalid changes mean that the whole of the change_set
+    is flagged as invalid.
+ 
+    A complication here is that fix-its are expressed relative to coordinates
+    in the files when they were parsed, before any changes have been made, and
+    so if there's more that one fix-it to be applied, we have to adjust
+    later fix-its to allow for the changes made by earlier ones.  This
+    is done by the various "get_effective_column" methods.  */
+ 
+ class change_set
+ {
+  public:
+   change_set (file_cache &);
+ 
+   bool valid_p () const { return m_valid; }
+ 
+   void add_fixits (rich_location *richloc);
+ 
+   char *get_content (const char *filename);
+ 
+   int get_effective_column (const char *filename, int line, int column);
+ 
+   char *generate_diff (bool show_filenames);
+   void print_diff (pretty_printer *pp, bool show_filenames);
+ 
+   file_cache &get_file_cache () const { return m_file_cache; }
+ 
+  private:
+   bool apply_fixit (const fixit_hint *hint);
+   changed_file *get_file (const char *filename);
+   changed_file &get_or_insert_file (const char *filename);
+ 
+   file_cache &m_file_cache;
+   bool m_valid;
+   typed_splay_tree<const char *, changed_file *> m_files;
+ };
+ 
+ } // namespace diagnostics::changes
+ } // namespace diagnostics
+ 
+ #endif /* GCC_DIAGNOSTICS_CHANGES_H.  */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/client-data-hooks.h gcc-16-20250727/gcc/diagnostics/client-data-hooks.h
*** gcc-16-20250720/gcc/diagnostics/client-data-hooks.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/client-data-hooks.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,125 ----
+ /* Additional metadata about a client for a diagnostic context.
+    Copyright (C) 2022-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_CLIENT_DATA_HOOKS_H
+ #define GCC_DIAGNOSTICS_CLIENT_DATA_HOOKS_H
+ 
+ #include "diagnostics/logical-locations.h"
+ 
+ namespace diagnostics {
+ 
+ class sarif_object;
+ class client_version_info;
+ 
+ /* A bundle of additional metadata, owned by the diagnostics::context,
+    for querying things about the client, like version data.  */
+ 
+ class client_data_hooks
+ {
+  public:
+   virtual ~client_data_hooks () {}
+ 
+   /* Get version info for this client, or NULL.  */
+   virtual const client_version_info *get_any_version_info () const = 0;
+ 
+   /* Get the current logical_locations::manager for this client, or null.  */
+   virtual const logical_locations::manager *
+   get_logical_location_manager () const = 0;
+ 
+   /* Get the current logical location, or null.
+      If this returns a non-null logical location, then
+      get_logical_location_manager must return non-null.  */
+   virtual logical_locations::key
+   get_current_logical_location () const = 0;
+ 
+   /* Get a sourceLanguage value for FILENAME, or return NULL.
+      See SARIF v2.1.0 Appendix J for suggested values.  */
+   virtual const char *
+   maybe_get_sarif_source_language (const char *filename) const = 0;
+ 
+   /* Hook to allow client to populate a SARIF "invocation" object with
+      a custom property bag (see SARIF v2.1.0 section 3.8).  */
+   virtual void
+   add_sarif_invocation_properties (sarif_object &invocation_obj) const = 0;
+ };
+ 
+ class client_plugin_info;
+ 
+ /* Abstract base class for a diagnostics::context to get at
+    version information about the client.  */
+ 
+ class client_version_info
+ {
+ public:
+   class plugin_visitor
+   {
+   public:
+     virtual void on_plugin (const client_plugin_info &) = 0;
+   };
+ 
+   virtual ~client_version_info () {}
+ 
+   /* Get a string suitable for use as the value of the "name" property
+      (SARIF v2.1.0 section 3.19.8).  */
+   virtual const char *get_tool_name () const = 0;
+ 
+   /* Create a string suitable for use as the value of the "fullName" property
+      (SARIF v2.1.0 section 3.19.9).  */
+   virtual char *maybe_make_full_name () const = 0;
+ 
+   /* Get a string suitable for use as the value of the "version" property
+      (SARIF v2.1.0 section 3.19.13).  */
+   virtual const char *get_version_string () const = 0;
+ 
+   /* Create a string suitable for use as the value of the "informationUri"
+      property (SARIF v2.1.0 section 3.19.17).  */
+   virtual char *maybe_make_version_url () const = 0;
+ 
+   virtual void for_each_plugin (plugin_visitor &v) const = 0;
+ };
+ 
+ /* Abstract base class for a diagnostics::context to get at
+    information about a specific plugin within a client.  */
+ 
+ class client_plugin_info
+ {
+ public:
+   /* For use e.g. by SARIF "name" property (SARIF v2.1.0 section 3.19.8).  */
+   virtual const char *get_short_name () const = 0;
+ 
+   /* For use e.g. by SARIF "fullName" property
+      (SARIF v2.1.0 section 3.19.9).  */
+   virtual const char *get_full_name () const = 0;
+ 
+   /* For use e.g. by SARIF "version" property
+      (SARIF v2.1.0 section 3.19.13).  */
+   virtual const char *get_version () const = 0;
+ };
+ 
+ } // namespace diagnostics
+ 
+ /* Factory function for making an instance of client_data_hooks
+    for use in the compiler (i.e. with knowledge of "tree", access to
+    langhooks, etc).  */
+ 
+ extern std::unique_ptr<diagnostics::client_data_hooks>
+ make_compiler_data_hooks ();
+ 
+ #endif /* ! GCC_DIAGNOSTICS_CLIENT_DATA_HOOKS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/color.cc gcc-16-20250727/gcc/diagnostics/color.cc
*** gcc-16-20250720/gcc/diagnostics/color.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/color.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,536 ----
+ /* Output colorization.
+    Copyright (C) 2011-2025 Free Software Foundation, Inc.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3, or (at your option)
+    any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+    02110-1301, USA.  */
+ 
+ #include "config.h"
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "diagnostics/color.h"
+ #include "diagnostics/url.h"
+ #include "label-text.h"
+ 
+ #ifdef __MINGW32__
+ #  define WIN32_LEAN_AND_MEAN
+ #  include <windows.h>
+ #endif
+ 
+ #include "color-macros.h"
+ #include "selftest.h"
+ 
+ /* The context and logic for choosing default --color screen attributes
+    (foreground and background colors, etc.) are the following.
+       -- There are eight basic colors available, each with its own
+ 	 nominal luminosity to the human eye and foreground/background
+ 	 codes (black [0 %, 30/40], blue [11 %, 34/44], red [30 %, 31/41],
+ 	 magenta [41 %, 35/45], green [59 %, 32/42], cyan [70 %, 36/46],
+ 	 yellow [89 %, 33/43], and white [100 %, 37/47]).
+       -- Sometimes, white as a background is actually implemented using
+ 	 a shade of light gray, so that a foreground white can be visible
+ 	 on top of it (but most often not).
+       -- Sometimes, black as a foreground is actually implemented using
+ 	 a shade of dark gray, so that it can be visible on top of a
+ 	 background black (but most often not).
+       -- Sometimes, more colors are available, as extensions.
+       -- Other attributes can be selected/deselected (bold [1/22],
+ 	 underline [4/24], standout/inverse [7/27], blink [5/25], and
+ 	 invisible/hidden [8/28]).  They are sometimes implemented by
+ 	 using colors instead of what their names imply; e.g., bold is
+ 	 often achieved by using brighter colors.  In practice, only bold
+ 	 is really available to us, underline sometimes being mapped by
+ 	 the terminal to some strange color choice, and standout best
+ 	 being left for use by downstream programs such as less(1).
+       -- We cannot assume that any of the extensions or special features
+ 	 are available for the purpose of choosing defaults for everyone.
+       -- The most prevalent default terminal backgrounds are pure black
+ 	 and pure white, and are not necessarily the same shades of
+ 	 those as if they were selected explicitly with SGR sequences.
+ 	 Some terminals use dark or light pictures as default background,
+ 	 but those are covered over by an explicit selection of background
+ 	 color with an SGR sequence; their users will appreciate their
+ 	 background pictures not be covered like this, if possible.
+       -- Some uses of colors attributes is to make some output items
+ 	 more understated (e.g., context lines); this cannot be achieved
+ 	 by changing the background color.
+       -- For these reasons, the GCC color defaults should strive not
+ 	 to change the background color from its default, unless it's
+ 	 for a short item that should be highlighted, not understated.
+       -- The GCC foreground color defaults (without an explicitly set
+ 	 background) should provide enough contrast to be readable on any
+ 	 terminal with either a black (dark) or white (light) background.
+ 	 This only leaves red, magenta, green, and cyan (and their bold
+ 	 counterparts) and possibly bold blue.  */
+ /* Default colors. The user can overwrite them using environment
+    variable GCC_COLORS.  */
+ struct color_default
+ {
+   const char *m_name;
+   const char *m_val;
+ };
+ 
+ /* For GCC_COLORS.  */
+ static const color_default gcc_color_defaults[] =
+ {
+   { "error", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED) },
+   { "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA) },
+   { "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN) },
+   { "range1", SGR_SEQ (COLOR_FG_GREEN) },
+   { "range2", SGR_SEQ (COLOR_FG_BLUE) },
+   { "locus", SGR_SEQ (COLOR_BOLD) },
+   { "quote", SGR_SEQ (COLOR_BOLD) },
+   { "path", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN) },
+   { "fnname", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN) },
+   { "targs", SGR_SEQ (COLOR_FG_MAGENTA) },
+   { "fixit-insert", SGR_SEQ (COLOR_FG_GREEN) },
+   { "fixit-delete", SGR_SEQ (COLOR_FG_RED) },
+   { "diff-filename", SGR_SEQ (COLOR_BOLD) },
+   { "diff-hunk", SGR_SEQ (COLOR_FG_CYAN) },
+   { "diff-delete", SGR_SEQ (COLOR_FG_RED) },
+   { "diff-insert", SGR_SEQ (COLOR_FG_GREEN) },
+   { "type-diff", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN) },
+   { "valid", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN) },
+   { "invalid", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED) },
+   { "highlight-a", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN) },
+   { "highlight-b", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_BLUE) }
+ };
+ 
+ class diagnostic_color_dict
+ {
+ public:
+   diagnostic_color_dict (const color_default *default_values,
+ 			 size_t num_default_values);
+ 
+   bool parse_envvar_value (const char *const envvar_value);
+ 
+   const char *get_start_by_name (const char *name, size_t name_len) const;
+   const char *get_start_by_name (const char *name) const
+   {
+     return get_start_by_name (name, strlen (name));
+   }
+ 
+ private:
+   struct entry
+   {
+     entry (const color_default &d)
+     : m_name (d.m_name),
+       m_name_len (strlen (d.m_name)),
+       m_val (label_text::borrow (d.m_val))
+     {
+     }
+ 
+     const char *m_name;
+     size_t m_name_len;
+     label_text m_val;
+   };
+ 
+   const entry *get_entry_by_name (const char *name, size_t name_len) const;
+   entry *get_entry_by_name (const char *name, size_t name_len);
+ 
+   std::vector<entry> m_entries;
+ };
+ 
+ static diagnostic_color_dict *g_color_dict;
+ 
+ const char *
+ colorize_start (bool show_color, const char *name, size_t name_len)
+ {
+   if (!show_color)
+     return "";
+ 
+   if (!g_color_dict)
+     return "";
+ 
+   return g_color_dict->get_start_by_name (name, name_len);
+ }
+ 
+ /* Look for an entry named NAME of length NAME_LEN within this
+    diagnostic_color_dict, or nullptr if there isn't one.  */
+ 
+ const diagnostic_color_dict::entry *
+ diagnostic_color_dict::get_entry_by_name (const char *name,
+ 					  size_t name_len) const
+ {
+   for (auto &iter : m_entries)
+     if (iter.m_name_len == name_len
+ 	&& memcmp (iter.m_name, name, name_len) == 0)
+       return &iter;
+   return nullptr;
+ }
+ 
+ /* Non-const version of the above.  */
+ 
+ diagnostic_color_dict::entry *
+ diagnostic_color_dict::get_entry_by_name (const char *name,
+ 					  size_t name_len)
+ {
+   for (auto &iter : m_entries)
+     if (iter.m_name_len == name_len
+ 	&& memcmp (iter.m_name, name, name_len) == 0)
+       return &iter;
+   return nullptr;
+ }
+ 
+ /* Return the SGR codes to start a color entry named NAME of length
+    NAME_LEN within this diagnostic_color_dict, or the empty string if
+    there isn't one.  */
+ 
+ const char *
+ diagnostic_color_dict::get_start_by_name (const char *name,
+ 					  size_t name_len) const
+ {
+   if (const entry *e = get_entry_by_name (name, name_len))
+     return e->m_val.get ();
+ 
+   return "";
+ }
+ 
+ const char *
+ colorize_stop (bool show_color)
+ {
+   return show_color ? SGR_RESET : "";
+ }
+ 
+ /* diagnostic_color_dict's ctor.  Initialize it from the given array
+    of color_default values.  */
+ 
+ diagnostic_color_dict::
+ diagnostic_color_dict (const color_default *default_values,
+ 		       size_t num_default_values)
+ {
+   m_entries.reserve (num_default_values);
+   for (size_t idx = 0; idx < num_default_values; idx++)
+     m_entries.push_back (entry (default_values[idx]));
+ }
+ 
+ /* Parse a list of color definitions from an environment variable
+    value (such as that of GCC_COLORS).
+    No character escaping is needed or supported.  */
+ 
+ bool
+ diagnostic_color_dict::parse_envvar_value (const char *const envvar_value)
+ {
+   /* envvar not set: use the default colors.  */
+   if (envvar_value == nullptr)
+     return true;
+ 
+   /* envvar set to empty string: disable colorization.  */
+   if (*envvar_value == '\0')
+     return false;
+ 
+   const char *q, *name, *val;
+   size_t name_len = 0, val_len = 0;
+ 
+   name = q = envvar_value;
+   val = nullptr;
+   /* From now on, be well-formed or you're gone.  */
+   for (;;)
+     if (*q == ':' || *q == '\0')
+       {
+ 	if (val)
+ 	  val_len = q - val;
+ 	else
+ 	  name_len = q - name;
+ 	/* Empty name without val (empty cap)
+ 	   won't match and will be ignored.  */
+ 	entry *e = get_entry_by_name (name, name_len);
+ 	/* If name unknown, go on for forward compatibility.  */
+ 	if (e && val)
+ 	  {
+ 	    char *b = XNEWVEC (char, val_len + sizeof (SGR_SEQ ("")));
+ 	    memcpy (b, SGR_START, strlen (SGR_START));
+ 	    memcpy (b + strlen (SGR_START), val, val_len);
+ 	    memcpy (b + strlen (SGR_START) + val_len, SGR_END,
+ 		    sizeof (SGR_END));
+ 	    e->m_val = label_text::take (b);
+ 	  }
+ 	if (*q == '\0')
+ 	  return true;
+ 	name = ++q;
+ 	val = nullptr;
+       }
+     else if (*q == '=')
+       {
+ 	if (q == name || val)
+ 	  return true;
+ 
+ 	name_len = q - name;
+ 	val = ++q; /* Can be the empty string.  */
+       }
+     else if (val == nullptr)
+       q++; /* Accumulate name.  */
+     else if (*q == ';' || (*q >= '0' && *q <= '9'))
+       q++; /* Accumulate val.  Protect the terminal from being sent
+ 	      garbage.  */
+     else
+       return true;
+ }
+ 
+ /* Parse GCC_COLORS.  The default would look like:
+    GCC_COLORS='error=01;31:warning=01;35:note=01;36:\
+    range1=32:range2=34:locus=01:quote=01:path=01;36:\
+    fixit-insert=32:fixit-delete=31:'\
+    diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\
+    type-diff=01;32'.  */
+ static bool
+ parse_gcc_colors ()
+ {
+   if (!g_color_dict)
+     return false;
+   return g_color_dict->parse_envvar_value (getenv ("GCC_COLORS")); /* Plural! */
+ }
+ 
+ /* Return true if we should use color when in auto mode, false otherwise. */
+ static bool
+ should_colorize (void)
+ {
+ #ifdef __MINGW32__
+   /* For consistency reasons, one should check the handle returned by
+      _get_osfhandle(_fileno(stderr)) because the function
+      pp_write_text_to_stream() in pretty-print.cc calls fputs() on
+      that stream.  However, the code below for non-Windows doesn't seem
+      to care about it either...  */
+   HANDLE handle;
+   DWORD mode;
+   BOOL isconsole = false;
+ 
+   handle = GetStdHandle (STD_ERROR_HANDLE);
+ 
+   if ((handle != INVALID_HANDLE_VALUE) && (handle != nullptr))
+     isconsole = GetConsoleMode (handle, &mode);
+ 
+ #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+   if (isconsole)
+     {
+       /* Try to enable processing of VT100 escape sequences */
+       mode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+       SetConsoleMode (handle, mode);
+     }
+ #endif
+ 
+   return isconsole;
+ #else
+   char const *t = getenv ("TERM");
+   /* emacs M-x shell sets TERM="dumb".  */
+   return t && strcmp (t, "dumb") != 0 && isatty (STDERR_FILENO);
+ #endif
+ }
+ 
+ bool
+ colorize_init (diagnostic_color_rule_t rule)
+ {
+   if (!g_color_dict)
+     g_color_dict = new diagnostic_color_dict (gcc_color_defaults,
+ 					      ARRAY_SIZE (gcc_color_defaults));
+ 
+   switch (rule)
+     {
+     case DIAGNOSTICS_COLOR_NO:
+       return false;
+     case DIAGNOSTICS_COLOR_YES:
+       return parse_gcc_colors ();
+     case DIAGNOSTICS_COLOR_AUTO:
+       if (should_colorize ())
+ 	return parse_gcc_colors ();
+       else
+ 	return false;
+     default:
+       gcc_unreachable ();
+     }
+ }
+ 
+ /* Return URL_FORMAT_XXX which tells how we should emit urls
+    when in always mode.
+    We use GCC_URLS and if that is not defined TERM_URLS.
+    If neither is defined the feature is enabled by default.  */
+ 
+ static diagnostic_url_format
+ parse_env_vars_for_urls ()
+ {
+   const char *p;
+ 
+   p = getenv ("GCC_URLS"); /* Plural! */
+   if (p == nullptr)
+     p = getenv ("TERM_URLS");
+ 
+   if (p == nullptr)
+     return URL_FORMAT_DEFAULT;
+ 
+   if (*p == '\0')
+     return URL_FORMAT_NONE;
+ 
+   if (!strcmp (p, "no"))
+     return URL_FORMAT_NONE;
+ 
+   if (!strcmp (p, "st"))
+     return URL_FORMAT_ST;
+ 
+   if (!strcmp (p, "bel"))
+     return URL_FORMAT_BEL;
+ 
+   return URL_FORMAT_DEFAULT;
+ }
+ 
+ /* Return true if we should use urls when in auto mode, false otherwise.  */
+ 
+ static bool
+ auto_enable_urls ()
+ {
+   const char *term, *colorterm;
+ 
+   /* First check the terminal is capable of printing color escapes,
+      if not URLs won't work either.  */
+   if (!should_colorize ())
+     return false;
+ 
+ #ifdef __MINGW32__
+   HANDLE handle;
+   DWORD mode;
+ 
+   handle = GetStdHandle (STD_ERROR_HANDLE);
+   if ((handle == INVALID_HANDLE_VALUE) || (handle == nullptr))
+     return false;
+ 
+   /* If ansi escape sequences aren't supported by the console, then URLs will
+      print mangled from mingw_ansi_fputs's console API translation. It wouldn't
+      be useful even if this weren't the case.  */
+   if (GetConsoleMode (handle, &mode)
+ #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+       && !(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+ #endif
+       )
+     return false;
+ #endif
+ 
+   /* xfce4-terminal is known to not implement URLs at this time.
+      Recently new installations (0.8) will safely ignore the URL escape
+      sequences, but a large number of legacy installations (0.6.3) print
+      garbage when URLs are printed.  Therefore we lose nothing by
+      disabling this feature for that specific terminal type.  */
+   colorterm = getenv ("COLORTERM");
+   if (colorterm && !strcmp (colorterm, "xfce4-terminal"))
+     return false;
+ 
+   /* Old versions of gnome-terminal where URL escapes cause screen
+      corruptions set COLORTERM="gnome-terminal", recent versions
+      with working URL support set this to "truecolor".  */
+   if (colorterm && !strcmp (colorterm, "gnome-terminal"))
+     return false;
+ 
+   /* Since the following checks are less specific than the ones
+      above, let GCC_URLS and TERM_URLS override the decision.  */
+   if (getenv ("GCC_URLS") || getenv ("TERM_URLS"))
+     return true;
+ 
+   /* In an ssh session the COLORTERM is not there, but TERM=xterm
+      can be used as an indication of a incompatible terminal while
+      TERM=xterm-256color appears to be a working terminal.  */
+   term = getenv ("TERM");
+   if (!colorterm && term && !strcmp (term, "xterm"))
+     return false;
+ 
+   /* When logging in a linux over serial line, we see TERM=linux
+      and no COLORTERM, it is unlikely that the URL escapes will
+      work in that environmen either.  */
+   if (!colorterm && term && !strcmp (term, "linux"))
+     return false;
+ 
+   return true;
+ }
+ 
+ /* Determine if URLs should be enabled, based on RULE,
+    and, if so, which format to use.
+    This reuses the logic for colorization.  */
+ 
+ diagnostic_url_format
+ determine_url_format (diagnostic_url_rule_t rule)
+ {
+   switch (rule)
+     {
+     case DIAGNOSTICS_URL_NO:
+       return URL_FORMAT_NONE;
+     case DIAGNOSTICS_URL_YES:
+       return parse_env_vars_for_urls ();
+     case DIAGNOSTICS_URL_AUTO:
+       if (auto_enable_urls ())
+ 	return parse_env_vars_for_urls ();
+       else
+ 	return URL_FORMAT_NONE;
+     default:
+       gcc_unreachable ();
+     }
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace selftest {
+ 
+ /* Test of an empty diagnostic_color_dict.  */
+ 
+ static void
+ test_empty_color_dict ()
+ {
+   diagnostic_color_dict d (nullptr, 0);
+   ASSERT_STREQ (d.get_start_by_name ("warning"), "");
+   ASSERT_STREQ (d.get_start_by_name ("should-not-be-found"), "");
+ }
+ 
+ /* Test of a diagnostic_color_dict with GCC's defaults.  */
+ 
+ static void
+ test_default_color_dict ()
+ {
+   diagnostic_color_dict d (gcc_color_defaults,
+ 			   ARRAY_SIZE (gcc_color_defaults));
+   ASSERT_STREQ (d.get_start_by_name ("warning"),
+ 		SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA));
+   ASSERT_STREQ (d.get_start_by_name ("should-not-be-found"), "");
+ }
+ 
+ /* Test of a diagnostic_color_dict with GCC's defaults plus overrides from
+    an environment variable.  */
+ 
+ static void
+ test_color_dict_envvar_parsing ()
+ {
+   diagnostic_color_dict d (gcc_color_defaults,
+ 			   ARRAY_SIZE (gcc_color_defaults));
+ 
+   d.parse_envvar_value ("error=01;37:warning=01;42:unknown-value=01;36");
+ 
+   ASSERT_STREQ (d.get_start_by_name ("error"),
+ 		SGR_SEQ ("01;37"));
+   ASSERT_STREQ (d.get_start_by_name ("warning"),
+ 		SGR_SEQ ("01;42"));
+   ASSERT_STREQ (d.get_start_by_name ("unknown-value"), "");
+   ASSERT_STREQ (d.get_start_by_name ("should-not-be-found"), "");
+ }
+ 
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ color_cc_tests ()
+ {
+   test_empty_color_dict ();
+   test_default_color_dict ();
+   test_color_dict_envvar_parsing ();
+ }
+ 
+ } // namespace selftest
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/color.h gcc-16-20250727/gcc/diagnostics/color.h
*** gcc-16-20250720/gcc/diagnostics/color.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/color.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,65 ----
+ /* Copyright (C) 2013-2025 Free Software Foundation, Inc.
+    Contributed by Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ /* Based on code from: */
+ /* grep.c - main driver file for grep.
+    Copyright (C) 1992-2025 Free Software Foundation, Inc.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3, or (at your option)
+    any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+    02110-1301, USA.
+ 
+    Written July 1992 by Mike Haertel.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_COLOR_H
+ #define GCC_DIAGNOSTICS_COLOR_H
+ 
+ /* Whether to add color to diagnostics:
+    o DIAGNOSTICS_COLOR_NO: never
+    o DIAGNOSTICS_COLOR_YES: always
+    o DIAGNOSTICS_COLOR_AUTO: depending on the output stream.  */
+ typedef enum
+ {
+   DIAGNOSTICS_COLOR_NO       = 0,
+   DIAGNOSTICS_COLOR_YES      = 1,
+   DIAGNOSTICS_COLOR_AUTO     = 2
+ } diagnostic_color_rule_t;
+ 
+ const char *colorize_start (bool, const char *, size_t);
+ const char *colorize_stop (bool);
+ bool colorize_init (diagnostic_color_rule_t);
+ 
+ inline const char *
+ colorize_start (bool show_color, const char *name)
+ {
+   return colorize_start (show_color, name, strlen (name));
+ }
+ 
+ #endif /* ! GCC_DIAGNOSTICS_COLOR_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/context-options.h gcc-16-20250727/gcc/diagnostics/context-options.h
*** gcc-16-20250720/gcc/diagnostics/context-options.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/context-options.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,116 ----
+ /* Declare enums for diagnostics::context and related types.
+    Copyright (C) 2000-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_CONTEXT_OPTIONS_H
+ #define GCC_DIAGNOSTICS_CONTEXT_OPTIONS_H
+ 
+ /* An enum for controlling what units to use for the column number
+    when diagnostics are output, used by the -fdiagnostics-column-unit option.
+    Tabs will be expanded or not according to the value of -ftabstop.  The origin
+    (default 1) is controlled by -fdiagnostics-column-origin.  */
+ 
+ enum diagnostics_column_unit
+ {
+   /* The default from GCC 11 onwards: display columns.  */
+   DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
+ 
+   /* The behavior in GCC 10 and earlier: simple bytes.  */
+   DIAGNOSTICS_COLUMN_UNIT_BYTE
+ };
+ 
+ /* An enum for controlling how to print non-ASCII characters/bytes when
+    a diagnostic suggests escaping the source code on output.  */
+ 
+ enum diagnostics_escape_format
+ {
+   /* Escape non-ASCII Unicode characters in the form <U+XXXX> and
+      non-UTF-8 bytes in the form <XX>.  */
+   DIAGNOSTICS_ESCAPE_FORMAT_UNICODE,
+ 
+   /* Escape non-ASCII bytes in the form <XX> (thus showing the underlying
+      encoding of non-ASCII Unicode characters).  */
+   DIAGNOSTICS_ESCAPE_FORMAT_BYTES
+ };
+ 
+ /* Enum for overriding the standard output format.  */
+ 
+ enum diagnostics_output_format
+ {
+   /* The default: textual output.  */
+   DIAGNOSTICS_OUTPUT_FORMAT_TEXT,
+ 
+   /* SARIF-based output, as JSON to stderr.  */
+   DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR,
+ 
+   /* SARIF-based output, to a JSON file.  */
+   DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE
+ };
+ 
+ /* An enum for controlling how diagnostic paths should be printed.  */
+ enum diagnostic_path_format
+ {
+   /* Don't print diagnostic paths.  */
+   DPF_NONE,
+ 
+   /* Print diagnostic paths by emitting a separate "note" for every event
+      in the path.  */
+   DPF_SEPARATE_EVENTS,
+ 
+   /* Print diagnostic paths by consolidating events together where they
+      are close enough, and printing such runs of events with multiple
+      calls to diagnostic_show_locus, showing the individual events in
+      each run via labels in the source.  */
+   DPF_INLINE_EVENTS
+ };
+ 
+ /* An enum for capturing values of GCC_EXTRA_DIAGNOSTIC_OUTPUT,
+    and for -fdiagnostics-parseable-fixits.  */
+ 
+ enum diagnostics_extra_output_kind
+ {
+   /* No extra output, or an unrecognized value.  */
+   EXTRA_DIAGNOSTIC_OUTPUT_none,
+ 
+   /* Emit fix-it hints using the "fixits-v1" format, equivalent to
+      -fdiagnostics-parseable-fixits.  */
+   EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1,
+ 
+   /* Emit fix-it hints using the "fixits-v2" format.  */
+   EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
+ };
+ 
+ /* Values for -fdiagnostics-text-art-charset=.  */
+ 
+ enum diagnostic_text_art_charset
+ {
+   /* No text art diagrams shall be emitted.  */
+   DIAGNOSTICS_TEXT_ART_CHARSET_NONE,
+ 
+   /* Use pure ASCII for text art diagrams.  */
+   DIAGNOSTICS_TEXT_ART_CHARSET_ASCII,
+ 
+   /* Use ASCII + conservative use of other unicode characters
+      in text art diagrams.  */
+   DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE,
+ 
+   /* Use Emoji.  */
+   DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI
+ };
+ 
+ #endif /* ! GCC_DIAGNOSTICS_CONTEXT_OPTIONS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/context.cc gcc-16-20250727/gcc/diagnostics/context.cc
*** gcc-16-20250720/gcc/diagnostics/context.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/context.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,2151 ----
+ /* Language-independent diagnostic subroutines for the GNU Compiler Collection
+    Copyright (C) 1999-2025 Free Software Foundation, Inc.
+    Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ 
+ /* This file implements the language independent aspect of diagnostic
+    message module.  */
+ 
+ #include "config.h"
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "version.h"
+ #include "demangle.h"
+ #include "intl.h"
+ #include "backtrace.h"
+ #include "diagnostic.h"
+ #include "diagnostics/color.h"
+ #include "diagnostics/url.h"
+ #include "diagnostics/metadata.h"
+ #include "diagnostics/paths.h"
+ #include "diagnostics/client-data-hooks.h"
+ #include "diagnostics/diagram.h"
+ #include "diagnostics/sink.h"
+ #include "diagnostics/sarif-sink.h"
+ #include "diagnostics/text-sink.h"
+ #include "diagnostics/changes.h"
+ #include "selftest.h"
+ #include "diagnostics/selftest-context.h"
+ #include "opts.h"
+ #include "cpplib.h"
+ #include "text-art/theme.h"
+ #include "pretty-print-urlifier.h"
+ #include "diagnostics/logical-locations.h"
+ #include "diagnostics/buffering.h"
+ #include "diagnostics/file-cache.h"
+ 
+ #ifdef HAVE_TERMIOS_H
+ # include <termios.h>
+ #endif
+ 
+ #ifdef GWINSZ_IN_SYS_IOCTL
+ # include <sys/ioctl.h>
+ #endif
+ 
+ /* Disable warnings about quoting issues in the pp_xxx calls below
+    that (intentionally) don't follow GCC diagnostic conventions.  */
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic push
+ #  pragma GCC diagnostic ignored "-Wformat-diag"
+ #endif
+ 
+ static void real_abort (void) ATTRIBUTE_NORETURN;
+ 
+ /* Name of program invoked, sans directories.  */
+ 
+ const char *progname;
+ 
+ 
+ /* Return a malloc'd string containing MSG formatted a la printf.  The
+    caller is responsible for freeing the memory.  */
+ char *
+ build_message_string (const char *msg, ...)
+ {
+   char *str;
+   va_list ap;
+ 
+   va_start (ap, msg);
+   str = xvasprintf (msg, ap);
+   va_end (ap);
+ 
+   return str;
+ }
+ 
+ 
+ /* Return the value of the getenv("COLUMNS") as an integer. If the
+    value is not set to a positive integer, use ioctl to get the
+    terminal width. If it fails, return INT_MAX.  */
+ int
+ get_terminal_width (void)
+ {
+   const char * s = getenv ("COLUMNS");
+   if (s != nullptr) {
+     int n = atoi (s);
+     if (n > 0)
+       return n;
+   }
+ 
+ #ifdef TIOCGWINSZ
+   struct winsize w;
+   w.ws_col = 0;
+   if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
+     return w.ws_col;
+ #endif
+ 
+   return INT_MAX;
+ }
+ 
+ namespace diagnostics {
+ 
+ /* Set caret_max_width to value.  */
+ 
+ void
+ context::set_caret_max_width (int value)
+ {
+   /* One minus to account for the leading empty space.  */
+   value = value ? value - 1
+     : (isatty (fileno (pp_buffer (get_reference_printer ())->m_stream))
+        ? get_terminal_width () - 1 : INT_MAX);
+ 
+   if (value <= 0)
+     value = INT_MAX;
+ 
+   m_source_printing.max_width = value;
+ }
+ 
+ /* Initialize the diagnostic message outputting machinery.  */
+ 
+ void
+ context::initialize (int n_opts)
+ {
+   /* Allocate a basic pretty-printer.  Clients will replace this a
+      much more elaborated pretty-printer if they wish.  */
+   m_reference_printer = std::make_unique<pretty_printer> ().release ();
+ 
+   m_file_cache = new file_cache ();
+   m_diagnostic_counters.clear ();
+   m_warning_as_error_requested = false;
+   m_n_opts = n_opts;
+   m_option_classifier.init (n_opts);
+   m_source_printing.enabled = false;
+   set_caret_max_width (pp_line_cutoff (get_reference_printer ()));
+   for (int i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
+     m_source_printing.caret_chars[i] = '^';
+   m_show_cwe = false;
+   m_show_rules = false;
+   m_path_format = DPF_NONE;
+   m_show_path_depths = false;
+   m_show_option_requested = false;
+   m_abort_on_error = false;
+   m_show_column = false;
+   m_pedantic_errors = false;
+   m_permissive = false;
+   m_opt_permissive = 0;
+   m_fatal_errors = false;
+   m_inhibit_warnings = false;
+   m_warn_system_headers = false;
+   m_max_errors = 0;
+   m_internal_error = nullptr;
+   m_adjust_diagnostic_info = nullptr;
+   m_text_callbacks.m_begin_diagnostic = default_text_starter;
+   m_text_callbacks.m_text_start_span
+     = default_start_span_fn<to_text>;
+   m_text_callbacks.m_html_start_span
+     = default_start_span_fn<to_html>;
+   m_text_callbacks.m_end_diagnostic = default_text_finalizer;
+   m_option_mgr = nullptr;
+   m_urlifier_stack = new auto_vec<urlifier_stack_node> ();
+   m_last_location = UNKNOWN_LOCATION;
+   m_client_aux_data = nullptr;
+   m_lock = 0;
+   m_inhibit_notes_p = false;
+   m_source_printing.colorize_source_p = false;
+   m_source_printing.show_labels_p = false;
+   m_source_printing.show_line_numbers_p = false;
+   m_source_printing.min_margin_width = 0;
+   m_source_printing.show_ruler_p = false;
+   m_source_printing.show_event_links_p = false;
+   m_report_bug = false;
+   m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_none;
+   if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
+     {
+       if (!strcmp (var, "fixits-v1"))
+ 	m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
+       else if (!strcmp (var, "fixits-v2"))
+ 	m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
+       /* Silently ignore unrecognized values.  */
+     }
+   m_column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
+   m_column_origin = 1;
+   m_tabstop = 8;
+   m_escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+   m_fixits_change_set = nullptr;
+   m_diagnostic_groups.m_group_nesting_depth = 0;
+   m_diagnostic_groups.m_diagnostic_nesting_level = 0;
+   m_diagnostic_groups.m_emission_count = 0;
+   m_diagnostic_groups.m_inhibiting_notes_from = 0;
+   m_sinks.safe_push (new text_sink (*this, nullptr, true));
+   m_set_locations_cb = nullptr;
+   m_client_data_hooks = nullptr;
+   m_diagrams.m_theme = nullptr;
+   m_original_argv = nullptr;
+   m_diagnostic_buffer = nullptr;
+ 
+   enum diagnostic_text_art_charset text_art_charset
+     = DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI;
+   if (const char *lang = getenv ("LANG"))
+     {
+       /* For LANG=C, don't assume the terminal supports anything
+ 	 other than ASCII.  */
+       if (!strcmp (lang, "C"))
+ 	text_art_charset = DIAGNOSTICS_TEXT_ART_CHARSET_ASCII;
+     }
+   set_text_art_charset (text_art_charset);
+ }
+ 
+ /* Maybe initialize the color support. We require clients to do this
+    explicitly, since most clients don't want color.  When called
+    without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT.  */
+ 
+ void
+ context::color_init (int value)
+ {
+   /* value == -1 is the default value.  */
+   if (value < 0)
+     {
+       /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
+ 	 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
+ 	 otherwise default to -fdiagnostics-color=never, for other
+ 	 values default to that
+ 	 -fdiagnostics-color={never,auto,always}.  */
+       if (DIAGNOSTICS_COLOR_DEFAULT == -1)
+ 	{
+ 	  if (!getenv ("GCC_COLORS"))
+ 	    return;
+ 	  value = DIAGNOSTICS_COLOR_AUTO;
+ 	}
+       else
+ 	value = DIAGNOSTICS_COLOR_DEFAULT;
+     }
+   pp_show_color (m_reference_printer)
+     = colorize_init ((diagnostic_color_rule_t) value);
+   for (auto sink_ : m_sinks)
+     if (sink_->follows_reference_printer_p ())
+       pp_show_color (sink_->get_printer ())
+ 	= pp_show_color (m_reference_printer);
+ }
+ 
+ /* Initialize URL support within this context based on VALUE,
+    handling "auto".  */
+ 
+ void
+ context::urls_init (int value)
+ {
+   /* value == -1 is the default value.  */
+   if (value < 0)
+     {
+       /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
+ 	 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
+ 	 environment, otherwise default to -fdiagnostics-urls=never,
+ 	 for other values default to that
+ 	 -fdiagnostics-urls={never,auto,always}.  */
+       if (DIAGNOSTICS_URLS_DEFAULT == -1)
+ 	{
+ 	  if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
+ 	    return;
+ 	  value = DIAGNOSTICS_URL_AUTO;
+ 	}
+       else
+ 	value = DIAGNOSTICS_URLS_DEFAULT;
+     }
+ 
+   m_reference_printer->set_url_format
+     (determine_url_format ((diagnostic_url_rule_t) value));
+   for (auto sink_ : m_sinks)
+     if (sink_->follows_reference_printer_p ())
+       sink_->get_printer ()->set_url_format
+ 	(m_reference_printer->get_url_format ());
+ }
+ 
+ /* Create the file_cache, if not already created, and tell it how to
+    translate files on input.  */
+ void
+ context::initialize_input_context (diagnostic_input_charset_callback ccb,
+ 				   bool should_skip_bom)
+ {
+   m_file_cache->initialize_input_context (ccb, should_skip_bom);
+ }
+ 
+ /* Do any cleaning up required after the last diagnostic is emitted.  */
+ 
+ void
+ context::finish ()
+ {
+   /* We might be handling a fatal error.
+      Close any active diagnostic groups, which may trigger flushing
+      sinks.  */
+   while (m_diagnostic_groups.m_group_nesting_depth > 0)
+     end_group ();
+ 
+   set_diagnostic_buffer (nullptr);
+ 
+   /* Clean ups.  */
+ 
+   while (!m_sinks.is_empty ())
+     delete m_sinks.pop ();
+ 
+   if (m_diagrams.m_theme)
+     {
+       delete m_diagrams.m_theme;
+       m_diagrams.m_theme = nullptr;
+     }
+ 
+   delete m_file_cache;
+   m_file_cache = nullptr;
+ 
+   m_option_classifier.fini ();
+ 
+   delete m_reference_printer;
+   m_reference_printer = nullptr;
+ 
+   if (m_fixits_change_set)
+     {
+       delete m_fixits_change_set;
+       m_fixits_change_set = nullptr;
+     }
+ 
+   if (m_client_data_hooks)
+     {
+       delete m_client_data_hooks;
+       m_client_data_hooks = nullptr;
+     }
+ 
+   delete m_option_mgr;
+   m_option_mgr = nullptr;
+ 
+   if (m_urlifier_stack)
+     {
+       while (!m_urlifier_stack->is_empty ())
+ 	pop_urlifier ();
+       delete m_urlifier_stack;
+       m_urlifier_stack = nullptr;
+     }
+ 
+   freeargv (m_original_argv);
+   m_original_argv = nullptr;
+ }
+ 
+ /* Dump state of this diagnostics::context to OUT, for debugging.  */
+ 
+ void
+ context::dump (FILE *out) const
+ {
+   fprintf (out, "diagnostics::context:\n");
+   m_diagnostic_counters.dump (out, 2);
+   fprintf (out, "  reference printer:\n");
+   m_reference_printer->dump (out, 4);
+   fprintf (out, "  output sinks:\n");
+   if (m_sinks.length () > 0)
+     {
+       for (unsigned i = 0; i < m_sinks.length (); ++i)
+ 	{
+ 	  fprintf (out, "  sink %i:\n", i);
+ 	  m_sinks[i]->dump (out, 4);
+ 	}
+     }
+   else
+     fprintf (out, "    (none):\n");
+   fprintf (out, "  diagnostic buffer:\n");
+   if (m_diagnostic_buffer)
+     m_diagnostic_buffer->dump (out, 4);
+   else
+     fprintf (out, "    (none):\n");
+   fprintf (out, "  file cache:\n");
+   if (m_file_cache)
+     m_file_cache->dump (out, 4);
+   else
+     fprintf (out, "    (none):\n");
+ }
+ 
+ /* Return true if sufficiently severe diagnostics have been seen that
+    we ought to exit with a non-zero exit code.  */
+ 
+ bool
+ context::execution_failed_p () const
+ {
+   /* Equivalent to (seen_error () || werrorcount), but on
+      this context, rather than global_dc.  */
+   return (diagnostic_count (kind::error)
+ 	  || diagnostic_count (kind::sorry)
+ 	  || diagnostic_count (kind::werror));
+ }
+ 
+ void
+ context::remove_all_output_sinks ()
+ {
+   while (!m_sinks.is_empty ())
+     delete m_sinks.pop ();
+ }
+ 
+ void
+ context::set_sink (std::unique_ptr<sink> sink_)
+ {
+   remove_all_output_sinks ();
+   m_sinks.safe_push (sink_.release ());
+ }
+ 
+ sink &
+ context::get_sink (size_t idx) const
+ {
+   gcc_assert (idx < m_sinks.length ());
+   gcc_assert (m_sinks[idx]);
+   return *m_sinks[idx];
+ }
+ 
+ void
+ context::add_sink (std::unique_ptr<sink> sink_)
+ {
+   m_sinks.safe_push (sink_.release ());
+ }
+ 
+ /* Return true if there are no machine-readable formats writing to stderr.  */
+ 
+ bool
+ context::supports_fnotice_on_stderr_p () const
+ {
+   for (auto sink_ : m_sinks)
+     if (sink_->machine_readable_stderr_p ())
+       return false;
+   return true;
+ }
+ 
+ void
+ context::set_main_input_filename (const char *filename)
+ {
+   for (auto sink_ : m_sinks)
+     sink_->set_main_input_filename (filename);
+ }
+ 
+ void
+ context::set_client_data_hooks (std::unique_ptr<client_data_hooks> hooks)
+ {
+   delete m_client_data_hooks;
+   /* Ideally the field would be a std::unique_ptr here.  */
+   m_client_data_hooks = hooks.release ();
+ }
+ 
+ void
+ context::set_original_argv (unique_argv original_argv)
+ {
+   /* Ideally we'd use a unique_argv for m_original_argv, but
+      diagnostics::context doesn't yet have a ctor/dtor pair.  */
+ 
+   // Ensure any old value is freed
+   freeargv (m_original_argv);
+ 
+   // Take ownership of the new value
+   m_original_argv = original_argv.release ();
+ }
+ 
+ void
+ context::set_option_manager (std::unique_ptr<option_manager> mgr,
+ 			     unsigned lang_mask)
+ {
+   delete m_option_mgr;
+   m_option_mgr = mgr.release ();
+   m_lang_mask = lang_mask;
+ }
+ 
+ void
+ context::push_owned_urlifier (std::unique_ptr<urlifier> ptr)
+ {
+   gcc_assert (m_urlifier_stack);
+   const urlifier_stack_node node = { ptr.release (), true };
+   m_urlifier_stack->safe_push (node);
+ }
+ 
+ void
+ context::push_borrowed_urlifier (const urlifier &loan)
+ {
+   gcc_assert (m_urlifier_stack);
+   const urlifier_stack_node node = { const_cast <urlifier *> (&loan), false };
+   m_urlifier_stack->safe_push (node);
+ }
+ 
+ void
+ context::pop_urlifier ()
+ {
+   gcc_assert (m_urlifier_stack);
+   gcc_assert (m_urlifier_stack->length () > 0);
+ 
+   const urlifier_stack_node node = m_urlifier_stack->pop ();
+   if (node.m_owned)
+     delete node.m_urlifier;
+ }
+ 
+ const logical_locations::manager *
+ context::get_logical_location_manager () const
+ {
+   if (!m_client_data_hooks)
+     return nullptr;
+   return m_client_data_hooks->get_logical_location_manager ();
+ }
+ 
+ const urlifier *
+ context::get_urlifier () const
+ {
+   if (!m_urlifier_stack)
+     return nullptr;
+   if (m_urlifier_stack->is_empty ())
+     return nullptr;
+   return m_urlifier_stack->last ().m_urlifier;
+ }
+ 
+ 
+ /* Set PP as the reference printer for this context.
+    Refresh all output sinks.  */
+ 
+ void
+ context::set_pretty_printer (std::unique_ptr<pretty_printer> pp)
+ {
+   delete m_reference_printer;
+   m_reference_printer = pp.release ();
+   refresh_output_sinks ();
+ }
+ 
+ /* Give all output sinks a chance to rebuild their pretty_printer.  */
+ 
+ void
+ context::refresh_output_sinks ()
+ {
+   for (auto sink_ : m_sinks)
+     sink_->update_printer ();
+ }
+ 
+ /* Set FORMAT_DECODER on the reference printer and on the pretty_printer
+    of all output sinks.  */
+ 
+ void
+ context::set_format_decoder (printer_fn format_decoder)
+ {
+   pp_format_decoder (m_reference_printer) = format_decoder;
+   for (auto sink_ : m_sinks)
+     pp_format_decoder (sink_->get_printer ()) = format_decoder;
+ }
+ 
+ void
+ context::set_show_highlight_colors (bool val)
+ {
+   pp_show_highlight_colors (m_reference_printer) = val;
+   for (auto sink_ : m_sinks)
+     if (sink_->follows_reference_printer_p ())
+       pp_show_highlight_colors (sink_->get_printer ()) = val;
+ }
+ 
+ void
+ context::set_prefixing_rule (diagnostic_prefixing_rule_t rule)
+ {
+   pp_prefixing_rule (m_reference_printer) = rule;
+   for (auto sink_ : m_sinks)
+     if (sink_->follows_reference_printer_p ())
+       pp_prefixing_rule (sink_->get_printer ()) = rule;
+ }
+ 
+ void
+ context::initialize_fixits_change_set ()
+ {
+   delete m_fixits_change_set;
+   gcc_assert (m_file_cache);
+   m_fixits_change_set = new changes::change_set (*m_file_cache);
+ }
+ 
+ } // namespace diagnostics
+ 
+ /* Initialize DIAGNOSTIC, where the message MSG has already been
+    translated.  */
+ void
+ diagnostic_set_info_translated (diagnostics::diagnostic_info *diagnostic,
+ 				const char *msg, va_list *args,
+ 				rich_location *richloc,
+ 				enum diagnostics::kind kind)
+ {
+   gcc_assert (richloc);
+   diagnostic->m_message.m_err_no = errno;
+   diagnostic->m_message.m_args_ptr = args;
+   diagnostic->m_message.m_format_spec = msg;
+   diagnostic->m_message.m_richloc = richloc;
+   diagnostic->m_richloc = richloc;
+   diagnostic->m_metadata = nullptr;
+   diagnostic->m_kind = kind;
+   diagnostic->m_option_id = 0;
+ }
+ 
+ /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
+    translated.  */
+ void
+ diagnostic_set_info (diagnostics::diagnostic_info *diagnostic,
+ 		     const char *gmsgid, va_list *args,
+ 		     rich_location *richloc,
+ 		     enum diagnostics::kind kind)
+ {
+   gcc_assert (richloc);
+   diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
+ }
+ 
+ namespace diagnostics {
+ 
+ static const char *const diagnostic_kind_text[] = {
+ #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
+ #include "diagnostics/kinds.def"
+ #undef DEFINE_DIAGNOSTIC_KIND
+   "must-not-happen"
+ };
+ 
+ /* Get unlocalized string describing KIND.  */
+ 
+ const char *
+ get_text_for_kind (enum kind kind)
+ {
+   return diagnostic_kind_text[static_cast<int> (kind)];
+ }
+ 
+ static const char *const diagnostic_kind_color[] = {
+ #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
+ #include "diagnostics/kinds.def"
+ #undef DEFINE_DIAGNOSTIC_KIND
+   nullptr
+ };
+ 
+ /* Get a color name for diagnostics of type KIND
+    Result could be nullptr.  */
+ 
+ const char *
+ get_color_for_kind (enum kind kind)
+ {
+   return diagnostic_kind_color[static_cast<int> (kind)];
+ }
+ 
+ /* Given an expanded_location, convert the column (which is in 1-based bytes)
+    to the requested units, without converting the origin.
+    Return -1 if the column is invalid (<= 0).  */
+ 
+ static int
+ convert_column_unit (file_cache &fc,
+ 		     enum diagnostics_column_unit column_unit,
+ 		     int tabstop,
+ 		     expanded_location s)
+ {
+   if (s.column <= 0)
+     return -1;
+ 
+   switch (column_unit)
+     {
+     default:
+       gcc_unreachable ();
+ 
+     case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
+       {
+ 	cpp_char_column_policy policy (tabstop, cpp_wcwidth);
+ 	return location_compute_display_column (fc, s, policy);
+       }
+ 
+     case DIAGNOSTICS_COLUMN_UNIT_BYTE:
+       return s.column;
+     }
+ }
+ 
+ column_policy::column_policy (const context &dc)
+ : m_file_cache (dc.get_file_cache ()),
+   m_column_unit (dc.m_column_unit),
+   m_column_origin (dc.m_column_origin),
+   m_tabstop (dc.m_tabstop)
+ {
+ }
+ 
+ /* Given an expanded_location, convert the column (which is in 1-based bytes)
+    to the requested units and origin.  Return -1 if the column is
+    invalid (<= 0).  */
+ int
+ column_policy::converted_column (expanded_location s) const
+ {
+   int one_based_col = convert_column_unit (m_file_cache,
+ 					   m_column_unit, m_tabstop, s);
+   if (one_based_col <= 0)
+     return -1;
+   return one_based_col + (m_column_origin - 1);
+ }
+ 
+ /* Return a string describing a location e.g. "foo.c:42:10".  */
+ 
+ label_text
+ column_policy::get_location_text (const expanded_location &s,
+ 				  bool show_column,
+ 				  bool colorize) const
+ {
+   const char *locus_cs = colorize_start (colorize, "locus");
+   const char *locus_ce = colorize_stop (colorize);
+   const char *file = s.file ? s.file : progname;
+   int line = 0;
+   int col = -1;
+   if (strcmp (file, special_fname_builtin ()))
+     {
+       line = s.line;
+       if (show_column)
+ 	col = converted_column (s);
+     }
+ 
+   const char *line_col = maybe_line_and_column (line, col);
+   return label_text::take (build_message_string ("%s%s%s:%s", locus_cs, file,
+ 						 line_col, locus_ce));
+ }
+ 
+ location_print_policy::
+ location_print_policy (const context &dc)
+ : m_column_policy (dc),
+   m_show_column (dc.m_show_column)
+ {
+ }
+ 
+ location_print_policy::
+ location_print_policy (const text_sink &text_output)
+ :
+   m_column_policy (text_output.get_context ()),
+   m_show_column (text_output.get_context ().m_show_column)
+ {
+ }
+ 
+ } // namespace diagnostics
+ 
+ /* Functions at which to stop the backtrace print.  It's not
+    particularly helpful to print the callers of these functions.  */
+ 
+ static const char * const bt_stop[] =
+ {
+   "main",
+   "toplev::main",
+   "execute_one_pass",
+   "compile_file",
+ };
+ 
+ /* A callback function passed to the backtrace_full function.  */
+ 
+ static int
+ bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
+ 	     const char *function)
+ {
+   int *pcount = (int *) data;
+ 
+   /* If we don't have any useful information, don't print
+      anything.  */
+   if (filename == nullptr && function == nullptr)
+     return 0;
+ 
+   /* Skip functions in context.cc.  */
+   if (*pcount == 0
+       && filename != nullptr
+       && strcmp (lbasename (filename), "context.cc") == 0)
+     return 0;
+ 
+   /* Print up to 20 functions.  We could make this a --param, but
+      since this is only for debugging just use a constant for now.  */
+   if (*pcount >= 20)
+     {
+       /* Returning a non-zero value stops the backtrace.  */
+       return 1;
+     }
+   ++*pcount;
+ 
+   char *alc = nullptr;
+   if (function != nullptr)
+     {
+       char *str = cplus_demangle_v3 (function,
+ 				     (DMGL_VERBOSE | DMGL_ANSI
+ 				      | DMGL_GNU_V3 | DMGL_PARAMS));
+       if (str != nullptr)
+ 	{
+ 	  alc = str;
+ 	  function = str;
+ 	}
+ 
+       for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
+ 	{
+ 	  size_t len = strlen (bt_stop[i]);
+ 	  if (strncmp (function, bt_stop[i], len) == 0
+ 	      && (function[len] == '\0' || function[len] == '('))
+ 	    {
+ 	      if (alc != nullptr)
+ 		free (alc);
+ 	      /* Returning a non-zero value stops the backtrace.  */
+ 	      return 1;
+ 	    }
+ 	}
+     }
+ 
+   fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
+ 	   (unsigned long) pc,
+ 	   function == nullptr ? "???" : function,
+ 	   filename == nullptr ? "???" : filename,
+ 	   lineno);
+ 
+   if (alc != nullptr)
+     free (alc);
+ 
+   return 0;
+ }
+ 
+ /* A callback function passed to the backtrace_full function.  This is
+    called if backtrace_full has an error.  */
+ 
+ static void
+ bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
+ {
+   if (errnum < 0)
+     {
+       /* This means that no debug info was available.  Just quietly
+ 	 skip printing backtrace info.  */
+       return;
+     }
+   fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
+ 	   errnum == 0 ? "" : xstrerror (errnum));
+ }
+ 
+ namespace diagnostics {
+ 
+ /* Check if we've met the maximum error limit, and if so fatally exit
+    with a message.
+    FLUSH indicates whether a diagnostics::context::finish call is needed.  */
+ 
+ void
+ context::check_max_errors (bool flush)
+ {
+   if (!m_max_errors)
+     return;
+ 
+   int count = (diagnostic_count (kind::error)
+ 	       + diagnostic_count (kind::sorry)
+ 	       + diagnostic_count (kind::werror));
+ 
+   if (count >= m_max_errors)
+     {
+       fnotice (stderr,
+ 	       "compilation terminated due to -fmax-errors=%u.\n",
+ 	       m_max_errors);
+       if (flush)
+ 	finish ();
+       exit (FATAL_EXIT_CODE);
+     }
+ }
+ 
+ /* Take any action which is expected to happen after the diagnostic
+    is written out.  This function does not always return.  */
+ 
+ void
+ context::action_after_output (enum kind diag_kind)
+ {
+   switch (diag_kind)
+     {
+     case kind::debug:
+     case kind::note:
+     case kind::anachronism:
+     case kind::warning:
+       break;
+ 
+     case kind::error:
+     case kind::sorry:
+       if (m_abort_on_error)
+ 	real_abort ();
+       if (m_fatal_errors)
+ 	{
+ 	  fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
+ 	  finish ();
+ 	  exit (FATAL_EXIT_CODE);
+ 	}
+       break;
+ 
+     case kind::ice:
+     case kind::ice_nobt:
+       {
+ 	/* Attempt to ensure that any outputs are flushed e.g. that .sarif
+ 	   files are written out.
+ 	   Only do it once.  */
+ 	static bool finishing_due_to_ice = false;
+ 	if (!finishing_due_to_ice)
+ 	  {
+ 	    finishing_due_to_ice = true;
+ 	    finish ();
+ 	  }
+ 
+ 	struct backtrace_state *state = nullptr;
+ 	if (diag_kind == kind::ice)
+ 	  state = backtrace_create_state (nullptr, 0, bt_err_callback, nullptr);
+ 	int count = 0;
+ 	if (state != nullptr)
+ 	  backtrace_full (state, 2, bt_callback, bt_err_callback,
+ 			  (void *) &count);
+ 
+ 	if (m_abort_on_error)
+ 	  real_abort ();
+ 
+ 	if (m_report_bug)
+ 	  fnotice (stderr, "Please submit a full bug report, "
+ 		   "with preprocessed source.\n");
+ 	else
+ 	  fnotice (stderr, "Please submit a full bug report, "
+ 		   "with preprocessed source (by using -freport-bug).\n");
+ 
+ 	if (count > 0)
+ 	  fnotice (stderr, "Please include the complete backtrace "
+ 		   "with any bug report.\n");
+ 	fnotice (stderr, "See %s for instructions.\n", bug_report_url);
+ 
+ 	exit (ICE_EXIT_CODE);
+       }
+ 
+     case kind::fatal:
+       if (m_abort_on_error)
+ 	real_abort ();
+       fnotice (stderr, "compilation terminated.\n");
+       finish ();
+       exit (FATAL_EXIT_CODE);
+ 
+     default:
+       gcc_unreachable ();
+     }
+ }
+ 
+ /* State whether we should inhibit notes in the current diagnostic_group and
+    its future children if any.  */
+ 
+ void
+ context::inhibit_notes_in_group (bool inhibit)
+ {
+   int curr_depth = (m_diagnostic_groups.m_group_nesting_depth
+ 		    + m_diagnostic_groups.m_diagnostic_nesting_level);
+ 
+   if (inhibit)
+     {
+       /* If we're already inhibiting, there's nothing to do.  */
+       if (m_diagnostic_groups.m_inhibiting_notes_from)
+ 	return;
+ 
+       /* Since we're called via warning/error/... that all have their own
+ 	 diagnostic_group, we must consider that we started inhibiting in their
+ 	 parent.  */
+       gcc_assert (m_diagnostic_groups.m_group_nesting_depth > 0);
+       m_diagnostic_groups.m_inhibiting_notes_from = curr_depth - 1;
+     }
+   else if (m_diagnostic_groups.m_inhibiting_notes_from)
+     {
+       /* Only cancel inhibition at the depth that set it up.  */
+       if (curr_depth >= m_diagnostic_groups.m_inhibiting_notes_from)
+ 	return;
+ 
+       m_diagnostic_groups.m_inhibiting_notes_from = 0;
+     }
+ }
+ 
+ /* Return whether notes must be inhibited in the current diagnostic_group.  */
+ 
+ bool
+ context::notes_inhibited_in_group () const
+ {
+   if (m_diagnostic_groups.m_inhibiting_notes_from
+       && (m_diagnostic_groups.m_group_nesting_depth
+ 	  + m_diagnostic_groups.m_diagnostic_nesting_level
+ 	  >= m_diagnostic_groups.m_inhibiting_notes_from))
+     return true;
+   return false;
+ }
+ 
+ /* class diagnostics::logical_locations::manager.  */
+ 
+ /* Return true iff this is a function or method.  */
+ 
+ bool
+ logical_locations::manager::function_p (key k) const
+ {
+   switch (get_kind (k))
+     {
+     default:
+       gcc_unreachable ();
+     case kind::unknown:
+     case kind::module_:
+     case kind::namespace_:
+     case kind::type:
+     case kind::return_type:
+     case kind::parameter:
+     case kind::variable:
+       return false;
+ 
+     case kind::function:
+     case kind::member:
+       return true;
+     }
+ }
+ 
+ /* Helper function for print_parseable_fixits.  Print TEXT to PP, obeying the
+    escaping rules for -fdiagnostics-parseable-fixits.  */
+ 
+ static void
+ print_escaped_string (pretty_printer *pp, const char *text)
+ {
+   gcc_assert (pp);
+   gcc_assert (text);
+ 
+   pp_character (pp, '"');
+   for (const char *ch = text; *ch; ch++)
+     {
+       switch (*ch)
+ 	{
+ 	case '\\':
+ 	  /* Escape backslash as two backslashes.  */
+ 	  pp_string (pp, "\\\\");
+ 	  break;
+ 	case '\t':
+ 	  /* Escape tab as "\t".  */
+ 	  pp_string (pp, "\\t");
+ 	  break;
+ 	case '\n':
+ 	  /* Escape newline as "\n".  */
+ 	  pp_string (pp, "\\n");
+ 	  break;
+ 	case '"':
+ 	  /* Escape doublequotes as \".  */
+ 	  pp_string (pp, "\\\"");
+ 	  break;
+ 	default:
+ 	  if (ISPRINT (*ch))
+ 	    pp_character (pp, *ch);
+ 	  else
+ 	    /* Use octal for non-printable chars.  */
+ 	    {
+ 	      unsigned char c = (*ch & 0xff);
+ 	      pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
+ 	    }
+ 	  break;
+ 	}
+     }
+   pp_character (pp, '"');
+ }
+ 
+ /* Implementation of -fdiagnostics-parseable-fixits and
+    GCC_EXTRA_DIAGNOSTIC_OUTPUT.
+    Print a machine-parseable version of all fixits in RICHLOC to PP,
+    using COLUMN_UNIT to express columns.
+    Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY.  */
+ 
+ static void
+ print_parseable_fixits (file_cache &fc,
+ 			pretty_printer *pp, rich_location *richloc,
+ 			enum diagnostics_column_unit column_unit,
+ 			int tabstop)
+ {
+   gcc_assert (pp);
+   gcc_assert (richloc);
+ 
+   char *saved_prefix = pp_take_prefix (pp);
+   pp_set_prefix (pp, nullptr);
+ 
+   for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
+     {
+       const fixit_hint *hint = richloc->get_fixit_hint (i);
+       location_t start_loc = hint->get_start_loc ();
+       expanded_location start_exploc = expand_location (start_loc);
+       pp_string (pp, "fix-it:");
+       print_escaped_string (pp, start_exploc.file);
+       /* For compatibility with clang, print as a half-open range.  */
+       location_t next_loc = hint->get_next_loc ();
+       expanded_location next_exploc = expand_location (next_loc);
+       int start_col
+ 	= convert_column_unit (fc, column_unit, tabstop, start_exploc);
+       int next_col
+ 	= convert_column_unit (fc, column_unit, tabstop, next_exploc);
+       pp_printf (pp, ":{%i:%i-%i:%i}:",
+ 		 start_exploc.line, start_col,
+ 		 next_exploc.line, next_col);
+       print_escaped_string (pp, hint->get_string ());
+       pp_newline (pp);
+     }
+ 
+   pp_set_prefix (pp, saved_prefix);
+ }
+ 
+ /* Update the inlining info in this context for a DIAGNOSTIC.  */
+ 
+ void
+ context::get_any_inlining_info (diagnostic_info *diagnostic)
+ {
+   auto &ilocs = diagnostic->m_iinfo.m_ilocs;
+ 
+   if (m_set_locations_cb)
+     /* Retrieve the locations into which the expression about to be
+        diagnosed has been inlined, including those of all the callers
+        all the way down the inlining stack.  */
+     m_set_locations_cb (this, diagnostic);
+   else
+     {
+       /* When there's no callback use just the one location provided
+ 	 by the caller of the diagnostic function.  */
+       location_t loc = diagnostic_location (diagnostic);
+       ilocs.safe_push (loc);
+       diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
+     }
+ }
+ 
+ /* Generate a URL string describing CWE.  The caller is responsible for
+    freeing the string.  */
+ 
+ char *
+ get_cwe_url (int cwe)
+ {
+   return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
+ }
+ 
+ /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
+    as appropriate for #pragma GCC diagnostic and -Werror=foo.  */
+ 
+ bool
+ context::diagnostic_enabled (diagnostic_info *diagnostic)
+ {
+   /* Update the inlining stack for this diagnostic.  */
+   get_any_inlining_info (diagnostic);
+ 
+   /* Diagnostics with no option or -fpermissive are always enabled.  */
+   if (!diagnostic->m_option_id.m_idx
+       || diagnostic->m_option_id == m_opt_permissive)
+     return true;
+ 
+   /* This tests if the user provided the appropriate -Wfoo or
+      -Wno-foo option.  */
+   if (!option_enabled_p (diagnostic->m_option_id))
+     return false;
+ 
+   /* This tests for #pragma diagnostic changes.  */
+   enum kind diag_class
+     = m_option_classifier.update_effective_level_from_pragmas (diagnostic);
+ 
+   /* This tests if the user provided the appropriate -Werror=foo
+      option.  */
+   if (diag_class == kind::unspecified
+       && !option_unspecified_p (diagnostic->m_option_id))
+     {
+       const enum kind new_kind
+ 	= m_option_classifier.get_current_override (diagnostic->m_option_id);
+       if (new_kind != kind::any)
+ 	/* kind::any means the diagnostic is not to be ignored, but we don't want
+ 	   to change it specifically to kind::error or kind::warning; we want to
+ 	   preserve whatever the caller has specified.  */
+ 	diagnostic->m_kind = new_kind;
+     }
+ 
+   /* This allows for future extensions, like temporarily disabling
+      warnings for ranges of source code.  */
+   if (diagnostic->m_kind == kind::ignored)
+     return false;
+ 
+   return true;
+ }
+ 
+ /* Returns whether warning OPT_ID is enabled at LOC.  */
+ 
+ bool
+ context::warning_enabled_at (location_t loc,
+ 			     option_id opt_id)
+ {
+   if (!diagnostic_report_warnings_p (this, loc))
+     return false;
+ 
+   rich_location richloc (line_table, loc);
+   diagnostic_info diagnostic = {};
+   diagnostic.m_option_id = opt_id;
+   diagnostic.m_richloc = &richloc;
+   diagnostic.m_message.m_richloc = &richloc;
+   diagnostic.m_kind = kind::warning;
+   return diagnostic_enabled (&diagnostic);
+ }
+ 
+ /* Emit a diagnostic within a diagnostic group on this context.  */
+ 
+ bool
+ context::emit_diagnostic_with_group (enum kind kind,
+ 				     rich_location &richloc,
+ 				     const metadata *metadata,
+ 				     option_id opt_id,
+ 				     const char *gmsgid, ...)
+ {
+   begin_group ();
+ 
+   va_list ap;
+   va_start (ap, gmsgid);
+   bool ret = emit_diagnostic_with_group_va (kind, richloc, metadata, opt_id,
+ 					    gmsgid, &ap);
+   va_end (ap);
+ 
+   end_group ();
+ 
+   return ret;
+ }
+ 
+ /* As above, but taking a va_list *.  */
+ 
+ bool
+ context::emit_diagnostic_with_group_va (enum kind kind,
+ 					rich_location &richloc,
+ 					const metadata *metadata,
+ 					option_id opt_id,
+ 					const char *gmsgid, va_list *ap)
+ {
+   begin_group ();
+ 
+   bool ret = diagnostic_impl (&richloc, metadata, opt_id,
+ 			      gmsgid, ap, kind);
+ 
+   end_group ();
+ 
+   return ret;
+ }
+ 
+ /* Report a diagnostic message (an error or a warning) as specified by
+    this diagnostics::context.
+    front-end independent format specifiers are exactly those described
+    in the documentation of output_format.
+    Return true if a diagnostic was printed, false otherwise.  */
+ 
+ bool
+ context::report_diagnostic (diagnostic_info *diagnostic)
+ {
+   enum kind orig_diag_kind = diagnostic->m_kind;
+ 
+   /* Every call to report_diagnostic should be within a
+      begin_group/end_group pair so that output formats can reliably
+      flush diagnostics with on_end_group when the topmost group is ended.  */
+   gcc_assert (m_diagnostic_groups.m_group_nesting_depth > 0);
+ 
+   /* Give preference to being able to inhibit warnings, before they
+      get reclassified to something else.  */
+   bool was_warning = (diagnostic->m_kind == kind::warning
+ 		      || diagnostic->m_kind == kind::pedwarn);
+   if (was_warning && m_inhibit_warnings)
+     {
+       inhibit_notes_in_group ();
+       return false;
+     }
+ 
+   if (m_adjust_diagnostic_info)
+     m_adjust_diagnostic_info (this, diagnostic);
+ 
+   if (diagnostic->m_kind == kind::pedwarn)
+     {
+       diagnostic->m_kind = m_pedantic_errors ? kind::error : kind::warning;
+ 
+       /* We do this to avoid giving the message for -pedantic-errors.  */
+       orig_diag_kind = diagnostic->m_kind;
+     }
+ 
+   if (diagnostic->m_kind == kind::note && m_inhibit_notes_p)
+     return false;
+ 
+   /* If the user requested that warnings be treated as errors, so be
+      it.  Note that we do this before the next block so that
+      individual warnings can be overridden back to warnings with
+      -Wno-error=*.  */
+   if (m_warning_as_error_requested
+       && diagnostic->m_kind == kind::warning)
+     diagnostic->m_kind = kind::error;
+ 
+   diagnostic->m_message.m_data = &diagnostic->m_x_data;
+ 
+   /* Check to see if the diagnostic is enabled at the location and
+      not disabled by #pragma GCC diagnostic anywhere along the inlining
+      stack.  .  */
+   if (!diagnostic_enabled (diagnostic))
+     {
+       inhibit_notes_in_group ();
+       return false;
+     }
+ 
+   if ((was_warning || diagnostic->m_kind == kind::warning)
+       && ((!m_warn_system_headers
+ 	   && diagnostic->m_iinfo.m_allsyslocs)
+ 	  || m_inhibit_warnings))
+     /* Bail if the warning is not to be reported because all locations in the
+        inlining stack (if there is one) are in system headers.  */
+     return false;
+ 
+   if (diagnostic->m_kind == kind::note && notes_inhibited_in_group ())
+     /* Bail for all the notes in the diagnostic_group that started to inhibit notes.  */
+     return false;
+ 
+   if (diagnostic->m_kind != kind::note && diagnostic->m_kind != kind::ice)
+     check_max_errors (false);
+ 
+   if (m_lock > 0)
+     {
+       /* If we're reporting an ICE in the middle of some other error,
+ 	 try to flush out the previous error, then let this one
+ 	 through.  Don't do this more than once.  */
+       if ((diagnostic->m_kind == kind::ice
+ 	   || diagnostic->m_kind == kind::ice_nobt)
+ 	  && m_lock == 1)
+ 	pp_newline_and_flush (m_reference_printer);
+       else
+ 	error_recursion ();
+     }
+ 
+   /* We are accepting the diagnostic, so should stop inhibiting notes.  */
+   inhibit_notes_in_group (/*inhibit=*/false);
+ 
+   m_lock++;
+ 
+   if (diagnostic->m_kind == kind::ice || diagnostic->m_kind == kind::ice_nobt)
+     {
+       /* When not checking, ICEs are converted to fatal errors when an
+ 	 error has already occurred.  This is counteracted by
+ 	 abort_on_error.  */
+       if (!CHECKING_P
+ 	  && (diagnostic_count (kind::error) > 0
+ 	      || diagnostic_count (kind::sorry) > 0)
+ 	  && !m_abort_on_error)
+ 	{
+ 	  expanded_location s
+ 	    = expand_location (diagnostic_location (diagnostic));
+ 	  fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
+ 		   s.file, s.line);
+ 	  exit (ICE_EXIT_CODE);
+ 	}
+       if (m_internal_error)
+ 	(*m_internal_error) (this,
+ 			     diagnostic->m_message.m_format_spec,
+ 			     diagnostic->m_message.m_args_ptr);
+     }
+ 
+   /* Increment the counter for the appropriate diagnostic kind, either
+      within this context, or within the diagnostic_buffer.  */
+   {
+     const enum kind kind_for_count =
+       ((diagnostic->m_kind == kind::error && orig_diag_kind == kind::warning)
+        ? kind::werror
+        : diagnostic->m_kind);
+     counters &cs
+       = (m_diagnostic_buffer
+ 	 ? m_diagnostic_buffer->m_diagnostic_counters
+ 	 : m_diagnostic_counters);
+     ++cs.m_count_for_kind[static_cast<size_t> (kind_for_count)];
+   }
+ 
+   /* Is this the initial diagnostic within the stack of groups?  */
+   if (m_diagnostic_groups.m_emission_count == 0)
+     for (auto sink_ : m_sinks)
+       sink_->on_begin_group ();
+   m_diagnostic_groups.m_emission_count++;
+ 
+   va_list *orig_args = diagnostic->m_message.m_args_ptr;
+   for (auto sink_ : m_sinks)
+     {
+       /* Formatting the message is done per-output-format,
+ 	 so that each output format gets its own set of pp_token_lists
+ 	 to work with.
+ 
+ 	 Run phases 1 and 2 of formatting the message before calling
+ 	 the format's on_report_diagnostic.
+ 	 In particular, some format codes may have side-effects here which
+ 	 need to happen before sending the diagnostic to the output format.
+ 	 For example, Fortran's %C and %L formatting codes populate the
+ 	 rich_location.
+ 	 Such side-effects must be idempotent, since they are run per
+ 	 output-format.
+ 
+ 	 Make a duplicate of the varargs for each call to pp_format,
+ 	 so that each has its own set to consume.  */
+       va_list copied_args;
+       va_copy (copied_args, *orig_args);
+       diagnostic->m_message.m_args_ptr = &copied_args;
+       pp_format (sink_->get_printer (), &diagnostic->m_message);
+       va_end (copied_args);
+ 
+       /* Call vfunc in the output format.  This is responsible for
+ 	 phase 3 of formatting, and for printing the result.  */
+       sink_->on_report_diagnostic (*diagnostic, orig_diag_kind);
+     }
+ 
+   switch (m_extra_output_kind)
+     {
+     default:
+       break;
+     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
+       print_parseable_fixits (get_file_cache (),
+ 			      m_reference_printer, diagnostic->m_richloc,
+ 			      DIAGNOSTICS_COLUMN_UNIT_BYTE,
+ 			      m_tabstop);
+       pp_flush (m_reference_printer);
+       break;
+     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
+       print_parseable_fixits (get_file_cache (),
+ 			      m_reference_printer, diagnostic->m_richloc,
+ 			      DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
+ 			      m_tabstop);
+       pp_flush (m_reference_printer);
+       break;
+     }
+   if (m_diagnostic_buffer == nullptr
+       || diagnostic->m_kind == kind::ice
+       || diagnostic->m_kind == kind::ice_nobt)
+     action_after_output (diagnostic->m_kind);
+   diagnostic->m_x_data = nullptr;
+ 
+   if (m_fixits_change_set)
+     if (diagnostic->m_richloc->fixits_can_be_auto_applied_p ())
+       if (!m_diagnostic_buffer)
+ 	m_fixits_change_set->add_fixits (diagnostic->m_richloc);
+ 
+   m_lock--;
+ 
+   if (!m_diagnostic_buffer)
+     for (auto sink_ : m_sinks)
+       sink_->after_diagnostic (*diagnostic);
+ 
+   return true;
+ }
+ 
+ void
+ context::report_verbatim (text_info &text)
+ {
+   va_list *orig_args = text.m_args_ptr;
+   for (auto sink_ : m_sinks)
+     {
+       va_list copied_args;
+       va_copy (copied_args, *orig_args);
+       text.m_args_ptr = &copied_args;
+       sink_->on_report_verbatim (text);
+       va_end (copied_args);
+     }
+ }
+ 
+ void
+ context::report_global_digraph (const lazily_created<digraphs::digraph> &ldg)
+ {
+   for (auto sink_ : m_sinks)
+     sink_->report_global_digraph (ldg);
+ }
+ 
+ /* Get the number of digits in the decimal representation of VALUE.  */
+ 
+ int
+ num_digits (int value)
+ {
+   /* Perhaps simpler to use log10 for this, but doing it this way avoids
+      using floating point.  */
+   gcc_assert (value >= 0);
+ 
+   if (value == 0)
+     return 1;
+ 
+   int digits = 0;
+   while (value > 0)
+     {
+       digits++;
+       value /= 10;
+     }
+   return digits;
+ }
+ 
+ } // namespace diagnostics
+ 
+ /* Given a partial pathname as input, return another pathname that
+    shares no directory elements with the pathname of __FILE__.  This
+    is used by fancy_abort() to print `internal compiler error in expr.cc'
+    instead of `internal compiler error in ../../GCC/gcc/expr.cc'.  */
+ 
+ const char *
+ trim_filename (const char *name)
+ {
+   static const char this_file[] = __FILE__;
+   const char *p = name, *q = this_file;
+ 
+   /* First skip any "../" in each filename.  This allows us to give a proper
+      reference to a file in a subdirectory.  */
+   while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
+     p += 3;
+ 
+   while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
+     q += 3;
+ 
+   /* Now skip any parts the two filenames have in common.  */
+   while (*p == *q && *p != 0 && *q != 0)
+     p++, q++;
+ 
+   /* Now go backwards until the previous directory separator.  */
+   while (p > name && !IS_DIR_SEPARATOR (p[-1]))
+     p--;
+ 
+   return p;
+ }
+ 
+ namespace diagnostics {
+ 
+ /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
+    permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
+    and internal_error_no_backtrace, as documented and defined below.  */
+ bool
+ context::diagnostic_impl (rich_location *richloc,
+ 			  const metadata *metadata,
+ 			  option_id opt_id,
+ 			  const char *gmsgid,
+ 			  va_list *ap, enum kind kind)
+ {
+   diagnostic_info diagnostic;
+   if (kind == diagnostics::kind::permerror)
+     {
+       diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
+ 			   (m_permissive
+ 			    ? diagnostics::kind::warning
+ 			    : diagnostics::kind::error));
+       diagnostic.m_option_id = (opt_id.m_idx != -1 ? opt_id : m_opt_permissive);
+     }
+   else
+     {
+       diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
+       if (kind == diagnostics::kind::warning
+ 	  || kind == diagnostics::kind::pedwarn)
+ 	diagnostic.m_option_id = opt_id;
+     }
+   diagnostic.m_metadata = metadata;
+   return report_diagnostic (&diagnostic);
+ }
+ 
+ /* Implement inform_n, warning_n, and error_n, as documented and
+    defined below.  */
+ bool
+ context::diagnostic_n_impl (rich_location *richloc,
+ 			    const metadata *metadata,
+ 			    option_id opt_id,
+ 			    unsigned HOST_WIDE_INT n,
+ 			    const char *singular_gmsgid,
+ 			    const char *plural_gmsgid,
+ 			    va_list *ap, enum kind kind)
+ {
+   diagnostic_info diagnostic;
+   unsigned long gtn;
+ 
+   if (sizeof n <= sizeof gtn)
+     gtn = n;
+   else
+     /* Use the largest number ngettext can handle, otherwise
+        preserve the six least significant decimal digits for
+        languages where the plural form depends on them.  */
+     gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
+ 
+   const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
+   diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
+   if (kind == diagnostics::kind::warning)
+     diagnostic.m_option_id = opt_id;
+   diagnostic.m_metadata = metadata;
+   return report_diagnostic (&diagnostic);
+ }
+ 
+ 
+ /* Emit DIAGRAM to this context, respecting the output format.  */
+ 
+ void
+ context::emit_diagram (const diagram &diag)
+ {
+   if (m_diagrams.m_theme == nullptr)
+     return;
+ 
+   for (auto sink_ : m_sinks)
+     sink_->on_diagram (diag);
+ }
+ 
+ /* Inform the user that an error occurred while trying to report some
+    other error.  This indicates catastrophic internal inconsistencies,
+    so give up now.  But do try to flush out the previous error.
+    This mustn't use internal_error, that will cause infinite recursion.  */
+ 
+ void
+ context::error_recursion ()
+ {
+   if (m_lock < 3)
+     pp_newline_and_flush (m_reference_printer);
+ 
+   fnotice (stderr,
+ 	   "internal compiler error: error reporting routines re-entered.\n");
+ 
+   /* Call action_after_output to get the "please submit a bug report"
+      message.  */
+   action_after_output (kind::ice);
+ 
+   /* Do not use gcc_unreachable here; that goes through internal_error
+      and therefore would cause infinite recursion.  */
+   real_abort ();
+ }
+ 
+ } // namespace diagnostics
+ 
+ /* Report an internal compiler error in a friendly manner.  This is
+    the function that gets called upon use of abort() in the source
+    code generally, thanks to a special macro.  */
+ 
+ void
+ fancy_abort (const char *file, int line, const char *function)
+ {
+   /* If fancy_abort is called before the diagnostic subsystem is initialized,
+      internal_error will crash internally in a way that prevents a
+      useful message reaching the user.
+      This can happen with libgccjit in the case of gcc_assert failures
+      that occur outside of the libgccjit mutex that guards the rest of
+      gcc's state, including global_dc (when global_dc may not be
+      initialized yet, or might be in use by another thread).
+      Handle such cases as gracefully as possible by falling back to a
+      minimal abort handler that only relies on i18n.  */
+   if (global_dc->get_reference_printer () == nullptr)
+     {
+       /* Print the error message.  */
+       fnotice (stderr, diagnostics::get_text_for_kind (diagnostics::kind::ice));
+       fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
+       fputc ('\n', stderr);
+ 
+       /* Attempt to print a backtrace.  */
+       struct backtrace_state *state
+ 	= backtrace_create_state (nullptr, 0, bt_err_callback, nullptr);
+       int count = 0;
+       if (state != nullptr)
+ 	backtrace_full (state, 2, bt_callback, bt_err_callback,
+ 			(void *) &count);
+ 
+       /* We can't call warn_if_plugins or emergency_dump_function as these
+ 	 rely on GCC state that might not be initialized, or might be in
+ 	 use by another thread.  */
+ 
+       /* Abort the process.  */
+       real_abort ();
+     }
+ 
+   internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
+ }
+ 
+ namespace diagnostics {
+ 
+ /* class diagnostics::context.  */
+ 
+ void
+ context::begin_group ()
+ {
+   m_diagnostic_groups.m_group_nesting_depth++;
+ }
+ 
+ void
+ context::end_group ()
+ {
+   if (--m_diagnostic_groups.m_group_nesting_depth == 0)
+     {
+       /* Handle the case where we've popped the final diagnostic group.
+ 	 If any diagnostics were emitted, give the context a chance
+ 	 to do something.  */
+       if (m_diagnostic_groups.m_emission_count > 0)
+ 	for (auto sink_ : m_sinks)
+ 	  sink_->on_end_group ();
+       m_diagnostic_groups.m_emission_count = 0;
+     }
+   /* We're popping one level, so might need to stop inhibiting notes.  */
+   inhibit_notes_in_group (/*inhibit=*/false);
+ }
+ 
+ void
+ context::push_nesting_level ()
+ {
+   ++m_diagnostic_groups.m_diagnostic_nesting_level;
+ }
+ 
+ void
+ context::pop_nesting_level ()
+ {
+   --m_diagnostic_groups.m_diagnostic_nesting_level;
+   /* We're popping one level, so might need to stop inhibiting notes.  */
+   inhibit_notes_in_group (/*inhibit=*/false);
+ }
+ 
+ void
+ sink::dump (FILE *out, int indent) const
+ {
+   fprintf (out, "%*sprinter:\n", indent, "");
+   m_printer->dump (out, indent + 2);
+ }
+ 
+ void
+ sink::on_report_verbatim (text_info &)
+ {
+   /* No-op.  */
+ }
+ 
+ /* Set the output format for DC to FORMAT, using BASE_FILE_NAME for
+    file-based output formats.  */
+ 
+ void
+ output_format_init (context &dc,
+ 		    const char *main_input_filename_,
+ 		    const char *base_file_name,
+ 		    enum diagnostics_output_format format,
+ 		    bool json_formatting)
+ {
+   sink *new_sink = nullptr;
+   switch (format)
+     {
+     default:
+       gcc_unreachable ();
+     case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
+       /* The default; do nothing.  */
+       break;
+ 
+     case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
+       new_sink = &init_sarif_stderr (dc,
+ 				     line_table,
+ 				     json_formatting);
+       break;
+ 
+     case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
+       new_sink = &init_sarif_file (dc,
+ 				   line_table,
+ 				   json_formatting,
+ 				   base_file_name);
+       break;
+     }
+   if (new_sink)
+     new_sink->set_main_input_filename (main_input_filename_);
+ }
+ 
+ /* Initialize this context's m_diagrams based on CHARSET.
+    Specifically, make a text_art::theme object for m_diagrams.m_theme,
+    (or nullptr for "no diagrams").  */
+ 
+ void
+ context::set_text_art_charset (enum diagnostic_text_art_charset charset)
+ {
+   delete m_diagrams.m_theme;
+   switch (charset)
+     {
+     default:
+       gcc_unreachable ();
+ 
+     case DIAGNOSTICS_TEXT_ART_CHARSET_NONE:
+       m_diagrams.m_theme = nullptr;
+       break;
+ 
+     case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII:
+       m_diagrams.m_theme = new text_art::ascii_theme ();
+       break;
+ 
+     case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE:
+       m_diagrams.m_theme = new text_art::unicode_theme ();
+       break;
+ 
+     case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI:
+       m_diagrams.m_theme = new text_art::emoji_theme ();
+       break;
+     }
+ }
+ 
+ /* struct diagnostics::counters.  */
+ 
+ counters::counters ()
+ {
+   clear ();
+ }
+ 
+ void
+ counters::dump (FILE *out, int indent) const
+ {
+   fprintf (out, "%*scounts:\n", indent, "");
+   bool none = true;
+   for (int i = 0; i < static_cast<int> (kind::last_diagnostic_kind); i++)
+     if (m_count_for_kind[i] > 0)
+       {
+ 	fprintf (out, "%*s%s%i\n",
+ 		 indent + 2, "",
+ 		 get_text_for_kind (static_cast<enum kind> (i)),
+ 		 m_count_for_kind[i]);
+ 	none = false;
+       }
+   if (none)
+     fprintf (out, "%*s(none)\n", indent + 2, "");
+ }
+ 
+ void
+ counters::move_to (counters &dest)
+ {
+   for (int i = 0; i < static_cast<int> (kind::last_diagnostic_kind); i++)
+     dest.m_count_for_kind[i] += m_count_for_kind[i];
+   clear ();
+ }
+ 
+ void
+ counters::clear ()
+ {
+   memset (&m_count_for_kind, 0, sizeof m_count_for_kind);
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace selftest {
+ 
+ using line_table_test = ::selftest::line_table_test;
+ using temp_source_file = ::selftest::temp_source_file;
+ 
+ /* Helper function for test_print_escaped_string.  */
+ 
+ static void
+ assert_print_escaped_string (const ::selftest::location &loc,
+ 			     const char *expected_output,
+ 			     const char *input)
+ {
+   pretty_printer pp;
+   print_escaped_string (&pp, input);
+   ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
+ }
+ 
+ #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
+     assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
+ 
+ /* Tests of print_escaped_string.  */
+ 
+ static void
+ test_print_escaped_string ()
+ {
+   /* Empty string.  */
+   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
+ 
+   /* Non-empty string.  */
+   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
+ 
+   /* Various things that need to be escaped:  */
+   /* Backslash.  */
+   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
+ 				     "before\\after");
+   /* Tab.  */
+   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
+ 				     "before\tafter");
+   /* Newline.  */
+   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
+ 				     "before\nafter");
+   /* Double quote.  */
+   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
+ 				     "before\"after");
+ 
+   /* Non-printable characters: BEL: '\a': 0x07 */
+   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
+ 				     "before\aafter");
+   /* Non-printable characters: vertical tab: '\v': 0x0b */
+   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
+ 				     "before\vafter");
+ }
+ 
+ /* Tests of print_parseable_fixits.  */
+ 
+ /* Verify that print_parseable_fixits emits the empty string if there
+    are no fixits.  */
+ 
+ static void
+ test_print_parseable_fixits_none ()
+ {
+   pretty_printer pp;
+   file_cache fc;
+   rich_location richloc (line_table, UNKNOWN_LOCATION);
+ 
+   print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+   ASSERT_STREQ ("", pp_formatted_text (&pp));
+ }
+ 
+ /* Verify that print_parseable_fixits does the right thing if there
+    is an insertion fixit hint.  */
+ 
+ static void
+ test_print_parseable_fixits_insert ()
+ {
+   pretty_printer pp;
+   file_cache fc;
+   rich_location richloc (line_table, UNKNOWN_LOCATION);
+ 
+   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
+   linemap_line_start (line_table, 5, 100);
+   linemap_add (line_table, LC_LEAVE, false, nullptr, 0);
+   location_t where = linemap_position_for_column (line_table, 10);
+   richloc.add_fixit_insert_before (where, "added content");
+ 
+   print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
+ 		pp_formatted_text (&pp));
+ }
+ 
+ /* Verify that print_parseable_fixits does the right thing if there
+    is an removal fixit hint.  */
+ 
+ static void
+ test_print_parseable_fixits_remove ()
+ {
+   pretty_printer pp;
+   file_cache fc;
+   rich_location richloc (line_table, UNKNOWN_LOCATION);
+ 
+   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
+   linemap_line_start (line_table, 5, 100);
+   linemap_add (line_table, LC_LEAVE, false, nullptr, 0);
+   source_range where;
+   where.m_start = linemap_position_for_column (line_table, 10);
+   where.m_finish = linemap_position_for_column (line_table, 20);
+   richloc.add_fixit_remove (where);
+ 
+   print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
+ 		pp_formatted_text (&pp));
+ }
+ 
+ /* Verify that print_parseable_fixits does the right thing if there
+    is an replacement fixit hint.  */
+ 
+ static void
+ test_print_parseable_fixits_replace ()
+ {
+   pretty_printer pp;
+   file_cache fc;
+   rich_location richloc (line_table, UNKNOWN_LOCATION);
+ 
+   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
+   linemap_line_start (line_table, 5, 100);
+   linemap_add (line_table, LC_LEAVE, false, nullptr, 0);
+   source_range where;
+   where.m_start = linemap_position_for_column (line_table, 10);
+   where.m_finish = linemap_position_for_column (line_table, 20);
+   richloc.add_fixit_replace (where, "replacement");
+ 
+   print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
+ 		pp_formatted_text (&pp));
+ }
+ 
+ /* Verify that print_parseable_fixits correctly handles
+    DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN.  */
+ 
+ static void
+ test_print_parseable_fixits_bytes_vs_display_columns ()
+ {
+   line_table_test ltt;
+   rich_location richloc (line_table, UNKNOWN_LOCATION);
+ 
+   /* 1-based byte offsets:     12345677778888999900001234567.  */
+   const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
+   /* 1-based display cols:     123456[......7-8.....]9012345.  */
+   const int tabstop = 8;
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+   file_cache fc;
+   const char *const fname = tmp.get_filename ();
+ 
+   linemap_add (line_table, LC_ENTER, false, fname, 0);
+   linemap_line_start (line_table, 1, 100);
+   linemap_add (line_table, LC_LEAVE, false, nullptr, 0);
+   source_range where;
+   where.m_start = linemap_position_for_column (line_table, 12);
+   where.m_finish = linemap_position_for_column (line_table, 17);
+   richloc.add_fixit_replace (where, "color");
+ 
+   /* Escape fname.  */
+   pretty_printer tmp_pp;
+   print_escaped_string (&tmp_pp, fname);
+   char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
+ 
+   const int buf_len = strlen (escaped_fname) + 100;
+   char *const expected = XNEWVEC (char, buf_len);
+ 
+   {
+     pretty_printer pp;
+     print_parseable_fixits (fc, &pp, &richloc,
+ 			    DIAGNOSTICS_COLUMN_UNIT_BYTE,
+ 			    tabstop);
+     snprintf (expected, buf_len,
+ 	      "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
+     ASSERT_STREQ (expected, pp_formatted_text (&pp));
+   }
+   {
+     pretty_printer pp;
+     print_parseable_fixits (fc, &pp, &richloc,
+ 			    DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
+ 			    tabstop);
+     snprintf (expected, buf_len,
+ 	      "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
+     ASSERT_STREQ (expected, pp_formatted_text (&pp));
+   }
+ 
+   XDELETEVEC (expected);
+   free (escaped_fname);
+ }
+ 
+ /* Verify that
+      diagnostics::column_policy::get_location_text (..., SHOW_COLUMN, ...)
+    generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
+    colorization disabled.  */
+ 
+ static void
+ assert_location_text (const char *expected_loc_text,
+ 		      const char *filename, int line, int column,
+ 		      bool show_column,
+ 		      int origin = 1,
+ 		      enum diagnostics_column_unit column_unit
+ 			= DIAGNOSTICS_COLUMN_UNIT_BYTE)
+ {
+   diagnostics::selftest::test_context dc;
+   dc.m_column_unit = column_unit;
+   dc.m_column_origin = origin;
+ 
+   expanded_location xloc;
+   xloc.file = filename;
+   xloc.line = line;
+   xloc.column = column;
+   xloc.data = nullptr;
+   xloc.sysp = false;
+ 
+   diagnostics::column_policy column_policy (dc);
+   label_text actual_loc_text
+     = column_policy.get_location_text (xloc, show_column, false);
+   ASSERT_STREQ (expected_loc_text, actual_loc_text.get ());
+ }
+ 
+ /* Verify that get_location_text works as expected.  */
+ 
+ static void
+ test_get_location_text ()
+ {
+   const char *old_progname = progname;
+   progname = "PROGNAME";
+   assert_location_text ("PROGNAME:", nullptr, 0, 0, true);
+   char *built_in_colon = concat (special_fname_builtin (), ":", (char *) 0);
+   assert_location_text (built_in_colon, special_fname_builtin (),
+ 			42, 10, true);
+   free (built_in_colon);
+   assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
+   assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
+   assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
+   for (int origin = 0; origin != 2; ++origin)
+     assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
+   assert_location_text ("foo.c:", "foo.c", 0, 10, true);
+   assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
+   assert_location_text ("foo.c:", "foo.c", 0, 10, false);
+ 
+   diagnostics::maybe_line_and_column (INT_MAX, INT_MAX);
+   diagnostics::maybe_line_and_column (INT_MIN, INT_MIN);
+ 
+   {
+     /* In order to test display columns vs byte columns, we need to create a
+        file for location_get_source_line() to read.  */
+ 
+     const char *const content = "smile \xf0\x9f\x98\x82\n";
+     const int line_bytes = strlen (content) - 1;
+     const int def_tabstop = 8;
+     const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
+     const int display_width = cpp_display_width (content, line_bytes, policy);
+     ASSERT_EQ (line_bytes - 2, display_width);
+     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+     const char *const fname = tmp.get_filename ();
+     const int buf_len = strlen (fname) + 16;
+     char *const expected = XNEWVEC (char, buf_len);
+ 
+     snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
+     assert_location_text (expected, fname, 1, line_bytes, true,
+ 			  1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
+ 
+     snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
+     assert_location_text (expected, fname, 1, line_bytes, true,
+ 			  0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
+ 
+     snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
+     assert_location_text (expected, fname, 1, line_bytes, true,
+ 			  1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
+ 
+     snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
+     assert_location_text (expected, fname, 1, line_bytes, true,
+ 			  0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
+ 
+     XDELETEVEC (expected);
+   }
+ 
+ 
+   progname = old_progname;
+ }
+ 
+ /* Selftest for num_digits.  */
+ 
+ static void
+ test_num_digits ()
+ {
+   ASSERT_EQ (1, num_digits (0));
+   ASSERT_EQ (1, num_digits (9));
+   ASSERT_EQ (2, num_digits (10));
+   ASSERT_EQ (2, num_digits (99));
+   ASSERT_EQ (3, num_digits (100));
+   ASSERT_EQ (3, num_digits (999));
+   ASSERT_EQ (4, num_digits (1000));
+   ASSERT_EQ (4, num_digits (9999));
+   ASSERT_EQ (5, num_digits (10000));
+   ASSERT_EQ (5, num_digits (99999));
+   ASSERT_EQ (6, num_digits (100000));
+   ASSERT_EQ (6, num_digits (999999));
+   ASSERT_EQ (7, num_digits (1000000));
+   ASSERT_EQ (7, num_digits (9999999));
+   ASSERT_EQ (8, num_digits (10000000));
+   ASSERT_EQ (8, num_digits (99999999));
+ }
+ 
+ /* Run all of the selftests within this file.
+ 
+    According to https://gcc.gnu.org/pipermail/gcc/2021-November/237703.html
+    there are some language-specific assumptions within these tests, so only
+    run them from C/C++.  */
+ 
+ void
+ context_cc_tests ()
+ {
+   test_print_escaped_string ();
+   test_print_parseable_fixits_none ();
+   test_print_parseable_fixits_insert ();
+   test_print_parseable_fixits_remove ();
+   test_print_parseable_fixits_replace ();
+   test_print_parseable_fixits_bytes_vs_display_columns ();
+   test_get_location_text ();
+   test_num_digits ();
+ }
+ 
+ } // namespace diagnostics::selftest
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
+ 
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic pop
+ #endif
+ 
+ static void real_abort (void) ATTRIBUTE_NORETURN;
+ 
+ /* Really call the system 'abort'.  This has to go right at the end of
+    this file, so that there are no functions after it that call abort
+    and get the system abort instead of our macro.  */
+ #undef abort
+ static void
+ real_abort (void)
+ {
+   abort ();
+ }
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/context.h gcc-16-20250727/gcc/diagnostics/context.h
*** gcc-16-20250720/gcc/diagnostics/context.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/context.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,959 ----
+ /* Declare diagnostics::context and related types.
+    Copyright (C) 2000-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_CONTEXT_H
+ #define GCC_DIAGNOSTICS_CONTEXT_H
+ 
+ #include "lazily-created.h"
+ #include "unique-argv.h"
+ #include "diagnostics/option-classifier.h"
+ #include "diagnostics/context-options.h"
+ 
+ namespace diagnostics {
+ 
+   namespace changes {
+     class change_set;
+   }
+ 
+   namespace digraphs { class digraph; }
+ 
+   namespace logical_locations {
+     class manager;
+   }
+ 
+   class buffer;
+   class client_data_hooks;
+   class diagram;
+   class sink;
+     class text_sink;
+ 
+   class source_effect_info;
+ 
+ } // namespace diagnostics
+ 
+ namespace text_art
+ {
+   class theme;
+ } // namespace text_art
+ 
+ namespace xml
+ {
+   class printer;
+ } // namespace xml
+ 
+ namespace diagnostics {
+ 
+ /*  Forward declarations.  */
+ class context;
+ class location_print_policy;
+ class source_print_policy;
+ 
+ typedef void (*text_starter_fn) (text_sink &,
+ 				 const diagnostic_info *);
+ 
+ struct to_text;
+ struct to_html;
+ 
+ extern pretty_printer *get_printer (to_text &);
+ 
+ template <typename TextOrHtml>
+ using start_span_fn = void (*) (const location_print_policy &,
+ 				TextOrHtml &text_or_html,
+ 				expanded_location);
+ 
+ typedef void (*text_finalizer_fn) (text_sink &,
+ 				   const diagnostic_info *,
+ 				   enum kind);
+ 
+ /* Abstract base class for the diagnostic subsystem to make queries
+    about command-line options.  */
+ 
+ class option_manager
+ {
+ public:
+   virtual ~option_manager () {}
+ 
+   /* Return 1 if option OPT_ID is enabled, 0 if it is disabled,
+      or -1 if it isn't a simple on-off switch
+      (or if the value is unknown, typically set later in target).  */
+   virtual int option_enabled_p (option_id opt_id) const = 0;
+ 
+   /* Return malloced memory for the name of the option OPT_ID
+      which enabled a diagnostic, originally of type ORIG_DIAG_KIND but
+      possibly converted to DIAG_KIND by options such as -Werror.
+      May return NULL if no name is to be printed.
+      May be passed 0 as well as the index of a particular option.  */
+   virtual char *make_option_name (option_id opt_id,
+ 				  enum kind orig_diag_kind,
+ 				  enum kind diag_kind) const = 0;
+ 
+   /* Return malloced memory for a URL describing the option that controls
+      a diagnostic.
+      May return NULL if no URL is available.
+      May be passed 0 as well as the index of a particular option.  */
+   virtual char *make_option_url (option_id opt_id) const = 0;
+ };
+ 
+ /* A bundle of options relating to printing the user's source code
+    (potentially with a margin, underlining, labels, etc).  */
+ 
+ struct source_printing_options
+ {
+   /* True if we should print the source line with a caret indicating
+      the location.
+      Corresponds to -fdiagnostics-show-caret.  */
+   bool enabled;
+ 
+   /* Maximum width of the source line printed.  */
+   int max_width;
+ 
+   /* Character used at the caret when printing source locations.  */
+   char caret_chars[rich_location::STATICALLY_ALLOCATED_RANGES];
+ 
+   /* When printing source code, should the characters at carets and ranges
+      be colorized? (assuming colorization is on at all).
+      This should be true for frontends that generate range information
+      (so that the ranges of code are colorized),
+      and false for frontends that merely specify points within the
+      source code (to avoid e.g. colorizing just the first character in
+      a token, which would look strange).  */
+   bool colorize_source_p;
+ 
+   /* When printing source code, should labelled ranges be printed?
+      Corresponds to -fdiagnostics-show-labels.  */
+   bool show_labels_p;
+ 
+   /* When printing source code, should there be a left-hand margin
+      showing line numbers?
+      Corresponds to -fdiagnostics-show-line-numbers.  */
+   bool show_line_numbers_p;
+ 
+   /* If printing source code, what should the minimum width of the margin
+      be?  Line numbers will be right-aligned, and padded to this width.
+      Corresponds to -fdiagnostics-minimum-margin-width=VALUE.  */
+   int min_margin_width;
+ 
+   /* Usable by plugins; if true, print a debugging ruler above the
+      source output.  */
+   bool show_ruler_p;
+ 
+   /* When printing events in an inline path, should we print lines
+      visualizing links between related events (e.g. for CFG paths)?
+      Corresponds to -fdiagnostics-show-event-links.  */
+   bool show_event_links_p;
+ };
+ 
+ /* A bundle of state for determining column numbers in diagnostics
+    (tab stops, whether to start at 0 or 1, etc).
+    Uses a file_cache to handle tabs.  */
+ 
+ class column_policy
+ {
+ public:
+   column_policy (const context &dc);
+ 
+   int converted_column (expanded_location s) const;
+ 
+   label_text get_location_text (const expanded_location &s,
+ 				bool show_column,
+ 				bool colorize) const;
+ 
+   int get_tabstop () const { return m_tabstop; }
+ 
+ private:
+   file_cache &m_file_cache;
+   enum diagnostics_column_unit m_column_unit;
+   int m_column_origin;
+   int m_tabstop;
+ };
+ 
+ /* A bundle of state for printing locations within diagnostics
+    (e.g. "FILENAME:LINE:COLUMN"), to isolate the interactions between
+    context and the start_span callbacks.  */
+ 
+ class location_print_policy
+ {
+ public:
+   location_print_policy (const context &dc);
+   location_print_policy (const text_sink &);
+ 
+   bool show_column_p () const { return m_show_column; }
+ 
+   const column_policy &
+   get_column_policy () const { return m_column_policy; }
+ 
+   void
+   print_text_span_start (const context &dc,
+ 			 pretty_printer &pp,
+ 			 const expanded_location &exploc);
+ 
+   void
+   print_html_span_start (const context &dc,
+ 			 xml::printer &xp,
+ 			 const expanded_location &exploc);
+ 
+ private:
+   column_policy m_column_policy;
+   bool m_show_column;
+ };
+ 
+ /* Abstract base class for optionally supplying extra tags when writing
+    out annotation labels in HTML output.  */
+ 
+ class html_label_writer
+ {
+ public:
+   virtual ~html_label_writer () {}
+   virtual void begin_label () = 0;
+   virtual void end_label () = 0;
+ };
+ 
+ /* A bundle of state for printing source within a diagnostic,
+    to isolate the interactions between context and the
+    implementation of diagnostic_show_locus.  */
+ 
+ class source_print_policy
+ {
+ public:
+   source_print_policy (const context &);
+   source_print_policy (const context &,
+ 		       const source_printing_options &);
+ 
+   void
+   print (pretty_printer &pp,
+ 	 const rich_location &richloc,
+ 	 enum kind diagnostic_kind,
+ 	 source_effect_info *effect_info) const;
+ 
+   void
+   print_as_html (xml::printer &xp,
+ 		 const rich_location &richloc,
+ 		 enum kind diagnostic_kind,
+ 		 source_effect_info *effect_info,
+ 		 html_label_writer *label_writer) const;
+ 
+   const source_printing_options &
+   get_options () const { return m_options; }
+ 
+   start_span_fn<to_text>
+   get_text_start_span_fn () const { return m_text_start_span_cb; }
+ 
+   start_span_fn<to_html>
+   get_html_start_span_fn () const { return m_html_start_span_cb; }
+ 
+   file_cache &
+   get_file_cache () const { return m_file_cache; }
+ 
+   enum diagnostics_escape_format
+   get_escape_format () const
+   {
+     return m_escape_format;
+   }
+ 
+   text_art::theme *
+   get_diagram_theme () const { return m_diagram_theme; }
+ 
+   const column_policy &get_column_policy () const
+   {
+     return m_location_policy.get_column_policy ();
+   }
+ 
+   const location_print_policy &get_location_policy () const
+   {
+     return m_location_policy;
+   }
+ 
+ private:
+   const source_printing_options &m_options;
+   location_print_policy m_location_policy;
+   start_span_fn<to_text> m_text_start_span_cb;
+   start_span_fn<to_html> m_html_start_span_cb;
+   file_cache &m_file_cache;
+ 
+   /* Other data copied from context.  */
+   text_art::theme *m_diagram_theme;
+   enum diagnostics_escape_format m_escape_format;
+ };
+ 
+ /* A collection of counters of diagnostics, per-kind
+    (e.g. "3 errors and 1 warning"), for use by both context
+    and by diagnostics::buffer.  */
+ 
+ struct counters
+ {
+   counters ();
+ 
+   void dump (FILE *out, int indent) const;
+   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
+ 
+   int get_count (enum kind kind) const
+   {
+     return m_count_for_kind[static_cast<size_t> (kind)];
+   }
+ 
+   void move_to (counters &dest);
+   void clear ();
+ 
+   int m_count_for_kind[static_cast<size_t> (kind::last_diagnostic_kind)];
+ };
+ 
+ /* This class encapsulates the state of the diagnostics subsystem
+    as a whole (either directly, or via owned objects of other classes, to
+    avoid global variables).
+ 
+    It has responsibility for:
+    - being a central place for clients to report diagnostics
+    - reporting those diagnostics to zero or more output sinks
+      (e.g. text vs SARIF)
+    - providing a "dump" member function for a debug dump of the state of
+      the diagnostics subsytem
+    - direct vs buffered diagnostics (see class diagnostics::buffer)
+    - tracking the original argv of the program (for SARIF output)
+    - crash-handling
+ 
+    It delegates responsibility to various other classes:
+    - the various output sinks (instances of diagnostics::sink
+      subclasses)
+    - formatting of messages (class pretty_printer)
+    - an optional urlifier to inject URLs into formatted messages
+    - counting the number of diagnostics reported of each kind
+      (class diagnostics::counters)
+    - calling out to a option_manager to determine if
+      a particular warning is enabled or disabled
+    - tracking pragmas that enable/disable warnings in a range of
+      source code
+    - a cache for use when quoting the user's source code (class file_cache)
+    - a text_art::theme
+    - a diagnostics::changes::change_set for generating patches from fix-it hints
+    - diagnostics::client_data_hooks for metadata.
+ 
+    Try to avoid adding new responsibilities to this class itself, to avoid
+    the "blob" anti-pattern.  */
+ 
+ class context
+ {
+ public:
+   /* Give access to m_text_callbacks.  */
+   // FIXME: these need updating
+   friend text_starter_fn &
+   text_starter (context *dc);
+   friend start_span_fn<to_text> &
+   start_span (context *dc);
+   friend text_finalizer_fn &
+   text_finalizer (context *dc);
+ 
+   friend class source_print_policy;
+   friend class text_sink;
+   friend class buffer;
+ 
+   typedef void (*set_locations_callback_t) (context *,
+ 					    diagnostic_info *);
+ 
+   void initialize (int n_opts);
+   void color_init (int value);
+   void urls_init (int value);
+   void set_pretty_printer (std::unique_ptr<pretty_printer> pp);
+   void refresh_output_sinks ();
+ 
+   void finish ();
+ 
+   void dump (FILE *out) const;
+   void DEBUG_FUNCTION dump () const { dump (stderr); }
+ 
+   bool execution_failed_p () const;
+ 
+   void set_original_argv (unique_argv original_argv);
+   const char * const *get_original_argv ()
+   {
+     return const_cast<const char * const *> (m_original_argv);
+   }
+ 
+   void set_set_locations_callback (set_locations_callback_t cb)
+   {
+     m_set_locations_cb = cb;
+   }
+ 
+   void
+   initialize_input_context (diagnostic_input_charset_callback ccb,
+ 			    bool should_skip_bom);
+ 
+   void begin_group ();
+   void end_group ();
+ 
+   void push_nesting_level ();
+   void pop_nesting_level ();
+ 
+   bool warning_enabled_at (location_t loc, option_id opt_id);
+ 
+   bool option_unspecified_p (option_id opt_id) const
+   {
+     return m_option_classifier.option_unspecified_p (opt_id);
+   }
+ 
+   bool emit_diagnostic_with_group (enum kind kind,
+ 				   rich_location &richloc,
+ 				   const metadata *metadata,
+ 				   option_id opt_id,
+ 				   const char *gmsgid, ...)
+     ATTRIBUTE_GCC_DIAG(6,7);
+   bool emit_diagnostic_with_group_va (enum kind kind,
+ 				      rich_location &richloc,
+ 				      const metadata *metadata,
+ 				      option_id opt_id,
+ 				      const char *gmsgid, va_list *ap)
+     ATTRIBUTE_GCC_DIAG(6,0);
+ 
+   bool report_diagnostic (diagnostic_info *);
+   void report_verbatim (text_info &);
+ 
+   /* Report a directed graph associated with the run as a whole
+      to any sinks that support directed graphs.  */
+   void
+   report_global_digraph (const lazily_created<digraphs::digraph> &);
+ 
+   enum kind
+   classify_diagnostic (option_id opt_id,
+ 		       enum kind new_kind,
+ 		       location_t where)
+   {
+     return m_option_classifier.classify_diagnostic (this,
+ 						    opt_id,
+ 						    new_kind,
+ 						    where);
+   }
+ 
+   void push_diagnostics (location_t where ATTRIBUTE_UNUSED)
+   {
+     m_option_classifier.push ();
+   }
+   void pop_diagnostics (location_t where)
+   {
+     m_option_classifier.pop (where);
+   }
+ 
+   void maybe_show_locus (const rich_location &richloc,
+ 			 const source_printing_options &opts,
+ 			 enum kind diagnostic_kind,
+ 			 pretty_printer &pp,
+ 			 source_effect_info *effect_info);
+   void maybe_show_locus_as_html (const rich_location &richloc,
+ 				 const source_printing_options &opts,
+ 				 enum kind diagnostic_kind,
+ 				 xml::printer &xp,
+ 				 source_effect_info *effect_info,
+ 				 html_label_writer *label_writer);
+ 
+   void emit_diagram (const diagram &diag);
+ 
+   /* Various setters for use by option-handling logic.  */
+   void set_sink (std::unique_ptr<sink> sink_);
+   void set_text_art_charset (enum diagnostic_text_art_charset charset);
+   void set_client_data_hooks (std::unique_ptr<client_data_hooks> hooks);
+ 
+   void push_owned_urlifier (std::unique_ptr<urlifier>);
+   void push_borrowed_urlifier (const urlifier &);
+   void pop_urlifier ();
+ 
+   void initialize_fixits_change_set ();
+   void set_warning_as_error_requested (bool val)
+   {
+     m_warning_as_error_requested = val;
+   }
+   void set_report_bug (bool val) { m_report_bug = val; }
+   void set_extra_output_kind (enum diagnostics_extra_output_kind kind)
+   {
+     m_extra_output_kind = kind;
+   }
+   void set_show_cwe (bool val) { m_show_cwe = val;  }
+   void set_show_rules (bool val) { m_show_rules = val; }
+   void set_show_highlight_colors (bool val);
+   void set_path_format (enum diagnostic_path_format val)
+   {
+     m_path_format = val;
+   }
+   void set_show_path_depths (bool val) { m_show_path_depths = val; }
+   void set_show_option_requested (bool val) { m_show_option_requested = val; }
+   void set_max_errors (int val) { m_max_errors = val; }
+   void set_escape_format (enum diagnostics_escape_format val)
+   {
+     m_escape_format = val;
+   }
+ 
+   void set_format_decoder (printer_fn format_decoder);
+   void set_prefixing_rule (diagnostic_prefixing_rule_t rule);
+ 
+   /* Various accessors.  */
+   bool warning_as_error_requested_p () const
+   {
+     return m_warning_as_error_requested;
+   }
+   bool show_path_depths_p () const { return m_show_path_depths; }
+   sink &get_sink (size_t idx) const;
+   enum diagnostic_path_format get_path_format () const { return m_path_format; }
+   enum diagnostics_escape_format get_escape_format () const
+   {
+     return m_escape_format;
+   }
+ 
+   file_cache &
+   get_file_cache () const
+   {
+     gcc_assert (m_file_cache);
+     return *m_file_cache;
+   }
+ 
+   changes::change_set *get_fixits_change_set () const
+   {
+     return m_fixits_change_set;
+   }
+   const client_data_hooks *get_client_data_hooks () const
+   {
+     return m_client_data_hooks;
+   }
+ 
+   const logical_locations::manager *
+   get_logical_location_manager () const;
+ 
+   const urlifier *get_urlifier () const;
+ 
+   text_art::theme *get_diagram_theme () const { return m_diagrams.m_theme; }
+ 
+   int &diagnostic_count (enum kind kind)
+   {
+     return m_diagnostic_counters.m_count_for_kind[static_cast<size_t> (kind)];
+   }
+   int diagnostic_count (enum kind kind) const
+   {
+     return m_diagnostic_counters.get_count (kind);
+   }
+ 
+   /* Option-related member functions.  */
+   inline bool option_enabled_p (option_id opt_id) const
+   {
+     if (!m_option_mgr)
+       return true;
+     return m_option_mgr->option_enabled_p (opt_id);
+   }
+ 
+   inline char *make_option_name (option_id opt_id,
+ 				 enum kind orig_diag_kind,
+ 				 enum kind diag_kind) const
+   {
+     if (!m_option_mgr)
+       return nullptr;
+     return m_option_mgr->make_option_name (opt_id,
+ 					   orig_diag_kind,
+ 					   diag_kind);
+   }
+ 
+   inline char *make_option_url (option_id opt_id) const
+   {
+     if (!m_option_mgr)
+       return nullptr;
+     return m_option_mgr->make_option_url (opt_id);
+   }
+ 
+   void
+   set_option_manager (std::unique_ptr<option_manager> mgr,
+ 		      unsigned lang_mask);
+ 
+   unsigned get_lang_mask () const
+   {
+     return m_lang_mask;
+   }
+ 
+   bool diagnostic_impl (rich_location *, const metadata *,
+ 			option_id, const char *,
+ 			va_list *, enum kind) ATTRIBUTE_GCC_DIAG(5,0);
+   bool diagnostic_n_impl (rich_location *, const metadata *,
+ 			  option_id, unsigned HOST_WIDE_INT,
+ 			  const char *, const char *, va_list *,
+ 			  enum kind) ATTRIBUTE_GCC_DIAG(7,0);
+ 
+   int get_diagnostic_nesting_level () const
+   {
+     return m_diagnostic_groups.m_diagnostic_nesting_level;
+   }
+ 
+   char *build_indent_prefix () const;
+ 
+   int
+   pch_save (FILE *f)
+   {
+     return m_option_classifier.pch_save (f);
+   }
+ 
+   int
+   pch_restore (FILE *f)
+   {
+     return m_option_classifier.pch_restore (f);
+   }
+ 
+ 
+   void set_diagnostic_buffer (buffer *);
+   buffer *get_diagnostic_buffer () const
+   {
+     return m_diagnostic_buffer;
+   }
+   void clear_diagnostic_buffer (buffer &);
+   void flush_diagnostic_buffer (buffer &);
+ 
+   std::unique_ptr<pretty_printer> clone_printer () const
+   {
+     return m_reference_printer->clone ();
+   }
+ 
+   pretty_printer *get_reference_printer () const
+   {
+     return m_reference_printer;
+   }
+ 
+   void
+   add_sink (std::unique_ptr<sink>);
+ 
+   void remove_all_output_sinks ();
+ 
+   bool supports_fnotice_on_stderr_p () const;
+ 
+   /* Raise SIGABRT on any diagnostic of severity kind::error or higher.  */
+   void
+   set_abort_on_error (bool val)
+   {
+     m_abort_on_error = val;
+   }
+ 
+   /* Accessor for use in serialization, e.g. by C++ modules.  */
+   auto &
+   get_classification_history ()
+   {
+     return m_option_classifier.m_classification_history;
+   }
+ 
+   void set_main_input_filename (const char *filename);
+ 
+   void
+   set_permissive_option (option_id opt_permissive)
+   {
+     m_opt_permissive = opt_permissive;
+   }
+ 
+   void
+   set_fatal_errors (bool fatal_errors)
+   {
+     m_fatal_errors = fatal_errors;
+   }
+ 
+   void
+   set_internal_error_callback (void (*cb) (context *,
+ 					   const char *,
+ 					   va_list *))
+   {
+     m_internal_error = cb;
+   }
+ 
+   void
+   set_adjust_diagnostic_info_callback (void (*cb) (context *,
+ 						   diagnostic_info *))
+   {
+     m_adjust_diagnostic_info = cb;
+   }
+ 
+   void
+   inhibit_notes () { m_inhibit_notes_p = true; }
+ 
+   source_printing_options &
+   get_source_printing_options ()
+   {
+     return m_source_printing;
+   }
+   const source_printing_options &
+   get_source_printing_options () const
+   {
+     return m_source_printing;
+   }
+ 
+   void set_caret_max_width (int value);
+ 
+ private:
+   void error_recursion () ATTRIBUTE_NORETURN;
+ 
+   bool diagnostic_enabled (diagnostic_info *diagnostic);
+ 
+   void get_any_inlining_info (diagnostic_info *diagnostic);
+ 
+   void check_max_errors (bool flush);
+   void action_after_output (enum kind diag_kind);
+ 
+   /* Data members.
+      Ideally, all of these would be private.  */
+ 
+ private:
+   /* A reference instance of pretty_printer created by the client
+      and owned by the context.  Used for cloning when creating/adding
+      output formats.
+      Owned by the context; this would be a std::unique_ptr if
+      context had a proper ctor.  */
+   pretty_printer *m_reference_printer;
+ 
+   /* Cache of source code.
+      Owned by the context; this would be a std::unique_ptr if
+      context had a proper ctor.  */
+   file_cache *m_file_cache;
+ 
+   /* The number of times we have issued diagnostics.  */
+   counters m_diagnostic_counters;
+ 
+   /* True if it has been requested that warnings be treated as errors.  */
+   bool m_warning_as_error_requested;
+ 
+   /* The number of option indexes that can be passed to warning() et
+      al.  */
+   int m_n_opts;
+ 
+   /* The stack of sets of overridden diagnostic option severities.  */
+   option_classifier m_option_classifier;
+ 
+   /* True if we should print any CWE identifiers associated with
+      diagnostics.  */
+   bool m_show_cwe;
+ 
+   /* True if we should print any rules associated with diagnostics.  */
+   bool m_show_rules;
+ 
+   /* How should diagnostics::paths::path objects be printed.  */
+   enum diagnostic_path_format m_path_format;
+ 
+   /* True if we should print stack depths when printing diagnostic paths.  */
+   bool m_show_path_depths;
+ 
+   /* True if we should print the command line option which controls
+      each diagnostic, if known.  */
+   bool m_show_option_requested;
+ 
+   /* True if we should raise a SIGABRT on errors.  */
+   bool m_abort_on_error;
+ 
+ public:
+   /* True if we should show the column number on diagnostics.  */
+   bool m_show_column;
+ 
+   /* True if pedwarns are errors.  */
+   bool m_pedantic_errors;
+ 
+   /* True if permerrors are warnings.  */
+   bool m_permissive;
+ 
+ private:
+   /* The option to associate with turning permerrors into warnings,
+      if any.  */
+   option_id m_opt_permissive;
+ 
+   /* True if errors are fatal.  */
+   bool m_fatal_errors;
+ 
+ public:
+   /* True if all warnings should be disabled.  */
+   bool m_inhibit_warnings;
+ 
+   /* True if warnings should be given in system headers.  */
+   bool m_warn_system_headers;
+ 
+ private:
+   /* Maximum number of errors to report.  */
+   int m_max_errors;
+ 
+   /* Client-supplied callbacks for use in text output.  */
+   struct {
+     /* This function is called before any message is printed out.  It is
+        responsible for preparing message prefix and such.  For example, it
+        might say:
+        In file included from "/usr/local/include/curses.h:5:
+        from "/home/gdr/src/nifty_printer.h:56:
+        ...
+     */
+     text_starter_fn m_begin_diagnostic;
+ 
+     /* This function is called by diagnostic_show_locus in between
+        disjoint spans of source code, so that the context can print
+        something to indicate that a new span of source code has begun.  */
+     start_span_fn<to_text> m_text_start_span;
+     start_span_fn<to_html> m_html_start_span;
+ 
+     /* This function is called after the diagnostic message is printed.  */
+     text_finalizer_fn m_end_diagnostic;
+   } m_text_callbacks;
+ 
+   /* Client hook to report an internal error.  */
+   void (*m_internal_error) (context *, const char *, va_list *);
+ 
+   /* Client hook to adjust properties of the given diagnostic that we're
+      about to issue, such as its kind.  */
+   void (*m_adjust_diagnostic_info)(context *, diagnostic_info *);
+ 
+   /* Owned by the context; this would be a std::unique_ptr if
+      context had a proper ctor.  */
+   option_manager *m_option_mgr;
+   unsigned m_lang_mask;
+ 
+   /* A stack of optional hooks for adding URLs to quoted text strings in
+      diagnostics.  Only used for the main diagnostic message.
+      Typically a single one owner by the context, but can be temporarily
+      overridden by a borrowed urlifier (e.g. on-stack).  */
+   struct urlifier_stack_node
+   {
+     urlifier *m_urlifier;
+     bool m_owned;
+   };
+   auto_vec<urlifier_stack_node> *m_urlifier_stack;
+ 
+ public:
+   /* Auxiliary data for client.  */
+   void *m_client_aux_data;
+ 
+   /* Used to detect that the last caret was printed at the same location.  */
+   location_t m_last_location;
+ 
+ private:
+   int m_lock;
+ 
+   bool m_inhibit_notes_p;
+ 
+   source_printing_options m_source_printing;
+ 
+   /* True if -freport-bug option is used.  */
+   bool m_report_bug;
+ 
+   /* Used to specify additional diagnostic output to be emitted after the
+      rest of the diagnostic.  This is for implementing
+      -fdiagnostics-parseable-fixits and GCC_EXTRA_DIAGNOSTIC_OUTPUT.  */
+   enum diagnostics_extra_output_kind m_extra_output_kind;
+ 
+ public:
+   /* What units to use when outputting the column number.  */
+   enum diagnostics_column_unit m_column_unit;
+ 
+   /* The origin for the column number (1-based or 0-based typically).  */
+   int m_column_origin;
+ 
+   /* The size of the tabstop for tab expansion.  */
+   int m_tabstop;
+ 
+ private:
+   /* How should non-ASCII/non-printable bytes be escaped when
+      a diagnostic suggests escaping the source code on output.  */
+   enum diagnostics_escape_format m_escape_format;
+ 
+   /* If non-NULL, a diagnostics::changes::change_set to which fix-it hints
+      should be applied, for generating patches.
+      Owned by the context; this would be a std::unique_ptr if
+      context had a proper ctor.  */
+   changes::change_set *m_fixits_change_set;
+ 
+   /* Fields relating to diagnostic groups.  */
+   struct {
+     /* How many diagnostic_group instances are currently alive.  */
+     int m_group_nesting_depth;
+ 
+     /* How many nesting levels have been pushed within this group.  */
+     int m_diagnostic_nesting_level;
+ 
+     /* How many diagnostics have been emitted since the bottommost
+        diagnostic_group was pushed.  */
+     int m_emission_count;
+ 
+     /* The "group+diagnostic" nesting depth from which to inhibit notes.  */
+     int m_inhibiting_notes_from;
+   } m_diagnostic_groups;
+ 
+   void inhibit_notes_in_group (bool inhibit = true);
+   bool notes_inhibited_in_group () const;
+ 
+   /* The various sinks to which diagnostics are to be outputted
+      (text vs structured formats such as SARIF).
+      The sinks are owned by the context; this would be a
+      std::vector<std::unique_ptr> if context had a
+      proper ctor.  */
+   auto_vec<sink *> m_sinks;
+ 
+   /* Callback to set the locations of call sites along the inlining
+      stack corresponding to a diagnostic location.  Needed to traverse
+      the BLOCK_SUPERCONTEXT() chain hanging off the LOCATION_BLOCK()
+      of a diagnostic's location.  */
+   set_locations_callback_t m_set_locations_cb;
+ 
+   /* A bundle of hooks for providing data to the context about its client
+      e.g. version information, plugins, etc.
+      Used by SARIF output to give metadata about the client that's
+      producing diagnostics.
+      Owned by the context; this would be a std::unique_ptr if
+      context had a proper ctor.  */
+   client_data_hooks *m_client_data_hooks;
+ 
+   /* Support for diagrams.  */
+   struct
+   {
+     /* Theme to use when generating diagrams.
+        Can be NULL (if text art is disabled).
+        Owned by the context; this would be a std::unique_ptr if
+        context had a proper ctor.  */
+     text_art::theme *m_theme;
+ 
+   } m_diagrams;
+ 
+   /* Owned by the context.  */
+   char **m_original_argv;
+ 
+   /* Borrowed pointer to the active diagnostics::buffer, if any.
+      If null (the default), then diagnostics that are reported to the
+      context are immediately issued to the output format.
+      If non-null, then diagnostics that are reported to the context
+      are buffered in the buffer, and may be issued to the output format
+      later (if the buffer is flushed), moved to other buffers, or
+      discarded (if the buffer is cleared).  */
+   buffer *m_diagnostic_buffer;
+ };
+ 
+ /* Client supplied function to announce a diagnostic
+    (for text-based diagnostic output).  */
+ inline text_starter_fn &
+ text_starter (context *dc)
+ {
+   return dc->m_text_callbacks.m_begin_diagnostic;
+ }
+ 
+ /* Client supplied function called between disjoint spans of source code,
+    so that the context can print
+    something to indicate that a new span of source code has begun.  */
+ inline start_span_fn<to_text> &
+ start_span (context *dc)
+ {
+   return dc->m_text_callbacks.m_text_start_span;
+ }
+ 
+ /* Client supplied function called after a diagnostic message is
+    displayed (for text-based diagnostic output).  */
+ inline text_finalizer_fn &
+ text_finalizer (context *dc)
+ {
+   return dc->m_text_callbacks.m_end_diagnostic;
+ }
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_CONTEXT_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/diagnostic-info.h gcc-16-20250727/gcc/diagnostics/diagnostic-info.h
*** gcc-16-20250720/gcc/diagnostics/diagnostic-info.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/diagnostic-info.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,75 ----
+ /* Various declarations for language-independent diagnostics subroutines.
+    Copyright (C) 2000-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_DIAGNOSTIC_INFO_H
+ #define GCC_DIAGNOSTICS_DIAGNOSTIC_INFO_H
+ 
+ namespace diagnostics {
+ 
+ class metadata;
+ 
+ /* A diagnostic is described by the MESSAGE to send, the FILE and LINE of
+    its context and its KIND (ice, error, warning, note, ...)  See complete
+    list in diagnostics/kinds.def.  */
+ 
+ struct diagnostic_info
+ {
+   diagnostic_info ()
+   : m_message (),
+     m_richloc (),
+     m_metadata (),
+     m_x_data (),
+     m_kind (),
+     m_option_id (),
+     m_iinfo ()
+   { }
+ 
+   /* Text to be formatted.  */
+   text_info m_message;
+ 
+   /* The location at which the diagnostic is to be reported.  */
+   rich_location *m_richloc;
+ 
+   /* An optional bundle of metadata associated with the diagnostic
+      (or NULL).  */
+   const metadata *m_metadata;
+ 
+   /* Auxiliary data for client.  */
+   void *m_x_data;
+   /* The kind of diagnostic it is about.  */
+   kind m_kind;
+   /* Which OPT_* directly controls this diagnostic.  */
+   option_id m_option_id;
+ 
+   /* Inlining context containing locations for each call site along
+      the inlining stack.  */
+   struct inlining_info
+   {
+     /* Locations along the inlining stack.  */
+     auto_vec<location_t, 8> m_ilocs;
+     /* The abstract origin of the location.  */
+     void *m_ao;
+     /* Set if every M_ILOCS element is in a system header.  */
+     bool m_allsyslocs;
+   } m_iinfo;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_DIAGNOSTIC_INFO_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/diagnostics-selftests.cc gcc-16-20250727/gcc/diagnostics/diagnostics-selftests.cc
*** gcc-16-20250720/gcc/diagnostics/diagnostics-selftests.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/diagnostics-selftests.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,59 ----
+ /* Selftest support for diagnostics.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ 
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "selftest.h"
+ #include "diagnostics/diagnostics-selftests.h"
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ 
+ namespace selftest {
+ 
+ /* Run all diagnostics-specific selftests,
+    apart from context_cc_tests, which according to
+    https://gcc.gnu.org/pipermail/gcc/2021-November/237703.html
+    has some language-specific assumptions, and thus is run from
+    c_family_tests instead.  */
+ 
+ void
+ run_diagnostics_selftests ()
+ {
+   color_cc_tests ();
+   file_cache_cc_tests ();
+   source_printing_cc_tests ();
+   html_sink_cc_tests ();
+   sarif_sink_cc_tests ();
+   digraphs_cc_tests ();
+   output_spec_cc_tests ();
+   state_graphs_cc_tests ();
+   lazy_paths_cc_tests ();
+   paths_output_cc_tests ();
+   changes_cc_tests ();
+ }
+ 
+ } /* end of namespace diagnostics::selftest.  */
+ 
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/diagnostics-selftests.h gcc-16-20250727/gcc/diagnostics/diagnostics-selftests.h
*** gcc-16-20250720/gcc/diagnostics/diagnostics-selftests.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/diagnostics-selftests.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,55 ----
+ /* Selftests for diagnostics.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ 
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_SELFTESTS_H
+ #define GCC_DIAGNOSTICS_SELFTESTS_H
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ 
+ namespace selftest {
+ 
+ extern void run_diagnostics_selftests ();
+ 
+ /* Declarations for specific families of tests (by source file within
+    "diagnostics/"), in alphabetical order.  */
+ 
+ extern void changes_cc_tests ();
+ extern void color_cc_tests ();
+ extern void context_cc_tests ();
+ extern void digraphs_cc_tests ();
+ extern void file_cache_cc_tests ();
+ extern void html_sink_cc_tests ();
+ extern void lazy_paths_cc_tests ();
+ extern void output_spec_cc_tests ();
+ extern void paths_output_cc_tests ();
+ extern void sarif_sink_cc_tests ();
+ extern void selftest_logical_locations_cc_tests ();
+ extern void source_printing_cc_tests ();
+ extern void state_graphs_cc_tests ();
+ 
+ } /* end of namespace diagnostics::selftest.  */
+ 
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
+ 
+ #endif /* GCC_DIAGNOSTICS_SELFTESTS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/diagram.h gcc-16-20250727/gcc/diagnostics/diagram.h
*** gcc-16-20250720/gcc/diagnostics/diagram.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/diagram.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,55 ----
+ /* Support for diagrams within diagnostics.
+    Copyright (C) 2023-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_DIAGRAM_H
+ #define GCC_DIAGNOSTICS_DIAGRAM_H
+ 
+ namespace text_art
+ {
+   class canvas;
+ } // namespace text_art
+ 
+ namespace diagnostics {
+ 
+ /* A text art diagram, along with an "alternative text" string
+    describing it.  */
+ 
+ class diagram
+ {
+  public:
+   diagram (const text_art::canvas &canvas,
+ 	   const char *alt_text)
+   : m_canvas (canvas),
+     m_alt_text (alt_text)
+   {
+     gcc_assert (alt_text);
+   }
+ 
+   const text_art::canvas &get_canvas () const { return m_canvas; }
+   const char *get_alt_text () const { return m_alt_text; }
+ 
+  private:
+   const text_art::canvas &m_canvas;
+   const char *const m_alt_text;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_DIAGRAM_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/digraphs.cc gcc-16-20250727/gcc/diagnostics/digraphs.cc
*** gcc-16-20250720/gcc/diagnostics/digraphs.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/digraphs.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,464 ----
+ /* Directed graphs associated with a diagnostic.
+    Copyright (C) 2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ 
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #define INCLUDE_ALGORITHM
+ #define INCLUDE_MAP
+ #define INCLUDE_SET
+ #define INCLUDE_STRING
+ #define INCLUDE_VECTOR
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ 
+ #include "graphviz.h"
+ #include "diagnostics/digraphs.h"
+ #include "diagnostics/sarif-sink.h"
+ 
+ #include "selftest.h"
+ 
+ using digraph = diagnostics::digraphs::digraph;
+ using digraph_node = diagnostics::digraphs::node;
+ using digraph_edge = diagnostics::digraphs::edge;
+ 
+ namespace {
+ 
+ class conversion_to_dot
+ {
+ public:
+   std::unique_ptr<dot::graph>
+   make_dot_graph_from_diagnostic_graph (const digraph &);
+ 
+   std::unique_ptr<dot::stmt>
+   make_dot_node_from_digraph_node (const digraph_node &);
+ 
+   std::unique_ptr<dot::edge_stmt>
+   make_dot_edge_from_digraph_edge (const digraph_edge &);
+ 
+   dot::id
+   get_dot_id_for_node (const digraph_node &);
+ 
+   bool
+   has_edges_p (const digraph_node &);
+ 
+ private:
+   std::set<const digraph_node *> m_nodes_with_edges;
+   std::map<const digraph_node *, dot::stmt *> m_node_map;
+ };
+ 
+ } // anonymous namespace
+ 
+ // class conversion_to_dot
+ 
+ std::unique_ptr<dot::graph>
+ conversion_to_dot::
+ make_dot_graph_from_diagnostic_graph (const diagnostics::digraphs::digraph &input_graph)
+ {
+   auto output_graph = std::make_unique<dot::graph> ();
+ 
+   if (const char *description = input_graph.get_description ())
+     output_graph->m_stmt_list.add_attr (dot::id ("label"),
+ 					dot::id (description));
+ 
+   const int num_nodes = input_graph.get_num_nodes ();
+   const int num_edges = input_graph.get_num_edges ();
+ 
+   /* Determine which nodes have in-edges and out-edges.  */
+   for (int i = 0; i < num_edges; ++i)
+     {
+       const digraph_edge &input_edge = input_graph.get_edge (i);
+       m_nodes_with_edges.insert (&input_edge.get_src_node ());
+       m_nodes_with_edges.insert (&input_edge.get_dst_node ());
+     }
+ 
+   for (int i = 0; i < num_nodes; ++i)
+     {
+       const digraph_node &input_node = input_graph.get_node (i);
+       auto dot_node_stmt = make_dot_node_from_digraph_node (input_node);
+       output_graph->m_stmt_list.add_stmt (std::move (dot_node_stmt));
+     }
+ 
+   for (int i = 0; i < num_edges; ++i)
+     {
+       const digraph_edge &input_edge = input_graph.get_edge (i);
+       auto dot_edge_stmt = make_dot_edge_from_digraph_edge (input_edge);
+       output_graph->m_stmt_list.add_stmt (std::move (dot_edge_stmt));
+     }
+ 
+   return output_graph;
+ }
+ 
+ std::unique_ptr<dot::stmt>
+ conversion_to_dot::
+ make_dot_node_from_digraph_node (const diagnostics::digraphs::node &input_node)
+ {
+   dot::id dot_id (get_dot_id_for_node (input_node));
+ 
+   /* For now, we can only do either edges or children, not both
+      ...but see https://graphviz.org/docs/attrs/compound/  */
+ 
+   if (has_edges_p (input_node))
+     {
+       auto output_node
+ 	= std::make_unique<dot::node_stmt> (std::move (dot_id));
+       m_node_map[&input_node] = output_node.get ();
+       if (const char *label = input_node.get_label ())
+ 	output_node->set_label (dot::id (label));
+       return output_node;
+     }
+   else
+     {
+       auto output_node = std::make_unique<dot::subgraph> (std::move (dot_id));
+       m_node_map[&input_node] = output_node.get ();
+       if (const char *label = input_node.get_label ())
+ 	output_node->add_attr (dot::id ("label"), dot::id (label));
+       const int num_children = input_node.get_num_children ();
+       for (int i = 0; i < num_children; ++i)
+ 	{
+ 	  const digraph_node &input_child = input_node.get_child (i);
+ 	  auto dot_child_stmt = make_dot_node_from_digraph_node (input_child);
+ 	  output_node->m_stmt_list.add_stmt (std::move (dot_child_stmt));
+ 	}
+       return output_node;
+     }
+ }
+ 
+ std::unique_ptr<dot::edge_stmt>
+ conversion_to_dot::
+ make_dot_edge_from_digraph_edge (const digraph_edge &input_edge)
+ {
+   const digraph_node &src_dnode = input_edge.get_src_node ();
+   const digraph_node &dst_dnode = input_edge.get_dst_node ();
+   auto output_edge
+     = std::make_unique<dot::edge_stmt>
+     (get_dot_id_for_node (src_dnode),
+      get_dot_id_for_node (dst_dnode));
+   if (const char *label = input_edge.get_label ())
+     output_edge->set_label (dot::id (label));
+   return output_edge;
+ }
+ 
+ dot::id
+ conversion_to_dot::get_dot_id_for_node (const digraph_node &input_node)
+ {
+   if (has_edges_p (input_node))
+     return input_node.get_id ();
+   else
+     return std::string ("cluster_") + input_node.get_id ();
+ }
+ 
+ bool
+ conversion_to_dot::has_edges_p (const digraph_node &input_node)
+ {
+   return m_nodes_with_edges.find (&input_node) != m_nodes_with_edges.end ();
+ }
+ 
+ // class object
+ 
+ const char *
+ diagnostics::digraphs::object::
+ get_attr (const char *key_prefix, const char *key) const
+ {
+   if (!m_property_bag)
+     return nullptr;
+   std::string prefixed_key = std::string (key_prefix) + key;
+   if (json::value *jv = m_property_bag->get (prefixed_key.c_str ()))
+     if (json::string *jstr = jv->dyn_cast_string ())
+       return jstr->get_string ();
+   return nullptr;
+ }
+ 
+ void
+ diagnostics::digraphs::object::
+ set_attr (const char *key_prefix, const char *key, const char *value)
+ {
+   set_json_attr (key_prefix, key, std::make_unique<json::string> (value));
+ }
+ 
+ void
+ diagnostics::digraphs::object::
+ set_json_attr (const char *key_prefix, const char *key, std::unique_ptr<json::value> value)
+ {
+   std::string prefixed_key = std::string (key_prefix) + key;
+   if (!m_property_bag)
+     m_property_bag = std::make_unique<json::object> ();
+   m_property_bag->set (prefixed_key.c_str (), std::move (value));
+ }
+ 
+ // class digraph
+ 
+ DEBUG_FUNCTION void
+ diagnostics::digraphs::digraph::dump () const
+ {
+   make_json_sarif_graph ()->dump ();
+ }
+ 
+ std::unique_ptr<json::object>
+ diagnostics::digraphs::digraph::make_json_sarif_graph () const
+ {
+   return make_sarif_graph (*this, nullptr, nullptr);
+ }
+ 
+ std::unique_ptr<dot::graph>
+ diagnostics::digraphs::digraph::make_dot_graph () const
+ {
+   conversion_to_dot to_dot;
+   return to_dot.make_dot_graph_from_diagnostic_graph (*this);
+ }
+ 
+ std::unique_ptr<diagnostics::digraphs::digraph>
+ diagnostics::digraphs::digraph::clone () const
+ {
+   auto result = std::make_unique<diagnostics::digraphs::digraph> ();
+ 
+   if (get_property_bag ())
+     result->set_property_bag (get_property_bag ()->clone_as_object ());
+ 
+   std::map<diagnostics::digraphs::node *, diagnostics::digraphs::node *> node_mapping;
+ 
+   for (auto &iter : m_nodes)
+     result->add_node (iter->clone (*result, node_mapping));
+   for (auto &iter : m_edges)
+     result->add_edge (iter->clone (*result, node_mapping));
+ 
+   return result;
+ }
+ 
+ void
+ diagnostics::digraphs::digraph::add_edge (const char *id,
+ 					  node &src_node,
+ 					  node &dst_node,
+ 					  const char *label)
+ {
+   auto e = std::make_unique<digraph_edge> (*this,
+ 					   id,
+ 					   src_node,
+ 					   dst_node);
+   if (label)
+     e->set_label (label);
+   add_edge (std::move (e));
+ }
+ 
+ /* Utility function for edge ids: either use EDGE_ID, or
+    generate a unique one for when we don't care about the name.
+ 
+    Edges in SARIF "SHALL" have an id that's unique within the graph
+    (SARIF 2.1.0 §3.41.2).  This is so that graph traversals can refer
+    to edges by id (SARIF 2.1.0's §3.43.2 edgeId property).  */
+ 
+ std::string
+ diagnostics::digraphs::digraph::make_edge_id (const char *edge_id)
+ {
+   /* If we have an id, use it.  */
+   if (edge_id)
+     return edge_id;
+ 
+   /* Otherwise, generate a unique one of the form "edgeN".  */
+   while (true)
+     {
+       auto candidate (std::string ("edge")
+ 		      + std::to_string (m_next_edge_id_index++));
+       auto iter = m_id_to_edge_map.find (candidate);
+       if (iter != m_id_to_edge_map.end ())
+ 	{
+ 	  // Try again with the next index...
+ 	  continue;
+ 	}
+       return candidate;
+     }
+ }
+ 
+ // class node
+ 
+ DEBUG_FUNCTION void
+ diagnostics::digraphs::node::dump () const
+ {
+   to_json_sarif_node ()->dump ();
+ }
+ 
+ std::unique_ptr<json::object>
+ diagnostics::digraphs::node::to_json_sarif_node () const
+ {
+   return make_sarif_node (*this, nullptr, nullptr);
+ }
+ 
+ std::unique_ptr<diagnostics::digraphs::node>
+ diagnostics::digraphs::node::clone (digraph &new_graph,
+ 				    std::map<node *, node *> &node_mapping) const
+ {
+   auto result
+     = std::make_unique<diagnostics::digraphs::node> (new_graph,
+ 						     get_id ());
+   node_mapping.insert ({const_cast <node *> (this), result.get ()});
+ 
+   result->set_logical_loc (m_logical_loc);
+ 
+   if (get_property_bag ())
+     result->set_property_bag (get_property_bag ()->clone_as_object ());
+ 
+   for (auto &iter : m_children)
+     result->add_child (iter->clone (new_graph, node_mapping));
+ 
+   return result;
+ }
+ 
+ // class edge
+ 
+ std::unique_ptr<digraph_edge>
+ digraph_edge::clone (digraph &new_graph,
+ 		     const std::map<node *, node *> &node_mapping) const
+ {
+   auto iter_new_src = node_mapping.find (&m_src_node);
+   gcc_assert (iter_new_src != node_mapping.end ());
+   auto iter_new_dst = node_mapping.find (&m_dst_node);
+   gcc_assert (iter_new_dst != node_mapping.end ());
+   auto result
+     = std::make_unique<digraph_edge> (new_graph,
+ 				      m_id.c_str (),
+ 				      *iter_new_src->second,
+ 				      *iter_new_dst->second);
+   if (get_property_bag ())
+     result->set_property_bag (get_property_bag ()->clone_as_object ());
+ 
+   return result;
+ }
+ 
+ DEBUG_FUNCTION void
+ diagnostics::digraphs::edge::dump () const
+ {
+   to_json_sarif_edge ()->dump ();
+ }
+ 
+ std::unique_ptr<json::object>
+ diagnostics::digraphs::edge::to_json_sarif_edge () const
+ {
+   return make_sarif_edge (*this, nullptr);
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace selftest {
+ 
+ static void
+ test_empty_graph ()
+ {
+   digraph g;
+ 
+   {
+     auto sarif = g.make_json_sarif_graph ();
+ 
+     pretty_printer pp;
+     sarif->print (&pp, true);
+     ASSERT_STREQ
+       (pp_formatted_text (&pp),
+        ("{\"nodes\": [],\n"
+ 	" \"edges\": []}"));
+   }
+ 
+   {
+     auto dg = g.make_dot_graph ();
+ 
+     pretty_printer pp;
+     dot::writer w (pp);
+     dg->print (w);
+     ASSERT_STREQ
+       (pp_formatted_text (&pp),
+        ("digraph {\n"
+ 	"}\n"));
+   }
+ }
+ 
+ static void
+ test_simple_graph ()
+ {
+ #define KEY_PREFIX "/placeholder/"
+   auto g = std::make_unique<digraph> ();
+   g->set_description ("test graph");
+   g->set_attr (KEY_PREFIX, "date", "1066");
+ 
+   auto a = std::make_unique<digraph_node> (*g, "a");
+   auto b = std::make_unique<digraph_node> (*g, "b");
+   b->set_attr (KEY_PREFIX, "color", "red");
+   auto c = std::make_unique<digraph_node> (*g, "c");
+   c->set_label ("I am a node label");
+ 
+   auto e = std::make_unique<digraph_edge> (*g, nullptr, *a, *c);
+   e->set_attr (KEY_PREFIX, "status", "copacetic");
+   e->set_label ("I am an edge label");
+   g->add_edge (std::move (e));
+ 
+   g->add_node (std::move (a));
+ 
+   b->add_child (std::move (c));
+   g->add_node (std::move (b));
+ #undef KEY_PREFIX
+ 
+   {
+     auto sarif = g->make_json_sarif_graph ();
+ 
+     pretty_printer pp;
+     sarif->print (&pp, true);
+     ASSERT_STREQ
+       (pp_formatted_text (&pp),
+        ("{\"properties\": {\"/placeholder/date\": \"1066\"},\n"
+ 	" \"nodes\": [{\"id\": \"a\"},\n"
+ 	"           {\"id\": \"b\",\n"
+ 	"            \"properties\": {\"/placeholder/color\": \"red\"},\n"
+ 	"            \"children\": [{\"id\": \"c\"}]}],\n"
+ 	" \"edges\": [{\"id\": \"edge0\",\n"
+ 	"            \"properties\": {\"/placeholder/status\": \"copacetic\"},\n"
+ 	"            \"sourceNodeId\": \"a\",\n"
+ 	"            \"targetNodeId\": \"c\"}]}"));
+   }
+ 
+   {
+     auto dg = g->make_dot_graph ();
+ 
+     pretty_printer pp;
+     dot::writer w (pp);
+     dg->print (w);
+     ASSERT_STREQ
+       (pp_formatted_text (&pp),
+        ("digraph {\n"
+ 	"    label=\"test graph\";\n"
+ 	"    a;\n"
+ 	"    \n"
+ 	"    subgraph cluster_b {\n"
+ 	"        c [label=\"I am a node label\"];\n"
+ 	"\n"
+ 	"    };\n"
+ 	"    a -> c [label=\"I am an edge label\"];\n"
+ 	"}\n"));
+   }
+ }
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ digraphs_cc_tests ()
+ {
+   test_empty_graph ();
+   test_simple_graph ();
+ }
+ 
+ } // namespace diagnostics::selftest
+ } // namespace diagnostics
+ 
+ #endif /* CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/digraphs.h gcc-16-20250727/gcc/diagnostics/digraphs.h
*** gcc-16-20250720/gcc/diagnostics/digraphs.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/digraphs.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,379 ----
+ /* Directed graphs associated with a diagnostic.
+    Copyright (C) 2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_DIGRAPHS_H
+ #define GCC_DIAGNOSTICS_DIGRAPHS_H
+ 
+ #include "json.h"
+ #include "diagnostics/logical-locations.h"
+ 
+ class graphviz_out;
+ 
+ class sarif_graph;
+ class sarif_node;
+ class sarif_edge;
+ 
+ namespace dot { class graph; }
+ 
+ namespace diagnostics {
+ namespace digraphs {
+ 
+ /* A family of classes: digraph, node, and edge, closely related to
+    SARIF's graph, node, and edge types (SARIF v2.1.0 sections 3.39-3.41).
+ 
+    Nodes can have child nodes, allowing for arbitrarily deep nesting.
+    Edges can be between any pair of nodes (potentially at different
+    nesting levels).
+ 
+    Digraphs, nodes, and edges also optionally have a JSON property bag,
+    allowing round-tripping of arbitrary key/value pairs through SARIF.  */
+ 
+ class digraph;
+ class node;
+ class edge;
+ 
+ /* A base class for digraph, node, and edge to allow them to have
+    an optional JSON property bag.  */
+ 
+ class object
+ {
+ public:
+   const char *
+   get_attr (const char *key_prefix,
+ 	    const char *key) const;
+ 
+   void
+   set_attr (const char *key_prefix,
+ 	    const char *key,
+ 	    const char *value);
+ 
+   void
+   set_json_attr (const char *key_prefix,
+ 		 const char *key,
+ 		 std::unique_ptr<json::value> value);
+ 
+   json::object *
+   get_property_bag () const { return m_property_bag.get (); }
+ 
+   void
+   set_property_bag (std::unique_ptr<json::object> property_bag)
+   {
+     m_property_bag = std::move (property_bag);
+   }
+ 
+ private:
+   std::unique_ptr<json::object> m_property_bag;
+ };
+ 
+ // A directed graph, corresponding to SARIF v2.1.0 section 3.39.
+ 
+ class digraph : public object
+ {
+  public:
+   friend class node;
+   friend class edge;
+ 
+   digraph () : m_next_edge_id_index (0) {}
+   virtual ~digraph () {}
+ 
+   const char *
+   get_description () const
+   {
+     if (!m_description)
+       return nullptr;
+     return m_description->c_str ();
+   }
+ 
+   void
+   set_description (const char *desc)
+   {
+     if (desc)
+       m_description = std::make_unique<std::string> (desc);
+     else
+       m_description = nullptr;
+   }
+   void
+   set_description (std::string desc)
+   {
+     m_description = std::make_unique<std::string> (std::move (desc));
+   }
+ 
+   node *
+   get_node_by_id (const char *id) const
+   {
+     auto iter = m_id_to_node_map.find (id);
+     if (iter == m_id_to_node_map.end ())
+       return nullptr;
+     return iter->second;
+   }
+ 
+   edge *
+   get_edge_by_id (const char *id) const
+   {
+     auto iter = m_id_to_edge_map.find (id);
+     if (iter == m_id_to_edge_map.end ())
+       return nullptr;
+     return iter->second;
+   }
+ 
+   size_t
+   get_num_nodes () const
+   {
+     return m_nodes.size ();
+   }
+ 
+   node &
+   get_node (size_t idx) const
+   {
+     return *m_nodes[idx].get ();
+   }
+ 
+   size_t
+   get_num_edges () const
+   {
+     return m_edges.size ();
+   }
+ 
+   edge &
+   get_edge (size_t idx) const
+   {
+     return *m_edges[idx].get ();
+   }
+ 
+   void
+   dump () const;
+ 
+   std::unique_ptr<json::object>
+   make_json_sarif_graph () const;
+ 
+   std::unique_ptr<dot::graph>
+   make_dot_graph () const;
+ 
+   void
+   add_node (std::unique_ptr<node> n)
+   {
+     gcc_assert (n);
+     m_nodes.push_back (std::move (n));
+   }
+ 
+   void
+   add_edge (std::unique_ptr<edge> e)
+   {
+     gcc_assert (e);
+     m_edges.push_back (std::move (e));
+   }
+ 
+   void
+   add_edge (const char *id,
+ 	    node &src_node,
+ 	    node &dst_node,
+ 	    const char *label = nullptr);
+ 
+   std::unique_ptr<digraph> clone () const;
+ 
+  private:
+   void
+   add_node_id (std::string node_id, node &new_node)
+   {
+     m_id_to_node_map.insert ({std::move (node_id), &new_node});
+   }
+   void
+   add_edge_id (std::string edge_id, edge &new_edge)
+   {
+     m_id_to_edge_map.insert ({std::move (edge_id), &new_edge});
+   }
+ 
+   std::string
+   make_edge_id (const char *edge_id);
+ 
+   std::unique_ptr<std::string> m_description;
+   std::map<std::string, node *> m_id_to_node_map;
+   std::map<std::string, edge *> m_id_to_edge_map;
+   std::vector<std::unique_ptr<node>> m_nodes;
+   std::vector<std::unique_ptr<edge>> m_edges;
+   size_t m_next_edge_id_index;
+ };
+ 
+ // A node in a directed graph, corresponding to SARIF v2.1.0 section 3.40.
+ 
+ class node : public object
+ {
+  public:
+   virtual ~node () {}
+ 
+   node (digraph &g, std::string id)
+   : m_id (id),
+     m_physical_loc (UNKNOWN_LOCATION)
+   {
+     g.add_node_id (std::move (id), *this);
+   }
+   node (const node &) = delete;
+ 
+   std::string
+   get_id () const { return m_id; }
+ 
+   const char *
+   get_label () const
+   {
+     if (!m_label)
+       return nullptr;
+     return m_label->c_str ();
+   }
+ 
+   void
+   set_label (const char *label)
+   {
+     if (label)
+       m_label = std::make_unique<std::string> (label);
+     else
+       m_label = nullptr;
+   }
+   void
+   set_label (std::string label)
+   {
+     m_label = std::make_unique<std::string> (std::move (label));
+   }
+ 
+   size_t
+   get_num_children () const { return m_children.size (); }
+ 
+   node &
+   get_child (size_t idx) const { return *m_children[idx].get (); }
+ 
+   void
+   add_child (std::unique_ptr<node> child)
+   {
+     gcc_assert (child);
+     m_children.push_back (std::move (child));
+   }
+ 
+   location_t
+   get_physical_loc () const
+   {
+     return m_physical_loc;
+   }
+ 
+   void
+   set_physical_loc (location_t physical_loc)
+   {
+     m_physical_loc = physical_loc;
+   }
+ 
+   logical_locations::key
+   get_logical_loc () const
+   {
+     return m_logical_loc;
+   }
+ 
+   void
+   set_logical_loc (logical_locations::key logical_loc)
+   {
+     m_logical_loc = logical_loc;
+   }
+ 
+   void print (graphviz_out &gv) const;
+ 
+   void
+   dump () const;
+ 
+   std::unique_ptr<json::object>
+   to_json_sarif_node () const;
+ 
+   std::unique_ptr<node>
+   clone (digraph &new_graph,
+ 	 std::map<node *, node *> &node_mapping) const;
+ 
+  private:
+   std::string m_id;
+   std::unique_ptr<std::string> m_label;
+   std::vector<std::unique_ptr<node>> m_children;
+   location_t m_physical_loc;
+   logical_locations::key m_logical_loc;
+ };
+ 
+ // An edge in a directed graph, corresponding to SARIF v2.1.0 section 3.41.
+ 
+ class edge : public object
+ {
+  public:
+   virtual ~edge () {}
+ 
+   /* SARIF requires us to provide unique edge IDs within a graph,
+      but otherwise we don't need them.
+      Pass in nullptr for the id to get the graph to generate a unique
+      edge id for us.  */
+   edge (digraph &g,
+ 	const char *id,
+ 	node &src_node,
+ 	node &dst_node)
+   : m_id (g.make_edge_id (id)),
+     m_src_node (src_node),
+     m_dst_node (dst_node)
+   {
+     g.add_edge_id (m_id, *this);
+   }
+ 
+   std::string
+   get_id () const { return m_id; }
+ 
+   const char *
+   get_label () const
+   {
+     if (!m_label)
+       return nullptr;
+     return m_label->c_str ();
+   }
+ 
+   void
+   set_label (const char *label)
+   {
+     if (label)
+       m_label = std::make_unique<std::string> (label);
+     else
+       m_label = nullptr;
+   }
+ 
+   node &
+   get_src_node () const { return m_src_node; }
+ 
+   node &
+   get_dst_node () const { return m_dst_node; }
+ 
+   void
+   dump () const;
+ 
+   std::unique_ptr<json::object>
+   to_json_sarif_edge () const;
+ 
+   std::unique_ptr<edge>
+   clone (digraph &new_graph,
+ 	 const std::map<diagnostics::digraphs::node *, diagnostics::digraphs::node *> &node_mapping) const;
+ 
+ private:
+   std::string m_id;
+   std::unique_ptr<std::string> m_label;
+   node &m_src_node;
+   node &m_dst_node;
+ };
+ 
+ } // namespace digraphs
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_DIGRAPHS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/event-id.h gcc-16-20250727/gcc/diagnostics/event-id.h
*** gcc-16-20250720/gcc/diagnostics/event-id.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/event-id.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,83 ----
+ /* A class for referring to events within a diagnostics::paths::path.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_EVENT_ID_H
+ #define GCC_DIAGNOSTICS_EVENT_ID_H
+ 
+ /* A class for referring to events within a diagnostics::paths::path.
+ 
+    They are stored as 0-based offsets into the events, but
+    printed (e.g. via %@) as 1-based numbers.
+ 
+    For example, a 3-event path has event offsets 0, 1, and 2,
+    which would be shown to the user as "(1)", "(2)" and "(3)".
+ 
+    This has its own header so that pretty-print.cc can use this
+    to implement "%@" without bringing in all of diagnostics::paths.
+ 
+    This has to be in the global namespace for compatibility with
+    c-format.cc in GCC 10 onwards.  */
+ 
+ class diagnostic_event_id_t
+ {
+  public:
+   diagnostic_event_id_t () : m_index (UNKNOWN_EVENT_IDX) {}
+   diagnostic_event_id_t (int zero_based_idx) : m_index (zero_based_idx) {}
+ 
+   bool known_p () const { return m_index != UNKNOWN_EVENT_IDX; }
+ 
+   int zero_based () const
+   {
+     gcc_assert (known_p ());
+     return m_index;
+   }
+ 
+   int one_based () const
+   {
+     gcc_assert (known_p ());
+     return m_index + 1;
+   }
+ 
+  private:
+   static const int UNKNOWN_EVENT_IDX = -1;
+   int m_index; // zero-based
+ };
+ 
+ namespace diagnostics {
+ namespace paths {
+ 
+ typedef diagnostic_event_id_t event_id_t;
+ 
+ /* A type for compactly referring to a particular thread within a
+    diagnostics::paths::path.  Typically there is just one thread per path,
+    with id 0.  */
+ typedef int thread_id_t;
+ 
+ } // namespace paths
+ } // namespace diagnostics
+ 
+ 
+ /* A pointer to a diagnostic_event_id_t, for use with the "%@" format
+    code, which will print a 1-based representation for it, with suitable
+    colorization, e.g. "(1)".
+    The %@ format code requires that known_p be true for the event ID. */
+ typedef diagnostic_event_id_t *diagnostic_event_id_ptr;
+ 
+ #endif /* ! GCC_DIAGNOSTICS_EVENT_ID_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/file-cache.cc gcc-16-20250727/gcc/diagnostics/file-cache.cc
*** gcc-16-20250720/gcc/diagnostics/file-cache.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/file-cache.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,1083 ----
+ /* Caching input files for use by diagnostics.
+    Copyright (C) 2004-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "cpplib.h"
+ #include "diagnostics/file-cache.h"
+ #include "selftest.h"
+ 
+ #ifndef HAVE_ICONV
+ #define HAVE_ICONV 0
+ #endif
+ 
+ namespace diagnostics {
+ 
+ /* Input charset configuration.  */
+ static const char *default_charset_callback (const char *)
+ {
+   return nullptr;
+ }
+ 
+ void
+ file_cache::initialize_input_context (diagnostic_input_charset_callback ccb,
+ 				      bool should_skip_bom)
+ {
+   m_input_context.ccb = (ccb ? ccb : default_charset_callback);
+   m_input_context.should_skip_bom = should_skip_bom;
+ }
+ 
+ /* This is a cache used by get_next_line to store the content of a
+    file to be searched for file lines.  */
+ class file_cache_slot
+ {
+ public:
+   file_cache_slot ();
+   ~file_cache_slot ();
+ 
+   void dump (FILE *out, int indent) const;
+   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
+ 
+   bool read_line_num (size_t line_num,
+ 		      char ** line, ssize_t *line_len);
+ 
+   /* Accessors.  */
+   const char *get_file_path () const { return m_file_path; }
+   unsigned get_use_count () const { return m_use_count; }
+   bool missing_trailing_newline_p () const
+   {
+     return m_missing_trailing_newline;
+   }
+   char_span get_full_file_content ();
+ 
+   void inc_use_count () { m_use_count++; }
+ 
+   bool create (const file_cache::input_context &in_context,
+ 	       const char *file_path, FILE *fp, unsigned highest_use_count);
+   void evict ();
+   void set_content (const char *buf, size_t sz);
+ 
+   static size_t tune (size_t line_record_size_)
+   {
+     size_t ret = line_record_size;
+     line_record_size = line_record_size_;
+     return ret;
+   }
+ 
+  private:
+   /* These are information used to store a line boundary.  */
+   class line_info
+   {
+   public:
+     /* The line number.  It starts from 1.  */
+     size_t line_num;
+ 
+     /* The position (byte count) of the beginning of the line,
+        relative to the file data pointer.  This starts at zero.  */
+     size_t start_pos;
+ 
+     /* The position (byte count) of the last byte of the line.  This
+        normally points to the '\n' character, or to one byte after the
+        last byte of the file, if the file doesn't contain a '\n'
+        character.  */
+     size_t end_pos;
+ 
+     line_info (size_t l, size_t s, size_t e)
+       : line_num (l), start_pos (s), end_pos (e)
+     {}
+ 
+     line_info ()
+       :line_num (0), start_pos (0), end_pos (0)
+     {}
+ 
+     static bool less_than(const line_info &a, const line_info &b)
+     {
+       return a.line_num < b.line_num;
+     }
+   };
+ 
+   bool needs_read_p () const;
+   bool needs_grow_p () const;
+   void maybe_grow ();
+   bool read_data ();
+   bool maybe_read_data ();
+   bool get_next_line (char **line, ssize_t *line_len);
+   bool read_next_line (char ** line, ssize_t *line_len);
+   bool goto_next_line ();
+ 
+   static const size_t buffer_size = 4 * 1024;
+   static size_t line_record_size;
+   static size_t recent_cached_lines_shift;
+ 
+   /* The number of time this file has been accessed.  This is used
+      to designate which file cache to evict from the cache
+      array.  */
+   unsigned m_use_count;
+ 
+   /* The file_path is the key for identifying a particular file in
+      the cache.  This copy is owned by the slot.  */
+   char *m_file_path;
+ 
+   FILE *m_fp;
+ 
+   /* True when an read error happened.  */
+   bool m_error;
+ 
+   /* This points to the content of the file that we've read so
+      far.  */
+   char *m_data;
+ 
+   /* The allocated buffer to be freed may start a little earlier than DATA,
+      e.g. if a UTF8 BOM was skipped at the beginning.  */
+   int m_alloc_offset;
+ 
+   /*  The size of the DATA array above.*/
+   size_t m_size;
+ 
+   /* The number of bytes read from the underlying file so far.  This
+      must be less (or equal) than SIZE above.  */
+   size_t m_nb_read;
+ 
+   /* The index of the beginning of the current line.  */
+   size_t m_line_start_idx;
+ 
+   /* The number of the previous line read.  This starts at 1.  Zero
+      means we've read no line so far.  */
+   size_t m_line_num;
+ 
+   /* Could this file be missing a trailing newline on its final line?
+      Initially true (to cope with empty files), set to true/false
+      as each line is read.  */
+   bool m_missing_trailing_newline;
+ 
+   /* This is a record of the beginning and end of the lines we've seen
+      while reading the file.  This is useful to avoid walking the data
+      from the beginning when we are asked to read a line that is
+      before LINE_START_IDX above.  When the lines exceed line_record_size
+      this is scaled down dynamically, with the line_info becoming anchors.  */
+   vec<line_info, va_heap> m_line_record;
+ 
+   /* A cache of the recently seen lines. This is maintained as a ring
+      buffer. */
+   vec<line_info, va_heap> m_line_recent;
+ 
+   /* First and last valid entry in m_line_recent.  */
+   size_t m_line_recent_last, m_line_recent_first;
+ 
+   void offset_buffer (int offset)
+   {
+     gcc_assert (offset < 0 ? m_alloc_offset + offset >= 0
+ 		: (size_t) offset <= m_size);
+     gcc_assert (m_data);
+     m_alloc_offset += offset;
+     m_data += offset;
+     m_size -= offset;
+   }
+ 
+ };
+ 
+ size_t file_cache_slot::line_record_size = 0;
+ size_t file_cache_slot::recent_cached_lines_shift = 8;
+ 
+ /* Tune file_cache.  */
+ void
+ file_cache::tune (size_t num_file_slots, size_t lines)
+ {
+   if (file_cache_slot::tune (lines) != lines
+       || m_num_file_slots != num_file_slots)
+     {
+       delete[] m_file_slots;
+       m_file_slots = new file_cache_slot[num_file_slots];
+     }
+   m_num_file_slots = num_file_slots;
+ }
+ 
+ static const char *
+ find_end_of_line (const char *s, size_t len);
+ 
+ /* Lookup the cache used for the content of a given file accessed by
+    caret diagnostic.  Return the found cached file, or NULL if no
+    cached file was found.  */
+ 
+ file_cache_slot *
+ file_cache::lookup_file (const char *file_path)
+ {
+   gcc_assert (file_path);
+ 
+   /* This will contain the found cached file.  */
+   file_cache_slot *r = NULL;
+   for (unsigned i = 0; i < m_num_file_slots; ++i)
+     {
+       file_cache_slot *c = &m_file_slots[i];
+       if (c->get_file_path () && !strcmp (c->get_file_path (), file_path))
+ 	{
+ 	  c->inc_use_count ();
+ 	  r = c;
+ 	}
+     }
+ 
+   if (r)
+     r->inc_use_count ();
+ 
+   return r;
+ }
+ 
+ /* Purge any mention of FILENAME from the cache of files used for
+    printing source code.  For use in selftests when working
+    with tempfiles.  */
+ 
+ void
+ file_cache::forcibly_evict_file (const char *file_path)
+ {
+   gcc_assert (file_path);
+ 
+   file_cache_slot *r = lookup_file (file_path);
+   if (!r)
+     /* Not found.  */
+     return;
+ 
+   r->evict ();
+ }
+ 
+ /* Determine if FILE_PATH missing a trailing newline on its final line.
+    Only valid to call once all of the file has been loaded, by
+    requesting a line number beyond the end of the file.  */
+ 
+ bool
+ file_cache::missing_trailing_newline_p (const char *file_path)
+ {
+   gcc_assert (file_path);
+ 
+   file_cache_slot *r = lookup_or_add_file (file_path);
+   return r->missing_trailing_newline_p ();
+ }
+ 
+ void
+ file_cache::add_buffered_content (const char *file_path,
+ 				  const char *buffer,
+ 				  size_t sz)
+ {
+   gcc_assert (file_path);
+ 
+   file_cache_slot *r = lookup_file (file_path);
+   if (!r)
+     {
+       unsigned highest_use_count = 0;
+       r = evicted_cache_tab_entry (&highest_use_count);
+       if (!r->create (m_input_context, file_path, nullptr, highest_use_count))
+ 	return;
+     }
+ 
+   r->set_content (buffer, sz);
+ }
+ 
+ void
+ file_cache_slot::evict ()
+ {
+   free (m_file_path);
+   m_file_path = NULL;
+   if (m_fp)
+     fclose (m_fp);
+   m_error = false;
+   m_fp = NULL;
+   m_nb_read = 0;
+   m_line_start_idx = 0;
+   m_line_num = 0;
+   m_line_record.truncate (0);
+   m_line_recent_first = 0;
+   m_line_recent_last = 0;
+   m_use_count = 0;
+   m_missing_trailing_newline = true;
+ }
+ 
+ /* Return the file cache that has been less used, recently, or the
+    first empty one.  If HIGHEST_USE_COUNT is non-null,
+    *HIGHEST_USE_COUNT is set to the highest use count of the entries
+    in the cache table.  */
+ 
+ file_cache_slot*
+ file_cache::evicted_cache_tab_entry (unsigned *highest_use_count)
+ {
+   file_cache_slot *to_evict = &m_file_slots[0];
+   unsigned huc = to_evict->get_use_count ();
+   for (unsigned i = 1; i < m_num_file_slots; ++i)
+     {
+       file_cache_slot *c = &m_file_slots[i];
+       bool c_is_empty = (c->get_file_path () == NULL);
+ 
+       if (c->get_use_count () < to_evict->get_use_count ()
+ 	  || (to_evict->get_file_path () && c_is_empty))
+ 	/* We evict C because it's either an entry with a lower use
+ 	   count or one that is empty.  */
+ 	to_evict = c;
+ 
+       if (huc < c->get_use_count ())
+ 	huc = c->get_use_count ();
+ 
+       if (c_is_empty)
+ 	/* We've reached the end of the cache; subsequent elements are
+ 	   all empty.  */
+ 	break;
+     }
+ 
+   if (highest_use_count)
+     *highest_use_count = huc;
+ 
+   return to_evict;
+ }
+ 
+ /* Create the cache used for the content of a given file to be
+    accessed by caret diagnostic.  This cache is added to an array of
+    cache and can be retrieved by lookup_file_in_cache_tab.  This
+    function returns the created cache.  Note that only the last
+    m_num_file_slots files are cached.
+ 
+    This can return nullptr if the FILE_PATH can't be opened for
+    reading, or if the content can't be converted to the input_charset.  */
+ 
+ file_cache_slot*
+ file_cache::add_file (const char *file_path)
+ {
+ 
+   FILE *fp = fopen (file_path, "r");
+   if (fp == NULL)
+     return NULL;
+ 
+   unsigned highest_use_count = 0;
+   file_cache_slot *r = evicted_cache_tab_entry (&highest_use_count);
+   if (!r->create (m_input_context, file_path, fp, highest_use_count))
+     return NULL;
+   return r;
+ }
+ 
+ /* Get a borrowed char_span to the full content of this file
+    as decoded according to the input charset, encoded as UTF-8.  */
+ 
+ char_span
+ file_cache_slot::get_full_file_content ()
+ {
+   char *line;
+   ssize_t line_len;
+   while (get_next_line (&line, &line_len))
+     {
+     }
+   return char_span (m_data, m_nb_read);
+ }
+ 
+ /* Populate this slot for use on FILE_PATH and FP, dropping any
+    existing cached content within it.  */
+ 
+ bool
+ file_cache_slot::create (const file_cache::input_context &in_context,
+ 			 const char *file_path, FILE *fp,
+ 			 unsigned highest_use_count)
+ {
+   m_file_path = file_path ? xstrdup (file_path) : nullptr;
+   if (m_fp)
+     fclose (m_fp);
+   m_error = false;
+   m_fp = fp;
+   if (m_alloc_offset)
+     offset_buffer (-m_alloc_offset);
+   m_nb_read = 0;
+   m_line_start_idx = 0;
+   m_line_num = 0;
+   m_line_recent_first = 0;
+   m_line_recent_last = 0;
+   m_line_record.truncate (0);
+   /* Ensure that this cache entry doesn't get evicted next time
+      add_file_to_cache_tab is called.  */
+   m_use_count = ++highest_use_count;
+   m_missing_trailing_newline = true;
+ 
+ 
+   /* Check the input configuration to determine if we need to do any
+      transformations, such as charset conversion or BOM skipping.  */
+   if (const char *input_charset = in_context.ccb (file_path))
+     {
+       /* Need a full-blown conversion of the input charset.  */
+       fclose (m_fp);
+       m_fp = NULL;
+       const cpp_converted_source cs
+ 	= cpp_get_converted_source (file_path, input_charset);
+       if (!cs.data)
+ 	return false;
+       if (m_data)
+ 	XDELETEVEC (m_data);
+       m_data = cs.data;
+       m_nb_read = m_size = cs.len;
+       m_alloc_offset = cs.data - cs.to_free;
+     }
+   else if (in_context.should_skip_bom)
+     {
+       if (read_data ())
+ 	{
+ 	  const int offset = cpp_check_utf8_bom (m_data, m_nb_read);
+ 	  offset_buffer (offset);
+ 	  m_nb_read -= offset;
+ 	}
+     }
+ 
+   return true;
+ }
+ 
+ void
+ file_cache_slot::set_content (const char *buf, size_t sz)
+ {
+   m_data = (char *)xmalloc (sz);
+   memcpy (m_data, buf, sz);
+   m_nb_read = m_size = sz;
+   m_alloc_offset = 0;
+ 
+   if (m_fp)
+     {
+       fclose (m_fp);
+       m_fp = nullptr;
+     }
+ }
+ 
+ /* file_cache's ctor.  */
+ 
+ file_cache::file_cache ()
+ : m_num_file_slots (16), m_file_slots (new file_cache_slot[m_num_file_slots])
+ {
+   initialize_input_context (nullptr, false);
+ }
+ 
+ /* file_cache's dtor.  */
+ 
+ file_cache::~file_cache ()
+ {
+   delete[] m_file_slots;
+ }
+ 
+ void
+ file_cache::dump (FILE *out, int indent) const
+ {
+   for (size_t i = 0; i < m_num_file_slots; ++i)
+     {
+       fprintf (out, "%*sslot[%i]:\n", indent, "", (int)i);
+       m_file_slots[i].dump (out, indent + 2);
+     }
+ }
+ 
+ void
+ file_cache::dump () const
+ {
+   dump (stderr, 0);
+ }
+ 
+ /* Lookup the cache used for the content of a given file accessed by
+    caret diagnostic.  If no cached file was found, create a new cache
+    for this file, add it to the array of cached file and return
+    it.
+ 
+    This can return nullptr on a cache miss if FILE_PATH can't be opened for
+    reading, or if the content can't be converted to the input_charset.  */
+ 
+ file_cache_slot*
+ file_cache::lookup_or_add_file (const char *file_path)
+ {
+   file_cache_slot *r = lookup_file (file_path);
+   if (r == NULL)
+     r = add_file (file_path);
+   return r;
+ }
+ 
+ /* Default constructor for a cache of file used by caret
+    diagnostic.  */
+ 
+ file_cache_slot::file_cache_slot ()
+ : m_use_count (0), m_file_path (NULL), m_fp (NULL), m_error (false), m_data (0),
+   m_alloc_offset (0), m_size (0), m_nb_read (0), m_line_start_idx (0),
+   m_line_num (0), m_missing_trailing_newline (true),
+   m_line_recent_last (0), m_line_recent_first (0)
+ {
+   m_line_record.create (0);
+   m_line_recent.create (1U << recent_cached_lines_shift);
+   for (int i = 0; i < 1 << recent_cached_lines_shift; i++)
+     m_line_recent.quick_push (file_cache_slot::line_info (0, 0, 0));
+ }
+ 
+ /* Destructor for a cache of file used by caret diagnostic.  */
+ 
+ file_cache_slot::~file_cache_slot ()
+ {
+   free (m_file_path);
+   if (m_fp)
+     {
+       fclose (m_fp);
+       m_fp = NULL;
+     }
+   if (m_data)
+     {
+       offset_buffer (-m_alloc_offset);
+       XDELETEVEC (m_data);
+       m_data = 0;
+     }
+   m_line_record.release ();
+   m_line_recent.release ();
+ }
+ 
+ void
+ file_cache_slot::dump (FILE *out, int indent) const
+ {
+   if (!m_file_path)
+     {
+       fprintf (out, "%*s(unused)\n", indent, "");
+       return;
+     }
+   fprintf (out, "%*sfile_path: %s\n", indent, "", m_file_path);
+   fprintf (out, "%*sfp: %p\n", indent, "", (void *)m_fp);
+   fprintf (out, "%*sneeds_read_p: %i\n", indent, "", (int)needs_read_p ());
+   fprintf (out, "%*sneeds_grow_p: %i\n", indent, "", (int)needs_grow_p ());
+   fprintf (out, "%*suse_count: %i\n", indent, "", m_use_count);
+   fprintf (out, "%*ssize: %zi\n", indent, "", m_size);
+   fprintf (out, "%*snb_read: %zi\n", indent, "", m_nb_read);
+   fprintf (out, "%*sstart_line_idx: %zi\n", indent, "", m_line_start_idx);
+   fprintf (out, "%*sline_num: %zi\n", indent, "", m_line_num);
+   fprintf (out, "%*smissing_trailing_newline: %i\n",
+ 	   indent, "", (int)m_missing_trailing_newline);
+   fprintf (out, "%*sline records (%i):\n",
+ 	   indent, "", m_line_record.length ());
+   int idx = 0;
+   for (auto &line : m_line_record)
+     fprintf (out, "%*s[%i]: line %zi: byte offsets: %zi-%zi\n",
+ 	     indent + 2, "",
+ 	     idx++, line.line_num, line.start_pos, line.end_pos);
+ }
+ 
+ /* Returns TRUE iff the cache would need to be filled with data coming
+    from the file.  That is, either the cache is empty or full or the
+    current line is empty.  Note that if the cache is full, it would
+    need to be extended and filled again.  */
+ 
+ bool
+ file_cache_slot::needs_read_p () const
+ {
+   return m_fp && (m_nb_read == 0
+ 	  || m_nb_read == m_size
+ 	  || (m_line_start_idx >= m_nb_read - 1));
+ }
+ 
+ /*  Return TRUE iff the cache is full and thus needs to be
+     extended.  */
+ 
+ bool
+ file_cache_slot::needs_grow_p () const
+ {
+   return m_nb_read == m_size;
+ }
+ 
+ /* Grow the cache if it needs to be extended.  */
+ 
+ void
+ file_cache_slot::maybe_grow ()
+ {
+   if (!needs_grow_p ())
+     return;
+ 
+   if (!m_data)
+     {
+       gcc_assert (m_size == 0 && m_alloc_offset == 0);
+       m_size = buffer_size;
+       m_data = XNEWVEC (char, m_size);
+     }
+   else
+     {
+       const int offset = m_alloc_offset;
+       offset_buffer (-offset);
+       m_size *= 2;
+       m_data = XRESIZEVEC (char, m_data, m_size);
+       offset_buffer (offset);
+     }
+ }
+ 
+ /*  Read more data into the cache.  Extends the cache if need be.
+     Returns TRUE iff new data could be read.  */
+ 
+ bool
+ file_cache_slot::read_data ()
+ {
+   if (feof (m_fp) || ferror (m_fp))
+     return false;
+ 
+   maybe_grow ();
+ 
+   char * from = m_data + m_nb_read;
+   size_t to_read = m_size - m_nb_read;
+   size_t nb_read = fread (from, 1, to_read, m_fp);
+ 
+   if (ferror (m_fp))
+     {
+       m_error = true;
+       return false;
+     }
+ 
+   m_nb_read += nb_read;
+   return !!nb_read;
+ }
+ 
+ /* Read new data iff the cache needs to be filled with more data
+    coming from the file FP.  Return TRUE iff the cache was filled with
+    mode data.  */
+ 
+ bool
+ file_cache_slot::maybe_read_data ()
+ {
+   if (!needs_read_p ())
+     return false;
+   return read_data ();
+ }
+ 
+ /* Helper function for file_cache_slot::get_next_line (), to find the end of
+    the next line.  Returns with the memchr convention, i.e. nullptr if a line
+    terminator was not found.  We need to determine line endings in the same
+    manner that libcpp does: any of \n, \r\n, or \r is a line ending.  */
+ 
+ static const char *
+ find_end_of_line (const char *s, size_t len)
+ {
+   for (const auto end = s + len; s != end; ++s)
+     {
+       if (*s == '\n')
+ 	return s;
+       if (*s == '\r')
+ 	{
+ 	  const auto next = s + 1;
+ 	  if (next == end)
+ 	    {
+ 	      /* Don't find the line ending if \r is the very last character
+ 		 in the buffer; we do not know if it's the end of the file or
+ 		 just the end of what has been read so far, and we wouldn't
+ 		 want to break in the middle of what's actually a \r\n
+ 		 sequence.  Instead, we will handle the case of a file ending
+ 		 in a \r later.  */
+ 	      break;
+ 	    }
+ 	  return (*next == '\n' ? next : s);
+ 	}
+     }
+   return nullptr;
+ }
+ 
+ /* Read a new line from file FP, using C as a cache for the data
+    coming from the file.  Upon successful completion, *LINE is set to
+    the beginning of the line found.  *LINE points directly in the
+    line cache and is only valid until the next call of get_next_line.
+    *LINE_LEN is set to the length of the line.  Note that the line
+    does not contain any terminal delimiter.  This function returns
+    true if some data was read or process from the cache, false
+    otherwise.  Note that subsequent calls to get_next_line might
+    make the content of *LINE invalid.  */
+ 
+ bool
+ file_cache_slot::get_next_line (char **line, ssize_t *line_len)
+ {
+   /* Fill the cache with data to process.  */
+   maybe_read_data ();
+ 
+   size_t remaining_size = m_nb_read - m_line_start_idx;
+   if (remaining_size == 0)
+     /* There is no more data to process.  */
+     return false;
+ 
+   const char *line_start = m_data + m_line_start_idx;
+ 
+   const char *next_line_start = NULL;
+   size_t len = 0;
+   const char *line_end = find_end_of_line (line_start, remaining_size);
+   if (line_end == NULL)
+     {
+       /* We haven't found an end-of-line delimiter in the cache.
+ 	 Fill the cache with more data from the file and look again.  */
+       while (maybe_read_data ())
+ 	{
+ 	  line_start = m_data + m_line_start_idx;
+ 	  remaining_size = m_nb_read - m_line_start_idx;
+ 	  line_end = find_end_of_line (line_start, remaining_size);
+ 	  if (line_end != NULL)
+ 	    {
+ 	      next_line_start = line_end + 1;
+ 	      break;
+ 	    }
+ 	}
+       if (line_end == NULL)
+ 	{
+ 	  /* We've loaded all the file into the cache and still no
+ 	     terminator.  Let's say the line ends up at one byte past the
+ 	     end of the file.  This is to stay consistent with the case
+ 	     of when the line ends up with a terminator and line_end points to
+ 	     that.  That consistency is useful below in the len calculation.
+ 
+ 	     If the file ends in a \r, we didn't identify it as a line
+ 	     terminator above, so do that now instead.  */
+ 	  line_end = m_data + m_nb_read;
+ 	  if (m_nb_read && line_end[-1] == '\r')
+ 	    {
+ 	      --line_end;
+ 	      m_missing_trailing_newline = false;
+ 	    }
+ 	  else
+ 	    m_missing_trailing_newline = true;
+ 	}
+       else
+ 	m_missing_trailing_newline = false;
+     }
+   else
+     {
+       next_line_start = line_end + 1;
+       m_missing_trailing_newline = false;
+     }
+ 
+   if (m_error)
+     return false;
+ 
+   /* At this point, we've found the end of the of line.  It either points to
+      the line terminator or to one byte after the last byte of the file.  */
+   gcc_assert (line_end != NULL);
+ 
+   len = line_end - line_start;
+ 
+   if (m_line_start_idx < m_nb_read)
+     *line = const_cast<char *> (line_start);
+ 
+   ++m_line_num;
+ 
+   /* Now update our line record so that re-reading lines from the
+      before m_line_start_idx is faster.  */
+   size_t rlen = m_line_record.length ();
+   /* Only update when beyond the previously cached region.  */
+   if (rlen == 0 || m_line_record[rlen - 1].line_num < m_line_num)
+     {
+       size_t spacing
+ 	= (rlen >= 2
+ 	   ? (m_line_record[rlen - 1].line_num
+ 	      - m_line_record[rlen - 2].line_num) : 1);
+       size_t delta
+ 	= rlen >= 1 ? m_line_num - m_line_record[rlen - 1].line_num : 1;
+ 
+       size_t max_size = line_record_size;
+       /* One anchor per hundred input lines.  */
+       if (max_size == 0)
+ 	max_size = m_line_num / 100;
+ 
+       /* If we're too far beyond drop half of the lines to rebalance.  */
+       if (rlen == max_size && delta >= spacing * 2)
+ 	{
+ 	  size_t j = 0;
+ 	  for (size_t i = 1; i < rlen; i += 2)
+ 	    m_line_record[j++] = m_line_record[i];
+ 	  m_line_record.truncate (j);
+ 	  rlen = j;
+ 	  spacing *= 2;
+ 	}
+ 
+       if (rlen < max_size && delta >= spacing)
+ 	{
+ 	  file_cache_slot::line_info li (m_line_num, m_line_start_idx,
+ 					 line_end - m_data);
+ 	  m_line_record.safe_push (li);
+ 	}
+     }
+ 
+   /* Cache recent tail lines separately for fast access. This assumes
+      most accesses do not skip backwards.  */
+   if (m_line_recent_last == m_line_recent_first
+       || m_line_recent[m_line_recent_last].line_num == m_line_num - 1)
+     {
+       size_t mask = ((size_t) 1 << recent_cached_lines_shift) - 1;
+       m_line_recent_last = (m_line_recent_last + 1) & mask;
+       if (m_line_recent_last == m_line_recent_first)
+ 	m_line_recent_first = (m_line_recent_first + 1) & mask;
+       m_line_recent[m_line_recent_last]
+ 	= file_cache_slot::line_info (m_line_num, m_line_start_idx,
+ 				      line_end - m_data);
+     }
+ 
+   /* Update m_line_start_idx so that it points to the next line to be
+      read.  */
+   if (next_line_start)
+     m_line_start_idx = next_line_start - m_data;
+   else
+     /* We didn't find any terminal '\n'.  Let's consider that the end
+        of line is the end of the data in the cache.  The next
+        invocation of get_next_line will either read more data from the
+        underlying file or return false early because we've reached the
+        end of the file.  */
+     m_line_start_idx = m_nb_read;
+ 
+   *line_len = len;
+ 
+   return true;
+ }
+ 
+ /* Consume the next bytes coming from the cache (or from its
+    underlying file if there are remaining unread bytes in the file)
+    until we reach the next end-of-line (or end-of-file).  There is no
+    copying from the cache involved.  Return TRUE upon successful
+    completion.  */
+ 
+ bool
+ file_cache_slot::goto_next_line ()
+ {
+   char *l;
+   ssize_t len;
+ 
+   return get_next_line (&l, &len);
+ }
+ 
+ /* Read an arbitrary line number LINE_NUM from the file cached in C.
+    If the line was read successfully, *LINE points to the beginning
+    of the line in the file cache and *LINE_LEN is the length of the
+    line.  *LINE is not nul-terminated, but may contain zero bytes.
+    *LINE is only valid until the next call of read_line_num.
+    This function returns bool if a line was read.  */
+ 
+ bool
+ file_cache_slot::read_line_num (size_t line_num,
+ 				char ** line, ssize_t *line_len)
+ {
+   gcc_assert (line_num > 0);
+ 
+   /* Is the line in the recent line cache?
+      This assumes the main file processing is only using
+      a single contiguous cursor with only temporary excursions.  */
+   if (m_line_recent_first != m_line_recent_last
+ 	&& m_line_recent[m_line_recent_first].line_num <= line_num
+ 	&& m_line_recent[m_line_recent_last].line_num >= line_num)
+     {
+       line_info &last = m_line_recent[m_line_recent_last];
+       size_t mask = (1U << recent_cached_lines_shift) - 1;
+       size_t idx = (m_line_recent_last - (last.line_num - line_num)) & mask;
+       line_info &recent = m_line_recent[idx];
+       gcc_assert (recent.line_num == line_num);
+       *line = m_data + recent.start_pos;
+       *line_len = recent.end_pos - recent.start_pos;
+       return true;
+     }
+ 
+   if (line_num <= m_line_num)
+     {
+       line_info l (line_num, 0, 0);
+       int i = m_line_record.lower_bound (l, line_info::less_than);
+       if (i == 0)
+ 	{
+ 	  m_line_start_idx = 0;
+ 	  m_line_num = 0;
+ 	}
+       else if (m_line_record[i - 1].line_num == line_num)
+ 	{
+ 	  /* We have the start/end of the line.  */
+ 	  *line = m_data + m_line_record[i - 1].start_pos;
+ 	  *line_len = m_line_record[i - 1].end_pos - m_line_record[i - 1].start_pos;
+ 	  return true;
+ 	}
+       else
+        {
+ 	 gcc_assert (m_line_record[i - 1].line_num < m_line_num);
+ 	 m_line_start_idx = m_line_record[i - 1].start_pos;
+ 	 m_line_num = m_line_record[i - 1].line_num - 1;
+        }
+     }
+ 
+   /*  Let's walk from line m_line_num up to line_num - 1, without
+       copying any line.  */
+   while (m_line_num < line_num - 1)
+     if (!goto_next_line ())
+       return false;
+ 
+   /* The line we want is the next one.  Let's read it.  */
+   return get_next_line (line, line_len);
+ }
+ 
+ /* Return the physical source line that corresponds to FILE_PATH/LINE.
+    The line is not nul-terminated.  The returned pointer is only
+    valid until the next call of location_get_source_line.
+    Note that the line can contain several null characters,
+    so the returned value's length has the actual length of the line.
+    If the function fails, a NULL char_span is returned.  */
+ 
+ char_span
+ file_cache::get_source_line (const char *file_path, int line)
+ {
+   char *buffer = NULL;
+   ssize_t len;
+ 
+   if (line == 0)
+     return char_span (NULL, 0);
+ 
+   if (file_path == NULL)
+     return char_span (NULL, 0);
+ 
+   file_cache_slot *c = lookup_or_add_file (file_path);
+   if (c == NULL)
+     return char_span (NULL, 0);
+ 
+   bool read = c->read_line_num (line, &buffer, &len);
+   if (!read)
+     return char_span (NULL, 0);
+ 
+   return char_span (buffer, len);
+ }
+ 
+ char_span
+ file_cache::get_source_file_content (const char *file_path)
+ {
+   file_cache_slot *c = lookup_or_add_file (file_path);
+   if (c == nullptr)
+     return char_span (nullptr, 0);
+   return c->get_full_file_content ();
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace selftest {
+ 
+  using temp_source_file = ::selftest::temp_source_file;
+ 
+ /* Verify reading of a specific line LINENUM in TMP, FC.  */
+ 
+ static void
+ check_line (temp_source_file &tmp, file_cache &fc, int linenum)
+ {
+   char_span line = fc.get_source_line (tmp.get_filename (), linenum);
+   int n;
+   const char *b = line.get_buffer ();
+   size_t l = line.length ();
+   char buf[5];
+   ASSERT_LT (l, 5);
+   memcpy (buf, b, l);
+   buf[l] = '\0';
+   ASSERT_TRUE (sscanf (buf, "%d", &n) == 1);
+   ASSERT_EQ (n, linenum);
+ }
+ 
+ /* Test file cache replacement.  */
+ 
+ static void
+ test_replacement ()
+ {
+   const int maxline = 1000;
+ 
+   char *vec = XNEWVEC (char, maxline * 5);
+   char *p = vec;
+   int i;
+   for (i = 1; i <= maxline; i++)
+     p += sprintf (p, "%d\n", i);
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".txt", vec);
+   free (vec);
+   file_cache fc;
+ 
+   for (i = 2; i <= maxline; i++)
+     {
+       check_line (tmp, fc, i);
+       check_line (tmp, fc, i - 1);
+       if (i >= 10)
+ 	check_line (tmp, fc, i - 9);
+       if (i >= 350) /* Exceed the look behind cache.  */
+ 	check_line (tmp, fc, i - 300);
+     }
+   for (i = 5; i <= maxline; i += 100)
+     check_line (tmp, fc, i);
+   for (i = 1; i <= maxline; i++)
+     check_line (tmp, fc, i);
+ }
+ 
+ /* Verify reading of input files (e.g. for caret-based diagnostics).  */
+ 
+ static void
+ test_reading_source_line ()
+ {
+   /* Create a tempfile and write some text to it.  */
+   temp_source_file tmp (SELFTEST_LOCATION, ".txt",
+ 			"01234567890123456789\n"
+ 			"This is the test text\n"
+ 			"This is the 3rd line");
+   file_cache fc;
+ 
+   /* Read back a specific line from the tempfile.  */
+   char_span source_line = fc.get_source_line (tmp.get_filename (), 3);
+   ASSERT_TRUE (source_line);
+   ASSERT_TRUE (source_line.get_buffer () != NULL);
+   ASSERT_EQ (20, source_line.length ());
+   ASSERT_TRUE (!strncmp ("This is the 3rd line",
+ 			 source_line.get_buffer (), source_line.length ()));
+ 
+   source_line = fc.get_source_line (tmp.get_filename (), 2);
+   ASSERT_TRUE (source_line);
+   ASSERT_TRUE (source_line.get_buffer () != NULL);
+   ASSERT_EQ (21, source_line.length ());
+   ASSERT_TRUE (!strncmp ("This is the test text",
+ 			 source_line.get_buffer (), source_line.length ()));
+ 
+   source_line = fc.get_source_line (tmp.get_filename (), 4);
+   ASSERT_FALSE (source_line);
+   ASSERT_TRUE (source_line.get_buffer () == NULL);
+ }
+ 
+ /* Verify reading from buffers (e.g. for sarif-replay).  */
+ 
+ static void
+ test_reading_source_buffer ()
+ {
+   const char *text = ("01234567890123456789\n"
+ 		      "This is the test text\n"
+ 		      "This is the 3rd line");
+   const char *filename = "foo.txt";
+   file_cache fc;
+   fc.add_buffered_content (filename, text, strlen (text));
+ 
+   /* Read back a specific line from the tempfile.  */
+   char_span source_line = fc.get_source_line (filename, 3);
+   ASSERT_TRUE (source_line);
+   ASSERT_TRUE (source_line.get_buffer () != NULL);
+   ASSERT_EQ (20, source_line.length ());
+   ASSERT_TRUE (!strncmp ("This is the 3rd line",
+ 			 source_line.get_buffer (), source_line.length ()));
+ 
+   source_line = fc.get_source_line (filename, 2);
+   ASSERT_TRUE (source_line);
+   ASSERT_TRUE (source_line.get_buffer () != NULL);
+   ASSERT_EQ (21, source_line.length ());
+   ASSERT_TRUE (!strncmp ("This is the test text",
+ 			 source_line.get_buffer (), source_line.length ()));
+ 
+   source_line = fc.get_source_line (filename, 4);
+   ASSERT_FALSE (source_line);
+   ASSERT_TRUE (source_line.get_buffer () == NULL);
+ }
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ file_cache_cc_tests ()
+ {
+   test_reading_source_line ();
+   test_reading_source_buffer ();
+   test_replacement ();
+ }
+ 
+ } // namespace selftest
+ 
+ #endif /* CHECKING_P */
+ 
+ } // namespace diagnostics
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/file-cache.h gcc-16-20250727/gcc/diagnostics/file-cache.h
*** gcc-16-20250720/gcc/diagnostics/file-cache.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/file-cache.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,125 ----
+ /* Caching input files for use by diagnostics.
+    Copyright (C) 2004-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_FILE_CACHE_H
+ #define GCC_DIAGNOSTICS_FILE_CACHE_H
+ 
+ namespace diagnostics {
+ 
+ /* A class capturing the bounds of a buffer, to allow for run-time
+    bounds-checking in a checked build.  */
+ 
+ class char_span
+ {
+  public:
+   char_span (const char *ptr, size_t n_elts) : m_ptr (ptr), m_n_elts (n_elts) {}
+ 
+   /* Test for a non-NULL pointer.  */
+   operator bool() const { return m_ptr; }
+ 
+   /* Get length, not including any 0-terminator (which may not be,
+      in fact, present).  */
+   size_t length () const { return m_n_elts; }
+ 
+   const char *get_buffer () const { return m_ptr; }
+ 
+   char operator[] (int idx) const
+   {
+     gcc_assert (idx >= 0);
+     gcc_assert ((size_t)idx < m_n_elts);
+     return m_ptr[idx];
+   }
+ 
+   char_span subspan (int offset, int n_elts) const
+   {
+     gcc_assert (offset >= 0);
+     gcc_assert (offset < (int)m_n_elts);
+     gcc_assert (n_elts >= 0);
+     gcc_assert (offset + n_elts <= (int)m_n_elts);
+     return char_span (m_ptr + offset, n_elts);
+   }
+ 
+   char *xstrdup () const
+   {
+     return ::xstrndup (m_ptr, m_n_elts);
+   }
+ 
+  private:
+   const char *m_ptr;
+   size_t m_n_elts;
+ };
+ 
+ /* Forward decl of slot within file_cache, so that the definition doesn't
+    need to be in this header.  */
+ class file_cache_slot;
+ 
+ /* A cache of source files for use when emitting diagnostics
+    (and in a few places in the C/C++ frontends).
+ 
+    Results are only valid until the next call to the cache, as
+    slots can be evicted.
+ 
+    Filenames are stored by pointer, and so must outlive the cache
+    instance.  */
+ 
+ class file_cache
+ {
+  public:
+   file_cache ();
+   ~file_cache ();
+ 
+   void dump (FILE *out, int indent) const;
+   void DEBUG_FUNCTION dump () const;
+ 
+   file_cache_slot *lookup_or_add_file (const char *file_path);
+   void forcibly_evict_file (const char *file_path);
+ 
+   /* See comments in diagnostic.h about the input conversion context.  */
+   struct input_context
+   {
+     diagnostic_input_charset_callback ccb;
+     bool should_skip_bom;
+   };
+   void initialize_input_context (diagnostic_input_charset_callback ccb,
+ 				 bool should_skip_bom);
+ 
+   char_span get_source_file_content (const char *file_path);
+   char_span get_source_line (const char *file_path, int line);
+   bool missing_trailing_newline_p (const char *file_path);
+ 
+   void add_buffered_content (const char *file_path,
+ 			     const char *buffer,
+ 			     size_t sz);
+ 
+   void tune (size_t num_file_slots, size_t lines);
+ 
+  private:
+   file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count);
+   file_cache_slot *add_file (const char *file_path);
+   file_cache_slot *lookup_file (const char *file_path);
+ 
+  private:
+   size_t m_num_file_slots;
+   file_cache_slot *m_file_slots;
+   input_context m_input_context;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif // #ifndef GCC_DIAGNOSTICS_FILE_CACHE_H
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/html-sink.cc gcc-16-20250727/gcc/diagnostics/html-sink.cc
*** gcc-16-20250720/gcc/diagnostics/html-sink.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/html-sink.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,1707 ----
+ /* HTML output for diagnostics.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #define INCLUDE_MAP
+ #define INCLUDE_STRING
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "diagnostic.h"
+ #include "diagnostics/metadata.h"
+ #include "diagnostics/sink.h"
+ #include "diagnostics/html-sink.h"
+ #include "diagnostics/text-sink.h"
+ #include "diagnostics/sarif-sink.h"
+ #include "diagnostics/output-file.h"
+ #include "diagnostics/buffering.h"
+ #include "diagnostics/paths.h"
+ #include "diagnostics/client-data-hooks.h"
+ #include "selftest.h"
+ #include "diagnostics/selftest-context.h"
+ #include "pretty-print-format-impl.h"
+ #include "pretty-print-urlifier.h"
+ #include "diagnostics/changes.h"
+ #include "intl.h"
+ #include "xml.h"
+ #include "xml-printer.h"
+ #include "diagnostics/digraphs.h"
+ #include "diagnostics/state-graphs.h"
+ #include "graphviz.h"
+ #include "json.h"
+ #include "selftest-xml.h"
+ 
+ namespace diagnostics {
+ 
+ // struct html_generation_options
+ 
+ html_generation_options::html_generation_options ()
+ : m_css (true),
+   m_javascript (true),
+   m_show_state_diagrams (false),
+   m_show_state_diagrams_sarif (false),
+   m_show_state_diagrams_dot_src (false)
+ {
+ }
+ 
+ class html_builder;
+ 
+ /* Concrete buffering implementation subclass for HTML output.  */
+ 
+ class html_sink_buffer : public per_sink_buffer
+ {
+ public:
+   friend class html_builder;
+   friend class html_sink;
+ 
+   html_sink_buffer (html_builder &builder)
+   : m_builder (builder)
+   {}
+ 
+   void dump (FILE *out, int indent) const final override;
+   bool empty_p () const final override;
+   void move_to (per_sink_buffer &dest) final override;
+   void clear () final override;
+   void flush () final override;
+ 
+   void add_result (std::unique_ptr<xml::element> result)
+   {
+     m_results.push_back (std::move (result));
+   }
+ 
+ private:
+   html_builder &m_builder;
+   std::vector<std::unique_ptr<xml::element>> m_results;
+ };
+ 
+ /* A class for managing HTML output of diagnostics.
+ 
+    Implemented:
+    - message text
+ 
+    Known limitations/missing functionality:
+    - title for page
+    - file/line/column
+    - error vs warning
+    - CWEs
+    - rules
+    - fix-it hints
+    - paths
+ */
+ 
+ class html_builder
+ {
+ public:
+   friend class html_sink_buffer;
+ 
+   html_builder (context &dc,
+ 		pretty_printer &pp,
+ 		const line_maps *line_maps,
+ 		const html_generation_options &html_gen_opts);
+ 
+   void
+   set_main_input_filename (const char *name);
+ 
+   void on_report_diagnostic (const diagnostic_info &diagnostic,
+ 			     enum kind orig_diag_kind,
+ 			     html_sink_buffer *buffer);
+   void emit_diagram (const diagram &d);
+   void emit_global_graph (const lazily_created<digraphs::digraph> &);
+ 
+   void end_group ();
+ 
+   std::unique_ptr<xml::element> take_current_diagnostic ()
+   {
+     return std::move (m_cur_diagnostic_element);
+   }
+ 
+   void flush_to_file (FILE *outf);
+ 
+   const xml::document &get_document () const { return *m_document; }
+ 
+   void set_printer (pretty_printer &pp)
+   {
+     m_printer = &pp;
+   }
+ 
+   std::unique_ptr<xml::element>
+   make_element_for_metadata (const metadata &);
+ 
+   std::unique_ptr<xml::element>
+   make_element_for_patch (const diagnostic_info &diagnostic);
+ 
+   void add_focus_id (std::string focus_id)
+   {
+     m_ui_focus_ids.append_string (focus_id.c_str ());
+   }
+ 
+   std::unique_ptr<xml::node>
+   maybe_make_state_diagram (const paths::event &event);
+ 
+ private:
+   void
+   add_stylesheet (std::string url);
+ 
+   std::unique_ptr<xml::element>
+   make_element_for_diagnostic (const diagnostic_info &diagnostic,
+ 			       enum kind orig_diag_kind,
+ 			       bool alert);
+ 
+   std::unique_ptr<xml::element>
+   make_metadata_element (label_text label,
+ 			 label_text url);
+ 
+   void
+   add_at_nesting_level (size_t nesting_level,
+ 			std::unique_ptr<xml::element> child_diag_element);
+ 
+   void
+   push_nesting_level ();
+ 
+   void
+   pop_nesting_level ();
+ 
+   void
+   add_graph (const digraphs::digraph &dg,
+ 	     xml::element &parent_element);
+ 
+   context &m_context;
+   pretty_printer *m_printer;
+   const line_maps *m_line_maps;
+   html_generation_options m_html_gen_opts;
+   const logical_locations::manager *m_logical_loc_mgr;
+ 
+   std::unique_ptr<xml::document> m_document;
+   xml::element *m_head_element;
+   xml::element *m_title_element;
+   xml::element *m_body_element;
+   xml::element *m_diagnostics_element;
+   std::unique_ptr<xml::element> m_cur_diagnostic_element;
+   std::vector<xml::element *> m_cur_nesting_levels;
+   int m_next_diag_id; // for handing out unique IDs
+   json::array m_ui_focus_ids;
+   logical_locations::key m_last_logical_location;
+   location_t m_last_location;
+   expanded_location m_last_expanded_location;
+ };
+ 
+ static std::unique_ptr<xml::element>
+ make_div (std::string class_)
+ {
+   auto div = std::make_unique<xml::element> ("div", false);
+   div->set_attr ("class", std::move (class_));
+   return div;
+ }
+ 
+ static std::unique_ptr<xml::element>
+ make_span (std::string class_)
+ {
+   auto span = std::make_unique<xml::element> ("span", true);
+   span->set_attr ("class", std::move (class_));
+   return span;
+ }
+ 
+ /* class html_sink_buffer : public per_sink_buffer.  */
+ 
+ void
+ html_sink_buffer::dump (FILE *out, int indent) const
+ {
+   fprintf (out, "%*shtml_sink_buffer:\n", indent, "");
+   int idx = 0;
+   for (auto &result : m_results)
+     {
+       fprintf (out, "%*sresult[%i]:\n", indent + 2, "", idx);
+       result->dump (out);
+       fprintf (out, "\n");
+       ++idx;
+     }
+ }
+ 
+ bool
+ html_sink_buffer::empty_p () const
+ {
+   return m_results.empty ();
+ }
+ 
+ void
+ html_sink_buffer::move_to (per_sink_buffer &base)
+ {
+   html_sink_buffer &dest
+     = static_cast<html_sink_buffer &> (base);
+   for (auto &&result : m_results)
+     dest.m_results.push_back (std::move (result));
+   m_results.clear ();
+ }
+ 
+ void
+ html_sink_buffer::clear ()
+ {
+   m_results.clear ();
+ }
+ 
+ void
+ html_sink_buffer::flush ()
+ {
+   for (auto &&result : m_results)
+     m_builder.m_diagnostics_element->add_child (std::move (result));
+   m_results.clear ();
+ }
+ 
+ /* class html_builder.  */
+ 
+ /* Style information for writing out HTML paths.
+    Colors taken from https://pf3.patternfly.org/v3/styles/color-palette/ */
+ 
+ static const char * const HTML_STYLE
+   = ("  <style>\n"
+      "    .linenum { color: white;\n"
+      "               background-color: #0088ce;\n"
+      "               white-space: pre;\n"
+      "               border-right: 1px solid black; }\n"
+      "    .ruler { color: red;\n"
+      "              white-space: pre; }\n"
+      "    .source { color: blue;\n"
+      "              background-color: white;\n"
+      "              white-space: pre; }\n"
+      "    .annotation { color: green;\n"
+      "                  background-color: white;\n"
+      "                  white-space: pre; }\n"
+      "    .linenum-gap { text-align: center;\n"
+      "                   border-top: 1px solid black;\n"
+      "                   border-right: 1px solid black;\n"
+      "                   background-color: #ededed; }\n"
+      "    .source-gap { border-bottom: 1px dashed black;\n"
+      "                  border-top: 1px dashed black;\n"
+      "                  background-color: #ededed; }\n"
+      "    .no-locus-event { font-family: monospace;\n"
+      "                      color: green;\n"
+      "                      white-space: pre; }\n"
+      "    .funcname { font-weight: bold; }\n"
+      "    .events-hdr { color: white;\n"
+      "                  background-color: #030303; }\n"
+      "    .event-range {  border: 1px solid black;\n"
+      "                    padding: 0px; }\n"
+      "    .event-range-with-margin { border-spacing: 0; }\n"
+      "    .locus { font-family: monospace;\n"
+      "             border-spacing: 0px; }\n"
+      "    .selected { color: white;\n"
+      "                background-color: #0088ce; }\n"
+      "    .stack-frame-with-margin { border-spacing: 0; }\n"
+      "    .stack-frame {  padding: 5px;\n"
+      "                    box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.5); }\n"
+      "    .frame-funcname { text-align: right;\n"
+      "                      font-style: italic; } \n"
+      "    .highlight-a { color: #703fec;\n" // pf-purple-400
+      "                   font-weight: bold; }\n"
+      "    .highlight-b { color: #3f9c35;\n" // pf-green-400
+      "                   font-weight: bold; }\n"
+      "    .gcc-quoted-text { font-weight: bold;\n"
+      "                       font-family: mono; }\n"
+      "  </style>\n");
+ 
+ /* A little JavaScript for ease of navigation.
+    Keys j/k move forward and backward cyclically through a list
+    of focus ids (written out in another <script> tag as the HTML
+    is flushed).  */
+ 
+ const char * const HTML_SCRIPT
+   = ("  var current_focus_idx = 0;\n"
+      "\n"
+      "  function get_focus_span (focus_idx)\n"
+      "  {\n"
+      "      const element_id = focus_ids[focus_idx];\n"
+      "      return document.getElementById(element_id);\n"
+      "  }\n"
+      "  function get_any_state_diagram (focus_idx)\n"
+      "  {\n"
+      "      const element_id = focus_ids[focus_idx];\n"
+      "      return document.getElementById(element_id + \"-state-diagram\");\n"
+      "  }\n"
+      "  function unhighlight_current_focus_idx ()\n"
+      "  {\n"
+      "      get_focus_span (current_focus_idx).classList.remove ('selected');\n"
+      "      state_diagram = get_any_state_diagram (current_focus_idx);\n"
+      "      if (state_diagram) {\n"
+      "          state_diagram.style.visibility = \"hidden\";\n"
+      "      }\n"
+      "  }\n"
+      "  function highlight_current_focus_idx ()\n"
+      "  {\n"
+      "      const el = get_focus_span (current_focus_idx);\n"
+      "      el.classList.add ('selected');\n"
+      "      state_diagram = get_any_state_diagram (current_focus_idx);\n"
+      "      if (state_diagram) {\n"
+      "          state_diagram.style.visibility = \"visible\";\n"
+      "      }\n"
+      "      // Center the element on the screen\n"
+      "      const top_y = el.getBoundingClientRect ().top + window.pageYOffset;\n"
+      "      const middle = top_y - (window.innerHeight / 2);\n"
+      "      window.scrollTo (0, middle);\n"
+      "  }\n"
+      "  function select_prev_focus_idx ()\n"
+      "  {\n"
+      "      unhighlight_current_focus_idx ();\n"
+      "      if (current_focus_idx > 0)\n"
+      "          current_focus_idx -= 1;\n"
+      "      else\n"
+      "          current_focus_idx = focus_ids.length - 1;\n"
+      "      highlight_current_focus_idx ();\n"
+      "  }\n"
+      "  function select_next_focus_idx ()\n"
+      "  {\n"
+      "      unhighlight_current_focus_idx ();\n"
+      "      if (current_focus_idx < focus_ids.length - 1)\n"
+      "          current_focus_idx += 1;\n"
+      "      else\n"
+      "          current_focus_idx = 0;\n"
+      "      highlight_current_focus_idx ();\n"
+      "  }\n"
+      "  document.addEventListener('keydown', function (ev) {\n"
+      "      if (ev.key == 'j')\n"
+      "          select_next_focus_idx ();\n"
+      "      else if (ev.key == 'k')\n"
+      "          select_prev_focus_idx ();\n"
+      "  });\n"
+      "  highlight_current_focus_idx ();\n");
+ 
+ struct html_doctypedecl : public xml::doctypedecl
+ {
+   void write_as_xml (pretty_printer *pp,
+ 		     int depth, bool indent) const final override
+   {
+     if (indent)
+       {
+ 	for (int i = 0; i < depth; ++i)
+ 	  pp_string (pp, "  ");
+       }
+     pp_string (pp, "<!DOCTYPE html\n"
+ 	       "     PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
+ 	       "     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
+     if (indent)
+       pp_newline (pp);
+   }
+ };
+ 
+ /* html_builder's ctor.  */
+ 
+ html_builder::html_builder (context &dc,
+ 			    pretty_printer &pp,
+ 			    const line_maps *line_maps,
+ 			    const html_generation_options &html_gen_opts)
+ : m_context (dc),
+   m_printer (&pp),
+   m_line_maps (line_maps),
+   m_html_gen_opts (html_gen_opts),
+   m_logical_loc_mgr (nullptr),
+   m_head_element (nullptr),
+   m_title_element (nullptr),
+   m_body_element (nullptr),
+   m_diagnostics_element (nullptr),
+   m_next_diag_id (0),
+   m_last_location (UNKNOWN_LOCATION),
+   m_last_expanded_location ({})
+ {
+   gcc_assert (m_line_maps);
+ 
+   if (auto client_data_hooks = dc.get_client_data_hooks ())
+     m_logical_loc_mgr = client_data_hooks->get_logical_location_manager ();
+ 
+   m_document = std::make_unique<xml::document> ();
+   m_document->m_doctypedecl = std::make_unique<html_doctypedecl> ();
+   {
+     auto html_element = std::make_unique<xml::element> ("html", false);
+     html_element->set_attr ("xmlns",
+ 			    "http://www.w3.org/1999/xhtml");
+     xml::printer xp (*html_element.get ());
+     m_document->add_child (std::move (html_element));
+ 
+     {
+       xml::auto_print_element head (xp, "head");
+       m_head_element = xp.get_insertion_point ();
+       {
+ 	xml::auto_print_element title (xp, "title", true);
+ 	m_title_element = xp.get_insertion_point ();
+ 	m_title_element->add_text (" ");
+       }
+ 
+       if (m_html_gen_opts.m_css)
+ 	{
+ 	  add_stylesheet ("https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly.min.css");
+ 	  add_stylesheet ("https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly-additions.min.css");
+ 	  xp.add_raw (HTML_STYLE);
+ 	}
+       if (m_html_gen_opts.m_javascript)
+ 	{
+ 	  xp.push_tag ("script");
+ 	  /* Escaping rules are different for HTML <script> elements,
+ 	     so add the script "raw" for now.  */
+ 	  xp.add_raw (HTML_SCRIPT);
+ 	  xp.pop_tag ("script");
+ 	}
+     }
+ 
+     {
+       xml::auto_print_element body (xp, "body");
+       m_body_element = xp.get_insertion_point ();
+       {
+ 	auto diagnostics_element = make_div ("gcc-diagnostic-list");
+ 	m_diagnostics_element = diagnostics_element.get ();
+ 	xp.append (std::move (diagnostics_element));
+       }
+     }
+   }
+ }
+ 
+ void
+ html_builder::set_main_input_filename (const char *name)
+ {
+   gcc_assert (m_title_element);
+   if (name)
+     {
+       m_title_element->m_children.clear ();
+       m_title_element->add_text (name);
+     }
+ }
+ 
+ void
+ html_builder::add_stylesheet (std::string url)
+ {
+   gcc_assert (m_head_element);
+ 
+   xml::printer xp (*m_head_element);
+   xp.push_tag ("link", false);
+   xp.set_attr ("rel", "stylesheet");
+   xp.set_attr ("type", "text/css");
+   xp.set_attr ("href", std::move (url));
+ }
+ 
+ /* Implementation of "on_report_diagnostic" for HTML output.  */
+ 
+ void
+ html_builder::on_report_diagnostic (const diagnostic_info &diagnostic,
+ 				    enum kind orig_diag_kind,
+ 				    html_sink_buffer *buffer)
+ {
+   if (diagnostic.m_kind == kind::ice || diagnostic.m_kind == kind::ice_nobt)
+     {
+       /* Print a header for the remaining output to stderr, and
+ 	 return, attempting to print the usual ICE messages to
+ 	 stderr.  Hopefully this will be helpful to the user in
+ 	 indicating what's gone wrong (also for DejaGnu, for pruning
+ 	 those messages).   */
+       fnotice (stderr, "Internal compiler error:\n");
+     }
+ 
+   const int nesting_level = m_context.get_diagnostic_nesting_level ();
+   bool alert = true;
+   if (m_cur_diagnostic_element && nesting_level > 0)
+     alert = false;
+   if (!m_cur_diagnostic_element)
+     m_last_logical_location = logical_locations::key ();
+   auto diag_element
+     = make_element_for_diagnostic (diagnostic, orig_diag_kind, alert);
+   if (buffer)
+     {
+       gcc_assert (!m_cur_diagnostic_element);
+       buffer->m_results.push_back (std::move (diag_element));
+     }
+   else
+     {
+       if (m_cur_diagnostic_element)
+ 	{
+ 	  /* Nested diagnostic.  */
+ 	  gcc_assert (nesting_level >= 0);
+ 	  add_at_nesting_level (nesting_level, std::move (diag_element));
+ 	}
+       else
+ 	/* Top-level diagnostic.  */
+ 	{
+ 	  m_cur_diagnostic_element = std::move (diag_element);
+ 	  m_cur_nesting_levels.clear ();
+ 	}
+     }
+ }
+ 
+ // For ease of comparison with experimental-nesting-show-levels=yes
+ 
+ static void
+ add_nesting_level_attr (xml::element &element,
+ 			int nesting_level)
+ {
+   element.set_attr ("nesting-level", std::to_string (nesting_level));
+ }
+ 
+ void
+ html_builder::
+ add_at_nesting_level (size_t nesting_level,
+ 		      std::unique_ptr<xml::element> child_diag_element)
+ {
+   gcc_assert (m_cur_diagnostic_element);
+   while (nesting_level > m_cur_nesting_levels.size ())
+     push_nesting_level ();
+   while (nesting_level < m_cur_nesting_levels.size ())
+     pop_nesting_level ();
+ 
+   if (nesting_level > 0)
+     {
+       gcc_assert (!m_cur_nesting_levels.empty ());
+       auto current_nesting_level = m_cur_nesting_levels.back ();
+       xml::printer xp (*current_nesting_level);
+       xp.push_tag ("li");
+       add_nesting_level_attr (*xp.get_insertion_point (),
+ 			      m_cur_nesting_levels.size ());
+       xp.append (std::move (child_diag_element));
+       xp.pop_tag ("li");
+     }
+   else
+     m_cur_diagnostic_element->add_child (std::move (child_diag_element));
+ }
+ 
+ void
+ html_builder::push_nesting_level ()
+ {
+   gcc_assert (m_cur_diagnostic_element);
+   auto new_nesting_level = std::make_unique<xml::element> ("ul", false);
+   add_nesting_level_attr (*new_nesting_level,
+ 			  m_cur_nesting_levels.size () + 1);
+   xml::element *current_nesting_level = nullptr;
+   if (!m_cur_nesting_levels.empty ())
+     current_nesting_level = m_cur_nesting_levels.back ();
+   m_cur_nesting_levels.push_back (new_nesting_level.get ());
+   if (current_nesting_level)
+     current_nesting_level->add_child (std::move (new_nesting_level));
+   else
+     m_cur_diagnostic_element->add_child (std::move (new_nesting_level));
+ }
+ 
+ void
+ html_builder::pop_nesting_level ()
+ {
+   gcc_assert (m_cur_diagnostic_element);
+   m_cur_nesting_levels.pop_back ();
+ }
+ 
+ static void
+ print_pre_source (xml::printer &xp, const char *text)
+ {
+   xp.push_tag_with_class ("pre", "source", true);
+   xp.add_text (text);
+   xp.pop_tag ("pre");
+ }
+ 
+ std::unique_ptr<xml::node>
+ html_builder::maybe_make_state_diagram (const paths::event &event)
+ {
+   if (!m_html_gen_opts.m_show_state_diagrams)
+     return nullptr;
+ 
+   if (!m_logical_loc_mgr)
+     return nullptr;
+ 
+   /* Get state graph; if we're going to print it later, also request
+      the debug version.  */
+   auto state_graph
+     = event.maybe_make_diagnostic_state_graph
+ 	(m_html_gen_opts.m_show_state_diagrams_sarif);
+   if (!state_graph)
+     return nullptr;
+ 
+   // Convert it to .dot AST
+   auto dot_graph = state_graphs::make_dot_graph (*state_graph,
+ 						 *m_logical_loc_mgr);
+   gcc_assert (dot_graph);
+ 
+   auto wrapper = std::make_unique<xml::element> ("div", false);
+   xml::printer xp (*wrapper);
+ 
+   if (m_html_gen_opts.m_show_state_diagrams_sarif)
+     {
+       // For debugging, show the SARIF src inline:
+       pretty_printer pp;
+       state_graph->make_json_sarif_graph ()->print (&pp, true);
+       print_pre_source (xp, pp_formatted_text (&pp));
+     }
+ 
+   if (m_html_gen_opts.m_show_state_diagrams_dot_src)
+     {
+       // For debugging, show the dot src inline:
+       pretty_printer pp;
+       dot::writer w (pp);
+       dot_graph->print (w);
+       print_pre_source (xp, pp_formatted_text (&pp));
+     }
+ 
+   // Turn the .dot into SVG and splice into place
+   auto svg = dot::make_svg_from_graph (*dot_graph);
+   if (svg)
+     xp.append (std::move (svg));
+ 
+   return wrapper;
+ }
+ 
+ /* Custom subclass of html_label_writer.
+    Wrap labels within a <span> element, supplying them with event IDs.
+    Add the IDs to the list of focus IDs.  */
+ 
+ class html_path_label_writer : public html_label_writer
+ {
+ public:
+   html_path_label_writer (xml::printer &xp,
+ 			  html_builder &builder,
+ 			  const paths::path &path,
+ 			  const std::string &event_id_prefix)
+   : m_xp (xp),
+     m_html_builder (builder),
+     m_path (path),
+     m_event_id_prefix (event_id_prefix),
+     m_next_event_idx (0),
+     m_curr_event_id ()
+   {
+   }
+ 
+   void begin_label () final override
+   {
+     m_curr_event_id = m_next_event_idx++;
+     m_xp.push_tag_with_class ("span", "event", true);
+     m_xp.set_attr ("id", get_element_id ());
+     m_html_builder.add_focus_id (get_element_id ());
+   }
+ 
+   void end_label () final override
+   {
+     const paths::event &event
+       = m_path.get_event (m_curr_event_id.zero_based ());
+     if (auto state_doc = m_html_builder.maybe_make_state_diagram (event))
+     {
+       m_xp.push_tag_with_class ("div", "state-diagram", false);
+       m_xp.set_attr ("id", get_element_id () + "-state-diagram");
+       m_xp.set_attr ("style",
+ 		     ("position: absolute;"
+ 		      " z-index: 1;"
+ 		      " visibility: hidden;"));
+       m_xp.append (std::move (state_doc));
+       m_xp.pop_tag ("div");
+     }
+ 
+     m_xp.pop_tag ("span"); // from begin_label
+   }
+ 
+ private:
+   std::string
+   get_element_id () const
+   {
+     gcc_assert (m_curr_event_id.known_p ());
+     return (m_event_id_prefix
+ 	    + std::to_string (m_curr_event_id.zero_based ()));
+   }
+ 
+   xml::printer &m_xp;
+   html_builder &m_html_builder;
+   const paths::path &m_path;
+   const std::string &m_event_id_prefix;
+   int m_next_event_idx;
+   paths::event_id_t m_curr_event_id;
+ };
+ 
+ /* See https://pf3.patternfly.org/v3/pattern-library/widgets/#alerts */
+ static const char *
+ get_pf_class_for_alert_div (enum kind diag_kind)
+ {
+   switch (diag_kind)
+     {
+     case kind::debug:
+     case kind::note:
+       return "alert alert-info";
+ 
+     case kind::anachronism:
+     case kind::warning:
+       return "alert alert-warning";
+ 
+     case kind::error:
+     case kind::sorry:
+     case kind::ice:
+     case kind::ice_nobt:
+     case kind::fatal:
+       return "alert alert-danger";
+ 
+     default:
+       gcc_unreachable ();
+     }
+ }
+ 
+ static const char *
+ get_pf_class_for_alert_icon (enum kind diag_kind)
+ {
+   switch (diag_kind)
+     {
+     case kind::debug:
+     case kind::note:
+       return "pficon pficon-info";
+ 
+     case kind::anachronism:
+     case kind::warning:
+       return "pficon pficon-warning-triangle-o";
+ 
+     case kind::error:
+     case kind::sorry:
+     case kind::ice:
+     case kind::ice_nobt:
+     case kind::fatal:
+       return "pficon pficon-error-circle-o";
+ 
+     default:
+       gcc_unreachable ();
+     }
+ }
+ 
+ static const char *
+ get_label_for_logical_location_kind (enum logical_locations::kind kind)
+ {
+   switch (kind)
+     {
+     default:
+       gcc_unreachable ();
+     case logical_locations::kind::unknown:
+       return nullptr;
+ 
+     /* Kinds within executable code.  */
+     case logical_locations::kind::function:
+       return "Function";
+     case logical_locations::kind::member:
+       return "Member";
+     case logical_locations::kind::module_:
+       return "Module";
+     case logical_locations::kind::namespace_:
+       return "Namespace";
+     case logical_locations::kind::type:
+       return "Type";
+     case logical_locations::kind::return_type:
+       return "Return type";
+     case logical_locations::kind::parameter:
+       return "Parameter";
+     case logical_locations::kind::variable:
+       return "Variable";
+ 
+     /* Kinds within XML or HTML documents.  */
+     case logical_locations::kind::element:
+       return "Element";
+     case logical_locations::kind::attribute:
+       return "Attribute";
+     case logical_locations::kind::text:
+       return "Text";
+     case logical_locations::kind::comment:
+       return "Comment";
+     case logical_locations::kind::processing_instruction:
+       return "Processing Instruction";
+     case logical_locations::kind::dtd:
+       return "DTD";
+     case logical_locations::kind::declaration:
+       return "Declaration";
+ 
+   /* Kinds within JSON documents.  */
+     case logical_locations::kind::object:
+       return "Object";
+     case logical_locations::kind::array:
+       return "Array";
+     case logical_locations::kind::property:
+       return "Property";
+     case logical_locations::kind::value:
+       return "Value";
+     }
+ }
+ 
+ static void
+ add_labelled_value (xml::printer &xp,
+ 		    std::string id,
+ 		    std::string label,
+ 		    std::string value,
+ 		    bool quote_value)
+ {
+   xp.push_tag ("div", true);
+   xp.set_attr ("id", id);
+   xp.push_tag ("span");
+   xp.add_text (label);
+   xp.add_text (" ");
+   xp.pop_tag ("span");
+   xp.push_tag ("span");
+   if (quote_value)
+     xp.set_attr ("class", "gcc-quoted-text");
+   xp.add_text (std::move (value));
+   xp.pop_tag ("span");
+   xp.pop_tag ("div");
+ }
+ 
+ class html_token_printer : public token_printer
+ {
+ public:
+   html_token_printer (xml::element &parent_element)
+     /* Ideally pp_token_lists that reach a token_printer should be
+        "balanced", but for now they can have mismatching pp_tokens
+        e.g. a begin_color without an end_color (PR other/120610).
+        Give html_token_printer its own xml::printer as a firewall to
+        limit the scope of the mismatches in the HTML.  */
+     : m_xp (parent_element,
+ 	    /* Similarly we don't check that the popped tags match.  */
+ 	    false)
+   {
+   }
+   void print_tokens (pretty_printer */*pp*/,
+ 		     const pp_token_list &tokens) final override
+   {
+     /* Implement print_tokens by adding child elements to
+        m_parent_element.  */
+     for (auto iter = tokens.m_first; iter; iter = iter->m_next)
+       switch (iter->m_kind)
+ 	{
+ 	default:
+ 	  gcc_unreachable ();
+ 
+ 	case pp_token::kind::text:
+ 	  {
+ 	    pp_token_text *sub = as_a <pp_token_text *> (iter);
+ 	    /* The value might be in the obstack, so we may need to
+ 	       copy it.  */
+ 	    m_xp.add_text (sub->m_value.get ());
+ 	    }
+ 	  break;
+ 
+ 	case pp_token::kind::begin_color:
+ 	  {
+ 	    pp_token_begin_color *sub = as_a <pp_token_begin_color *> (iter);
+ 	    gcc_assert (sub->m_value.get ());
+ 	    m_xp.push_tag_with_class ("span", sub->m_value.get ());
+ 	  }
+ 	  break;
+ 
+ 	case pp_token::kind::end_color:
+ 	  m_xp.pop_tag ("span");
+ 	  break;
+ 
+ 	case pp_token::kind::begin_quote:
+ 	  {
+ 	    m_xp.add_text (open_quote);
+ 	    m_xp.push_tag_with_class ("span", "gcc-quoted-text");
+ 	  }
+ 	  break;
+ 	case pp_token::kind::end_quote:
+ 	  {
+ 	    m_xp.pop_tag ("span");
+ 	    m_xp.add_text (close_quote);
+ 	  }
+ 	  break;
+ 
+ 	case pp_token::kind::begin_url:
+ 	  {
+ 	    pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter);
+ 	    m_xp.push_tag ("a", true);
+ 	    m_xp.set_attr ("href", sub->m_value.get ());
+ 	  }
+ 	  break;
+ 	case pp_token::kind::end_url:
+ 	  m_xp.pop_tag ("a");
+ 	  break;
+ 
+ 	case pp_token::kind::event_id:
+ 	  {
+ 	    pp_token_event_id *sub = as_a <pp_token_event_id *> (iter);
+ 	    gcc_assert (sub->m_event_id.known_p ());
+ 	    m_xp.add_text ("(");
+ 	    m_xp.add_text (std::to_string (sub->m_event_id.one_based ()));
+ 	    m_xp.add_text (")");
+ 	  }
+ 	  break;
+ 	}
+   }
+ 
+ private:
+   xml::printer m_xp;
+ };
+ 
+ /* Make a <div class="gcc-diagnostic"> for DIAGNOSTIC.
+ 
+    If ALERT is true, make it be a PatternFly alert (see
+    https://pf3.patternfly.org/v3/pattern-library/widgets/#alerts) and
+    show severity text (e.g. "error: ").
+ 
+    If ALERT is false, don't show the severity text and don't show
+    the filename if it's the same as the previous diagnostic within the
+    diagnostic group.  */
+ 
+ std::unique_ptr<xml::element>
+ html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic,
+ 					   enum kind orig_diag_kind,
+ 					   bool alert)
+ {
+   const int diag_idx = m_next_diag_id++;
+   std::string diag_id;
+   {
+     pretty_printer pp;
+     pp_printf (&pp, "gcc-diag-%i", diag_idx);
+     diag_id = pp_formatted_text (&pp);
+   }
+ 
+   // TODO: might be nice to emulate the text output format, but colorize it
+ 
+   /* See https://pf3.patternfly.org/v3/pattern-library/widgets/#alerts
+      which has this example:
+ <div class="alert alert-danger">
+   <span class="pficon pficon-error-circle-o"></span>
+   <strong>Hey there is a problem!</strong> Yeah this is really messed up and you should <a href="#" class="alert-link">know about it</a>.
+ </div>
+   */
+   auto diag_element = make_div ("gcc-diagnostic");
+   diag_element->set_attr ("id", diag_id);
+   if (alert)
+     diag_element->set_attr ("class",
+ 			    get_pf_class_for_alert_div (diagnostic.m_kind));
+ 
+   xml::printer xp (*diag_element.get ());
+   const size_t depth_within_alert_div = 1;
+ 
+   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+ 
+   if (alert)
+     {
+       xp.push_tag_with_class ("span",
+ 			      get_pf_class_for_alert_icon (diagnostic.m_kind),
+ 			      true);
+       xp.add_text (" ");
+       xp.pop_tag ("span");
+     }
+ 
+   // The rest goes in the <div>...
+   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+ 
+   xp.push_tag_with_class ("div", "gcc-message", true);
+   std::string message_alert_id (diag_id + "-message");
+   xp.set_attr ("id", message_alert_id);
+   add_focus_id (message_alert_id);
+ 
+   const size_t depth_within_message_div = depth_within_alert_div + 1;
+   gcc_assert (xp.get_num_open_tags () == depth_within_message_div);
+ 
+   // Severity e.g. "warning: "
+   bool show_severity = true;
+   if (!alert)
+     show_severity = false;
+   if (show_severity)
+   {
+     xp.push_tag ("strong");
+     xp.add_text (_(get_text_for_kind (diagnostic.m_kind)));
+     xp.pop_tag ("strong");
+     xp.add_text (" ");
+   }
+ 
+   // Add the message itself:
+   html_token_printer tok_printer (*xp.get_insertion_point ());
+   m_printer->set_token_printer (&tok_printer);
+   pp_output_formatted_text (m_printer, m_context.get_urlifier ());
+   m_printer->set_token_printer (nullptr);
+   pp_clear_output_area (m_printer);
+ 
+   // Add any metadata as a suffix to the message
+   if (diagnostic.m_metadata)
+     {
+       xp.add_text (" ");
+       xp.append (make_element_for_metadata (*diagnostic.m_metadata));
+     }
+ 
+   // Add any option as a suffix to the message
+ 
+   label_text option_text = label_text::take
+     (m_context.make_option_name (diagnostic.m_option_id,
+ 				 orig_diag_kind, diagnostic.m_kind));
+   if (option_text.get ())
+     {
+       label_text option_url = label_text::take
+ 	(m_context.make_option_url (diagnostic.m_option_id));
+ 
+       xp.add_text (" ");
+       auto option_span = make_span ("gcc-option");
+       option_span->add_text ("[");
+       {
+ 	if (option_url.get ())
+ 	  {
+ 	    auto anchor = std::make_unique<xml::element> ("a", true);
+ 	    anchor->set_attr ("href", option_url.get ());
+ 	    anchor->add_text (option_text.get ());
+ 	    option_span->add_child (std::move (anchor));
+ 	  }
+ 	else
+ 	  option_span->add_text (option_text.get ());
+ 	option_span->add_text ("]");
+       }
+       xp.append (std::move (option_span));
+     }
+ 
+   gcc_assert (xp.get_num_open_tags () == depth_within_message_div);
+ 
+   xp.pop_tag ("div");
+ 
+   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+ 
+   /* Show any logical location.  */
+   if (m_logical_loc_mgr)
+     if (auto client_data_hooks = m_context.get_client_data_hooks ())
+       if (auto logical_loc = client_data_hooks->get_current_logical_location ())
+ 	if (logical_loc != m_last_logical_location)
+ 	  {
+ 	    enum logical_locations::kind kind
+ 	      = m_logical_loc_mgr->get_kind (logical_loc);;
+ 	    if (const char *label = get_label_for_logical_location_kind (kind))
+ 	      if (const char *name_with_scope
+ 		  = m_logical_loc_mgr->get_name_with_scope (logical_loc))
+ 		add_labelled_value (xp, "logical-location",
+ 				    label, name_with_scope, true);
+ 	    m_last_logical_location = logical_loc;
+ 	  }
+ 
+   /* Show any physical location.  */
+   const expanded_location s
+     = diagnostic_expand_location (&diagnostic);
+   if (s != m_last_expanded_location
+       || alert)
+     {
+       if (s.file
+ 	  && (s.file != m_last_expanded_location.file
+ 	      || alert))
+ 	add_labelled_value (xp, "file", "File", s.file, false);
+       if (s.line)
+ 	{
+ 	  add_labelled_value (xp, "line", "Line", std::to_string (s.line), false);
+ 	  column_policy col_policy (m_context);
+ 	  int converted_column = col_policy.converted_column (s);
+ 	  if (converted_column >= 0)
+ 	    add_labelled_value (xp, "column", "Column",
+ 				std::to_string (converted_column),
+ 				false);
+ 	}
+       if (s.file)
+ 	m_last_expanded_location = s;
+     }
+ 
+   /* Source (and fix-it hints).  */
+   {
+     // TODO: m_context.m_last_location should be moved into the sink
+     location_t saved = m_context.m_last_location;
+     m_context.m_last_location = m_last_location;
+     m_context.maybe_show_locus_as_html
+       (*diagnostic.m_richloc,
+        m_context.get_source_printing_options (),
+        diagnostic.m_kind,
+        xp,
+        nullptr,
+        nullptr);
+     m_context.m_last_location = saved;
+     m_last_location = m_context.m_last_location;
+   }
+ 
+   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+ 
+   /* Execution path.  */
+   if (auto path = diagnostic.m_richloc->get_path ())
+     {
+       xp.push_tag ("div");
+       xp.set_attr ("id", "execution-path");
+ 
+       xp.push_tag ("label", true);
+       const int num_events = path->num_events ();
+       pretty_printer pp;
+       pp_printf_n (&pp, num_events,
+ 		   "Execution path with %i event",
+ 		   "Execution path with %i events",
+ 		   num_events);
+       xp.add_text_from_pp (pp);
+       xp.pop_tag ("label");
+ 
+       std::string event_id_prefix (diag_id + "-event-");
+       html_path_label_writer event_label_writer (xp, *this, *path,
+ 						 event_id_prefix);
+ 
+       source_print_policy dspp (m_context);
+       print_path_as_html (xp, *path, m_context, &event_label_writer,
+ 			  dspp);
+ 
+       xp.pop_tag ("div");
+     }
+ 
+   gcc_assert (xp.get_num_open_tags () == depth_within_alert_div);
+ 
+   // Try to display any per-diagnostic graphs
+   if (diagnostic.m_metadata)
+     if (auto ldg = diagnostic.m_metadata->get_lazy_digraphs ())
+       {
+ 	auto &digraphs = ldg->get_or_create ();
+ 	for (auto &dg : digraphs)
+ 	  add_graph (*dg, *xp.get_insertion_point ());
+       }
+ 
+   if (auto patch_element = make_element_for_patch (diagnostic))
+     {
+       xp.push_tag ("div");
+       xp.set_attr ("id", "suggested-fix");
+       xp.push_tag ("label", true);
+       xp.add_text ("Suggested fix");
+       xp.pop_tag ("label");
+       xp.append (std::move (patch_element));
+       xp.pop_tag ("div");
+     }
+ 
+   return diag_element;
+ }
+ 
+ std::unique_ptr<xml::element>
+ html_builder::make_element_for_patch (const diagnostic_info &diagnostic)
+ {
+   changes::change_set edit (m_context.get_file_cache ());
+   edit.add_fixits (diagnostic.m_richloc);
+   if (char *diff = edit.generate_diff (true))
+     {
+       if (strlen (diff) > 0)
+ 	{
+ 	  auto element = std::make_unique<xml::element> ("pre", true);
+ 	  element->set_attr ("class", "gcc-generated-patch");
+ 	  element->add_text (diff);
+ 	  free (diff);
+ 	  return element;
+ 	}
+       else
+ 	free (diff);
+     }
+   return nullptr;
+ }
+ 
+ std::unique_ptr<xml::element>
+ html_builder::make_metadata_element (label_text label,
+ 				     label_text url)
+ {
+   auto item = make_span ("gcc-metadata-item");
+   xml::printer xp (*item.get ());
+   xp.add_text ("[");
+   {
+     if (url.get ())
+       {
+ 	xp.push_tag ("a", true);
+ 	xp.set_attr ("href", url.get ());
+       }
+     xp.add_text (label.get ());
+     if (url.get ())
+       xp.pop_tag ("a");
+   }
+   xp.add_text ("]");
+   return item;
+ }
+ 
+ std::unique_ptr<xml::element>
+ html_builder::make_element_for_metadata (const metadata &m)
+ {
+   auto span_metadata = make_span ("gcc-metadata");
+ 
+   int cwe = m.get_cwe ();
+   if (cwe)
+     {
+       pretty_printer pp;
+       pp_printf (&pp, "CWE-%i", cwe);
+       label_text label = label_text::take (xstrdup (pp_formatted_text (&pp)));
+       label_text url = label_text::take (get_cwe_url (cwe));
+       span_metadata->add_child
+ 	(make_metadata_element (std::move (label), std::move (url)));
+     }
+ 
+   for (unsigned idx = 0; idx < m.get_num_rules (); ++idx)
+     {
+       auto &rule = m.get_rule (idx);
+       label_text label = label_text::take (rule.make_description ());
+       label_text url = label_text::take (rule.make_url ());
+       span_metadata->add_child
+ 	(make_metadata_element (std::move (label), std::move (url)));
+     }
+ 
+   return span_metadata;
+ }
+ 
+ /* Implementation of diagnostics::context::m_diagrams.m_emission_cb
+    for HTML output.  */
+ 
+ void
+ html_builder::emit_diagram (const diagram &)
+ {
+   /* We must be within the emission of a top-level diagnostic.  */
+   gcc_assert (m_cur_diagnostic_element);
+ 
+   // TODO: currently a no-op
+ }
+ 
+ void
+ html_builder::add_graph (const digraphs::digraph &dg,
+ 			 xml::element &parent_element)
+ {
+   if (auto dot_graph = dg.make_dot_graph ())
+     if (auto svg_element = dot::make_svg_from_graph (*dot_graph))
+       {
+ 	auto div = std::make_unique<xml::element> ("div", false);
+ 	div->set_attr ("class", "gcc-directed-graph");
+ 	xml::printer xp (*div);
+ 	if (const char *description = dg.get_description ())
+ 	  {
+ 	    xp.push_tag ("h2", true);
+ 	    xp.add_text (description);
+ 	    xp.pop_tag ("h2");
+ 	  }
+ 	xp.append (std::move (svg_element));
+ 	parent_element.add_child (std::move (div));
+       }
+ }
+ 
+ void
+ html_builder::emit_global_graph (const lazily_created<digraphs::digraph> &ldg)
+ {
+   auto &dg = ldg.get_or_create ();
+   gcc_assert (m_body_element);
+   add_graph (dg, *m_body_element);
+ }
+ 
+ /* Implementation of "end_group_cb" for HTML output.  */
+ 
+ void
+ html_builder::end_group ()
+ {
+   if (m_cur_diagnostic_element)
+     m_diagnostics_element->add_child (std::move (m_cur_diagnostic_element));
+ }
+ 
+ /* Create a top-level object, and add it to all the results
+    (and other entities) we've seen so far.
+ 
+    Flush it all to OUTF.  */
+ 
+ void
+ html_builder::flush_to_file (FILE *outf)
+ {
+   if (m_html_gen_opts.m_javascript)
+     {
+       gcc_assert (m_head_element);
+       xml::printer xp (*m_head_element);
+       /* Add an initialization of the global js variable "focus_ids"
+ 	 using the array of IDs we saved as we went.  */
+       xp.push_tag ("script");
+       pretty_printer pp;
+       pp_string (&pp, "focus_ids = ");
+       m_ui_focus_ids.print (&pp, true);
+       pp_string (&pp, ";\n");
+       xp.add_raw (pp_formatted_text (&pp));
+       xp.pop_tag ("script");
+     }
+   auto top = m_document.get ();
+   top->dump (outf);
+   fprintf (outf, "\n");
+ }
+ 
+ class html_sink : public sink
+ {
+ public:
+   ~html_sink ()
+   {
+     /* Any diagnostics should have been handled by now.
+        If not, then something's gone wrong with diagnostic
+        groupings.  */
+     std::unique_ptr<xml::element> pending_diag
+       = m_builder.take_current_diagnostic ();
+     gcc_assert (!pending_diag);
+   }
+ 
+   void dump (FILE *out, int indent) const override
+   {
+     fprintf (out, "%*shtml_sink\n", indent, "");
+     sink::dump (out, indent);
+   }
+ 
+   void
+   set_main_input_filename (const char *name) final override
+   {
+     m_builder.set_main_input_filename (name);
+   }
+ 
+   std::unique_ptr<per_sink_buffer>
+   make_per_sink_buffer () final override
+   {
+     return std::make_unique<html_sink_buffer> (m_builder);
+   }
+   void set_buffer (per_sink_buffer *base_buffer) final override
+   {
+     html_sink_buffer *buffer
+       = static_cast<html_sink_buffer *> (base_buffer);
+     m_buffer = buffer;
+   }
+ 
+   void on_begin_group () final override
+   {
+     /* No-op,  */
+   }
+   void on_end_group () final override
+   {
+     m_builder.end_group ();
+   }
+   void
+   on_report_diagnostic (const diagnostic_info &diagnostic,
+ 			enum kind orig_diag_kind) final override
+   {
+     m_builder.on_report_diagnostic (diagnostic, orig_diag_kind, m_buffer);
+   }
+   void on_diagram (const diagram &d) final override
+   {
+     m_builder.emit_diagram (d);
+   }
+   void after_diagnostic (const diagnostic_info &) final override
+   {
+     /* No-op, but perhaps could show paths here.  */
+   }
+   bool follows_reference_printer_p () const final override
+   {
+     return false;
+   }
+   void update_printer () final override
+   {
+     m_printer = m_context.clone_printer ();
+ 
+     /* Don't colorize the text.  */
+     pp_show_color (m_printer.get ()) = false;
+ 
+     /* No textual URLs.  */
+     m_printer->set_url_format (URL_FORMAT_NONE);
+ 
+     /* Update the builder to use the new printer.  */
+     m_builder.set_printer (*get_printer ());
+   }
+ 
+   void
+   report_global_digraph (const lazily_created<digraphs::digraph> &ldg)
+     final override
+   {
+     m_builder.emit_global_graph (ldg);
+   }
+ 
+   const xml::document &get_document () const
+   {
+     return m_builder.get_document ();
+   }
+ 
+   html_builder &get_builder () { return m_builder; }
+ 
+ protected:
+   html_sink (context &dc,
+ 	     const line_maps *line_maps,
+ 	     const html_generation_options &html_gen_opts)
+   : sink (dc),
+     m_builder (dc, *get_printer (), line_maps, html_gen_opts),
+     m_buffer (nullptr)
+   {}
+ 
+   html_builder m_builder;
+   html_sink_buffer *m_buffer;
+ };
+ 
+ class html_file_sink : public html_sink
+ {
+ public:
+   html_file_sink (context &dc,
+ 		  const line_maps *line_maps,
+ 		  const html_generation_options &html_gen_opts,
+ 		  output_file output_file_)
+   : html_sink (dc, line_maps, html_gen_opts),
+     m_output_file (std::move (output_file_))
+   {
+     gcc_assert (m_output_file.get_open_file ());
+     gcc_assert (m_output_file.get_filename ());
+   }
+   ~html_file_sink ()
+   {
+     m_builder.flush_to_file (m_output_file.get_open_file ());
+   }
+   void dump (FILE *out, int indent) const override
+   {
+     fprintf (out, "%*shtml_file_sink: %s\n",
+ 	     indent, "",
+ 	     m_output_file.get_filename ());
+     sink::dump (out, indent);
+   }
+   bool machine_readable_stderr_p () const final override
+   {
+     return false;
+   }
+ 
+ private:
+   output_file m_output_file;
+ };
+ 
+ /* Attempt to open BASE_FILE_NAME.html for writing.
+    Return a non-null output_file,
+    or return a null output_file and complain to DC
+    using LINE_MAPS.  */
+ 
+ output_file
+ open_html_output_file (context &dc,
+ 		       line_maps *line_maps,
+ 		       const char *base_file_name)
+ {
+   if (!base_file_name)
+     {
+       rich_location richloc (line_maps, UNKNOWN_LOCATION);
+       dc.emit_diagnostic_with_group
+ 	(kind::error, richloc, nullptr, 0,
+ 	 "unable to determine filename for HTML output");
+       return output_file ();
+     }
+ 
+   label_text filename = label_text::take (concat (base_file_name,
+ 						  ".html",
+ 						  nullptr));
+   FILE *outf = fopen (filename.get (), "w");
+   if (!outf)
+     {
+       rich_location richloc (line_maps, UNKNOWN_LOCATION);
+       dc.emit_diagnostic_with_group
+ 	(kind::error, richloc, nullptr, 0,
+ 	 "unable to open %qs for HTML output: %m",
+ 	 filename.get ());
+       return output_file ();
+     }
+   return output_file (outf, true, std::move (filename));
+ }
+ 
+ std::unique_ptr<sink>
+ make_html_sink (context &dc,
+ 		const line_maps &line_maps,
+ 		const html_generation_options &html_gen_opts,
+ 		output_file output_file_)
+ {
+   auto sink
+     = std::make_unique<html_file_sink> (dc,
+ 					&line_maps,
+ 					html_gen_opts,
+ 					std::move (output_file_));
+   sink->update_printer ();
+   return sink;
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace selftest {
+ 
+ /* Helper for writing tests of html_token_printer.
+    Printing to m_pp will appear as HTML within m_top_element, a <div>.  */
+ 
+ struct token_printer_test
+ {
+   token_printer_test ()
+   : m_top_element ("div", true),
+     m_tok_printer (m_top_element)
+   {
+     m_pp.set_token_printer (&m_tok_printer);
+   }
+ 
+   xml::element m_top_element;
+   html_token_printer m_tok_printer;
+   pretty_printer m_pp;
+ };
+ 
+ static void
+ test_token_printer ()
+ {
+   {
+     token_printer_test t;
+     pp_printf (&t.m_pp, "hello world");
+     ASSERT_XML_PRINT_EQ
+       (t.m_top_element,
+        "<div>hello world</div>\n");
+   }
+ 
+   {
+     token_printer_test t;
+     pp_printf (&t.m_pp, "%qs: %qs", "foo", "bar");
+     ASSERT_XML_PRINT_EQ
+       (t.m_top_element,
+        "<div>"
+        "`"
+        "<span class=\"gcc-quoted-text\">"
+        "foo"
+        "</span>"
+        "&apos;: `"
+        "<span class=\"gcc-quoted-text\">"
+        "bar"
+        "</span>"
+        "&apos;"
+        "</div>\n");
+   }
+ 
+   {
+     token_printer_test t;
+     paths::event_id_t event_id (0);
+     pp_printf (&t.m_pp, "foo %@ bar", &event_id);
+     ASSERT_XML_PRINT_EQ
+       (t.m_top_element,
+        "<div>foo (1) bar</div>\n");
+   }
+ }
+ 
+ /* A subclass of html_sink for writing selftests.
+    The XML output is cached internally, rather than written
+    out to a file.  */
+ 
+ class test_html_context : public test_context
+ {
+ public:
+   test_html_context ()
+   {
+     html_generation_options html_gen_opts;
+     html_gen_opts.m_css = false;
+     html_gen_opts.m_javascript = false;
+     auto sink = std::make_unique<html_buffered_sink> (*this,
+ 						      line_table,
+ 						      html_gen_opts);
+     sink->update_printer ();
+     sink->set_main_input_filename ("(main input filename)");
+     m_format = sink.get (); // borrowed
+ 
+     set_sink (std::move (sink));
+   }
+ 
+   const xml::document &get_document () const
+   {
+     return m_format->get_document ();
+   }
+ 
+   html_builder &get_builder () const
+   {
+     return m_format->get_builder ();
+   }
+ 
+ private:
+   class html_buffered_sink : public html_sink
+   {
+   public:
+     html_buffered_sink (context &dc,
+ 			const line_maps *line_maps,
+ 			const html_generation_options &html_gen_opts)
+     : html_sink (dc, line_maps, html_gen_opts)
+     {
+     }
+     bool machine_readable_stderr_p () const final override
+     {
+       return true;
+     }
+   };
+ 
+   html_sink *m_format; // borrowed
+ };
+ 
+ /* Test of reporting a diagnostic at UNKNOWN_LOCATION to a
+    diagnostics::context and examining the generated XML document.
+    Verify various basic properties. */
+ 
+ static void
+ test_simple_log ()
+ {
+   test_html_context dc;
+ 
+   rich_location richloc (line_table, UNKNOWN_LOCATION);
+   dc.report (kind::error, richloc, nullptr, 0, "this is a test: %qs", "foo");
+ 
+   const xml::document &doc  = dc.get_document ();
+ 
+   ASSERT_XML_PRINT_EQ
+     (doc,
+      ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+       "<!DOCTYPE html\n"
+       "     PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
+       "     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
+       "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
+       "  <head>\n"
+       "    <title>(main input filename)</title>\n"
+       "  </head>\n"
+       "  <body>\n"
+       "    <div class=\"gcc-diagnostic-list\">\n"
+       "      <div class=\"alert alert-danger\" id=\"gcc-diag-0\">\n"
+       "        <span class=\"pficon pficon-error-circle-o\"> </span>\n"
+       "        <div class=\"gcc-message\" id=\"gcc-diag-0-message\"><strong>error: </strong> this is a test: `<span class=\"gcc-quoted-text\">foo</span>&apos;</div>\n"
+       "      </div>\n"
+       "    </div>\n"
+       "  </body>\n"
+       "</html>\n"));
+ }
+ 
+ static void
+ test_metadata ()
+ {
+   test_html_context dc;
+   html_builder &b = dc.get_builder ();
+ 
+   {
+     metadata m;
+     m.add_cwe (415);
+     auto element = b.make_element_for_metadata (m);
+     ASSERT_XML_PRINT_EQ
+       (*element,
+        "<span class=\"gcc-metadata\">"
+        "<span class=\"gcc-metadata-item\">"
+        "["
+        "<a href=\"https://cwe.mitre.org/data/definitions/415.html\">"
+        "CWE-415"
+        "</a>"
+        "]"
+        "</span>"
+        "</span>\n");
+   }
+ 
+   {
+     metadata m;
+     metadata::precanned_rule rule ("MISC-42",
+ 				   "http://example.com");
+     m.add_rule (rule);
+     auto element = b.make_element_for_metadata (m);
+     ASSERT_XML_PRINT_EQ
+       (*element,
+        "<span class=\"gcc-metadata\">"
+        "<span class=\"gcc-metadata-item\">"
+        "["
+        "<a href=\"http://example.com\">"
+        "MISC-42"
+        "</a>"
+        "]"
+        "</span>"
+        "</span>\n");
+   }
+ }
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ html_sink_cc_tests ()
+ {
+   ::selftest::auto_fix_quotes fix_quotes;
+   test_token_printer ();
+   test_simple_log ();
+   test_metadata ();
+ }
+ 
+ } // namespace selftest
+ } // namespace diagnostics
+ 
+ #endif /* CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/html-sink.h gcc-16-20250727/gcc/diagnostics/html-sink.h
*** gcc-16-20250720/gcc/diagnostics/html-sink.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/html-sink.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,68 ----
+ /* HTML output for diagnostics.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_HTML_SINK_H
+ #define GCC_DIAGNOSTICS_HTML_SINK_H
+ 
+ #include "diagnostics/sink.h"
+ #include "diagnostics/output-file.h"
+ 
+ namespace diagnostics {
+ 
+ struct html_generation_options
+ {
+   html_generation_options ();
+ 
+   bool m_css;
+   bool m_javascript;
+ 
+   // Debugging options:
+ 
+   // If true, attempt to show state diagrams at events
+   bool m_show_state_diagrams;
+ 
+   // If true, show the SARIF form of the state with such diagrams
+   bool m_show_state_diagrams_sarif;
+ 
+   // If true, show the .dot source used for the diagram
+   bool m_show_state_diagrams_dot_src;
+ };
+ 
+ extern diagnostics::output_file
+ open_html_output_file (context &dc,
+ 		       line_maps *line_maps,
+ 		       const char *base_file_name);
+ 
+ extern std::unique_ptr<sink>
+ make_html_sink (context &dc,
+ 		const line_maps &line_maps,
+ 		const html_generation_options &html_gen_opts,
+ 		output_file output_file_);
+ 
+ extern void
+ print_path_as_html (xml::printer &xp,
+ 		    const paths::path &path,
+ 		    context &dc,
+ 		    html_label_writer *event_label_writer,
+ 		    const source_print_policy &dspp);
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_HTML_SINK_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/kinds.def gcc-16-20250727/gcc/diagnostics/kinds.def
*** gcc-16-20250720/gcc/diagnostics/kinds.def	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/kinds.def	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,55 ----
+ /* Copyright (C) 2001-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ /* kind::unspecified must be first so it has a value of zero.  We never
+    assign this kind to an actual diagnostic, we only use this in
+    variables that can hold a kind, to mean they have yet to have a
+    kind specified.  I.e. they're uninitialized.  Within the diagnostic
+    machinery, this kind also means "don't change the existing kind",
+    meaning "no change is specified".  */
+ DEFINE_DIAGNOSTIC_KIND (unspecified, "", NULL)
+ 
+ /* If a diagnostic is set to kind::ignored, it won't get reported at all.
+    This is used by the diagnostic machinery when it wants to disable a
+    diagnostic without disabling the option which causes it.  */
+ DEFINE_DIAGNOSTIC_KIND (ignored, "", NULL)
+ 
+ /* The remainder are real diagnostic types.  */
+ DEFINE_DIAGNOSTIC_KIND (fatal, "fatal error: ", "error")
+ DEFINE_DIAGNOSTIC_KIND (ice, "internal compiler error: ", "error")
+ DEFINE_DIAGNOSTIC_KIND (error, "error: ", "error")
+ DEFINE_DIAGNOSTIC_KIND (sorry, "sorry, unimplemented: ", "error")
+ DEFINE_DIAGNOSTIC_KIND (warning, "warning: ", "warning")
+ DEFINE_DIAGNOSTIC_KIND (anachronism, "anachronism: ", "warning")
+ DEFINE_DIAGNOSTIC_KIND (note, "note: ", "note")
+ DEFINE_DIAGNOSTIC_KIND (debug, "debug: ", "note")
+ 
+ /* For use when using the diagnostic_show_locus machinery to show
+    a range of events within a path.  */
+ DEFINE_DIAGNOSTIC_KIND (path, "path: ", "path")
+ 
+ /* These two would be re-classified as kind::warning or kind::error, so the
+ prefix does not matter.  */
+ DEFINE_DIAGNOSTIC_KIND (pedwarn, "pedwarn: ", NULL)
+ DEFINE_DIAGNOSTIC_KIND (permerror, "permerror: ", NULL)
+ /* This one is just for counting kind::warning promoted to kind::error
+    due to -Werror and -Werror=warning.  */
+ DEFINE_DIAGNOSTIC_KIND (werror, "error: ", NULL)
+ /* This is like kind::ICE, but backtrace is not printed.  Used in the driver
+    when reporting fatal signal in the compiler.  */
+ DEFINE_DIAGNOSTIC_KIND (ice_nobt, "internal compiler error: ", "error")
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/kinds.h gcc-16-20250727/gcc/diagnostics/kinds.h
*** gcc-16-20250720/gcc/diagnostics/kinds.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/kinds.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,45 ----
+ /* An enum used to discriminate severities of diagnostics.
+    Copyright (C) 1998-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_KINDS_H
+ #define GCC_DIAGNOSTICS_KINDS_H
+ 
+ namespace diagnostics {
+ 
+ /* Constants used to discriminate diagnostics.  */
+ enum class kind
+ {
+ #define DEFINE_DIAGNOSTIC_KIND(K, msgid, C) K,
+ #include "diagnostics/kinds.def"
+ #undef DEFINE_DIAGNOSTIC_KIND
+   last_diagnostic_kind,
+   /* This is used for tagging pragma pops in the diagnostic
+      classification history chain.  */
+   pop,
+   /* This is used internally to note that a diagnostic is enabled
+      without mandating any specific type.  */
+   any
+ };
+ 
+ extern const char *get_text_for_kind (enum diagnostics::kind);
+ extern const char *get_color_for_kind (enum diagnostics::kind);
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_KINDS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/lazy-paths.cc gcc-16-20250727/gcc/diagnostics/lazy-paths.cc
*** gcc-16-20250720/gcc/diagnostics/lazy-paths.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/lazy-paths.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,236 ----
+ /* Helper class for deferring path creation until a diagnostic is emitted.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ 
+ #include "config.h"
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "diagnostic.h"
+ #include "diagnostics/lazy-paths.h"
+ #include "selftest.h"
+ #include "diagnostics/selftest-context.h"
+ #include "diagnostics/selftest-paths.h"
+ #include "diagnostics/text-sink.h"
+ 
+ using namespace diagnostics::paths;
+ 
+ /* class lazy_path : public path.  */
+ 
+ /* Implementation of path vfuncs in terms of a lazily-generated
+    path.  */
+ 
+ unsigned
+ lazy_path::num_events () const
+ {
+   lazily_generate_path ();
+   return m_inner_path->num_events ();
+ }
+ 
+ const event &
+ lazy_path::get_event (int idx) const
+ {
+   lazily_generate_path ();
+   return m_inner_path->get_event (idx);
+ }
+ 
+ unsigned
+ lazy_path::num_threads () const
+ {
+   lazily_generate_path ();
+   return m_inner_path->num_threads ();
+ }
+ 
+ const thread &
+ lazy_path::get_thread (thread_id_t idx) const
+ {
+   lazily_generate_path ();
+   return m_inner_path->get_thread (idx);
+ }
+ 
+ bool
+ lazy_path::same_function_p (int event_idx_a,
+ 			    int event_idx_b) const
+ {
+   lazily_generate_path ();
+   return m_inner_path->same_function_p (event_idx_a, event_idx_b);
+ }
+ 
+ void
+ lazy_path::lazily_generate_path () const
+ {
+   if (!m_inner_path)
+     m_inner_path = make_inner_path ();
+   gcc_assert (m_inner_path != nullptr);
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace selftest {
+ 
+ using auto_fix_quotes = ::selftest::auto_fix_quotes;
+ 
+ class test_lazy_path : public lazy_path
+ {
+ public:
+   test_lazy_path (pretty_printer &pp)
+   : lazy_path (m_logical_loc_mgr),
+     m_pp (pp)
+   {
+   }
+   std::unique_ptr<path> make_inner_path () const final override
+   {
+     auto path
+       = std::make_unique<paths::selftest::test_path> (m_logical_loc_mgr,
+ 						      &m_pp);
+     path->add_event (UNKNOWN_LOCATION, "foo", 0, "first %qs", "free");
+     path->add_event (UNKNOWN_LOCATION, "foo", 0, "double %qs", "free");
+     return path;
+   }
+ private:
+   mutable logical_locations::selftest::test_manager m_logical_loc_mgr;
+   pretty_printer &m_pp;
+ };
+ 
+ static void
+ test_intraprocedural_path (pretty_printer *event_pp)
+ {
+   test_lazy_path path (*event_pp);
+   ASSERT_FALSE (path.generated_p ());
+   ASSERT_EQ (path.num_events (), 2);
+   ASSERT_TRUE (path.generated_p ());
+   ASSERT_EQ (path.num_threads (), 1);
+   ASSERT_FALSE (path.interprocedural_p ());
+   ASSERT_STREQ (path.get_event (0).get_desc (*event_pp).get (),
+ 		"first `free'");
+   ASSERT_STREQ (path.get_event (1).get_desc (*event_pp).get (),
+ 		"double `free'");
+ }
+ 
+ /* Implementation of diagnostics::option_manager for which all
+    options are disabled, for use in selftests.
+    Note that this is *not* called for option_id (0), which
+    means "always warn"  */
+ 
+ class all_warnings_disabled : public diagnostics::option_manager
+ {
+ public:
+   int option_enabled_p (diagnostics::option_id) const final override
+   {
+     /* Treat all options as disabled.  */
+     return 0;
+   }
+   char *make_option_name (diagnostics::option_id,
+ 			  enum kind,
+ 			  enum kind) const final override
+   {
+     return nullptr;
+   }
+   char *make_option_url (diagnostics::option_id) const final override
+   {
+     return nullptr;
+   }
+ };
+ 
+ static void
+ test_emission (pretty_printer *event_pp)
+ {
+   struct test_rich_location : public rich_location
+   {
+     test_rich_location (pretty_printer &event_pp)
+     : rich_location (line_table, UNKNOWN_LOCATION),
+       m_path (event_pp)
+     {
+       set_path (&m_path);
+     }
+     test_lazy_path m_path;
+   };
+ 
+   /* Verify that we don't bother generating the inner path if the warning
+      is skipped.  */
+   {
+     test_context dc;
+     dc.set_option_manager (std::make_unique<all_warnings_disabled> (), 0);
+ 
+     test_rich_location rich_loc (*event_pp);
+     ASSERT_FALSE (rich_loc.m_path.generated_p ());
+ 
+     diagnostics::option_id opt_id (42); // has to be non-zero
+     bool emitted
+       = dc.emit_diagnostic_with_group (kind::warning, rich_loc, nullptr,
+ 				       opt_id,
+ 				       "this warning should be skipped");
+     ASSERT_FALSE (emitted);
+     ASSERT_FALSE (rich_loc.m_path.generated_p ());
+   }
+ 
+   /* Verify that we *do* generate the inner path for a diagnostic that
+      is emitted, such as an error.  */
+   {
+     test_context dc;
+ 
+     test_rich_location rich_loc (*event_pp);
+     ASSERT_FALSE (rich_loc.m_path.generated_p ());
+ 
+     bool emitted
+       = dc.emit_diagnostic_with_group (kind::error, rich_loc, nullptr, 0,
+ 				       "this is a test");
+     ASSERT_TRUE (emitted);
+     ASSERT_TRUE (rich_loc.m_path.generated_p ());
+ 
+     /* Verify that the path works as expected.  */
+     dc.set_path_format (DPF_INLINE_EVENTS);
+     diagnostics::text_sink sink_ (dc);
+     pp_buffer (sink_.get_printer ())->m_flush_p = false;
+     sink_.print_path (rich_loc.m_path);
+     ASSERT_STREQ (pp_formatted_text (sink_.get_printer ()),
+ 		  "  `foo': event 1\n"
+ 		  " (1): first `free'\n"
+ 		  "  `foo': event 2\n"
+ 		  " (2): double `free'\n");
+   }
+ }
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ lazy_paths_cc_tests ()
+ {
+   /* In a few places we use the global dc's printer to determine
+      colorization so ensure this off during the tests.  */
+   pretty_printer *global_pp = global_dc->get_reference_printer ();
+   const bool saved_show_color = pp_show_color (global_pp);
+   pp_show_color (global_pp) = false;
+ 
+   auto_fix_quotes fix_quotes;
+   std::unique_ptr<pretty_printer> event_pp
+     = std::unique_ptr<pretty_printer> (global_pp->clone ());
+ 
+   test_intraprocedural_path (event_pp.get ());
+   test_emission (event_pp.get ());
+ 
+   pp_show_color (global_pp) = saved_show_color;
+ }
+ 
+ } // namespace diagnostics::selftest
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/lazy-paths.h gcc-16-20250727/gcc/diagnostics/lazy-paths.h
*** gcc-16-20250720/gcc/diagnostics/lazy-paths.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/lazy-paths.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,70 ----
+ /* Helper class for deferring path creation until a diagnostic is emitted.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_LAZY_PATHS_H
+ #define GCC_DIAGNOSTICS_LAZY_PATHS_H
+ 
+ #include "diagnostics/paths.h"
+ 
+ namespace diagnostics {
+ namespace paths {
+ 
+ /* An implementation of diagnostics::paths::path which has a trivial ctor
+    and lazily creates another path the first time the path
+    is queried, deferring to this inner path for all queries.
+ 
+    Use this to avoid expensive path creation logic when creating
+    rich_location instances, so that expense can be deferred until the path
+    is actually used by a diagnostic, and thus avoided for warnings that
+    are disabled.  */
+ 
+ class lazy_path : public path
+ {
+  public:
+   virtual ~lazy_path () {}
+ 
+   unsigned num_events () const final override;
+   const event & get_event (int idx) const final override;
+   unsigned num_threads () const final override;
+   const thread &
+   get_thread (thread_id_t) const final override;
+   bool
+   same_function_p (int event_idx_a,
+ 		   int event_idx_b) const final override;
+ 
+   bool generated_p () const { return m_inner_path != nullptr; }
+ 
+ protected:
+   lazy_path (const logical_locations::manager &logical_loc_mgr)
+   : path (logical_loc_mgr)
+   {
+   }
+ 
+  private:
+   void lazily_generate_path () const;
+   virtual std::unique_ptr<path> make_inner_path () const = 0;
+ 
+   mutable std::unique_ptr<path> m_inner_path;
+ };
+ 
+ } // namespace paths
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_LAZY_PATHS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/logical-locations.h gcc-16-20250727/gcc/diagnostics/logical-locations.h
*** gcc-16-20250720/gcc/diagnostics/logical-locations.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/logical-locations.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,180 ----
+ /* Logical location support, without knowledge of "tree".
+    Copyright (C) 2022-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_LOGICAL_LOCATIONS_H
+ #define GCC_DIAGNOSTICS_LOGICAL_LOCATIONS_H
+ 
+ #include "label-text.h"
+ 
+ namespace diagnostics {
+ namespace logical_locations {
+ 
+ /* An enum for discriminating between different kinds of logical location
+    for a diagnostic.
+ 
+    Roughly corresponds to logicalLocation's "kind" property in SARIF v2.1.0
+    (section 3.33.7).  */
+ 
+ enum class kind
+ {
+   unknown,
+ 
+   /* Kinds within executable code.  */
+   function,
+   member,
+   module_,
+   namespace_,
+   type,
+   return_type,
+   parameter,
+   variable,
+ 
+   /* Kinds within XML or HTML documents.  */
+   element,
+   attribute,
+   text,
+   comment,
+   processing_instruction,
+   dtd,
+   declaration,
+ 
+   /* Kinds within JSON documents.  */
+   object,
+   array,
+   property,
+   value
+ };
+ 
+ /* We want to efficiently support passing around logical locations in the
+    diagnostics subsystem, such as:
+    - "within function 'foo'", or
+    - "within method 'bar'"
+ 
+    However we want to do this *without* requiring knowledge of trees (or of
+    libgdiagnostics internals), and without requiring heap allocation of an
+    interface class when emitting a diagnostic.
+ 
+    To do this, we split the implementation into logical_locations::key, which is
+    a wrapper around a (const void *), and logical_locations::manager which
+    is provided by the client and has vfunc hooks for interpreting
+    key instances.
+ 
+    Every logical_locations::key is associated with a logical_locations::manager
+    and only has meaning in relation to that manager.
+ 
+    A "nullptr" within a key means "no logical location".
+ 
+    See tree-logical-location.h for concrete subclasses relating to trees,
+    where the pointer is a const_tree.
+ 
+    See diagnostics/selftest-logical-locations.h for a concrete subclass for
+    selftests.  */
+ 
+ /* Extrinsic state for identifying a specific logical location.
+    This will be our logical location type.
+    This only makes sense with respect to a specific manager.
+    e.g. for a tree-based one it's a wrapper around "tree".
+ 
+    "nullptr" means "no logical location".
+ 
+    Note that there is no integration with GCC's garbage collector and thus
+    keys can't be long-lived.  */
+ 
+ class key
+ {
+ public:
+   key () : m_ptr (nullptr) {}
+ 
+   static key from_ptr (const void *ptr)
+   {
+     return key (ptr);
+   }
+ 
+   operator bool () const
+   {
+     return m_ptr != nullptr;
+   }
+ 
+   template <typename T>
+   T cast_to () const { return static_cast<T> (m_ptr); }
+ 
+   bool
+   operator== (const key &other) const
+   {
+     return m_ptr == other.m_ptr;
+   }
+ 
+   bool
+   operator!= (const key &other) const
+   {
+     return m_ptr != other.m_ptr;
+   }
+ 
+   bool
+   operator< (const key &other) const
+   {
+     return m_ptr < other.m_ptr;
+   }
+ 
+ private:
+   explicit key (const void *ptr) : m_ptr (ptr) {}
+ 
+   const void *m_ptr;
+ };
+ 
+ /* Abstract base class for giving meaning to keys.
+    Typically there will just be one client-provided instance, of a
+    client-specific subclass.  */
+ 
+ class manager
+ {
+ public:
+   virtual ~manager () {}
+ 
+   /* vfuncs for interpreting keys.  */
+ 
+   /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
+      "name" property (SARIF v2.1.0 section 3.33.4).  */
+   virtual const char *get_short_name (key k) const = 0;
+ 
+   /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
+      "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
+   virtual const char *get_name_with_scope (key k) const = 0;
+ 
+   /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
+      "decoratedName" property (SARIF v2.1.0 section 3.33.6).  */
+   virtual const char *get_internal_name (key k) const = 0;
+ 
+   /* Get what kind of SARIF logicalLocation K is (if any).  */
+   virtual enum kind get_kind (key k) const = 0;
+ 
+   /* Get a string for location K in a form suitable for path output.  */
+   virtual label_text get_name_for_path_output (key k) const = 0;
+ 
+   /* Get the parent logical_logical of K, if any, or nullptr.  */
+   virtual key get_parent (key k) const = 0;
+ 
+   bool function_p (key k) const;
+ };
+ 
+ } // namespace diagnostics::logical_locations
+ } // namespace diagnostics
+ 
+ #endif /* GCC_DIAGNOSTICS_LOGICAL_LOCATIONS_H.  */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/macro-unwinding.cc gcc-16-20250727/gcc/diagnostics/macro-unwinding.cc
*** gcc-16-20250720/gcc/diagnostics/macro-unwinding.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/macro-unwinding.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,227 ----
+ /* Code for unwinding macro expansions in diagnostics.
+    Copyright (C) 1999-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tree.h"
+ #include "diagnostic.h"
+ #include "diagnostics/macro-unwinding.h"
+ #include "diagnostics/text-sink.h"
+ #include "intl.h"
+ 
+ namespace diagnostics {
+ 
+ /* This is a pair made of a location and the line map it originated
+    from.  It's used in the maybe_unwind_expanded_macro_loc function
+    below.  */
+ struct loc_map_pair
+ {
+   const line_map_macro *map;
+   location_t where;
+ };
+ 
+ 
+ /* Unwind the different macro expansions that lead to the token which
+    location is WHERE and emit diagnostics showing the resulting
+    unwound macro expansion trace.  Let's look at an example to see how
+    the trace looks like.  Suppose we have this piece of code,
+    artificially annotated with the line numbers to increase
+    legibility:
+ 
+     $ cat -n test.c
+       1    #define OPERATE(OPRD1, OPRT, OPRD2) \
+       2      OPRD1 OPRT OPRD2;
+       3
+       4    #define SHIFTL(A,B) \
+       5      OPERATE (A,<<,B)
+       6
+       7    #define MULT(A) \
+       8      SHIFTL (A,1)
+       9
+      10    void
+      11    g ()
+      12    {
+      13      MULT (1.0);// 1.0 << 1; <-- so this is an error.
+      14    }
+ 
+    Here is the diagnostic that we want the compiler to generate:
+ 
+     test.c: In function ‘g’:
+     test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’)
+     test.c:2:9: note: in definition of macro 'OPERATE'
+     test.c:8:3: note: in expansion of macro 'SHIFTL'
+     test.c:13:3: note: in expansion of macro 'MULT'
+ 
+    The part that goes from the third to the fifth line of this
+    diagnostic (the lines containing the 'note:' string) is called the
+    unwound macro expansion trace.  That's the part generated by this
+    function.  */
+ 
+ void
+ maybe_unwind_expanded_macro_loc (text_sink &text_output,
+                                  location_t where)
+ {
+   const struct line_map *map;
+   auto_vec<loc_map_pair> loc_vec;
+   unsigned ix;
+   loc_map_pair loc, *iter;
+ 
+   const location_t original_loc = where;
+ 
+   map = linemap_lookup (line_table, where);
+   if (!linemap_macro_expansion_map_p (map))
+     return;
+ 
+   /* Let's unwind the macros that got expanded and led to the token
+      which location is WHERE.  We are going to store these macros into
+      LOC_VEC, so that we can later walk it at our convenience to
+      display a somewhat meaningful trace of the macro expansion
+      history to the user.  Note that the first macro of the trace
+      (which is OPERATE in the example above) is going to be stored at
+      the beginning of LOC_VEC.  */
+ 
+   do
+     {
+       loc.where = where;
+       loc.map = linemap_check_macro (map);
+ 
+       loc_vec.safe_push (loc);
+ 
+       /* WHERE is the location of a token inside the expansion of a
+          macro.  MAP is the map holding the locations of that macro
+          expansion.  Let's get the location of the token inside the
+          context that triggered the expansion of this macro.
+          This is basically how we go "down" in the trace of macro
+          expansions that led to WHERE.  */
+       where = linemap_unwind_toward_expansion (line_table, where, &map);
+     } while (linemap_macro_expansion_map_p (map));
+ 
+   /* Now map is set to the map of the location in the source that
+      first triggered the macro expansion.  This must be an ordinary map.  */
+   const line_map_ordinary *ord_map = linemap_check_ordinary (map);
+ 
+   /* Walk LOC_VEC and print the macro expansion trace, unless the
+      first macro which expansion triggered this trace was expanded
+      inside a system header.  */
+   int saved_location_line =
+     expand_location_to_spelling_point (original_loc).line;
+ 
+   if (!LINEMAP_SYSP (ord_map))
+     FOR_EACH_VEC_ELT (loc_vec, ix, iter)
+       {
+ 	/* Sometimes, in the unwound macro expansion trace, we want to
+ 	   print a part of the context that shows where, in the
+ 	   definition of the relevant macro, is the token (we are
+ 	   looking at) used.  That is the case in the introductory
+ 	   comment of this function, where we print:
+ 
+ 	       test.c:2:9: note: in definition of macro 'OPERATE'.
+ 
+ 	   We print that "macro definition context" because the
+ 	   diagnostic line (emitted by the call to
+ 	   pp_ouput_formatted_text in diagnostic_report_diagnostic):
+ 
+ 	       test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’)
+ 
+ 	   does not point into the definition of the macro where the
+ 	   token '<<' (that is an argument to the function-like macro
+ 	   OPERATE) is used.  So we must "display" the line of that
+ 	   macro definition context to the user somehow.
+ 
+ 	   A contrario, when the first interesting diagnostic line
+ 	   points into the definition of the macro, we don't need to
+ 	   display any line for that macro definition in the trace
+ 	   anymore, otherwise it'd be redundant.  */
+ 
+         /* Okay, now here is what we want.  For each token resulting
+            from macro expansion we want to show: 1/ where in the
+            definition of the macro the token comes from; 2/ where the
+            macro got expanded.  */
+ 
+         /* Resolve the location iter->where into the locus 1/ of the
+            comment above.  */
+         location_t resolved_def_loc =
+           linemap_resolve_location (line_table, iter->where,
+                                     LRK_MACRO_DEFINITION_LOCATION, nullptr);
+ 
+ 	/* Don't print trace for locations that are reserved or from
+ 	   within a system header.  */
+         const line_map_ordinary *m = nullptr;
+         location_t l =
+           linemap_resolve_location (line_table, resolved_def_loc,
+                                     LRK_SPELLING_LOCATION,  &m);
+ 	location_t l0 = l;
+ 	if (IS_ADHOC_LOC (l0))
+ 	  l0 = get_location_from_adhoc_loc (line_table, l0);
+ 	if (l0 < RESERVED_LOCATION_COUNT || LINEMAP_SYSP (m))
+           continue;
+ 
+ 	/* We need to print the context of the macro definition only
+ 	   when the locus of the first displayed diagnostic (displayed
+ 	   before this trace) was inside the definition of the
+ 	   macro.  */
+ 	const int resolved_def_loc_line = SOURCE_LINE (m, l0);
+         if (ix == 0 && saved_location_line != resolved_def_loc_line)
+           {
+ 	    text_output.append_note (resolved_def_loc,
+ 				     "in definition of macro %qs",
+ 				     linemap_map_get_macro_name (iter->map));
+             /* At this step, as we've printed the context of the macro
+                definition, we don't want to print the context of its
+                expansion, otherwise, it'd be redundant.  */
+             continue;
+           }
+ 
+         /* Resolve the location of the expansion point of the macro
+            which expansion gave the token represented by def_loc.
+            This is the locus 2/ of the earlier comment.  */
+         location_t resolved_exp_loc =
+           linemap_resolve_location (line_table,
+                                     iter->map->get_expansion_point_location (),
+                                     LRK_MACRO_DEFINITION_LOCATION, nullptr);
+ 
+ 	text_output.append_note (resolved_exp_loc,
+ 				 "in expansion of macro %qs",
+ 				 linemap_map_get_macro_name (iter->map));
+       }
+ }
+ 
+ /*  This is a diagnostic finalizer implementation that is aware of
+     virtual locations produced by libcpp.
+ 
+     It has to be called by the diagnostic finalizer of front ends that
+     uses libcpp and wish to get diagnostics involving tokens resulting
+     from macro expansion.
+ 
+     For a given location, if said location belongs to a token
+     resulting from a macro expansion, this starter prints the context
+     of the token.  E.g, for multiply nested macro expansion, it
+     unwinds the nested macro expansions and prints them in a manner
+     that is similar to what is done for function call stacks, or
+     template instantiation contexts.  */
+ void
+ virt_loc_aware_text_finalizer (text_sink &text_output,
+ 			       const diagnostic_info *diagnostic)
+ {
+   maybe_unwind_expanded_macro_loc (text_output,
+ 				   diagnostic_location (diagnostic));
+ }
+ 
+ } // namespace diagnostics
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/macro-unwinding.h gcc-16-20250727/gcc/diagnostics/macro-unwinding.h
*** gcc-16-20250720/gcc/diagnostics/macro-unwinding.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/macro-unwinding.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,33 ----
+ /* Code for unwinding macro expansions in diagnostics.
+    Copyright (C) 2000-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_MACRO_UNWINDING_H
+ #define GCC_DIAGNOSTICS_MACRO_UNWINDING_H
+ 
+ namespace diagnostics {
+ 
+ extern void virt_loc_aware_text_finalizer (text_sink &,
+ 					   const diagnostic_info *);
+ 
+ extern void maybe_unwind_expanded_macro_loc (text_sink &,
+ 					     location_t where);
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_MACRO_UNWINDING_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/metadata.h gcc-16-20250727/gcc/diagnostics/metadata.h
*** gcc-16-20250720/gcc/diagnostics/metadata.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/metadata.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,124 ----
+ /* Additional metadata for a diagnostic.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_METADATA_H
+ #define GCC_DIAGNOSTICS_METADATA_H
+ 
+ #include "lazily-created.h"
+ 
+ namespace diagnostics {
+ 
+   class sarif_object;
+   namespace digraphs { class digraph; }
+ 
+ /* A bundle of additional metadata that can be associated with a
+    diagnostic.
+ 
+    This supports an optional CWE identifier, and zero or more
+    "rules".
+ 
+    Additionally, this provides a place to associate a diagnostic
+    with zero or more directed graphs.  */
+ 
+ class metadata
+ {
+  public:
+   using lazy_digraphs
+   = lazily_created<std::vector<std::unique_ptr<digraphs::digraph>>>;
+ 
+   /* Abstract base class for referencing a rule that has been violated,
+      such as within a coding standard, or within a specification.  */
+   class rule
+   {
+   public:
+     virtual char *make_description () const = 0;
+     virtual char *make_url () const = 0;
+   };
+ 
+   /* Concrete subclass.  */
+   class precanned_rule : public rule
+   {
+   public:
+     precanned_rule (const char *desc, const char *url)
+     : m_desc (desc), m_url (url)
+     {}
+ 
+     char *make_description () const final override
+     {
+       return m_desc ? xstrdup (m_desc) : NULL;
+     }
+ 
+     char *make_url () const final override
+     {
+       return m_url ? xstrdup (m_url) : NULL;
+     }
+ 
+   private:
+     const char *m_desc;
+     const char *m_url;
+   };
+ 
+   metadata () : m_cwe (0), m_lazy_digraphs (nullptr) {}
+   virtual ~metadata () {}
+ 
+   /* Hook for SARIF output to allow for adding diagnostic-specific
+      properties to  the result object's property bag.  */
+   virtual void
+   maybe_add_sarif_properties (sarif_object &/*result_obj*/) const
+   {
+   }
+ 
+   void add_cwe (int cwe) { m_cwe = cwe; }
+   int get_cwe () const { return m_cwe; }
+ 
+   /* Associate R with the diagnostic.  R must outlive
+      the metadata.  */
+   void add_rule (const rule &r)
+   {
+     m_rules.safe_push (&r);
+   }
+ 
+   unsigned get_num_rules () const { return m_rules.length (); }
+   const rule &get_rule (unsigned idx) const { return *(m_rules[idx]); }
+ 
+   void
+   set_lazy_digraphs (const lazy_digraphs *lazy_digraphs_)
+   {
+     m_lazy_digraphs = lazy_digraphs_;
+   }
+ 
+   const lazy_digraphs *
+   get_lazy_digraphs () const
+   {
+     return m_lazy_digraphs;
+   }
+ 
+  private:
+   int m_cwe;
+   auto_vec<const rule *> m_rules;
+ 
+   /* An optional way to create directed graphs associated with the
+      diagnostic, for the sinks that support this (e.g. SARIF).  */
+   const lazy_digraphs *m_lazy_digraphs;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_METADATA_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/option-classifier.cc gcc-16-20250727/gcc/diagnostics/option-classifier.cc
*** gcc-16-20250720/gcc/diagnostics/option-classifier.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/option-classifier.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,222 ----
+ /* Stacks of set of classifications of diagnostics.
+    Copyright (C) 1999-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "version.h"
+ #include "diagnostic.h"
+ 
+ namespace diagnostics {
+ 
+ void
+ option_classifier::init (int n_opts)
+ {
+   m_n_opts = n_opts;
+   m_classify_diagnostic = XNEWVEC (enum kind, n_opts);
+   for (int i = 0; i < n_opts; i++)
+     m_classify_diagnostic[i] = kind::unspecified;
+   m_push_list = vNULL;
+   m_classification_history = vNULL;
+ }
+ 
+ void
+ option_classifier::fini ()
+ {
+   XDELETEVEC (m_classify_diagnostic);
+   m_classify_diagnostic = nullptr;
+   m_classification_history.release ();
+   m_push_list.release ();
+ }
+ 
+ /* Save the diagnostics::option_classifier state to F for PCH
+    output.  Returns 0 on success, -1 on error.  */
+ 
+ int
+ option_classifier::pch_save (FILE *f)
+ {
+   unsigned int lengths[2] = { m_classification_history.length (),
+ 			      m_push_list.length () };
+   if (fwrite (lengths, sizeof (lengths), 1, f) != 1
+       || (lengths[0]
+ 	  && fwrite (m_classification_history.address (),
+ 		     sizeof (classification_change_t),
+ 		     lengths[0], f) != lengths[0])
+       || (lengths[1]
+ 	  && fwrite (m_push_list.address (), sizeof (int),
+ 		     lengths[1], f) != lengths[1]))
+     return -1;
+   return 0;
+ }
+ 
+ /* Read the diagnostics::option_classifier state from F for PCH
+    read.  Returns 0 on success, -1 on error.  */
+ 
+ int
+ option_classifier::pch_restore (FILE *f)
+ {
+   unsigned int lengths[2];
+   if (fread (lengths, sizeof (lengths), 1, f) != 1)
+     return -1;
+   gcc_checking_assert (m_classification_history.is_empty ());
+   gcc_checking_assert (m_push_list.is_empty ());
+   m_classification_history.safe_grow (lengths[0]);
+   m_push_list.safe_grow (lengths[1]);
+   if ((lengths[0]
+        && fread (m_classification_history.address (),
+ 		 sizeof (classification_change_t),
+ 		 lengths[0], f) != lengths[0])
+       || (lengths[1]
+ 	  && fread (m_push_list.address (), sizeof (int),
+ 		    lengths[1], f) != lengths[1]))
+     return -1;
+   return 0;
+ }
+ 
+ /* Save all diagnostic classifications in a stack.  */
+ 
+ void
+ option_classifier::push ()
+ {
+   m_push_list.safe_push (m_classification_history.length ());
+ }
+ 
+ /* Restore the topmost classification set off the stack.  If the stack
+    is empty, revert to the state based on command line parameters.  */
+ 
+ void
+ option_classifier::pop (location_t where)
+ {
+   int jump_to;
+ 
+   if (!m_push_list.is_empty ())
+     jump_to = m_push_list.pop ();
+   else
+     jump_to = 0;
+ 
+   classification_change_t v = { where, jump_to, kind::pop };
+   m_classification_history.safe_push (v);
+ }
+ 
+ /* Interface to specify diagnostic kind overrides.  Returns the
+    previous setting, or kind::unspecified if the parameters are out of
+    range.  If OPTION_ID is zero, the new setting is for all the
+    diagnostics.  */
+ 
+ enum kind
+ option_classifier::classify_diagnostic (const context *dc,
+ 					option_id opt_id,
+ 					enum kind new_kind,
+ 					location_t where)
+ {
+   enum kind old_kind;
+ 
+   if (opt_id.m_idx < 0
+       || opt_id.m_idx >= m_n_opts
+       || new_kind >= kind::last_diagnostic_kind)
+     return kind::unspecified;
+ 
+   old_kind = m_classify_diagnostic[opt_id.m_idx];
+ 
+   /* Handle pragmas separately, since we need to keep track of *where*
+      the pragmas were.  */
+   if (where != UNKNOWN_LOCATION)
+     {
+       unsigned i;
+ 
+       /* Record the command-line status, so we can reset it back on kind::pop. */
+       if (old_kind == kind::unspecified)
+ 	{
+ 	  old_kind = (!dc->option_enabled_p (opt_id)
+ 		      ? kind::ignored : kind::any);
+ 	  m_classify_diagnostic[opt_id.m_idx] = old_kind;
+ 	}
+ 
+       classification_change_t *p;
+       FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
+ 	if (p->option == opt_id.m_idx)
+ 	  {
+ 	    old_kind = p->kind;
+ 	    break;
+ 	  }
+ 
+       classification_change_t v
+ 	= { where, opt_id.m_idx, new_kind };
+       m_classification_history.safe_push (v);
+     }
+   else
+     m_classify_diagnostic[opt_id.m_idx] = new_kind;
+ 
+   return old_kind;
+ }
+ 
+ /* Update the kind of DIAGNOSTIC based on its location(s), including
+    any of those in its inlining stack, relative to any
+      #pragma GCC diagnostic
+    directives recorded within this object.
+ 
+    Return the new kind of DIAGNOSTIC if it was updated, or kind::unspecified
+    otherwise.  */
+ 
+ enum kind
+ option_classifier::
+ update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
+ {
+   if (m_classification_history.is_empty ())
+     return kind::unspecified;
+ 
+   /* Iterate over the locations, checking the diagnostic disposition
+      for the diagnostic at each.  If it's explicitly set as opposed
+      to unspecified, update the disposition for this instance of
+      the diagnostic and return it.  */
+   for (location_t loc: diagnostic->m_iinfo.m_ilocs)
+     {
+       /* FIXME: Stupid search.  Optimize later. */
+       unsigned int i;
+       classification_change_t *p;
+       FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
+ 	{
+ 	  location_t pragloc = p->location;
+ 	  if (!linemap_location_before_p (line_table, pragloc, loc))
+ 	    continue;
+ 
+ 	  if (p->kind == kind::pop)
+ 	    {
+ 	      /* Move on to the next region.  */
+ 	      i = p->option;
+ 	      continue;
+ 	    }
+ 
+ 	  option_id opt_id = p->option;
+ 	  /* The option 0 is for all the diagnostics.  */
+ 	  if (opt_id == 0 || opt_id == diagnostic->m_option_id)
+ 	    {
+ 	      enum kind kind = p->kind;
+ 	      if (kind != diagnostics::kind::unspecified)
+ 		diagnostic->m_kind = kind;
+ 	      return kind;
+ 	    }
+ 	}
+     }
+ 
+   return kind::unspecified;
+ }
+ 
+ } // namespace diagnostics
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/option-classifier.h gcc-16-20250727/gcc/diagnostics/option-classifier.h
*** gcc-16-20250720/gcc/diagnostics/option-classifier.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/option-classifier.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,110 ----
+ /* Stacks of set of classifications of diagnostics.
+    Copyright (C) 2000-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_OPTION_CLASSIFIER_H
+ #define GCC_DIAGNOSTICS_OPTION_CLASSIFIER_H
+ 
+ namespace diagnostics {
+ 
+ /*  Forward declarations.  */
+ class context;
+ 
+ /* A stack of sets of classifications: each entry in the stack is
+    a mapping from option index to diagnostic severity that can be changed
+    via pragmas.  The stack can be pushed and popped.  */
+ 
+ class option_classifier
+ {
+ public:
+   void init (int n_opts);
+   void fini ();
+ 
+   /* Save all diagnostic classifications in a stack.  */
+   void push ();
+ 
+   /* Restore the topmost classification set off the stack.  If the stack
+      is empty, revert to the state based on command line parameters.  */
+   void pop (location_t where);
+ 
+   bool option_unspecified_p (option_id opt_id) const
+   {
+     return get_current_override (opt_id) == kind::unspecified;
+   }
+ 
+   enum kind get_current_override (option_id opt_id) const
+   {
+     gcc_assert (opt_id.m_idx < m_n_opts);
+     return m_classify_diagnostic[opt_id.m_idx];
+   }
+ 
+   enum kind
+   classify_diagnostic (const context *context,
+ 		       option_id opt_id,
+ 		       enum kind new_kind,
+ 		       location_t where);
+ 
+   enum kind
+   update_effective_level_from_pragmas (diagnostic_info *diagnostic) const;
+ 
+   int pch_save (FILE *);
+   int pch_restore (FILE *);
+ 
+ private:
+   /* Each time a diagnostic's classification is changed with a pragma,
+      we record the change and the location of the change in an array of
+      these structs.  */
+   struct classification_change_t
+   {
+     location_t location;
+ 
+     /* For kind::pop, this is the index of the corresponding push (as stored
+        in m_push_list).
+        Otherwise, this is an option index.  */
+     int option;
+ 
+     enum kind kind;
+   };
+ 
+   int m_n_opts;
+ 
+   /* For each option index that can be passed to warning() et al
+      (OPT_* from options.h when using this code with the core GCC
+      options), this array may contain a new kind that the diagnostic
+      should be changed to before reporting, or kind::unspecified to leave
+      it as the reported kind, or kind::ignored to not report it at
+      all.  */
+   enum kind *m_classify_diagnostic;
+ 
+   /* History of all changes to the classifications above.  This list
+      is stored in location-order, so we can search it, either
+      binary-wise or end-to-front, to find the most recent
+      classification for a given diagnostic, given the location of the
+      diagnostic.  */
+   vec<classification_change_t> m_classification_history;
+ 
+   /* For context::get_classification_history, declared later.  */
+   friend class context;
+ 
+   /* For pragma push/pop.  */
+   vec<int> m_push_list;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_OPTION_CLASSIFIER_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/option-id.h gcc-16-20250727/gcc/diagnostics/option-id.h
*** gcc-16-20250720/gcc/diagnostics/option-id.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/option-id.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,49 ----
+ /* Declaration of struct diagnostics::option_id.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_OPTION_ID_H
+ #define GCC_DIAGNOSTICS_OPTION_ID_H
+ 
+ namespace diagnostics {
+ 
+ /* A class to use for the ID of an option that controls
+    a particular diagnostic.
+    This is just a wrapper around "int", but better documents
+    the intent of the code.  */
+ 
+ struct option_id
+ {
+   option_id () : m_idx (0) {}
+ 
+   option_id (int idx) : m_idx (idx) {}
+   /* Ideally we'd take an enum opt_code here, but we don't
+      want to depend on its decl.  */
+ 
+   bool operator== (option_id other) const
+   {
+     return m_idx == other.m_idx;
+   }
+ 
+   int m_idx;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_OPTION_ID_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/output-file.h gcc-16-20250727/gcc/diagnostics/output-file.h
*** gcc-16-20250720/gcc/diagnostics/output-file.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/output-file.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,111 ----
+ /* RAII class for managing FILE * for diagnostic formats.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_OUTPUT_FILE_H
+ #define GCC_DIAGNOSTICS_OUTPUT_FILE_H
+ 
+ namespace diagnostics {
+ 
+ /* RAII class for wrapping a FILE * that could be borrowed or owned,
+    along with the underlying filename.  */
+ 
+ class output_file
+ {
+ public:
+   output_file ()
+   : m_outf (nullptr),
+     m_owned (false),
+     m_filename ()
+   {
+   }
+   output_file (FILE *outf, bool owned, label_text filename)
+   : m_outf (outf),
+     m_owned (owned),
+     m_filename (std::move (filename))
+   {
+     gcc_assert (m_filename.get ());
+     if (m_owned)
+       gcc_assert (m_outf);
+   }
+   ~output_file ()
+   {
+     if (m_owned)
+       {
+ 	gcc_assert (m_outf);
+ 	fclose (m_outf);
+       }
+   }
+   output_file (const output_file &other) = delete;
+   output_file (output_file &&other)
+   : m_outf (other.m_outf),
+     m_owned (other.m_owned),
+     m_filename (std::move (other.m_filename))
+   {
+     other.m_outf = nullptr;
+     other.m_owned = false;
+ 
+     gcc_assert (m_filename.get ());
+     if (m_owned)
+       gcc_assert (m_outf);
+   }
+   output_file &
+   operator= (const output_file &other) = delete;
+   output_file &
+   operator= (output_file &&other)
+   {
+     if (m_owned)
+       {
+ 	gcc_assert (m_outf);
+ 	fclose (m_outf);
+       }
+ 
+     m_outf = other.m_outf;
+     other.m_outf = nullptr;
+ 
+     m_owned = other.m_owned;
+     other.m_owned = false;
+ 
+     m_filename = std::move (other.m_filename);
+ 
+     if (m_owned)
+       gcc_assert (m_outf);
+     return *this;
+   }
+ 
+   operator bool () const { return m_outf != nullptr; }
+   FILE *get_open_file () const { return m_outf; }
+   const char *get_filename () const { return m_filename.get (); }
+ 
+   static output_file
+   try_to_open (context &dc,
+ 	       line_maps *line_maps,
+ 	       const char *base_file_name,
+ 	       const char *extension,
+ 	       bool binary);
+ 
+ private:
+   FILE *m_outf;
+   bool m_owned;
+   label_text m_filename;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_OUTPUT_FILE_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/output-spec.cc gcc-16-20250727/gcc/diagnostics/output-spec.cc
*** gcc-16-20250720/gcc/diagnostics/output-spec.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/output-spec.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,851 ----
+ /* Support for the DSL of -fdiagnostics-add-output= and
+    -fdiagnostics-set-output=.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ /* This file implements the domain-specific language for the options
+    -fdiagnostics-add-output= and -fdiagnostics-set-output=, and for
+    the "diagnostic_manager_add_sink_from_spec" entrypoint to
+    libgdiagnostics.  */
+ 
+ #include "config.h"
+ #define INCLUDE_ARRAY
+ #define INCLUDE_STRING
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "version.h"
+ #include "intl.h"
+ #include "diagnostic.h"
+ #include "diagnostics/color.h"
+ #include "diagnostics/sink.h"
+ #include "diagnostics/html-sink.h"
+ #include "diagnostics/text-sink.h"
+ #include "diagnostics/sarif-sink.h"
+ #include "selftest.h"
+ #include "diagnostics/selftest-context.h"
+ #include "pretty-print-markup.h"
+ #include "diagnostics/output-spec.h"
+ 
+ /* A namespace for handling the DSL of the arguments of
+    -fdiagnostics-add-output= and -fdiagnostics-set-output=.  */
+ 
+ namespace diagnostics {
+ namespace output_spec {
+ 
+ /* Decls.  */
+ 
+ struct scheme_name_and_params
+ {
+   std::string m_scheme_name;
+   std::vector<std::pair<std::string, std::string>> m_kvs;
+ };
+ 
+ /* Class for parsing the arguments of -fdiagnostics-add-output= and
+    -fdiagnostics-set-output=, and making sink
+    instances (or issuing errors).  */
+ 
+ class output_factory
+ {
+ public:
+   class scheme_handler
+   {
+   public:
+     scheme_handler (std::string scheme_name)
+     : m_scheme_name (std::move (scheme_name))
+     {}
+     virtual ~scheme_handler () {}
+ 
+     const std::string &get_scheme_name () const { return m_scheme_name; }
+ 
+     virtual std::unique_ptr<sink>
+     make_sink (const context &ctxt,
+ 	       diagnostics::context &dc,
+ 	       const char *unparsed_arg,
+ 	       const scheme_name_and_params &parsed_arg) const = 0;
+ 
+   protected:
+     bool
+     parse_bool_value (const context &ctxt,
+ 		      const char *unparsed_arg,
+ 		      const std::string &key,
+ 		      const std::string &value,
+ 		      bool &out) const
+     {
+       if (value == "yes")
+ 	{
+ 	  out = true;
+ 	  return true;
+ 	}
+       else if (value == "no")
+ 	{
+ 	  out = false;
+ 	  return true;
+ 	}
+       else
+ 	{
+ 	  ctxt.report_error
+ 	    ("%<%s%s%>:"
+ 	     " unexpected value %qs for key %qs; expected %qs or %qs",
+ 	     ctxt.get_option_name (), unparsed_arg,
+ 	     value.c_str (),
+ 	     key.c_str (),
+ 	     "yes", "no");
+ 
+ 	  return false;
+ 	}
+     }
+     template <typename EnumType, size_t NumValues>
+     bool
+     parse_enum_value (const context &ctxt,
+ 		      const char *unparsed_arg,
+ 		      const std::string &key,
+ 		      const std::string &value,
+ 		      const std::array<std::pair<const char *, EnumType>, NumValues> &value_names,
+ 		      EnumType &out) const
+     {
+       for (auto &iter : value_names)
+ 	if (value == iter.first)
+ 	  {
+ 	    out = iter.second;
+ 	    return true;
+ 	  }
+ 
+       auto_vec<const char *> known_values;
+       for (auto iter : value_names)
+ 	known_values.safe_push (iter.first);
+       pp_markup::comma_separated_quoted_strings e (known_values);
+       ctxt.report_error
+ 	("%<%s%s%>:"
+ 	 " unexpected value %qs for key %qs; known values: %e",
+ 	 ctxt.get_option_name (), unparsed_arg,
+ 	 value.c_str (),
+ 	 key.c_str (),
+ 	 &e);
+       return false;
+     }
+ 
+   private:
+     const std::string m_scheme_name;
+   };
+ 
+   output_factory ();
+ 
+   std::unique_ptr<sink>
+   make_sink (const context &ctxt,
+ 	     diagnostics::context &dc,
+ 	     const char *unparsed_arg,
+ 	     const scheme_name_and_params &parsed_arg);
+ 
+   const scheme_handler *get_scheme_handler (const std::string &scheme_name);
+ 
+ private:
+   std::vector<std::unique_ptr<scheme_handler>> m_scheme_handlers;
+ };
+ 
+ class text_scheme_handler : public output_factory::scheme_handler
+ {
+ public:
+   text_scheme_handler () : scheme_handler ("text") {}
+ 
+   std::unique_ptr<sink>
+   make_sink (const context &ctxt,
+ 	     diagnostics::context &dc,
+ 	     const char *unparsed_arg,
+ 	     const scheme_name_and_params &parsed_arg) const final override;
+ };
+ 
+ class sarif_scheme_handler : public output_factory::scheme_handler
+ {
+ public:
+   sarif_scheme_handler () : scheme_handler ("sarif") {}
+ 
+   std::unique_ptr<sink>
+   make_sink (const context &ctxt,
+ 	     diagnostics::context &dc,
+ 	     const char *unparsed_arg,
+ 	     const scheme_name_and_params &parsed_arg) const final override;
+ 
+ private:
+   static sarif_generation_options
+   make_sarif_gen_opts (enum sarif_version version,
+ 		       bool state_graph);
+ 
+   static std::unique_ptr<sarif_serialization_format>
+   make_sarif_serialization_object (enum sarif_serialization_kind);
+ };
+ 
+ class html_scheme_handler : public output_factory::scheme_handler
+ {
+ public:
+   html_scheme_handler () : scheme_handler ("experimental-html") {}
+ 
+   std::unique_ptr<sink>
+   make_sink (const context &ctxt,
+ 	     diagnostics::context &dc,
+ 	     const char *unparsed_arg,
+ 	     const scheme_name_and_params &parsed_arg) const final override;
+ };
+ 
+ /* struct context.  */
+ 
+ void
+ context::report_error (const char *gmsgid, ...) const
+ {
+   va_list ap;
+   va_start (ap, gmsgid);
+   report_error_va (gmsgid, &ap);
+   va_end (ap);
+ }
+ 
+ void
+ context::report_unknown_key (const char *unparsed_arg,
+ 			     const std::string &key,
+ 			     const std::string &scheme_name,
+ 			     auto_vec<const char *> &known_keys) const
+ {
+   pp_markup::comma_separated_quoted_strings e (known_keys);
+   report_error
+     ("%<%s%s%>:"
+      " unknown key %qs for format %qs; known keys: %e",
+      get_option_name (), unparsed_arg,
+      key.c_str (), scheme_name.c_str (), &e);
+ }
+ 
+ void
+ context::report_missing_key (const char *unparsed_arg,
+ 			     const std::string &key,
+ 			     const std::string &scheme_name,
+ 			     const char *metavar) const
+ {
+   report_error
+     ("%<%s%s%>:"
+      " missing required key %qs for format %qs;"
+      " try %<%s%s:%s=%s%>",
+      get_option_name (), unparsed_arg,
+      key.c_str (), scheme_name.c_str (),
+      get_option_name (), scheme_name.c_str (), key.c_str (), metavar);
+ }
+ 
+ output_file
+ context::open_output_file (label_text &&filename) const
+ {
+   FILE *outf = fopen (filename.get (), "w");
+   if (!outf)
+     {
+       report_error ("unable to open %qs: %m", filename.get ());
+       return output_file (nullptr, false, std::move (filename));
+     }
+   return output_file (outf, true, std::move (filename));
+ }
+ 
+ static std::unique_ptr<scheme_name_and_params>
+ parse (const context &ctxt, const char *unparsed_arg)
+ {
+   scheme_name_and_params result;
+   if (const char *const colon = strchr (unparsed_arg, ':'))
+     {
+       result.m_scheme_name = std::string (unparsed_arg, colon - unparsed_arg);
+       /* Expect zero of more of KEY=VALUE,KEY=VALUE, etc  .*/
+       const char *iter = colon + 1;
+       const char *last_separator = ":";
+       while (iter)
+ 	{
+ 	  /* Look for a non-empty key string followed by '='.  */
+ 	  const char *eq = strchr (iter, '=');
+ 	  if (eq == nullptr || eq == iter)
+ 	    {
+ 	      /* Missing '='.  */
+ 	      ctxt.report_error
+ 		("%<%s%s%>:"
+ 		 " expected KEY=VALUE-style parameter for format %qs"
+ 		 " after %qs;"
+ 		 " got %qs",
+ 		 ctxt.get_option_name (), unparsed_arg,
+ 		 result.m_scheme_name.c_str (),
+ 		 last_separator,
+ 		 iter);
+ 	      return nullptr;
+ 	    }
+ 	  std::string key = std::string (iter, eq - iter);
+ 	  std::string value;
+ 	  const char *comma = strchr (iter, ',');
+ 	  if (comma)
+ 	    {
+ 	      value = std::string (eq + 1, comma - (eq + 1));
+ 	      iter = comma + 1;
+ 	      last_separator = ",";
+ 	    }
+ 	  else
+ 	    {
+ 	      value = std::string (eq + 1);
+ 	      iter = nullptr;
+ 	    }
+ 	  result.m_kvs.push_back ({std::move (key), std::move (value)});
+ 	}
+     }
+   else
+     result.m_scheme_name = unparsed_arg;
+   return std::make_unique<scheme_name_and_params> (std::move (result));
+ }
+ 
+ std::unique_ptr<sink>
+ context::parse_and_make_sink (const char *unparsed_arg,
+ 			      diagnostics::context &dc)
+ {
+   auto parsed_arg = parse (*this, unparsed_arg);
+   if (!parsed_arg)
+     return nullptr;
+ 
+   output_factory factory;
+   return factory.make_sink (*this, dc, unparsed_arg, *parsed_arg);
+ }
+ 
+ /* class output_factory::scheme_handler.  */
+ 
+ /* class output_factory.  */
+ 
+ output_factory::output_factory ()
+ {
+   m_scheme_handlers.push_back (std::make_unique<text_scheme_handler> ());
+   m_scheme_handlers.push_back (std::make_unique<sarif_scheme_handler> ());
+   m_scheme_handlers.push_back (std::make_unique<html_scheme_handler> ());
+ }
+ 
+ const output_factory::scheme_handler *
+ output_factory::get_scheme_handler (const std::string &scheme_name)
+ {
+   for (auto &iter : m_scheme_handlers)
+     if (iter->get_scheme_name () == scheme_name)
+       return iter.get ();
+   return nullptr;
+ }
+ 
+ std::unique_ptr<sink>
+ output_factory::make_sink (const context &ctxt,
+ 			   diagnostics::context &dc,
+ 			   const char *unparsed_arg,
+ 			   const scheme_name_and_params &parsed_arg)
+ {
+   auto scheme_handler = get_scheme_handler (parsed_arg.m_scheme_name);
+   if (!scheme_handler)
+     {
+       auto_vec<const char *> strings;
+       for (auto &iter : m_scheme_handlers)
+ 	strings.safe_push (iter->get_scheme_name ().c_str ());
+       pp_markup::comma_separated_quoted_strings e (strings);
+       ctxt.report_error ("%<%s%s%>:"
+ 			 " unrecognized format %qs; known formats: %e",
+ 			 ctxt.get_option_name (), unparsed_arg,
+ 			 parsed_arg.m_scheme_name.c_str (), &e);
+       return nullptr;
+     }
+ 
+   return scheme_handler->make_sink (ctxt, dc, unparsed_arg, parsed_arg);
+ }
+ 
+ /* class text_scheme_handler : public output_factory::scheme_handler.  */
+ 
+ std::unique_ptr<sink>
+ text_scheme_handler::make_sink (const context &ctxt,
+ 				diagnostics::context &dc,
+ 				const char *unparsed_arg,
+ 				const scheme_name_and_params &parsed_arg) const
+ {
+   bool show_color = pp_show_color (dc.get_reference_printer ());
+   bool show_nesting = false;
+   bool show_locations_in_nesting = true;
+   bool show_levels = false;
+   for (auto& iter : parsed_arg.m_kvs)
+     {
+       const std::string &key = iter.first;
+       const std::string &value = iter.second;
+       if (key == "color")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value, show_color))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+       if (key == "experimental-nesting")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
+ 				 show_nesting))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+       if (key == "experimental-nesting-show-locations")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
+ 				 show_locations_in_nesting))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+       if (key == "experimental-nesting-show-levels")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value, show_levels))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+ 
+       /* Key not found.  */
+       auto_vec<const char *> known_keys;
+       known_keys.safe_push ("color");
+       known_keys.safe_push ("experimental-nesting");
+       known_keys.safe_push ("experimental-nesting-show-locations");
+       known_keys.safe_push ("experimental-nesting-show-levels");
+       ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
+ 			       known_keys);
+       return nullptr;
+     }
+ 
+   auto sink = std::make_unique<diagnostics::text_sink> (dc);
+   sink->set_show_nesting (show_nesting);
+   sink->set_show_locations_in_nesting (show_locations_in_nesting);
+   sink->set_show_nesting_levels (show_levels);
+   return sink;
+ }
+ 
+ /* class sarif_scheme_handler : public output_factory::scheme_handler.  */
+ 
+ std::unique_ptr<sink>
+ sarif_scheme_handler::make_sink (const context &ctxt,
+ 				 diagnostics::context &dc,
+ 				 const char *unparsed_arg,
+ 				 const scheme_name_and_params &parsed_arg) const
+ {
+   label_text filename;
+   enum sarif_serialization_kind serialization_kind
+     = sarif_serialization_kind::json;
+   enum sarif_version version = sarif_version::v2_1_0;
+   bool state_graph = false;
+   for (auto& iter : parsed_arg.m_kvs)
+     {
+       const std::string &key = iter.first;
+       const std::string &value = iter.second;
+       if (key == "file")
+ 	{
+ 	  filename = label_text::take (xstrdup (value.c_str ()));
+ 	  continue;
+ 	}
+       if (key == "serialization")
+ 	{
+ 	  static const std::array<std::pair<const char *, enum sarif_serialization_kind>,
+ 				  (size_t)sarif_serialization_kind::num_values> value_names
+ 	    {{{"json", sarif_serialization_kind::json}}};
+ 
+ 	  if (!parse_enum_value<enum sarif_serialization_kind>
+ 		 (ctxt, unparsed_arg,
+ 		  key, value,
+ 		  value_names,
+ 		  serialization_kind))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+       if (key == "version")
+ 	{
+ 	  static const std::array<std::pair<const char *, enum sarif_version>,
+ 				  (size_t)sarif_version::num_versions> value_names
+ 	    {{{"2.1", sarif_version::v2_1_0},
+ 	      {"2.2-prerelease", sarif_version::v2_2_prerelease_2024_08_08}}};
+ 
+ 	    if (!parse_enum_value<enum sarif_version> (ctxt, unparsed_arg,
+ 						       key, value,
+ 						       value_names,
+ 						       version))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+       if (key == "state-graphs")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
+ 				 state_graph))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+ 
+       /* Key not found.  */
+       auto_vec<const char *> known_keys;
+       known_keys.safe_push ("file");
+       known_keys.safe_push ("serialization");
+       known_keys.safe_push ("state-graphs");
+       known_keys.safe_push ("version");
+       ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
+ 			       known_keys);
+       return nullptr;
+     }
+ 
+   output_file output_file_;
+   if (filename.get ())
+     output_file_ = ctxt.open_output_file (std::move (filename));
+   else
+     // Default filename
+     {
+       const char *basename = ctxt.get_base_filename ();
+       if (!basename)
+ 	{
+ 	  ctxt.report_missing_key (unparsed_arg,
+ 				   "file",
+ 				   get_scheme_name (),
+ 				   "FILENAME");
+ 	  return nullptr;
+ 	}
+       output_file_
+ 	= open_sarif_output_file (dc,
+ 				  ctxt.get_affected_location_mgr (),
+ 				  basename,
+ 				  serialization_kind);
+     }
+   if (!output_file_)
+     return nullptr;
+ 
+   auto sarif_gen_opts = make_sarif_gen_opts (version, state_graph);
+ 
+   auto serialization_obj = make_sarif_serialization_object (serialization_kind);
+ 
+   auto sink = make_sarif_sink (dc,
+ 			       *ctxt.get_affected_location_mgr (),
+ 			       std::move (serialization_obj),
+ 			       sarif_gen_opts,
+ 			       std::move (output_file_));
+   return sink;
+ }
+ 
+ sarif_generation_options
+ sarif_scheme_handler::make_sarif_gen_opts (enum sarif_version version,
+ 					   bool state_graph)
+ {
+   sarif_generation_options sarif_gen_opts;
+   sarif_gen_opts.m_version = version;
+   sarif_gen_opts.m_state_graph = state_graph;
+   return sarif_gen_opts;
+ }
+ 
+ std::unique_ptr<sarif_serialization_format>
+ sarif_scheme_handler::
+ make_sarif_serialization_object (enum sarif_serialization_kind kind)
+ {
+   switch (kind)
+     {
+     default:
+       gcc_unreachable ();
+     case sarif_serialization_kind::json:
+       return std::make_unique<sarif_serialization_format_json> (true);
+       break;
+     }
+ }
+ 
+ /* class html_scheme_handler : public output_factory::scheme_handler.  */
+ 
+ std::unique_ptr<sink>
+ html_scheme_handler::make_sink (const context &ctxt,
+ 				diagnostics::context &dc,
+ 				const char *unparsed_arg,
+ 				const scheme_name_and_params &parsed_arg) const
+ {
+   bool css = true;
+   label_text filename;
+   bool javascript = true;
+   bool show_state_diagrams = false;
+   bool show_state_diagrams_sarif = false;
+   bool show_state_diagrams_dot_src = false;
+   for (auto& iter : parsed_arg.m_kvs)
+     {
+       const std::string &key = iter.first;
+       const std::string &value = iter.second;
+       if (key == "css")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
+ 				 css))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+       if (key == "file")
+ 	{
+ 	  filename = label_text::take (xstrdup (value.c_str ()));
+ 	  continue;
+ 	}
+       if (key == "javascript")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
+ 				 javascript))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+       if (key == "show-state-diagrams")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
+ 				 show_state_diagrams))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+       if (key == "show-state-diagrams-dot-src")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
+ 				 show_state_diagrams_dot_src))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+       if (key == "show-state-diagrams-sarif")
+ 	{
+ 	  if (!parse_bool_value (ctxt, unparsed_arg, key, value,
+ 				 show_state_diagrams_sarif))
+ 	    return nullptr;
+ 	  continue;
+ 	}
+ 
+       /* Key not found.  */
+       auto_vec<const char *> known_keys;
+       known_keys.safe_push ("css");
+       known_keys.safe_push ("file");
+       known_keys.safe_push ("javascript");
+       known_keys.safe_push ("show-state-diagrams");
+       known_keys.safe_push ("show-state-diagram-dot-src");
+       known_keys.safe_push ("show-state-diagram-sarif");
+       ctxt.report_unknown_key (unparsed_arg, key, get_scheme_name (),
+ 			       known_keys);
+       return nullptr;
+     }
+ 
+   output_file output_file_;
+   if (filename.get ())
+     output_file_ = ctxt.open_output_file (std::move (filename));
+   else
+     // Default filename
+     {
+       const char *basename = ctxt.get_base_filename ();
+       if (!basename)
+ 	{
+ 	  ctxt.report_missing_key (unparsed_arg,
+ 				   "file",
+ 				   get_scheme_name (),
+ 				   "FILENAME");
+ 	  return nullptr;
+ 	}
+       output_file_
+ 	= open_html_output_file
+ 	    (dc,
+ 	     ctxt.get_affected_location_mgr (),
+ 	     basename);
+     }
+   if (!output_file_)
+     return nullptr;
+ 
+   html_generation_options html_gen_opts;
+   html_gen_opts.m_css = css;
+   html_gen_opts.m_javascript = javascript;
+   html_gen_opts.m_show_state_diagrams = show_state_diagrams;
+   html_gen_opts.m_show_state_diagrams_sarif = show_state_diagrams_sarif;
+   html_gen_opts.m_show_state_diagrams_dot_src = show_state_diagrams_dot_src;
+ 
+   auto sink = make_html_sink (dc,
+ 			      *ctxt.get_affected_location_mgr (),
+ 			      html_gen_opts,
+ 			      std::move (output_file_));
+   return sink;
+ }
+ 
+ } // namespace output_spec
+ 
+ #if CHECKING_P
+ 
+ namespace selftest {
+ 
+ using auto_fix_quotes = ::selftest::auto_fix_quotes;
+ 
+ /* RAII class to temporarily override "progname" to the
+    string "PROGNAME".  */
+ 
+ class auto_fix_progname
+ {
+ public:
+   auto_fix_progname ()
+   {
+     m_old_progname = progname;
+     progname = "PROGNAME";
+   }
+ 
+   ~auto_fix_progname ()
+   {
+     progname = m_old_progname;
+   }
+ 
+ private:
+   const char *m_old_progname;
+ };
+ 
+ struct parser_test
+ {
+   class test_spec_context : public diagnostics::output_spec::dc_spec_context
+   {
+   public:
+     test_spec_context (diagnostics::context &dc,
+ 		       line_maps *location_mgr,
+ 		       location_t loc,
+ 		       const char *option_name)
+     : dc_spec_context (dc,
+ 		       location_mgr,
+ 		       location_mgr,
+ 		       loc,
+ 		       option_name)
+     {
+     }
+ 
+     const char *
+     get_base_filename () const final override
+     {
+       return "BASE_FILENAME";
+     }
+   };
+ 
+   parser_test ()
+   : m_dc (),
+     m_ctxt (m_dc, line_table, UNKNOWN_LOCATION, "-fOPTION="),
+     m_fmt (m_dc.get_sink (0))
+   {
+     pp_buffer (m_fmt.get_printer ())->m_flush_p = false;
+   }
+ 
+   std::unique_ptr<diagnostics::output_spec::scheme_name_and_params>
+   parse (const char *unparsed_arg)
+   {
+     return diagnostics::output_spec::parse (m_ctxt, unparsed_arg);
+   }
+ 
+   bool execution_failed_p () const
+   {
+     return m_dc.execution_failed_p ();
+   }
+ 
+   const char *
+   get_diagnostic_text () const
+   {
+     return pp_formatted_text (m_fmt.get_printer ());
+   }
+ 
+ private:
+   diagnostics::selftest::test_context m_dc;
+   test_spec_context m_ctxt;
+   diagnostics::sink &m_fmt;
+ };
+ 
+ /* Selftests.  */
+ 
+ static void
+ test_output_arg_parsing ()
+ {
+   auto_fix_quotes fix_quotes;
+   auto_fix_progname fix_progname;
+ 
+   /* Minimal correct example.  */
+   {
+     parser_test pt;
+     auto result = pt.parse ("foo");
+     ASSERT_EQ (result->m_scheme_name, "foo");
+     ASSERT_EQ (result->m_kvs.size (), 0);
+     ASSERT_FALSE (pt.execution_failed_p ());
+   }
+ 
+   /* Stray trailing colon with no key/value pairs.  */
+   {
+     parser_test pt;
+     auto result = pt.parse ("foo:");
+     ASSERT_EQ (result, nullptr);
+     ASSERT_TRUE (pt.execution_failed_p ());
+     ASSERT_STREQ (pt.get_diagnostic_text (),
+ 		  "PROGNAME: error: `-fOPTION=foo:':"
+ 		  " expected KEY=VALUE-style parameter for format `foo'"
+ 		  " after `:';"
+ 		  " got `'\n");
+   }
+ 
+   /* No key before '='.  */
+   {
+     parser_test pt;
+     auto result = pt.parse ("foo:=");
+     ASSERT_EQ (result, nullptr);
+     ASSERT_TRUE (pt.execution_failed_p ());
+     ASSERT_STREQ (pt.get_diagnostic_text (),
+ 		  "PROGNAME: error: `-fOPTION=foo:=':"
+ 		  " expected KEY=VALUE-style parameter for format `foo'"
+ 		  " after `:';"
+ 		  " got `='\n");
+   }
+ 
+   /* No value for key.  */
+   {
+     parser_test pt;
+     auto result = pt.parse ("foo:key,");
+     ASSERT_EQ (result, nullptr);
+     ASSERT_TRUE (pt.execution_failed_p ());
+     ASSERT_STREQ (pt.get_diagnostic_text (),
+ 		  "PROGNAME: error: `-fOPTION=foo:key,':"
+ 		  " expected KEY=VALUE-style parameter for format `foo'"
+ 		  " after `:';"
+ 		  " got `key,'\n");
+   }
+ 
+   /* Correct example, with one key/value pair.  */
+   {
+     parser_test pt;
+     auto result = pt.parse ("foo:key=value");
+     ASSERT_EQ (result->m_scheme_name, "foo");
+     ASSERT_EQ (result->m_kvs.size (), 1);
+     ASSERT_EQ (result->m_kvs[0].first, "key");
+     ASSERT_EQ (result->m_kvs[0].second, "value");
+     ASSERT_FALSE (pt.execution_failed_p ());
+   }
+ 
+   /* Stray trailing comma.  */
+   {
+     parser_test pt;
+     auto result = pt.parse ("foo:key=value,");
+     ASSERT_EQ (result, nullptr);
+     ASSERT_TRUE (pt.execution_failed_p ());
+     ASSERT_STREQ (pt.get_diagnostic_text (),
+ 		  "PROGNAME: error: `-fOPTION=foo:key=value,':"
+ 		  " expected KEY=VALUE-style parameter for format `foo'"
+ 		  " after `,';"
+ 		  " got `'\n");
+   }
+ 
+   /* Correct example, with two key/value pairs.  */
+   {
+     parser_test pt;
+     auto result = pt.parse ("foo:color=red,shape=circle");
+     ASSERT_EQ (result->m_scheme_name, "foo");
+     ASSERT_EQ (result->m_kvs.size (), 2);
+     ASSERT_EQ (result->m_kvs[0].first, "color");
+     ASSERT_EQ (result->m_kvs[0].second, "red");
+     ASSERT_EQ (result->m_kvs[1].first, "shape");
+     ASSERT_EQ (result->m_kvs[1].second, "circle");
+     ASSERT_FALSE (pt.execution_failed_p ());
+   }
+ }
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ output_spec_cc_tests ()
+ {
+   test_output_arg_parsing ();
+ }
+ 
+ } // namespace diagnostics::selftest
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/output-spec.h gcc-16-20250727/gcc/diagnostics/output-spec.h
*** gcc-16-20250720/gcc/diagnostics/output-spec.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/output-spec.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,118 ----
+ /* Support for the DSL of -fdiagnostics-add-output= and
+    -fdiagnostics-set-output=.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_OUTPUT_SPEC_H
+ #define GCC_DIAGNOSTICS_OUTPUT_SPEC_H
+ 
+ #include "diagnostics/sink.h"
+ #include "diagnostics/output-file.h"
+ 
+ namespace diagnostics {
+ namespace output_spec {
+ 
+ /* An abstract base class for handling the DSL of -fdiagnostics-add-output=
+    and -fdiagnostics-set-output=.  */
+ 
+ class context
+ {
+  public:
+   std::unique_ptr<sink>
+   parse_and_make_sink (const char *,
+ 		       diagnostics::context &dc);
+ 
+   void
+   report_error (const char *gmsgid, ...) const
+     ATTRIBUTE_GCC_DIAG(2,3);
+ 
+   void
+   report_unknown_key (const char *unparsed_arg,
+ 		      const std::string &key,
+ 		      const std::string &scheme_name,
+ 		      auto_vec<const char *> &known_keys) const;
+ 
+   void
+   report_missing_key (const char *unparsed_arg,
+ 		      const std::string &key,
+ 		      const std::string &scheme_name,
+ 		      const char *metavar) const;
+ 
+   output_file
+   open_output_file (label_text &&filename) const;
+ 
+   const char *
+   get_option_name () const { return m_option_name; }
+ 
+   line_maps *
+   get_affected_location_mgr () const { return m_affected_location_mgr; }
+ 
+   virtual ~context () {}
+ 
+   virtual void
+   report_error_va (const char *gmsgid, va_list *ap) const = 0;
+ 
+   virtual const char *
+   get_base_filename () const = 0;
+ 
+ protected:
+   context (const char *option_name,
+ 	   line_maps *affected_location_mgr)
+   : m_option_name (option_name),
+     m_affected_location_mgr (affected_location_mgr)
+   {
+   }
+ 
+   const char *m_option_name;
+   line_maps *m_affected_location_mgr;
+ };
+ 
+ /* A subclass that implements reporting errors via a diagnostics::context.  */
+ 
+ struct dc_spec_context : public output_spec::context
+ {
+ public:
+   dc_spec_context (diagnostics::context &dc,
+ 		   line_maps *affected_location_mgr,
+ 		   line_maps *control_location_mgr,
+ 		   location_t loc,
+ 		   const char *option_name)
+   : context (option_name, affected_location_mgr),
+     m_dc (dc),
+     m_control_location_mgr (control_location_mgr),
+     m_loc (loc)
+   {}
+ 
+   void report_error_va (const char *gmsgid, va_list *ap) const final override
+     ATTRIBUTE_GCC_DIAG(2, 0)
+   {
+     m_dc.begin_group ();
+     rich_location richloc (m_control_location_mgr, m_loc);
+     m_dc.diagnostic_impl (&richloc, nullptr, -1, gmsgid, ap, kind::error);
+     m_dc.end_group ();
+   }
+ 
+   diagnostics::context &m_dc;
+   line_maps *m_control_location_mgr;
+   location_t m_loc;
+ };
+ 
+ } // namespace output_spec
+ } // namespace diagnostics
+ 
+ #endif // #ifndef GCC_DIAGNOSTICS_OUTPUT_SPEC_H
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/paths-output.cc gcc-16-20250727/gcc/diagnostics/paths-output.cc
*** gcc-16-20250720/gcc/diagnostics/paths-output.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/paths-output.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,2742 ----
+ /* Printing paths through the code associated with a diagnostic.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #define INCLUDE_ALGORITHM
+ #define INCLUDE_MAP
+ #define INCLUDE_STRING
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "diagnostic.h"
+ #include "diagnostics/macro-unwinding.h"
+ #include "intl.h"
+ #include "diagnostics/paths.h"
+ #include "gcc-rich-location.h"
+ #include "diagnostics/color.h"
+ #include "diagnostics/event-id.h"
+ #include "diagnostics/source-printing-effects.h"
+ #include "pretty-print-markup.h"
+ #include "selftest.h"
+ #include "diagnostics/selftest-context.h"
+ #include "diagnostics/selftest-paths.h"
+ #include "text-art/theme.h"
+ #include "diagnostics/text-sink.h"
+ #include "diagnostics/html-sink.h"
+ #include "xml.h"
+ #include "xml-printer.h"
+ 
+ /* Disable warnings about missing quoting in GCC diagnostics for the print
+    calls below.  */
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic push
+ #  pragma GCC diagnostic ignored "-Wformat-diag"
+ #endif
+ 
+ /* Anonymous namespace for path-printing code.  */
+ 
+ namespace {
+ 
+ using namespace diagnostics;
+ using namespace diagnostics::paths;
+ 
+ /* A bundle of state for printing a path.  */
+ 
+ class path_print_policy
+ {
+ public:
+   path_print_policy (const diagnostics::text_sink &text_output)
+   : m_source_policy (text_output.get_context ())
+   {
+   }
+ 
+   path_print_policy (const diagnostics::context &dc)
+   : m_source_policy (dc)
+   {
+   }
+ 
+   text_art::theme *
+   get_diagram_theme () const
+   {
+     return m_source_policy.get_diagram_theme ();
+   }
+ 
+   const diagnostics::source_print_policy &
+   get_source_policy () const { return m_source_policy; }
+ 
+ private:
+   diagnostics::source_print_policy m_source_policy;
+ };
+ 
+ /* Subclass of range_label for showing a particular event
+    when showing a consecutive run of events within a diagnostic path as
+    labelled ranges within one gcc_rich_location.  */
+ 
+ class path_label : public range_label
+ {
+  public:
+   path_label (const path &path_,
+ 	      const pretty_printer &ref_pp,
+ 	      unsigned start_idx,
+ 	      bool colorize,
+ 	      bool allow_emojis)
+   : m_path (path_),
+     m_ref_pp (ref_pp),
+     m_start_idx (start_idx), m_effects (*this),
+     m_colorize (colorize), m_allow_emojis (allow_emojis)
+   {}
+ 
+   label_text get_text (unsigned range_idx) const final override
+   {
+     unsigned event_idx = m_start_idx + range_idx;
+     const event &ev = m_path.get_event (event_idx);
+ 
+     const event::meaning meaning (ev.get_meaning ());
+ 
+     auto pp = m_ref_pp.clone ();
+     pp_show_color (pp.get ()) = m_colorize;
+     event_id_t event_id (event_idx);
+     pp_printf (pp.get (), "%@", &event_id);
+     pp_space (pp.get ());
+ 
+     if (meaning.m_verb == event::verb::danger
+ 	&& m_allow_emojis)
+       {
+ 	pp_unicode_character (pp.get (), 0x26A0); /* U+26A0 WARNING SIGN.  */
+ 	/* Append U+FE0F VARIATION SELECTOR-16 to select the emoji
+ 	   variation of the char.  */
+ 	pp_unicode_character (pp.get (), 0xFE0F);
+ 	/* U+26A0 WARNING SIGN has East_Asian_Width == Neutral, but in its
+ 	   emoji variant is printed (by vte at least) with a 2nd half
+ 	   overlapping the next char.  Hence we add two spaces here: a space
+ 	   to be covered by this overlap, plus another space of padding.  */
+ 	pp_string (pp.get (), "  ");
+       }
+ 
+     ev.print_desc (*pp.get ());
+ 
+     label_text result
+       = label_text::take (xstrdup (pp_formatted_text (pp.get ())));
+     return result;
+   }
+ 
+   const diagnostics::label_effects *
+   get_effects (unsigned /*range_idx*/) const final override
+   {
+     return &m_effects;
+   }
+ 
+  private:
+   class path_label_effects : public label_effects
+   {
+   public:
+     path_label_effects (const path_label &path_label)
+     : m_path_label (path_label)
+     {
+     }
+     bool has_in_edge (unsigned range_idx) const final override
+     {
+       if (const event *prev_event
+ 	    = m_path_label.get_prev_event (range_idx))
+ 	return prev_event->connect_to_next_event_p ();
+       return false;
+     }
+     bool has_out_edge (unsigned range_idx) const final override
+     {
+       const event &ev = m_path_label.get_event (range_idx);
+       return ev.connect_to_next_event_p ();
+     }
+ 
+   private:
+     const path_label &m_path_label;
+   };
+ 
+   const event &get_event (unsigned range_idx) const
+   {
+     unsigned event_idx = m_start_idx + range_idx;
+     return m_path.get_event (event_idx);
+   }
+ 
+   const event *get_prev_event (unsigned range_idx) const
+   {
+     if (m_start_idx + range_idx == 0)
+       return nullptr;
+     unsigned event_idx = m_start_idx + range_idx - 1;
+     return &m_path.get_event (event_idx);
+   }
+ 
+   const path &m_path;
+   const pretty_printer &m_ref_pp;
+   unsigned m_start_idx;
+   path_label_effects m_effects;
+   const bool m_colorize;
+   const bool m_allow_emojis;
+ };
+ 
+ /* Return true if E1 and E2 can be consolidated into the same run of events
+    when printing a diagnostic path.  */
+ 
+ static bool
+ can_consolidate_events (const path &p,
+ 			const event &e1,
+ 			unsigned ev1_idx,
+ 			const event &e2,
+ 			unsigned ev2_idx,
+ 			bool check_locations)
+ {
+   if (e1.get_thread_id () != e2.get_thread_id ())
+     return false;
+ 
+   if (!p.same_function_p (ev1_idx, ev2_idx))
+     return false;
+ 
+   if (e1.get_stack_depth () != e2.get_stack_depth ())
+     return false;
+ 
+   if (check_locations)
+     {
+       location_t loc1 = e1.get_location ();
+       location_t loc2 = e2.get_location ();
+ 
+       if (loc1 < RESERVED_LOCATION_COUNT
+ 	  || loc2 < RESERVED_LOCATION_COUNT)
+ 	return false;
+ 
+       /* Neither can be macro-based.  */
+       if (linemap_location_from_macro_expansion_p (line_table, loc1))
+ 	return false;
+       if (linemap_location_from_macro_expansion_p (line_table, loc2))
+ 	return false;
+     }
+ 
+   /* Passed all the tests.  */
+   return true;
+ }
+ 
+ struct event_range;
+ struct path_summary;
+ class thread_event_printer;
+ 
+ /* A bundle of information about all of the events in a diagnostic path
+    relating to a specific path, for use by path_summary.  */
+ 
+ class per_thread_summary
+ {
+ public:
+   per_thread_summary (const path &path_,
+ 		      const logical_locations::manager &logical_loc_mgr,
+ 		      label_text name, unsigned swimlane_idx)
+   : m_path (path_),
+     m_logical_loc_mgr (logical_loc_mgr),
+     m_name (std::move (name)),
+     m_swimlane_idx (swimlane_idx),
+     m_last_event (nullptr),
+     m_min_depth (INT_MAX),
+     m_max_depth (INT_MIN)
+   {}
+ 
+   void update_depth_limits (int stack_depth)
+   {
+     if (stack_depth < m_min_depth)
+       m_min_depth = stack_depth;
+     if (stack_depth > m_max_depth)
+       m_max_depth = stack_depth;
+   }
+ 
+   const char *get_name () const { return m_name.get (); }
+   unsigned get_swimlane_index () const { return m_swimlane_idx; }
+ 
+   bool interprocedural_p () const;
+ 
+ private:
+   friend struct path_summary;
+   friend class thread_event_printer;
+   friend struct event_range;
+ 
+   const path &m_path;
+   const logical_locations::manager &m_logical_loc_mgr;
+ 
+   const label_text m_name;
+ 
+   /* The "swimlane index" is the order in which this per_thread_summary
+      was created, for use when printing the events.  */
+   const unsigned m_swimlane_idx;
+ 
+   // The event ranges specific to this thread:
+   auto_vec<event_range *> m_event_ranges;
+ 
+   const event *m_last_event;
+ 
+   int m_min_depth;
+   int m_max_depth;
+ };
+ 
+ /* A stack frame for use in HTML output, holding child stack frames,
+    and event ranges. */
+ 
+ struct stack_frame
+ {
+   stack_frame (std::unique_ptr<stack_frame> parent,
+ 	       logical_locations::key logical_loc,
+ 	       int stack_depth)
+   : m_parent (std::move (parent)),
+     m_logical_loc (logical_loc),
+     m_stack_depth (stack_depth)
+   {}
+ 
+   std::unique_ptr<stack_frame> m_parent;
+   logical_locations::key m_logical_loc;
+   const int m_stack_depth;
+ };
+ 
+ /* Begin emitting content relating to a new stack frame within PARENT.
+    Allocated a new stack_frame and return it.  */
+ 
+ static std::unique_ptr<stack_frame>
+ begin_html_stack_frame (xml::printer &xp,
+ 			std::unique_ptr<stack_frame> parent,
+ 			logical_locations::key logical_loc,
+ 			int stack_depth,
+ 			const logical_locations::manager *logical_loc_mgr)
+ {
+   if (logical_loc)
+     {
+       gcc_assert (logical_loc_mgr);
+       xp.push_tag_with_class ("table", "stack-frame-with-margin", false);
+       xp.push_tag ("tr", false);
+       {
+ 	xp.push_tag_with_class ("td", "interprocmargin", false);
+ 	xp.set_attr ("style", "padding-left: 100px");
+ 	xp.pop_tag ("td");
+       }
+       xp.push_tag_with_class ("td", "stack-frame", false);
+       label_text funcname
+ 	= logical_loc_mgr->get_name_for_path_output (logical_loc);
+       if (funcname.get ())
+ 	{
+ 	  xp.push_tag_with_class ("div", "frame-funcname", false);
+ 	  xp.push_tag ("span", true);
+ 	  xp.add_text (funcname.get ());
+ 	  xp.pop_tag ("span");
+ 	  xp.pop_tag ("div");
+ 	}
+     }
+   return std::make_unique<stack_frame> (std::move (parent),
+ 					logical_loc,
+ 					stack_depth);
+ }
+ 
+ /* Finish emitting content for FRAME and delete it.
+    Return parent.  */
+ 
+ static std::unique_ptr<stack_frame>
+ end_html_stack_frame (xml::printer &xp,
+ 		      std::unique_ptr<stack_frame> frame)
+ {
+   auto parent = std::move (frame->m_parent);
+   if (frame->m_logical_loc)
+     {
+       xp.pop_tag ("td");
+       xp.pop_tag ("tr");
+       xp.pop_tag ("table");
+     }
+   return parent;
+ }
+ 
+ /* Append an HTML <div> element to XP containing an SVG arrow representing
+    a change in stack depth from OLD_DEPTH to NEW_DEPTH.  */
+ 
+ static void
+ emit_svg_arrow (xml::printer &xp, int old_depth, int new_depth)
+ {
+   const int pixels_per_depth = 100;
+   const int min_depth = MIN (old_depth, new_depth);
+   const int base_x = 20;
+   const int excess = 30;
+   const int last_x
+     = base_x + (old_depth - min_depth) * pixels_per_depth;
+   const int this_x
+     = base_x + (new_depth - min_depth) * pixels_per_depth;
+   pretty_printer tmp_pp;
+   pretty_printer *pp = &tmp_pp;
+   pp_printf (pp, "<div class=\"%s\">\n",
+ 	     old_depth < new_depth
+ 	     ? "between-ranges-call" : "between-ranges-return");
+   pp_printf (pp, "  <svg height=\"30\" width=\"%i\">\n",
+ 	     MAX (last_x, this_x) + excess);
+   pp_string
+     (pp,
+      "    <defs>\n"
+      "      <marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"7\"\n"
+      "              refX=\"0\" refY=\"3.5\" orient=\"auto\" stroke=\"#0088ce\" fill=\"#0088ce\">\n"
+      "      <polygon points=\"0 0, 10 3.5, 0 7\"/>\n"
+      "      </marker>\n"
+      "    </defs>\n");
+   pp_printf (pp,
+ 	     "    <polyline points=\"%i,0 %i,10 %i,10 %i,20\"\n",
+ 	     last_x, last_x, this_x, this_x);
+   pp_string
+     (pp,
+      "              style=\"fill:none;stroke: #0088ce\"\n"
+      "              marker-end=\"url(#arrowhead)\"/>\n"
+      "  </svg>\n"
+      "</div>\n\n");
+   xp.add_raw (pp_formatted_text (pp));
+ }
+ 
+ /* A range of consecutive events within a diagnostic path, all within the
+    same thread, and with the same fndecl and stack_depth, and which are suitable
+    to print with a single call to diagnostic_show_locus.  */
+ struct event_range
+ {
+   /* A struct for tracking the mergability of labels on a particular
+      source line.  In particular, track information about links between
+      labels to ensure that we only consolidate events involving links
+      that the source-printing code is able to handle (splitting them
+      otherwise).  */
+   struct per_source_line_info
+   {
+     void init (int line)
+     {
+       m_line = line;
+       m_has_in_edge = false;
+       m_has_out_edge = false;
+       m_min_label_source_column = INT_MAX;
+       m_max_label_source_column = INT_MIN;
+     }
+ 
+     /* Return true if our source-printing/labelling/linking code can handle
+        the events already on this source line, *and* a new event at COLUMN.  */
+     bool
+     can_add_label_for_event_p (bool has_in_edge,
+ 			       const event *prev_event,
+ 			       bool has_out_edge,
+ 			       int column) const
+     {
+       /* Any existing in-edge has to be the left-most label on its
+ 	 source line.  */
+       if (m_has_in_edge && column < m_min_label_source_column)
+ 	return false;
+       /* Any existing out-edge has to be the right-most label on its
+ 	 source line.  */
+       if (m_has_out_edge && column > m_max_label_source_column)
+ 	return false;
+       /* Can't have more than one in-edge.  */
+       if (m_has_in_edge && has_in_edge)
+ 	return false;
+       /* Can't have more than one out-edge.  */
+       if (m_has_out_edge && has_out_edge)
+ 	return false;
+ 
+       if (has_in_edge)
+ 	{
+ 	  /* Any new in-edge needs to be the left-most label on its
+ 	     source line.  */
+ 	  if (column > m_min_label_source_column)
+ 	    return false;
+ 
+ 	  gcc_assert (prev_event);
+ 	  const location_t prev_loc = prev_event->get_location ();
+ 	  expanded_location prev_exploc
+ 	    = linemap_client_expand_location_to_spelling_point
+ 		(line_table, prev_loc, LOCATION_ASPECT_CARET);
+ 	  /* The destination in-edge's line number has to be <= the
+ 	     source out-edge's line number (if any).  */
+ 	  if (prev_exploc.line >= m_line)
+ 	    return false;
+ 	}
+ 
+       /* Any new out-edge needs to be the right-most label on its
+ 	 source line.  */
+       if (has_out_edge)
+ 	if (column < m_max_label_source_column)
+ 	  return false;
+ 
+       /* All checks passed; we can add the new event at COLUMN.  */
+       return true;
+     }
+ 
+     void
+     add_label_for_event (bool has_in_edge, bool has_out_edge, int column)
+     {
+       if (has_in_edge)
+ 	m_has_in_edge = true;
+       if (has_out_edge)
+ 	m_has_out_edge = true;
+       m_min_label_source_column = std::min (m_min_label_source_column, column);
+       m_max_label_source_column = std::max (m_max_label_source_column, column);
+     }
+ 
+     int m_line;
+     bool m_has_in_edge;
+     bool m_has_out_edge;
+     int m_min_label_source_column;
+     int m_max_label_source_column;
+   };
+ 
+   event_range (const path &path_,
+ 	       const pretty_printer &ref_pp,
+ 	       unsigned start_idx,
+ 	       const event &initial_event,
+ 	       per_thread_summary &t,
+ 	       bool show_event_links,
+ 	       bool colorize_labels,
+ 	       bool allow_emojis)
+   : m_path (path_),
+     m_initial_event (initial_event),
+     m_logical_loc (initial_event.get_logical_location ()),
+     m_stack_depth (initial_event.get_stack_depth ()),
+     m_start_idx (start_idx), m_end_idx (start_idx),
+     m_path_label (path_, ref_pp,
+ 		  start_idx, colorize_labels, allow_emojis),
+     m_richloc (initial_event.get_location (), &m_path_label, nullptr),
+     m_thread_id (initial_event.get_thread_id ()),
+     m_per_thread_summary (t),
+     m_show_event_links (show_event_links)
+   {
+     if (m_show_event_links)
+       {
+ 	expanded_location exploc
+ 	  = linemap_client_expand_location_to_spelling_point
+ 	  (line_table, initial_event.get_location (), LOCATION_ASPECT_CARET);
+ 	per_source_line_info &source_line_info
+ 	  = get_per_source_line_info (exploc.line);
+ 
+ 	const event *prev_thread_event = t.m_last_event;
+ 	const bool has_in_edge
+ 	  = (prev_thread_event
+ 	     ? prev_thread_event->connect_to_next_event_p ()
+ 	     : false);
+ 	const bool has_out_edge = initial_event.connect_to_next_event_p ();
+ 
+ 	source_line_info.add_label_for_event
+ 	  (has_in_edge, has_out_edge, exploc.column);
+       }
+   }
+ 
+   per_source_line_info &
+   get_per_source_line_info (int source_line)
+   {
+     bool existed = false;
+     per_source_line_info &result
+       = m_source_line_info_map.get_or_insert (source_line, &existed);
+     if (!existed)
+       result.init (source_line);
+     return result;
+   }
+ 
+   bool maybe_add_event (const path_print_policy &policy,
+ 			const event &new_ev,
+ 			unsigned new_ev_idx,
+ 			bool check_rich_locations)
+   {
+     if (!can_consolidate_events (m_path,
+ 				 m_initial_event, m_start_idx,
+ 				 new_ev, new_ev_idx,
+ 				 check_rich_locations))
+       return false;
+ 
+     /* Verify compatibility of the new label and existing labels
+        with respect to the link-printing code.  */
+     expanded_location exploc
+       = linemap_client_expand_location_to_spelling_point
+       (line_table, new_ev.get_location (), LOCATION_ASPECT_CARET);
+     per_source_line_info &source_line_info
+       = get_per_source_line_info (exploc.line);
+     const event *prev_event = nullptr;
+     if (new_ev_idx > 0)
+       prev_event = &m_path.get_event (new_ev_idx - 1);
+     const bool has_in_edge = (prev_event
+ 			      ? prev_event->connect_to_next_event_p ()
+ 			      : false);
+     const bool has_out_edge = new_ev.connect_to_next_event_p ();
+     if (m_show_event_links)
+       if (!source_line_info.can_add_label_for_event_p
+ 	  (has_in_edge, prev_event,
+ 	   has_out_edge, exploc.column))
+ 	return false;
+ 
+     /* Potentially verify that the locations are sufficiently close.  */
+     if (check_rich_locations)
+       if (!m_richloc.add_location_if_nearby (policy.get_source_policy (),
+ 					     new_ev.get_location (),
+ 					     false, &m_path_label))
+ 	return false;
+ 
+     m_end_idx = new_ev_idx;
+     m_per_thread_summary.m_last_event = &new_ev;
+ 
+     if (m_show_event_links)
+       source_line_info.add_label_for_event
+ 	(has_in_edge, has_out_edge, exploc.column);
+ 
+     return true;
+   }
+ 
+   /* Print the events in this range to PP, typically as a single
+      call to diagnostic_show_locus.  */
+ 
+   void print_as_text (pretty_printer &pp,
+ 		      diagnostics::text_sink &text_output,
+ 		      diagnostics::source_effect_info *effect_info)
+   {
+     location_t initial_loc = m_initial_event.get_location ();
+ 
+     diagnostics::context &dc = text_output.get_context ();
+ 
+     /* Emit a span indicating the filename (and line/column) if the
+        line has changed relative to the last call to
+        diagnostic_show_locus.  */
+     if (dc.get_source_printing_options ().enabled)
+       {
+ 	expanded_location exploc
+ 	  = linemap_client_expand_location_to_spelling_point
+ 	  (line_table, initial_loc, LOCATION_ASPECT_CARET);
+ 	if (exploc.file != LOCATION_FILE (dc.m_last_location))
+ 	  {
+ 	    diagnostics::location_print_policy loc_policy (text_output);
+ 	    loc_policy.print_text_span_start (dc, pp, exploc);
+ 	  }
+       }
+ 
+     /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
+        primary location for an event, diagnostic_show_locus won't print
+        anything.
+ 
+        In particular the label for the event won't get printed.
+        Fail more gracefully in this case by showing the event
+        index and text, at no particular location.  */
+     if (get_pure_location (initial_loc) <= BUILTINS_LOCATION)
+       {
+ 	for (unsigned i = m_start_idx; i <= m_end_idx; i++)
+ 	  {
+ 	    const event &iter_event = m_path.get_event (i);
+ 	    diagnostic_event_id_t event_id (i);
+ 	    pp_printf (&pp, " %@: ", &event_id);
+ 	    iter_event.print_desc (pp);
+ 	    pp_newline (&pp);
+ 	  }
+ 	return;
+       }
+ 
+     /* Call diagnostic_show_locus to show the events using labels.  */
+     diagnostic_show_locus (&dc, text_output.get_source_printing_options (),
+ 			   &m_richloc, diagnostics::kind::path, &pp,
+ 			   effect_info);
+ 
+     /* If we have a macro expansion, show the expansion to the user.  */
+     if (linemap_location_from_macro_expansion_p (line_table, initial_loc))
+       {
+ 	gcc_assert (m_start_idx == m_end_idx);
+ 	maybe_unwind_expanded_macro_loc (text_output, initial_loc);
+       }
+   }
+ 
+   /* Print the events in this range to XP, typically as a single
+      call to diagnostic_show_locus_as_html.  */
+ 
+   void print_as_html (xml::printer &xp,
+ 		      diagnostics::context &dc,
+ 		      diagnostics::source_effect_info *effect_info,
+ 		      html_label_writer *event_label_writer)
+   {
+     location_t initial_loc = m_initial_event.get_location ();
+ 
+     /* Emit a span indicating the filename (and line/column) if the
+        line has changed relative to the last call to
+        diagnostic_show_locus.  */
+     if (dc.get_source_printing_options ().enabled)
+       {
+ 	expanded_location exploc
+ 	  = linemap_client_expand_location_to_spelling_point
+ 	  (line_table, initial_loc, LOCATION_ASPECT_CARET);
+ 	if (exploc.file != LOCATION_FILE (dc.m_last_location))
+ 	  {
+ 	    diagnostics::location_print_policy loc_policy (dc);
+ 	    loc_policy.print_html_span_start (dc, xp, exploc);
+ 	  }
+       }
+ 
+     /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
+        primary location for an event, diagnostic_show_locus_as_html won't print
+        anything.
+ 
+        In particular the label for the event won't get printed.
+        Fail more gracefully in this case by showing the event
+        index and text, at no particular location.  */
+     if (get_pure_location (initial_loc) <= BUILTINS_LOCATION)
+       {
+ 	for (unsigned i = m_start_idx; i <= m_end_idx; i++)
+ 	  {
+ 	    const event &iter_event = m_path.get_event (i);
+ 	    diagnostic_event_id_t event_id (i);
+ 	    pretty_printer pp;
+ 	    pp_printf (&pp, " %@: ", &event_id);
+ 	    iter_event.print_desc (pp);
+ 	    if (event_label_writer)
+ 	      event_label_writer->begin_label ();
+ 	    xp.add_text_from_pp (pp);
+ 	    if (event_label_writer)
+ 	      event_label_writer->end_label ();
+ 	  }
+ 	return;
+       }
+ 
+     /* Call diagnostic_show_locus_as_html to show the source,
+        showing events using labels.  */
+     diagnostic_show_locus_as_html (&dc, dc.get_source_printing_options (),
+ 				   &m_richloc, diagnostics::kind::path, xp,
+ 				   effect_info, event_label_writer);
+ 
+     // TODO: show macro expansions
+   }
+ 
+   const path &m_path;
+   const event &m_initial_event;
+   logical_locations::key m_logical_loc;
+   int m_stack_depth;
+   unsigned m_start_idx;
+   unsigned m_end_idx;
+   path_label m_path_label;
+   gcc_rich_location m_richloc;
+   thread_id_t m_thread_id;
+   per_thread_summary &m_per_thread_summary;
+   hash_map<int_hash<int, -1, -2>,
+ 	   per_source_line_info> m_source_line_info_map;
+   bool m_show_event_links;
+ };
+ 
+ /* A struct for grouping together the events in a path into
+    ranges of events, partitioned by thread and by stack frame (i.e. by fndecl
+    and stack depth).  */
+ 
+ struct path_summary
+ {
+   path_summary (const path_print_policy &policy,
+ 		const pretty_printer &ref_pp,
+ 		const path &path_,
+ 		bool check_rich_locations,
+ 		bool colorize = false,
+ 		bool show_event_links = true);
+ 
+   const logical_locations::manager &get_logical_location_manager () const
+   {
+     return m_logical_loc_mgr;
+   }
+   unsigned get_num_ranges () const { return m_ranges.length (); }
+   bool multithreaded_p () const { return m_per_thread_summary.length () > 1; }
+ 
+   const per_thread_summary &get_events_for_thread_id (thread_id_t tid)
+   {
+     per_thread_summary **slot = m_thread_id_to_events.get (tid);
+     gcc_assert (slot);
+     gcc_assert (*slot);
+     return **slot;
+   }
+ 
+   const logical_locations::manager &m_logical_loc_mgr;
+   auto_delete_vec <event_range> m_ranges;
+   auto_delete_vec <per_thread_summary> m_per_thread_summary;
+   hash_map<int_hash<thread_id_t, -1, -2>,
+ 	   per_thread_summary *> m_thread_id_to_events;
+ 
+ private:
+   per_thread_summary &
+   get_or_create_events_for_thread_id (const path &path_,
+ 				      thread_id_t tid)
+   {
+     if (per_thread_summary **slot = m_thread_id_to_events.get (tid))
+       return **slot;
+ 
+     const thread &thread = path_.get_thread (tid);
+     per_thread_summary *pts
+       = new per_thread_summary (path_,
+ 				m_logical_loc_mgr,
+ 				thread.get_name (false),
+ 				m_per_thread_summary.length ());
+     m_thread_id_to_events.put (tid, pts);
+     m_per_thread_summary.safe_push (pts);
+     return *pts;
+   }
+ };
+ 
+ /* Return true iff there is more than one stack frame used by the events
+    of this thread.  */
+ 
+ bool
+ per_thread_summary::interprocedural_p () const
+ {
+   if (m_event_ranges.is_empty ())
+     return false;
+   int first_stack_depth = m_event_ranges[0]->m_stack_depth;
+   for (auto range : m_event_ranges)
+     {
+       if (!m_path.same_function_p (m_event_ranges[0]->m_start_idx,
+ 				   range->m_start_idx))
+ 	  return true;
+       if (range->m_stack_depth != first_stack_depth)
+ 	return true;
+     }
+   return false;
+ }
+ 
+ /* path_summary's ctor.  */
+ 
+ path_summary::path_summary (const path_print_policy &policy,
+ 			    const pretty_printer &ref_pp,
+ 			    const path &path_,
+ 			    bool check_rich_locations,
+ 			    bool colorize,
+ 			    bool show_event_links)
+ : m_logical_loc_mgr (path_.get_logical_location_manager ())
+ {
+   const unsigned num_events = path_.num_events ();
+ 
+   event_range *cur_event_range = nullptr;
+   for (unsigned idx = 0; idx < num_events; idx++)
+     {
+       const event &ev = path_.get_event (idx);
+       const thread_id_t thread_id = ev.get_thread_id ();
+       per_thread_summary &pts
+ 	= get_or_create_events_for_thread_id (path_, thread_id);
+ 
+       pts.update_depth_limits (ev.get_stack_depth ());
+ 
+       if (cur_event_range)
+ 	if (cur_event_range->maybe_add_event (policy,
+ 					      ev,
+ 					      idx, check_rich_locations))
+ 	  continue;
+ 
+       auto theme = policy.get_diagram_theme ();
+       const bool allow_emojis = theme ? theme->emojis_p () : false;
+       cur_event_range = new event_range (path_, ref_pp,
+ 					 idx, ev, pts,
+ 					 show_event_links,
+ 					 colorize,
+ 					 allow_emojis);
+       m_ranges.safe_push (cur_event_range);
+       pts.m_event_ranges.safe_push (cur_event_range);
+       pts.m_last_event = &ev;
+     }
+ }
+ 
+ /* Write SPACES to PP.  */
+ 
+ static void
+ write_indent (pretty_printer *pp, int spaces)
+ {
+   for (int i = 0; i < spaces; i++)
+     pp_space (pp);
+ }
+ 
+ static const int base_indent = 2;
+ static const int per_frame_indent = 2;
+ 
+ /* A bundle of state for printing event_range instances for a particular
+    thread.  */
+ 
+ class thread_event_printer
+ {
+ public:
+   thread_event_printer (const per_thread_summary &t, bool show_depths)
+   : m_per_thread_summary (t),
+     m_show_depths (show_depths),
+     m_cur_indent (base_indent),
+     m_vbar_column_for_depth (),
+     m_num_printed (0)
+   {
+   }
+ 
+   /* Get the previous event_range within this thread, if any.  */
+   const event_range *get_any_prev_range () const
+   {
+     if (m_num_printed > 0)
+       return m_per_thread_summary.m_event_ranges[m_num_printed - 1];
+     else
+       return nullptr;
+   }
+ 
+   /* Get the next event_range within this thread, if any.  */
+   const event_range *get_any_next_range () const
+   {
+     if (m_num_printed < m_per_thread_summary.m_event_ranges.length () - 1)
+       return m_per_thread_summary.m_event_ranges[m_num_printed + 1];
+     else
+       return nullptr;
+   }
+ 
+   void
+   print_swimlane_for_event_range_as_text (diagnostics::text_sink &text_output,
+ 					  pretty_printer *pp,
+ 					  const logical_locations::manager &logical_loc_mgr,
+ 					  event_range *range,
+ 					  diagnostics::source_effect_info *effect_info)
+   {
+     gcc_assert (pp);
+     const char *const line_color = "path";
+     const char *start_line_color
+       = colorize_start (pp_show_color (pp), line_color);
+     const char *end_line_color = colorize_stop (pp_show_color (pp));
+ 
+     text_art::ascii_theme fallback_theme;
+     text_art::theme *theme = text_output.get_diagram_theme ();
+     if (!theme)
+       theme = &fallback_theme;
+ 
+     cppchar_t depth_marker_char = theme->get_cppchar
+       (text_art::theme::cell_kind::INTERPROCEDURAL_DEPTH_MARKER);
+     /* e.g. "|".  */
+ 
+     const bool interprocedural_p = m_per_thread_summary.interprocedural_p ();
+ 
+     write_indent (pp, m_cur_indent);
+     if (const event_range *prev_range = get_any_prev_range ())
+       {
+ 	if (range->m_stack_depth > prev_range->m_stack_depth)
+ 	  {
+ 	    gcc_assert (interprocedural_p);
+ 	    /* Show pushed stack frame(s).  */
+ 	    cppchar_t left = theme->get_cppchar
+ 	      (text_art::theme::cell_kind::INTERPROCEDURAL_PUSH_FRAME_LEFT);
+ 	    cppchar_t middle = theme->get_cppchar
+ 	      (text_art::theme::cell_kind::INTERPROCEDURAL_PUSH_FRAME_MIDDLE);
+ 	    cppchar_t right = theme->get_cppchar
+ 	      (text_art::theme::cell_kind::INTERPROCEDURAL_PUSH_FRAME_RIGHT);
+ 	    /* e.g. "+--> ".  */
+ 	    pp_string (pp, start_line_color);
+ 	    pp_unicode_character (pp, left);
+ 	    pp_unicode_character (pp, middle);
+ 	    pp_unicode_character (pp, middle);
+ 	    pp_unicode_character (pp, right);
+ 	    pp_space (pp);
+ 	    pp_string (pp, end_line_color);
+ 	    m_cur_indent += 5;
+ 	  }
+       }
+     if (range->m_logical_loc)
+       {
+ 	label_text name
+ 	  (logical_loc_mgr.get_name_for_path_output (range->m_logical_loc));
+ 	if (name.get ())
+ 	  pp_printf (pp, "%qs: ", name.get ());
+       }
+     if (range->m_start_idx == range->m_end_idx)
+       pp_printf (pp, "event %i",
+ 		 range->m_start_idx + 1);
+     else
+       pp_printf (pp, "events %i-%i",
+ 		 range->m_start_idx + 1, range->m_end_idx + 1);
+     if (m_show_depths)
+       pp_printf (pp, " (depth %i)", range->m_stack_depth);
+     pp_newline (pp);
+ 
+     /* Print a run of events.  */
+     if (interprocedural_p)
+       {
+ 	write_indent (pp, m_cur_indent + per_frame_indent);
+ 	pp_string (pp, start_line_color);
+ 	pp_unicode_character (pp, depth_marker_char);
+ 	pp_string (pp, end_line_color);
+ 	pp_newline (pp);
+ 
+ 	char *saved_prefix = pp_take_prefix (pp);
+ 	char *prefix;
+ 	{
+ 	  pretty_printer tmp_pp;
+ 	  write_indent (&tmp_pp, m_cur_indent + per_frame_indent);
+ 	  pp_string (&tmp_pp, start_line_color);
+ 	  pp_unicode_character (&tmp_pp, depth_marker_char);
+ 	  pp_string (&tmp_pp, end_line_color);
+ 	  prefix = xstrdup (pp_formatted_text (&tmp_pp));
+ 	}
+ 	pp_set_prefix (pp, prefix);
+ 	pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+ 	range->print_as_text (*pp, text_output, effect_info);
+ 	pp_set_prefix (pp, saved_prefix);
+ 
+ 	write_indent (pp, m_cur_indent + per_frame_indent);
+ 	pp_string (pp, start_line_color);
+ 	pp_unicode_character (pp, depth_marker_char);
+ 	pp_string (pp, end_line_color);
+ 	pp_newline (pp);
+       }
+     else
+       range->print_as_text (*pp, text_output, effect_info);
+ 
+     if (const event_range *next_range = get_any_next_range ())
+       {
+ 	if (range->m_stack_depth > next_range->m_stack_depth)
+ 	  {
+ 	    if (m_vbar_column_for_depth.get (next_range->m_stack_depth))
+ 	      {
+ 		/* Show returning from stack frame(s), by printing
+ 		   something like:
+ 		   "                   |\n"
+ 		   "     <-------------+\n"
+ 		   "     |\n".  */
+ 		gcc_assert (interprocedural_p);
+ 		cppchar_t left = theme->get_cppchar
+ 		  (text_art::theme::cell_kind::INTERPROCEDURAL_POP_FRAMES_LEFT);
+ 		cppchar_t middle = theme->get_cppchar
+ 		  (text_art::theme::cell_kind::INTERPROCEDURAL_POP_FRAMES_MIDDLE);
+ 		cppchar_t right = theme->get_cppchar
+ 		  (text_art::theme::cell_kind::INTERPROCEDURAL_POP_FRAMES_RIGHT);
+ 		int vbar_for_next_frame
+ 		  = *m_vbar_column_for_depth.get (next_range->m_stack_depth);
+ 
+ 		int indent_for_next_frame
+ 		  = vbar_for_next_frame - per_frame_indent;
+ 		write_indent (pp, vbar_for_next_frame);
+ 		pp_string (pp, start_line_color);
+ 		pp_unicode_character (pp, left);
+ 		for (int i = indent_for_next_frame + per_frame_indent;
+ 		     i < m_cur_indent + per_frame_indent - 1; i++)
+ 		  pp_unicode_character (pp, middle);
+ 		pp_unicode_character (pp, right);
+ 		pp_string (pp, end_line_color);
+ 		pp_newline (pp);
+ 		m_cur_indent = indent_for_next_frame;
+ 
+ 		write_indent (pp, vbar_for_next_frame);
+ 		pp_string (pp, start_line_color);
+ 		pp_unicode_character (pp, depth_marker_char);
+ 		pp_string (pp, end_line_color);
+ 		pp_newline (pp);
+ 	      }
+ 	    else
+ 	      {
+ 		/* Handle disjoint paths (e.g. a callback at some later
+ 		   time).  */
+ 		m_cur_indent = base_indent;
+ 	      }
+ 	  }
+ 	else if (range->m_stack_depth < next_range->m_stack_depth)
+ 	  {
+ 	    /* Prepare to show pushed stack frame.  */
+ 	    gcc_assert (interprocedural_p);
+ 	    gcc_assert (range->m_stack_depth != EMPTY);
+ 	    gcc_assert (range->m_stack_depth != DELETED);
+ 	    m_vbar_column_for_depth.put (range->m_stack_depth,
+ 					 m_cur_indent + per_frame_indent);
+ 	    m_cur_indent += per_frame_indent;
+ 	  }
+       }
+ 
+     m_num_printed++;
+   }
+ 
+   void
+   print_swimlane_for_event_range_as_html (diagnostics::context &dc,
+ 					  xml::printer &xp,
+ 					  html_label_writer *event_label_writer,
+ 					  event_range *range,
+ 					  diagnostics::source_effect_info *effect_info)
+   {
+     range->print_as_html (xp, dc, effect_info, event_label_writer);
+     m_num_printed++;
+   }
+ 
+   int get_cur_indent () const { return m_cur_indent; }
+ 
+ private:
+   const per_thread_summary &m_per_thread_summary;
+   bool m_show_depths;
+ 
+   /* Print the ranges.  */
+   int m_cur_indent;
+ 
+   /* Keep track of column numbers of existing '|' characters for
+      stack depths we've already printed.  */
+   static const int EMPTY = -1;
+   static const int DELETED = -2;
+   typedef int_hash <int, EMPTY, DELETED> vbar_hash;
+   hash_map <vbar_hash, int> m_vbar_column_for_depth;
+ 
+   /* How many event ranges within this swimlane have we printed.
+      This is the index of the next event_range to print.  */
+   unsigned  m_num_printed;
+ };
+ 
+ /* Print path_summary PS to TEXT_OUTPUT, giving an overview of the
+    interprocedural calls and returns.
+ 
+    Print the event descriptions in a nested form, printing the event
+    descriptions within calls to diagnostic_show_locus, using labels to
+    show the events:
+ 
+    'foo' (events 1-2)
+      | NN |
+      |    |
+      +--> 'bar' (events 3-4)
+             | NN |
+             |    |
+             +--> 'baz' (events 5-6)
+                    | NN |
+                    |    |
+      <------------ +
+      |
+    'foo' (events 7-8)
+      | NN |
+      |    |
+      +--> 'bar' (events 9-10)
+             | NN |
+             |    |
+             +--> 'baz' (events 11-12)
+                    | NN |
+                    |    |
+ 
+    If SHOW_DEPTHS is true, append " (depth N)" to the header of each run
+    of events.
+ 
+    For events with UNKNOWN_LOCATION, print a summary of each the event.  */
+ 
+ static void
+ print_path_summary_as_text (const path_summary &ps,
+ 			    diagnostics::text_sink &text_output,
+ 			    bool show_depths)
+ {
+   pretty_printer *const pp = text_output.get_printer ();
+ 
+   std::vector<thread_event_printer> thread_event_printers;
+   for (auto t : ps.m_per_thread_summary)
+     thread_event_printers.push_back (thread_event_printer (*t, show_depths));
+ 
+   unsigned i;
+   event_range *range;
+   int last_out_edge_column = -1;
+   FOR_EACH_VEC_ELT (ps.m_ranges, i, range)
+     {
+       const int swimlane_idx
+ 	= range->m_per_thread_summary.get_swimlane_index ();
+       if (ps.multithreaded_p ())
+ 	if (i == 0 || ps.m_ranges[i - 1]->m_thread_id != range->m_thread_id)
+ 	  {
+ 	    if (i > 0)
+ 	      pp_newline (pp);
+ 	    pp_printf (pp, "Thread: %qs",
+ 		       range->m_per_thread_summary.get_name ());
+ 	    pp_newline (pp);
+ 	  }
+       thread_event_printer &tep = thread_event_printers[swimlane_idx];
+       /* Wire up any trailing out-edge from previous range to leading in-edge
+ 	 of this range.  */
+       diagnostics::source_effect_info effect_info;
+       effect_info.m_leading_in_edge_column = last_out_edge_column;
+       tep.print_swimlane_for_event_range_as_text
+ 	(text_output, pp,
+ 	 ps.get_logical_location_manager (),
+ 	 range, &effect_info);
+       last_out_edge_column = effect_info.m_trailing_out_edge_column;
+     }
+ }
+ 
+ /* Print PS as HTML to XP, using DC and, if non-null EVENT_LABEL_WRITER.  */
+ 
+ static void
+ print_path_summary_as_html (const path_summary &ps,
+ 			    diagnostics::context &dc,
+ 			    xml::printer &xp,
+ 			    html_label_writer *event_label_writer,
+ 			    bool show_depths)
+ {
+   std::vector<thread_event_printer> thread_event_printers;
+   for (auto t : ps.m_per_thread_summary)
+     thread_event_printers.push_back (thread_event_printer (*t, show_depths));
+ 
+   const logical_locations::manager *logical_loc_mgr
+     = dc.get_logical_location_manager ();
+ 
+   xp.push_tag_with_class ("div", "event-ranges", false);
+ 
+   /* Group the ranges into stack frames.  */
+   std::unique_ptr<stack_frame> curr_frame;
+   unsigned i;
+   event_range *range;
+   int last_out_edge_column = -1;
+   FOR_EACH_VEC_ELT (ps.m_ranges, i, range)
+     {
+       const int swimlane_idx
+ 	= range->m_per_thread_summary.get_swimlane_index ();
+ 
+       const logical_locations::key this_logical_loc = range->m_logical_loc;
+       const int this_depth = range->m_stack_depth;
+       if (curr_frame)
+ 	{
+ 	  int old_stack_depth = curr_frame->m_stack_depth;
+ 	  if (this_depth > curr_frame->m_stack_depth)
+ 	    {
+ 	      emit_svg_arrow (xp, old_stack_depth, this_depth);
+ 	      curr_frame
+ 		= begin_html_stack_frame (xp,
+ 					  std::move (curr_frame),
+ 					  range->m_logical_loc,
+ 					  range->m_stack_depth,
+ 					  logical_loc_mgr);
+ 	    }
+ 	  else
+ 	    {
+ 	      while (this_depth < curr_frame->m_stack_depth
+ 		     || this_logical_loc != curr_frame->m_logical_loc)
+ 		{
+ 		  curr_frame = end_html_stack_frame (xp, std::move (curr_frame));
+ 		  if (curr_frame == nullptr)
+ 		    {
+ 		      curr_frame
+ 			= begin_html_stack_frame (xp,
+ 						  nullptr,
+ 						  range->m_logical_loc,
+ 						  range->m_stack_depth,
+ 						  logical_loc_mgr);
+ 		      break;
+ 		    }
+ 		}
+ 	      emit_svg_arrow (xp, old_stack_depth, this_depth);
+ 	    }
+ 	}
+       else
+ 	{
+ 	  curr_frame = begin_html_stack_frame (xp,
+ 					       nullptr,
+ 					       range->m_logical_loc,
+ 					       range->m_stack_depth,
+ 					       logical_loc_mgr);
+ 	}
+ 
+       xp.push_tag_with_class ("table", "event-range-with-margin", false);
+       xp.push_tag ("tr", false);
+       xp.push_tag_with_class ("td", "event-range", false);
+       xp.push_tag_with_class ("div", "events-hdr", true);
+       if (range->m_logical_loc)
+ 	{
+ 	  gcc_assert (logical_loc_mgr);
+ 	  label_text funcname
+ 	    = logical_loc_mgr->get_name_for_path_output (range->m_logical_loc);
+ 	  if (funcname.get ())
+ 	    {
+ 	      xp.push_tag_with_class ("span", "funcname", true);
+ 	      xp.add_text (funcname.get ());
+ 	      xp.pop_tag ("span");
+ 	      xp.add_text (": ");
+ 	    }
+ 	}
+       {
+ 	xp.push_tag_with_class ("span", "event-ids", true);
+ 	pretty_printer pp;
+ 	if (range->m_start_idx == range->m_end_idx)
+ 	  pp_printf (&pp, "event %i",
+ 		     range->m_start_idx + 1);
+ 	else
+ 	  pp_printf (&pp, "events %i-%i",
+ 		     range->m_start_idx + 1, range->m_end_idx + 1);
+ 	xp.add_text_from_pp (pp);
+ 	xp.pop_tag ("span");
+       }
+       if (show_depths)
+ 	{
+ 	  xp.add_text (" ");
+ 	  xp.push_tag_with_class ("span", "depth", true);
+ 	  pretty_printer pp;
+ 	  pp_printf (&pp, "(depth %i)", range->m_stack_depth);
+ 	  xp.add_text_from_pp (pp);
+ 	  xp.pop_tag ("span");
+ 	}
+       xp.pop_tag ("div");
+ 
+       /* Print a run of events.  */
+       thread_event_printer &tep = thread_event_printers[swimlane_idx];
+       /* Wire up any trailing out-edge from previous range to leading in-edge
+ 	 of this range.  */
+       diagnostics::source_effect_info effect_info;
+       effect_info.m_leading_in_edge_column = last_out_edge_column;
+       tep.print_swimlane_for_event_range_as_html (dc, xp, event_label_writer,
+ 						  range, &effect_info);
+       last_out_edge_column = effect_info.m_trailing_out_edge_column;
+ 
+       xp.pop_tag ("td");
+       xp.pop_tag ("tr");
+       xp.pop_tag ("table");
+     }
+ 
+   /* Close outstanding frames.  */
+   while (curr_frame)
+     curr_frame = end_html_stack_frame (xp, std::move (curr_frame));
+ 
+   xp.pop_tag ("div");
+ }
+ 
+ } /* end of anonymous namespace for path-printing code.  */
+ 
+ class element_event_desc : public pp_element
+ {
+ public:
+   element_event_desc (const event &event_)
+   : m_event (event_)
+   {
+   }
+ 
+   void add_to_phase_2 (pp_markup::context &ctxt) final override
+   {
+     auto pp = ctxt.m_pp.clone ();
+     m_event.print_desc (*pp.get ());
+     pp_string (&ctxt.m_pp, pp_formatted_text (pp.get ()));
+   }
+ 
+ private:
+   const event &m_event;
+ };
+ 
+ /* Print PATH according to the context's path_format.  */
+ 
+ void
+ diagnostics::text_sink::print_path (const path &path_)
+ {
+   const unsigned num_events = path_.num_events ();
+ 
+   switch (get_context ().get_path_format ())
+     {
+     case DPF_NONE:
+       /* Do nothing.  */
+       return;
+ 
+     case DPF_SEPARATE_EVENTS:
+       {
+ 	/* A note per event.  */
+ 	auto &logical_loc_mgr = path_.get_logical_location_manager ();
+ 	for (unsigned i = 0; i < num_events; i++)
+ 	  {
+ 	    const event &ev = path_.get_event (i);
+ 	    element_event_desc e_event_desc (ev);
+ 	    diagnostic_event_id_t event_id (i);
+ 	    if (get_context ().show_path_depths_p ())
+ 	      {
+ 		int stack_depth = ev.get_stack_depth ();
+ 		/* -fdiagnostics-path-format=separate-events doesn't print
+ 		   fndecl information, so with -fdiagnostics-show-path-depths
+ 		   print the fndecls too, if any.  */
+ 		if (logical_locations::key logical_loc
+ 		      = ev.get_logical_location ())
+ 		  {
+ 		    label_text name
+ 		      (logical_loc_mgr.get_name_for_path_output (logical_loc));
+ 		    inform (ev.get_location (),
+ 			    "%@ %e (fndecl %qs, depth %i)",
+ 			    &event_id, &e_event_desc,
+ 			    name.get (), stack_depth);
+ 		  }
+ 		else
+ 		  inform (ev.get_location (),
+ 			  "%@ %e (depth %i)",
+ 			  &event_id, &e_event_desc,
+ 			  stack_depth);
+ 	      }
+ 	    else
+ 	      inform (ev.get_location (),
+ 		      "%@ %e", &event_id, &e_event_desc);
+ 	  }
+       }
+       break;
+ 
+     case DPF_INLINE_EVENTS:
+       {
+ 	/* Consolidate related events.  */
+ 	path_print_policy policy (*this);
+ 	pretty_printer *const pp = get_printer ();
+ 	const bool check_rich_locations = true;
+ 	const bool colorize = pp_show_color (pp);
+ 	const bool show_event_links = m_source_printing.show_event_links_p;
+ 	path_summary summary (policy,
+ 			      *pp,
+ 			      path_,
+ 			      check_rich_locations,
+ 			      colorize,
+ 			      show_event_links);
+ 	char *saved_prefix = pp_take_prefix (pp);
+ 	pp_set_prefix (pp, nullptr);
+ 	print_path_summary_as_text (summary, *this,
+ 				    get_context ().show_path_depths_p ());
+ 	pp_flush (pp);
+ 	pp_set_prefix (pp, saved_prefix);
+       }
+       break;
+     }
+ }
+ 
+ /* Print PATH_ as HTML to XP, using DC and DSPP for settings.
+    If non-null, use EVENT_LABEL_WRITER when writing events.  */
+ 
+ void
+ diagnostics::print_path_as_html (xml::printer &xp,
+ 				 const path &path_,
+ 				 context &dc,
+ 				 html_label_writer *event_label_writer,
+ 				 const source_print_policy &dspp)
+ {
+   path_print_policy policy (dc);
+   const bool check_rich_locations = true;
+   const bool colorize = false;
+   const source_printing_options &source_printing_opts
+     = dspp.get_options ();
+   const bool show_event_links = source_printing_opts.show_event_links_p;
+   path_summary summary (policy,
+ 			*dc.get_reference_printer (),
+ 			path_,
+ 			check_rich_locations,
+ 			colorize,
+ 			show_event_links);
+   print_path_summary_as_html (summary, dc, xp, event_label_writer,
+ 			      dc.show_path_depths_p ());
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace paths {
+ namespace selftest {
+ 
+ using location = ::selftest::location;
+ using line_table_case = ::selftest::line_table_case;
+ using line_table_test = ::selftest::line_table_test;
+ using temp_source_file = ::selftest::temp_source_file;
+ 
+ using test_context = diagnostics::selftest::test_context;
+ 
+ /* Return true iff all events in PATH_ have locations for which column data
+    is available, so that selftests that require precise string output can
+    bail out for awkward line_table cases.  */
+ 
+ static bool
+ path_events_have_column_data_p (const path &path_)
+ {
+   for (unsigned idx = 0; idx < path_.num_events (); idx++)
+     {
+       location_t event_loc = path_.get_event (idx).get_location ();
+       if (line_table->get_pure_location (event_loc)
+ 	  > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ 	return false;
+       if (line_table->get_start (event_loc) > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ 	return false;
+       if (line_table->get_finish (event_loc) > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ 	return false;
+     }
+   return true;
+ }
+ 
+ /* Verify that empty paths are handled gracefully.  */
+ 
+ static void
+ test_empty_path (pretty_printer *event_pp)
+ {
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   ASSERT_FALSE (path.interprocedural_p ());
+ 
+   test_context dc;
+   text_sink text_output (dc);
+   path_print_policy policy (text_output);
+   path_summary summary (policy, *event_pp, path, false);
+   ASSERT_EQ (summary.get_num_ranges (), 0);
+ 
+   print_path_summary_as_text (summary, text_output, true);
+   ASSERT_STREQ ("",
+ 		pp_formatted_text (text_output.get_printer ()));
+ }
+ 
+ /* Verify that print_path_summary works on a purely intraprocedural path.  */
+ 
+ static void
+ test_intraprocedural_path (pretty_printer *event_pp)
+ {
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   const char *const funcname = "foo";
+   path.add_event (UNKNOWN_LOCATION, funcname, 0, "first %qs", "free");
+   path.add_event (UNKNOWN_LOCATION, funcname, 0, "double %qs", "free");
+ 
+   ASSERT_FALSE (path.interprocedural_p ());
+ 
+   selftest::test_context dc;
+   text_sink text_output (dc);
+   path_print_policy policy (text_output);
+   path_summary summary (policy, *event_pp, path, false, false, false);
+   ASSERT_EQ (summary.get_num_ranges (), 1);
+ 
+   print_path_summary_as_text (summary, text_output, true);
+   ASSERT_STREQ ("  `foo': events 1-2 (depth 0)\n"
+ 		" (1): first `free'\n"
+ 		" (2): double `free'\n",
+ 		pp_formatted_text (text_output.get_printer ()));
+ }
+ 
+ /* Verify that print_path_summary works on an interprocedural path.  */
+ 
+ static void
+ test_interprocedural_path_1 (pretty_printer *event_pp)
+ {
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   path.add_entry ("test", 0);
+   path.add_call ("test", 0, "make_boxed_int");
+   path.add_call ("make_boxed_int", 1, "wrapped_malloc");
+   path.add_event (UNKNOWN_LOCATION,
+ 		  "wrapped_malloc", 2, "calling malloc");
+   path.add_return ("test", 0);
+   path.add_call ("test", 0, "free_boxed_int");
+   path.add_call ("free_boxed_int", 1, "wrapped_free");
+   path.add_event (UNKNOWN_LOCATION, "wrapped_free", 2, "calling free");
+   path.add_return ("test", 0);
+   path.add_call ("test", 0, "free_boxed_int");
+   path.add_call ("free_boxed_int", 1, "wrapped_free");
+   path.add_event (UNKNOWN_LOCATION, "wrapped_free", 2, "calling free");
+   ASSERT_EQ (path.num_events (), 18);
+ 
+   ASSERT_TRUE (path.interprocedural_p ());
+ 
+   {
+     selftest::test_context dc;
+     text_sink text_output (dc, nullptr, false);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, false);
+     ASSERT_EQ (summary.get_num_ranges (), 9);
+ 
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     print_path_summary_as_text (summary, text_output, true);
+     ASSERT_STREQ
+       ("  `test': events 1-2 (depth 0)\n"
+        "    |\n"
+        "    | (1): entering `test'\n"
+        "    | (2): calling `make_boxed_int'\n"
+        "    |\n"
+        "    +--> `make_boxed_int': events 3-4 (depth 1)\n"
+        "           |\n"
+        "           | (3): entering `make_boxed_int'\n"
+        "           | (4): calling `wrapped_malloc'\n"
+        "           |\n"
+        "           +--> `wrapped_malloc': events 5-6 (depth 2)\n"
+        "                  |\n"
+        "                  | (5): entering `wrapped_malloc'\n"
+        "                  | (6): calling malloc\n"
+        "                  |\n"
+        "    <-------------+\n"
+        "    |\n"
+        "  `test': events 7-8 (depth 0)\n"
+        "    |\n"
+        "    | (7): returning to `test'\n"
+        "    | (8): calling `free_boxed_int'\n"
+        "    |\n"
+        "    +--> `free_boxed_int': events 9-10 (depth 1)\n"
+        "           |\n"
+        "           | (9): entering `free_boxed_int'\n"
+        "           | (10): calling `wrapped_free'\n"
+        "           |\n"
+        "           +--> `wrapped_free': events 11-12 (depth 2)\n"
+        "                  |\n"
+        "                  | (11): entering `wrapped_free'\n"
+        "                  | (12): calling free\n"
+        "                  |\n"
+        "    <-------------+\n"
+        "    |\n"
+        "  `test': events 13-14 (depth 0)\n"
+        "    |\n"
+        "    | (13): returning to `test'\n"
+        "    | (14): calling `free_boxed_int'\n"
+        "    |\n"
+        "    +--> `free_boxed_int': events 15-16 (depth 1)\n"
+        "           |\n"
+        "           | (15): entering `free_boxed_int'\n"
+        "           | (16): calling `wrapped_free'\n"
+        "           |\n"
+        "           +--> `wrapped_free': events 17-18 (depth 2)\n"
+        "                  |\n"
+        "                  | (17): entering `wrapped_free'\n"
+        "                  | (18): calling free\n"
+        "                  |\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, false);
+     print_path_summary_as_text (summary, text_output, true);
+     ASSERT_STREQ
+       ("  `test': events 1-2 (depth 0)\n"
+        "    │\n"
+        "    │ (1): entering `test'\n"
+        "    │ (2): calling `make_boxed_int'\n"
+        "    │\n"
+        "    └──> `make_boxed_int': events 3-4 (depth 1)\n"
+        "           │\n"
+        "           │ (3): entering `make_boxed_int'\n"
+        "           │ (4): calling `wrapped_malloc'\n"
+        "           │\n"
+        "           └──> `wrapped_malloc': events 5-6 (depth 2)\n"
+        "                  │\n"
+        "                  │ (5): entering `wrapped_malloc'\n"
+        "                  │ (6): calling malloc\n"
+        "                  │\n"
+        "    <─────────────┘\n"
+        "    │\n"
+        "  `test': events 7-8 (depth 0)\n"
+        "    │\n"
+        "    │ (7): returning to `test'\n"
+        "    │ (8): calling `free_boxed_int'\n"
+        "    │\n"
+        "    └──> `free_boxed_int': events 9-10 (depth 1)\n"
+        "           │\n"
+        "           │ (9): entering `free_boxed_int'\n"
+        "           │ (10): calling `wrapped_free'\n"
+        "           │\n"
+        "           └──> `wrapped_free': events 11-12 (depth 2)\n"
+        "                  │\n"
+        "                  │ (11): entering `wrapped_free'\n"
+        "                  │ (12): calling free\n"
+        "                  │\n"
+        "    <─────────────┘\n"
+        "    │\n"
+        "  `test': events 13-14 (depth 0)\n"
+        "    │\n"
+        "    │ (13): returning to `test'\n"
+        "    │ (14): calling `free_boxed_int'\n"
+        "    │\n"
+        "    └──> `free_boxed_int': events 15-16 (depth 1)\n"
+        "           │\n"
+        "           │ (15): entering `free_boxed_int'\n"
+        "           │ (16): calling `wrapped_free'\n"
+        "           │\n"
+        "           └──> `wrapped_free': events 17-18 (depth 2)\n"
+        "                  │\n"
+        "                  │ (17): entering `wrapped_free'\n"
+        "                  │ (18): calling free\n"
+        "                  │\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+ 
+ }
+ 
+ /* Example where we pop the stack to an intermediate frame, rather than the
+    initial one.  */
+ 
+ static void
+ test_interprocedural_path_2 (pretty_printer *event_pp)
+ {
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   path.add_entry ("foo", 0);
+   path.add_call ("foo", 0, "bar");
+   path.add_call ("bar", 1, "baz");
+   path.add_return ("bar", 1);
+   path.add_call ("bar", 1, "baz");
+   ASSERT_EQ (path.num_events (), 8);
+ 
+   ASSERT_TRUE (path.interprocedural_p ());
+ 
+   {
+     selftest::test_context dc;
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, false);
+     ASSERT_EQ (summary.get_num_ranges (), 5);
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     print_path_summary_as_text (summary, text_output, true);
+     ASSERT_STREQ
+       ("  `foo': events 1-2 (depth 0)\n"
+        "    |\n"
+        "    | (1): entering `foo'\n"
+        "    | (2): calling `bar'\n"
+        "    |\n"
+        "    +--> `bar': events 3-4 (depth 1)\n"
+        "           |\n"
+        "           | (3): entering `bar'\n"
+        "           | (4): calling `baz'\n"
+        "           |\n"
+        "           +--> `baz': event 5 (depth 2)\n"
+        "                  |\n"
+        "                  | (5): entering `baz'\n"
+        "                  |\n"
+        "           <------+\n"
+        "           |\n"
+        "         `bar': events 6-7 (depth 1)\n"
+        "           |\n"
+        "           | (6): returning to `bar'\n"
+        "           | (7): calling `baz'\n"
+        "           |\n"
+        "           +--> `baz': event 8 (depth 2)\n"
+        "                  |\n"
+        "                  | (8): entering `baz'\n"
+        "                  |\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, false);
+     print_path_summary_as_text (summary, text_output, true);
+     ASSERT_STREQ
+       ("  `foo': events 1-2 (depth 0)\n"
+        "    │\n"
+        "    │ (1): entering `foo'\n"
+        "    │ (2): calling `bar'\n"
+        "    │\n"
+        "    └──> `bar': events 3-4 (depth 1)\n"
+        "           │\n"
+        "           │ (3): entering `bar'\n"
+        "           │ (4): calling `baz'\n"
+        "           │\n"
+        "           └──> `baz': event 5 (depth 2)\n"
+        "                  │\n"
+        "                  │ (5): entering `baz'\n"
+        "                  │\n"
+        "           <──────┘\n"
+        "           │\n"
+        "         `bar': events 6-7 (depth 1)\n"
+        "           │\n"
+        "           │ (6): returning to `bar'\n"
+        "           │ (7): calling `baz'\n"
+        "           │\n"
+        "           └──> `baz': event 8 (depth 2)\n"
+        "                  │\n"
+        "                  │ (8): entering `baz'\n"
+        "                  │\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+ }
+ 
+ /* Verify that print_path_summary is sane in the face of a recursive
+    diagnostic path.  */
+ 
+ static void
+ test_recursion (pretty_printer *event_pp)
+ {
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   path.add_entry ("factorial", 0);
+   for (int depth = 0; depth < 3; depth++)
+     path.add_call ("factorial", depth, "factorial");
+   ASSERT_EQ (path.num_events (), 7);
+ 
+   ASSERT_TRUE (path.interprocedural_p ());
+ 
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+ 
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, false);
+     ASSERT_EQ (summary.get_num_ranges (), 4);
+ 
+     print_path_summary_as_text (summary, text_output, true);
+     ASSERT_STREQ
+       ("  `factorial': events 1-2 (depth 0)\n"
+        "    |\n"
+        "    | (1): entering `factorial'\n"
+        "    | (2): calling `factorial'\n"
+        "    |\n"
+        "    +--> `factorial': events 3-4 (depth 1)\n"
+        "           |\n"
+        "           | (3): entering `factorial'\n"
+        "           | (4): calling `factorial'\n"
+        "           |\n"
+        "           +--> `factorial': events 5-6 (depth 2)\n"
+        "                  |\n"
+        "                  | (5): entering `factorial'\n"
+        "                  | (6): calling `factorial'\n"
+        "                  |\n"
+        "                  +--> `factorial': event 7 (depth 3)\n"
+        "                         |\n"
+        "                         | (7): entering `factorial'\n"
+        "                         |\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+ 
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, false);
+     print_path_summary_as_text (summary, text_output, true);
+     ASSERT_STREQ
+       ("  `factorial': events 1-2 (depth 0)\n"
+        "    │\n"
+        "    │ (1): entering `factorial'\n"
+        "    │ (2): calling `factorial'\n"
+        "    │\n"
+        "    └──> `factorial': events 3-4 (depth 1)\n"
+        "           │\n"
+        "           │ (3): entering `factorial'\n"
+        "           │ (4): calling `factorial'\n"
+        "           │\n"
+        "           └──> `factorial': events 5-6 (depth 2)\n"
+        "                  │\n"
+        "                  │ (5): entering `factorial'\n"
+        "                  │ (6): calling `factorial'\n"
+        "                  │\n"
+        "                  └──> `factorial': event 7 (depth 3)\n"
+        "                         │\n"
+        "                         │ (7): entering `factorial'\n"
+        "                         │\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+ }
+ 
+ /* Helper class for writing tests of control flow visualization.  */
+ 
+ class control_flow_test
+ {
+ public:
+   control_flow_test (const selftest::location &loc,
+ 		     const line_table_case &case_,
+ 		     const char *content)
+   : m_tmp_file (loc, ".c", content,
+ 		/* gcc_rich_location::add_location_if_nearby implicitly
+ 		   uses global_dc's file_cache, so we need to evict
+ 		   tmp when we're done.  */
+ 		&global_dc->get_file_cache ()),
+     m_ltt (case_)
+   {
+     m_ord_map
+       = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ 					     m_tmp_file.get_filename (), 0));
+     linemap_line_start (line_table, 1, 100);
+   }
+ 
+   location_t get_line_and_column (int line, int column)
+   {
+     return linemap_position_for_line_and_column (line_table, m_ord_map,
+ 						 line, column);
+   }
+ 
+   location_t get_line_and_columns (int line, int first_column, int last_column)
+   {
+     return get_line_and_columns (line,
+ 				 first_column, first_column, last_column);
+   }
+ 
+   location_t get_line_and_columns (int line,
+ 				   int first_column,
+ 				   int caret_column,
+ 				   int last_column)
+   {
+     return make_location (get_line_and_column (line, caret_column),
+ 			  get_line_and_column (line, first_column),
+ 			  get_line_and_column (line, last_column));
+   }
+ 
+ private:
+   temp_source_file m_tmp_file;
+   line_table_test m_ltt;
+   const line_map_ordinary *m_ord_map;
+ };
+ 
+ /* Example of event edges where all events can go in the same layout,
+    testing the 6 combinations of:
+    - ASCII vs Unicode vs event links off
+    - line numbering on and off.  */
+ 
+ static void
+ test_control_flow_1 (const line_table_case &case_,
+ 		     pretty_printer *event_pp)
+ {
+   /* Create a tempfile and write some text to it.
+      ...000000000111111111122222222223333333333.
+      ...123456789012345678901234567890123456789.  */
+   const char *content
+     = ("int test (int *p)\n" /* line 1.  */
+        "{\n"                 /* line 2.  */
+        "  if (p)\n"          /* line 3.  */
+        "    return 0;\n"     /* line 4.  */
+        "  return *p;\n"      /* line 5.  */
+        "}\n");               /* line 6.  */
+ 
+   control_flow_test t (SELFTEST_LOCATION, case_, content);
+ 
+   const location_t conditional = t.get_line_and_column (3, 7);
+   const location_t cfg_dest = t.get_line_and_column (5, 10);
+ 
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   path.add_event (conditional, nullptr, 0,
+ 		  "following %qs branch (when %qs is NULL)...",
+ 		  "false", "p");
+   path.connect_to_next_event ();
+ 
+   path.add_event (cfg_dest, nullptr, 0,
+ 		  "...to here");
+   path.add_event (cfg_dest, nullptr, 0,
+ 		  "dereference of NULL %qs",
+ 		  "p");
+ 
+   if (!path_events_have_column_data_p (path))
+     return;
+ 
+ 
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     dc.show_event_links (true);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-3\n"
+        "FILENAME:3:7:\n"
+        "   if (p)\n"
+        "       ^\n"
+        "       |\n"
+        "       (1) following `false' branch (when `p' is NULL)... ->-+\n"
+        "                                                             |\n"
+        "FILENAME:5:10:\n"
+        "                                                             |\n"
+        "+------------------------------------------------------------+\n"
+        "|  return *p;\n"
+        "|         ~\n"
+        "|         |\n"
+        "+-------->(2) ...to here\n"
+        "          (3) dereference of NULL `p'\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     dc.show_event_links (false);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-3\n"
+        "FILENAME:3:7:\n"
+        "   if (p)\n"
+        "       ^\n"
+        "       |\n"
+        "       (1) following `false' branch (when `p' is NULL)...\n"
+        "FILENAME:5:10:\n"
+        "   return *p;\n"
+        "          ~\n"
+        "          |\n"
+        "          (2) ...to here\n"
+        "          (3) dereference of NULL `p'\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     dc.show_line_numbers (true);
+     dc.show_event_links (true);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-3\n"
+        "FILENAME:3:7:\n"
+        "    3 |   if (p)\n"
+        "      |       ^\n"
+        "      |       |\n"
+        "      |       (1) following `false' branch (when `p' is NULL)... ->-+\n"
+        "      |                                                             |\n"
+        "      |                                                             |\n"
+        "      |+------------------------------------------------------------+\n"
+        "    4 ||    return 0;\n"
+        "    5 ||  return *p;\n"
+        "      ||         ~\n"
+        "      ||         |\n"
+        "      |+-------->(2) ...to here\n"
+        "      |          (3) dereference of NULL `p'\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     dc.show_line_numbers (true);
+     dc.show_event_links (false);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-3\n"
+        "FILENAME:3:7:\n"
+        "    3 |   if (p)\n"
+        "      |       ^\n"
+        "      |       |\n"
+        "      |       (1) following `false' branch (when `p' is NULL)...\n"
+        "    4 |     return 0;\n"
+        "    5 |   return *p;\n"
+        "      |          ~\n"
+        "      |          |\n"
+        "      |          (2) ...to here\n"
+        "      |          (3) dereference of NULL `p'\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+     dc.show_event_links (true);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-3\n"
+        "FILENAME:3:7:\n"
+        "   if (p)\n"
+        "       ^\n"
+        "       |\n"
+        "       (1) following `false' branch (when `p' is NULL)... ─>─┐\n"
+        "                                                             │\n"
+        "FILENAME:5:10:\n"
+        "                                                             │\n"
+        "┌────────────────────────────────────────────────────────────┘\n"
+        "│  return *p;\n"
+        "│         ~\n"
+        "│         |\n"
+        "└────────>(2) ...to here\n"
+        "          (3) dereference of NULL `p'\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+     dc.show_event_links (true);
+     dc.show_line_numbers (true);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-3\n"
+        "FILENAME:3:7:\n"
+        "    3 |   if (p)\n"
+        "      |       ^\n"
+        "      |       |\n"
+        "      |       (1) following `false' branch (when `p' is NULL)... ─>─┐\n"
+        "      |                                                             │\n"
+        "      |                                                             │\n"
+        "      |┌────────────────────────────────────────────────────────────┘\n"
+        "    4 |│    return 0;\n"
+        "    5 |│  return *p;\n"
+        "      |│         ~\n"
+        "      |│         |\n"
+        "      |└────────>(2) ...to here\n"
+        "      |          (3) dereference of NULL `p'\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+ }
+ 
+ /* Complex example involving a backedge.  */
+ 
+ static void
+ test_control_flow_2 (const line_table_case &case_,
+ 		     pretty_printer *event_pp)
+ {
+   /* Create a tempfile and write some text to it.
+      ...000000000111111111122222222223333333333.
+      ...123456789012345678901234567890123456789.  */
+   const char *content
+     = ("int for_loop_noop_next (struct node *n)\n" /* <--------- line 1.  */
+        "{\n" /* <----------------------------------------------- line 2.  */
+        "  int sum = 0;\n" /* <---------------------------------- line 3.  */
+        "  for (struct node *iter = n; iter; iter->next)\n" /* <- line 4.  */
+        "    sum += n->val;\n" /* <------------------------------ line 5.  */
+        "  return sum;\n" /* <----------------------------------- line 6.  */
+        "}\n");  /* <-------------------------------------------- line 7.  */
+   /* Adapted from infinite-loop-linked-list.c where
+      "iter->next" should be "iter = iter->next".  */
+ 
+   control_flow_test t (SELFTEST_LOCATION, case_, content);
+ 
+   const location_t iter_test = t.get_line_and_columns (4, 31, 34);
+   const location_t loop_body_start = t.get_line_and_columns (5, 12, 17);
+   const location_t loop_body_end = t.get_line_and_columns (5, 5, 9, 17);
+ 
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   path.add_event (iter_test, nullptr, 0, "infinite loop here");
+ 
+   path.add_event (iter_test, nullptr, 0, "looping from here...");
+   path.connect_to_next_event ();
+ 
+   path.add_event (loop_body_start, nullptr, 0, "...to here");
+ 
+   path.add_event (loop_body_end, nullptr, 0, "looping back...");
+   path.connect_to_next_event ();
+ 
+   path.add_event (iter_test, nullptr, 0, "...to here");
+ 
+   if (!path_events_have_column_data_p (path))
+     return;
+ 
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     dc.show_event_links (true);
+     dc.show_line_numbers (true);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-3\n"
+        "FILENAME:4:31:\n"
+        "    4 |   for (struct node *iter = n; iter; iter->next)\n"
+        "      |                               ^~~~\n"
+        "      |                               |\n"
+        "      |                               (1) infinite loop here\n"
+        "      |                               (2) looping from here... ->-+\n"
+        "      |                                                           |\n"
+        "      |                                                           |\n"
+        "      |+----------------------------------------------------------+\n"
+        "    5 ||    sum += n->val;\n"
+        "      ||           ~~~~~~              \n"
+        "      ||           |\n"
+        "      |+---------->(3) ...to here\n"
+        /* We need to start an new event_range here as event (4) is to the
+ 	  left of event (3), and thus (4) would mess up the in-edge to (3).  */
+        "  event 4\n"
+        "    5 |     sum += n->val;\n"
+        "      |     ~~~~^~~~~~~~~\n"
+        "      |         |\n"
+        "      |         (4) looping back... ->-+\n"
+        "      |                                |\n"
+        /* We need to start an new event_range here as event (4) with an
+ 	  out-edge is on a later line (line 5) than its destination event (5),
+ 	  on line 4.  */
+        "  event 5\n"
+        "      |                                |\n"
+        "      |+-------------------------------+\n"
+        "    4 ||  for (struct node *iter = n; iter; iter->next)\n"
+        "      ||                              ^~~~\n"
+        "      ||                              |\n"
+        "      |+----------------------------->(5) ...to here\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+ }
+ 
+ /* Complex example involving a backedge and both an in-edge and out-edge
+    on the same line.  */
+ 
+ static void
+ test_control_flow_3 (const line_table_case &case_,
+ 		     pretty_printer *event_pp)
+ {
+   /* Create a tempfile and write some text to it.
+      ...000000000111111111122222222223333333333.
+      ...123456789012345678901234567890123456789.  */
+   const char *content
+     = ("void test_missing_comparison_in_for_condition_1 (int n)\n"
+        "{\n" /* <------------------------- line 2.  */
+        "  for (int i = 0; n; i++)\n" /* <- line 3.  */
+        "    {\n" /* <--------------------- line 4.  */
+        "    }\n" /* <--------------------- line 5.  */
+        "}\n"); /* <----------------------- line 6.  */
+   /* Adapted from infinite-loop-1.c where the condition should have been
+      "i < n", rather than just "n".  */
+ 
+   control_flow_test t (SELFTEST_LOCATION, case_, content);
+ 
+   const location_t iter_test = t.get_line_and_column (3, 19);
+   const location_t iter_next = t.get_line_and_columns (3, 22, 24);
+ 
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   path.add_event (iter_test, nullptr, 0, "infinite loop here");
+ 
+   path.add_event (iter_test, nullptr, 0, "looping from here...");
+   path.connect_to_next_event ();
+ 
+   path.add_event (iter_next, nullptr, 0, "...to here");
+ 
+   path.add_event (iter_next, nullptr, 0, "looping back...");
+   path.connect_to_next_event ();
+ 
+   path.add_event (iter_test, nullptr, 0, "...to here");
+ 
+   if (!path_events_have_column_data_p (path))
+     return;
+ 
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     dc.show_event_links (true);
+     dc.show_line_numbers (true);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-2\n"
+        "FILENAME:3:19:\n"
+        "    3 |   for (int i = 0; n; i++)\n"
+        "      |                   ^\n"
+        "      |                   |\n"
+        "      |                   (1) infinite loop here\n"
+        "      |                   (2) looping from here... ->-+\n"
+        "      |                                               |\n"
+        "  events 3-4\n"
+        "      |                                               |\n"
+        "      |+----------------------------------------------+\n"
+        "    3 ||  for (int i = 0; n; i++)\n"
+        "      ||                     ^~~\n"
+        "      ||                     |\n"
+        "      |+-------------------->(3) ...to here\n"
+        "      |                      (4) looping back... ->-+\n"
+        "      |                                             |\n"
+        /* We need to start an new event_range here as event (4) with an
+ 	  out-edge is on the same line as its destination event (5), but
+ 	  to the right, which we can't handle as a single event_range. */
+        "  event 5\n"
+        "      |                                             |\n"
+        "      |+--------------------------------------------+\n"
+        "    3 ||  for (int i = 0; n; i++)\n"
+        "      ||                  ^\n"
+        "      ||                  |\n"
+        "      |+----------------->(5) ...to here\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+ }
+ 
+ /* Implementation of ASSERT_CFG_EDGE_PATH_STREQ.  */
+ 
+ static void
+ assert_cfg_edge_path_streq (const location &loc,
+ 			    pretty_printer *event_pp,
+ 			    const location_t src_loc,
+ 			    const location_t dst_loc,
+ 			    const char *expected_str)
+ {
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   path.add_event (src_loc, nullptr, 0, "from here...");
+   path.connect_to_next_event ();
+ 
+   path.add_event (dst_loc, nullptr, 0, "...to here");
+ 
+   if (!path_events_have_column_data_p (path))
+     return;
+ 
+   selftest::test_context dc;
+   dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+   dc.show_event_links (true);
+   dc.show_line_numbers (true);
+   text_sink text_output (dc);
+   path_print_policy policy (text_output);
+   path_summary summary (policy, *event_pp, path, true);
+   print_path_summary_as_text (summary, text_output, false);
+   ASSERT_STREQ_AT (loc, expected_str,
+ 		   pp_formatted_text (text_output.get_printer ()));
+ }
+ 
+ /* Assert that if we make a path with an event with "from here..." at SRC_LOC
+    leading to an event "...to here" at DST_LOC that we print the path
+    as EXPECTED_STR.  */
+ 
+ #define ASSERT_CFG_EDGE_PATH_STREQ(SRC_LOC, DST_LOC, EXPECTED_STR) \
+   assert_cfg_edge_path_streq ((SELFTEST_LOCATION), (event_pp),	   \
+ 			      (SRC_LOC), (DST_LOC), (EXPECTED_STR))
+ 
+ /* Various examples of edge, trying to cover all combinations of:
+    - relative x positive of src label and dst label
+    - relative y position of labels:
+      - on same line
+      - on next line
+      - on line after next
+      - big gap, where src is before dst
+      - big gap, where src is after dst
+    and other awkward cases.  */
+ 
+ static void
+ test_control_flow_4 (const line_table_case &case_,
+ 		     pretty_printer *event_pp)
+ {
+   std::string many_lines;
+   for (int i = 1; i <= 100; i++)
+     /* ............000000000111
+        ............123456789012.  */
+     many_lines += "LHS      RHS\n";
+   control_flow_test t (SELFTEST_LOCATION, case_, many_lines.c_str ());
+ 
+   /* Same line.  */
+   {
+     /* LHS -> RHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (3, 1, 3),
+        t.get_line_and_columns (3, 10, 12),
+        ("  event 1\n"
+ 	"FILENAME:3:1:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      | ^~~\n"
+ 	"      | |\n"
+ 	"      | (1) from here... ->-+\n"
+ 	"      |                     |\n"
+ 	"  event 2\n"
+ 	"      |                     |\n"
+ 	"      |+--------------------+\n"
+ 	"    3 ||LHS      RHS\n"
+ 	"      ||         ^~~\n"
+ 	"      ||         |\n"
+ 	"      |+-------->(2) ...to here\n"));
+ 
+     /*  RHS -> LHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (3, 10, 12),
+        t.get_line_and_columns (3, 1, 3),
+        ("  event 1\n"
+ 	"FILENAME:3:10:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      |          ^~~\n"
+ 	"      |          |\n"
+ 	"      |          (1) from here... ->-+\n"
+ 	"      |                              |\n"
+ 	"  event 2\n"
+ 	"      |                              |\n"
+ 	"      |+-----------------------------+\n"
+ 	"    3 ||LHS      RHS\n"
+ 	"      ||^~~\n"
+ 	"      |||\n"
+ 	"      |+(2) ...to here\n"));
+   }
+ 
+   /* Next line.  */
+   {
+     /* LHS -> RHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (3, 1, 3),
+        t.get_line_and_columns (4, 5, 7),
+        ("  events 1-2\n"
+ 	"FILENAME:3:1:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      | ^~~\n"
+ 	"      | |\n"
+ 	"      | (1) from here... ->-+\n"
+ 	"      |                     |\n"
+ 	"      |                     |\n"
+ 	"      |+--------------------+\n"
+ 	"    4 ||LHS      RHS\n"
+ 	"      ||    ~~~\n"
+ 	"      ||    |\n"
+ 	"      |+--->(2) ...to here\n"));
+ 
+     /*  RHS -> LHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (3, 10, 12),
+        t.get_line_and_columns (4, 1, 3),
+        ("  events 1-2\n"
+ 	"FILENAME:3:10:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      |          ^~~\n"
+ 	"      |          |\n"
+ 	"      |          (1) from here... ->-+\n"
+ 	"      |                              |\n"
+ 	"      |                              |\n"
+ 	"      |+-----------------------------+\n"
+ 	"    4 ||LHS      RHS\n"
+ 	"      ||~~~       \n"
+ 	"      |||\n"
+ 	"      |+(2) ...to here\n"));
+   }
+ 
+   /* Line after next.  */
+   {
+     /* LHS -> RHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (3, 1, 3),
+        t.get_line_and_columns (5, 10, 12),
+        ("  events 1-2\n"
+ 	"FILENAME:3:1:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      | ^~~\n"
+ 	"      | |\n"
+ 	"      | (1) from here... ->-+\n"
+ 	"      |                     |\n"
+ 	"      |                     |\n"
+ 	"      |+--------------------+\n"
+ 	"    4 ||LHS      RHS\n"
+ 	"    5 ||LHS      RHS\n"
+ 	"      ||         ~~~\n"
+ 	"      ||         |\n"
+ 	"      |+-------->(2) ...to here\n"));
+ 
+     /*  RHS -> LHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (3, 10, 12),
+        t.get_line_and_columns (5, 1, 3),
+        ("  events 1-2\n"
+ 	"FILENAME:3:10:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      |          ^~~\n"
+ 	"      |          |\n"
+ 	"      |          (1) from here... ->-+\n"
+ 	"      |                              |\n"
+ 	"      |                              |\n"
+ 	"      |+-----------------------------+\n"
+ 	"    4 ||LHS      RHS\n"
+ 	"    5 ||LHS      RHS\n"
+ 	"      ||~~~       \n"
+ 	"      |||\n"
+ 	"      |+(2) ...to here\n"));
+   }
+ 
+   /* Big gap, increasing line number.  */
+   {
+     /* LHS -> RHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (3, 1, 3),
+        t.get_line_and_columns (97, 10, 12),
+        ("  events 1-2\n"
+ 	"FILENAME:3:1:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      | ^~~\n"
+ 	"      | |\n"
+ 	"      | (1) from here... ->-+\n"
+ 	"      |                     |\n"
+ 	"......\n"
+ 	"      |                     |\n"
+ 	"      |+--------------------+\n"
+ 	"   97 ||LHS      RHS\n"
+ 	"      ||         ~~~\n"
+ 	"      ||         |\n"
+ 	"      |+-------->(2) ...to here\n"));
+ 
+     /*  RHS -> LHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (3, 10, 12),
+        t.get_line_and_columns (97, 1, 3),
+        ("  events 1-2\n"
+ 	"FILENAME:3:10:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      |          ^~~\n"
+ 	"      |          |\n"
+ 	"      |          (1) from here... ->-+\n"
+ 	"      |                              |\n"
+ 	"......\n"
+ 	"      |                              |\n"
+ 	"      |+-----------------------------+\n"
+ 	"   97 ||LHS      RHS\n"
+ 	"      ||~~~       \n"
+ 	"      |||\n"
+ 	"      |+(2) ...to here\n"));
+   }
+ 
+   /* Big gap, decreasing line number.  */
+   {
+     /* LHS -> RHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (97, 1, 3),
+        t.get_line_and_columns (3, 10, 12),
+        ("  event 1\n"
+ 	"FILENAME:97:1:\n"
+ 	"   97 | LHS      RHS\n"
+ 	"      | ^~~\n"
+ 	"      | |\n"
+ 	"      | (1) from here... ->-+\n"
+ 	"      |                     |\n"
+ 	"  event 2\n"
+ 	"      |                     |\n"
+ 	"      |+--------------------+\n"
+ 	"    3 ||LHS      RHS\n"
+ 	"      ||         ^~~\n"
+ 	"      ||         |\n"
+ 	"      |+-------->(2) ...to here\n"));
+ 
+     /*  RHS -> LHS.  */
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (97, 10, 12),
+        t.get_line_and_columns (3, 1, 3),
+        ("  event 1\n"
+ 	"FILENAME:97:10:\n"
+ 	"   97 | LHS      RHS\n"
+ 	"      |          ^~~\n"
+ 	"      |          |\n"
+ 	"      |          (1) from here... ->-+\n"
+ 	"      |                              |\n"
+ 	"  event 2\n"
+ 	"      |                              |\n"
+ 	"      |+-----------------------------+\n"
+ 	"    3 ||LHS      RHS\n"
+ 	"      ||^~~\n"
+ 	"      |||\n"
+ 	"      |+(2) ...to here\n"));
+   }
+ 
+   /* Unknown src.  */
+   {
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (UNKNOWN_LOCATION,
+        t.get_line_and_columns (3, 10, 12),
+        ("  event 1\n"
+ 	" (1): from here...\n"
+ 	"  event 2\n"
+ 	"FILENAME:3:10:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      |          ^~~\n"
+ 	"      |          |\n"
+ 	"      |+-------->(2) ...to here\n"));
+   }
+ 
+   /* Unknown dst.  */
+   {
+     ASSERT_CFG_EDGE_PATH_STREQ
+       (t.get_line_and_columns (3, 1, 3),
+        UNKNOWN_LOCATION,
+        ("  event 1\n"
+ 	"FILENAME:3:1:\n"
+ 	"    3 | LHS      RHS\n"
+ 	"      | ^~~\n"
+ 	"      | |\n"
+ 	"      | (1) from here... ->-+\n"
+ 	"      |                     |\n"
+ 	"  event 2\n"
+ 	"FILENAME:\n"
+ 	" (2): ...to here\n"));
+   }
+ }
+ 
+ /* Another complex example, adapted from data-model-20.c.  */
+ 
+ static void
+ test_control_flow_5 (const line_table_case &case_,
+ 		     pretty_printer *event_pp)
+ {
+   /* Create a tempfile and write some text to it.
+      ...000000000111111111122222222223333333333444444444455555555556666666666.
+      ...123456789012345678901234567890123456789012345678901234567890123456789.  */
+   const char *content
+     = ("  if ((arr = (struct foo **)malloc(n * sizeof(struct foo *))) == NULL)\n"
+        "    return NULL;\n" /* <------------------------- line 2.  */
+        "\n" /* <----------------------------------------- line 3.  */
+        "  for (i = 0; i < n; i++) {\n" /* <-------------- line 4.  */
+        "    if ((arr[i] = (struct foo *)malloc(sizeof(struct foo))) == NULL) {\n");
+ 
+   control_flow_test t (SELFTEST_LOCATION, case_, content);
+ 
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   /* (1) */
+   path.add_event (t.get_line_and_column (1, 6), nullptr, 0,
+ 		  "following %qs branch (when %qs is non-NULL)...",
+ 		  "false", "arr");
+   path.connect_to_next_event ();
+ 
+   /* (2) */
+   path.add_event (t.get_line_and_columns (4, 8, 10, 12), nullptr, 0,
+ 		  "...to here");
+ 
+   /* (3) */
+   path.add_event (t.get_line_and_columns (4, 15, 17, 19), nullptr, 0,
+ 		  "following %qs branch (when %qs)...",
+ 		  "true", "i < n");
+   path.connect_to_next_event ();
+ 
+   /* (4) */
+   path.add_event (t.get_line_and_column (5, 13), nullptr, 0,
+ 		  "...to here");
+ 
+   /* (5) */
+   path.add_event (t.get_line_and_columns (5, 33, 58), nullptr, 0,
+ 		  "allocated here");
+ 
+   if (!path_events_have_column_data_p (path))
+     return;
+ 
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     dc.show_event_links (true);
+     dc.show_line_numbers (true);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-5\n"
+        "FILENAME:1:6:\n"
+        "    1 |   if ((arr = (struct foo **)malloc(n * sizeof(struct foo *))) == NULL)\n"
+        "      |      ^\n"
+        "      |      |\n"
+        "      |      (1) following `false' branch (when `arr' is non-NULL)... ->-+\n"
+        "      |                                                                  |\n"
+        "......\n"
+        "      |                                                                  |\n"
+        "      |+-----------------------------------------------------------------+\n"
+        "    4 ||  for (i = 0; i < n; i++) {\n"
+        "      ||       ~~~~~  ~~~~~\n"
+        "      ||         |      |\n"
+        "      ||         |      (3) following `true' branch (when `i < n')... ->-+\n"
+        "      |+-------->(2) ...to here                                          |\n"
+        "      |                                                                  |\n"
+        "      |                                                                  |\n"
+        "      |+-----------------------------------------------------------------+\n"
+        "    5 ||    if ((arr[i] = (struct foo *)malloc(sizeof(struct foo))) == NULL) {\n"
+        "      ||            ~                   ~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
+        "      ||            |                   |\n"
+        "      |+----------->(4) ...to here      (5) allocated here\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+ }
+ 
+ /* Another complex example, adapted from loop-3.c.  */
+ 
+ static void
+ test_control_flow_6 (const line_table_case &case_,
+ 		     pretty_printer *event_pp)
+ {
+   /* Create a tempfile and write some text to it.
+      ...000000000111111111122222222223333333.
+      ...123456789012345678901234567890123456.  */
+   const char *content
+     = ("#include <stdlib.h>\n" /* <------------------ line 1.  */
+        "\n" /* <------------------------------------- line 2.  */
+        "void test(int c)\n" /* <--------------------- line 3.  */
+        "{\n" /* <------------------------------------ line 4.  */
+        "  int i;\n" /* <----------------------------- line 5.  */
+        "  char *buffer = (char*)malloc(256);\n" /* <- line 6.  */
+        "\n" /* <------------------------------------- line 7.  */
+        "  for (i=0; i<255; i++) {\n" /* <------------ line 8.  */
+        "    buffer[i] = c;\n" /* <------------------- line 9.  */
+        "\n" /* <------------------------------------- line 10.  */
+        "    free(buffer);\n" /* <-------------------- line 11.  */
+        "  }\n"); /* <-------------------------------- line 12.  */
+ 
+   control_flow_test t (SELFTEST_LOCATION, case_, content);
+ 
+   logical_locations::selftest::test_manager logical_loc_mgr;
+   test_path path (logical_loc_mgr, event_pp);
+   /* (1) */
+   path.add_event (t.get_line_and_columns (6, 25, 35), nullptr, 0,
+ 		  "allocated here");
+ 
+   /* (2) */
+   path.add_event (t.get_line_and_columns (8, 13, 14, 17), nullptr, 0,
+ 		  "following %qs branch (when %qs)...",
+ 		  "true", "i <= 254");
+   path.connect_to_next_event ();
+ 
+   /* (3) */
+   path.add_event (t.get_line_and_columns (9, 5, 15, 17), nullptr, 0,
+ 		  "...to here");
+ 
+   /* (4) */
+   path.add_event (t.get_line_and_columns (8, 13, 14, 17), nullptr, 0,
+ 		  "following %qs branch (when %qs)...",
+ 		  "true", "i <= 254");
+   path.connect_to_next_event ();
+ 
+   /* (5) */
+   path.add_event (t.get_line_and_columns (9, 5, 15, 17), nullptr, 0,
+ 		  "...to here");
+ 
+   if (!path_events_have_column_data_p (path))
+     return;
+ 
+   {
+     selftest::test_context dc;
+     dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+     dc.show_event_links (true);
+     dc.show_line_numbers (true);
+     text_sink text_output (dc);
+     path_print_policy policy (text_output);
+     path_summary summary (policy, *event_pp, path, true);
+     print_path_summary_as_text (summary, text_output, false);
+     ASSERT_STREQ
+       ("  events 1-3\n"
+        "FILENAME:6:25:\n"
+        "    6 |   char *buffer = (char*)malloc(256);\n"
+        "      |                         ^~~~~~~~~~~\n"
+        "      |                         |\n"
+        "      |                         (1) allocated here\n"
+        "    7 | \n"
+        "    8 |   for (i=0; i<255; i++) {\n"
+        "      |             ~~~~~        \n"
+        "      |              |\n"
+        "      |              (2) following `true' branch (when `i <= 254')... ->-+\n"
+        "      |                                                                  |\n"
+        "      |                                                                  |\n"
+        "      |+-----------------------------------------------------------------+\n"
+        "    9 ||    buffer[i] = c;\n"
+        "      ||    ~~~~~~~~~~~~~        \n"
+        "      ||              |\n"
+        "      |+------------->(3) ...to here\n"
+        "  events 4-5\n"
+        "    8 |   for (i=0; i<255; i++) {\n"
+        "      |             ~^~~~\n"
+        "      |              |\n"
+        "      |              (4) following `true' branch (when `i <= 254')... ->-+\n"
+        "      |                                                                  |\n"
+        "      |                                                                  |\n"
+        "      |+-----------------------------------------------------------------+\n"
+        "    9 ||    buffer[i] = c;\n"
+        "      ||    ~~~~~~~~~~~~~\n"
+        "      ||              |\n"
+        "      |+------------->(5) ...to here\n",
+        pp_formatted_text (text_output.get_printer ()));
+   }
+ }
+ 
+ static void
+ control_flow_tests (const line_table_case &case_)
+ {
+   pretty_printer pp;
+   pp_show_color (&pp) = false;
+ 
+   test_control_flow_1 (case_, &pp);
+   test_control_flow_2 (case_, &pp);
+   test_control_flow_3 (case_, &pp);
+   test_control_flow_4 (case_, &pp);
+   test_control_flow_5 (case_, &pp);
+   test_control_flow_6 (case_, &pp);
+ }
+ 
+ } // namespace diagnostics::paths::selftest
+ } // namespace diagnostics::paths
+ 
+ namespace selftest { // diagnostics::selftest
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ paths_output_cc_tests ()
+ {
+   pretty_printer pp;
+   pp_show_color (&pp) = false;
+ 
+   ::selftest::auto_fix_quotes fix_quotes;
+   diagnostics::paths::selftest::test_empty_path (&pp);
+   diagnostics::paths::selftest::test_intraprocedural_path (&pp);
+   diagnostics::paths::selftest::test_interprocedural_path_1 (&pp);
+   diagnostics::paths::selftest::test_interprocedural_path_2 (&pp);
+   diagnostics::paths::selftest::test_recursion (&pp);
+   for_each_line_table_case (diagnostics::paths::selftest::control_flow_tests);
+ }
+ 
+ } // namespace diagnostics::selftest
+ } // namespace diagnostics
+ 
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic pop
+ #endif
+ 
+ #endif /* #if CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/paths.cc gcc-16-20250727/gcc/diagnostics/paths.cc
*** gcc-16-20250720/gcc/diagnostics/paths.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/paths.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,233 ----
+ /* Paths through the code associated with a diagnostic.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #define INCLUDE_ALGORITHM
+ #define INCLUDE_MAP
+ #define INCLUDE_STRING
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "diagnostic.h"
+ #include "diagnostics/paths.h"
+ #include "diagnostics/state-graphs.h"
+ 
+ /* Disable warnings about missing quoting in GCC diagnostics for the print
+    calls below.  */
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic push
+ #  pragma GCC diagnostic ignored "-Wformat-diag"
+ #endif
+ 
+ using namespace diagnostics;
+ using namespace diagnostics::paths;
+ 
+ /* class diagnostics::paths::event.  */
+ 
+ /* struct event::meaning.  */
+ 
+ void
+ event::meaning::dump_to_pp (pretty_printer *pp) const
+ {
+   bool need_comma = false;
+   pp_character (pp, '{');
+   if (const char *verb_str = maybe_get_verb_str (m_verb))
+     {
+       pp_printf (pp, "verb: %qs", verb_str);
+       need_comma = true;
+     }
+   if (const char *noun_str = maybe_get_noun_str (m_noun))
+     {
+       if (need_comma)
+ 	pp_string (pp, ", ");
+       pp_printf (pp, "noun: %qs", noun_str);
+       need_comma = true;
+     }
+   if (const char *property_str = maybe_get_property_str (m_property))
+     {
+       if (need_comma)
+ 	pp_string (pp, ", ");
+       pp_printf (pp, "property: %qs", property_str);
+       need_comma = true;
+     }
+   pp_character (pp, '}');
+ }
+ 
+ /* Get a string (or nullptr) for V suitable for use within a SARIF
+    threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
+ 
+ const char *
+ event::meaning::maybe_get_verb_str (enum verb v)
+ {
+   switch (v)
+     {
+     default:
+       gcc_unreachable ();
+     case verb::unknown:
+       return nullptr;
+     case verb::acquire:
+       return "acquire";
+     case verb::release:
+       return "release";
+     case verb::enter:
+       return "enter";
+     case verb::exit:
+       return "exit";
+     case verb::call:
+       return "call";
+     case verb::return_:
+       return "return";
+     case verb::branch:
+       return "branch";
+     case verb::danger:
+       return "danger";
+     }
+ }
+ 
+ /* Get a string (or nullptr) for N suitable for use within a SARIF
+    threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
+ 
+ const char *
+ event::meaning::maybe_get_noun_str (enum noun n)
+ {
+   switch (n)
+     {
+     default:
+       gcc_unreachable ();
+     case noun::unknown:
+       return nullptr;
+     case noun::taint:
+       return "taint";
+     case noun::sensitive:
+       return "sensitive";
+     case noun::function:
+       return "function";
+     case noun::lock:
+       return "lock";
+     case noun::memory:
+       return "memory";
+     case noun::resource:
+       return "resource";
+     }
+ }
+ 
+ /* Get a string (or nullptr) for P suitable for use within a SARIF
+    threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
+ 
+ const char *
+ event::meaning::maybe_get_property_str (enum property p)
+ {
+   switch (p)
+     {
+     default:
+       gcc_unreachable ();
+     case property::unknown:
+       return nullptr;
+     case property::true_:
+       return "true";
+     case property::false_:
+       return "false";
+     }
+ }
+ 
+ /* Generate a label_text containing the description of this event
+    (for debugging/logging purposes).  */
+ 
+ label_text
+ event::get_desc (pretty_printer &ref_pp) const
+ {
+   auto pp = ref_pp.clone ();
+   pp_show_color (pp.get ()) = false;
+   print_desc (*pp.get ());
+   return label_text::take (xstrdup (pp_formatted_text (pp.get ())));
+ }
+ 
+ // Base implementation of event::maybe_make_diagnostic_state_graph
+ 
+ std::unique_ptr<digraphs::digraph>
+ event::maybe_make_diagnostic_state_graph (bool) const
+ {
+   // Don't attempt to make a state graph:
+   return nullptr;
+ }
+ 
+ /* class diagnostics::paths::path.  */
+ 
+ /* Subroutine of path::interprocedural_p.
+    Look for the first event in this path that is within a function
+    i.e. has a non-null logical location for which function_p is true.
+    If found, write its index to *OUT_IDX and return true.
+    Otherwise return false.  */
+ 
+ bool
+ path::get_first_event_in_a_function (unsigned *out_idx) const
+ {
+   const unsigned num = num_events ();
+   for (unsigned i = 0; i < num; i++)
+     {
+       const event &event = get_event (i);
+       if (logical_locations::key logical_loc = event.get_logical_location ())
+ 	if (m_logical_loc_mgr.function_p (logical_loc))
+ 	  {
+ 	    *out_idx = i;
+ 	    return true;
+ 	  }
+     }
+   return false;
+ }
+ 
+ /* Return true if the events in this path involve more than one
+    function, or false if it is purely intraprocedural.  */
+ 
+ bool
+ path::interprocedural_p () const
+ {
+   /* Ignore leading events that are outside of any function.  */
+   unsigned first_fn_event_idx;
+   if (!get_first_event_in_a_function (&first_fn_event_idx))
+     return false;
+ 
+   const event &first_fn_event = get_event (first_fn_event_idx);
+   int first_fn_stack_depth = first_fn_event.get_stack_depth ();
+ 
+   const unsigned num = num_events ();
+   for (unsigned i = first_fn_event_idx + 1; i < num; i++)
+     {
+       if (!same_function_p (first_fn_event_idx, i))
+ 	return true;
+       if (get_event (i).get_stack_depth () != first_fn_stack_depth)
+ 	return true;
+     }
+   return false;
+ }
+ 
+ /* Print PATH by emitting a dummy "note" associated with it.  */
+ 
+ DEBUG_FUNCTION
+ void debug (path *p)
+ {
+   rich_location richloc (line_table, UNKNOWN_LOCATION);
+   richloc.set_path (p);
+   inform (&richloc, "debug path");
+ }
+ 
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic pop
+ #endif
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/paths.h gcc-16-20250727/gcc/diagnostics/paths.h
*** gcc-16-20250720/gcc/diagnostics/paths.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/paths.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,250 ----
+ /* Paths through the code associated with a diagnostic.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_PATHS_H
+ #define GCC_DIAGNOSTICS_PATHS_H
+ 
+ #include "diagnostic.h" /* for ATTRIBUTE_GCC_DIAG.  */
+ #include "diagnostics/event-id.h"
+ #include "diagnostics/logical-locations.h"
+ 
+ namespace diagnostics {
+   namespace digraphs {
+     class digraph;
+   } // namespace digraphs
+   namespace logical_locations {
+     class manager;
+   } // logical_locations
+   class sarif_builder;
+   class sarif_object;
+ } //namespace diagnostics
+ 
+ namespace diagnostics {
+ namespace paths {
+ 
+ /* A diagnostics::paths::path is an optional additional piece of metadata associated
+    with a diagnostic (via its rich_location).
+ 
+    It describes a sequence of events predicted by the compiler that
+    lead to the problem occurring, with their locations in the user's source,
+    and text descriptions.
+ 
+    For example, the following error has a 3-event path:
+ 
+      test.c: In function 'demo':
+      test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which
+        requires a non-NULL parameter
+         29 |     PyList_Append(list, item);
+            |     ^~~~~~~~~~~~~~~~~~~~~~~~~
+        'demo': events 1-3
+         25 |   list = PyList_New(0);
+            |          ^~~~~~~~~~~~~
+            |          |
+            |          (1) when 'PyList_New' fails, returning NULL
+         26 |
+         27 |   for (i = 0; i < count; i++) {
+            |   ~~~
+            |   |
+            |   (2) when 'i < count'
+         28 |     item = PyLong_FromLong(random());
+         29 |     PyList_Append(list, item);
+            |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+            |     |
+            |     (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
+ 
+     The diagnostic-printing code has consolidated the path into a single
+     run of events, since all the events are near each other and within the same
+     function; more complicated examples (such as interprocedural paths)
+     might be printed as multiple runs of events.  */
+ 
+ /* Abstract base classes, describing events within a path, and the paths
+    themselves.  */
+ 
+ /* One event within a path.  */
+ 
+ class event
+ {
+  public:
+   /* Enums for giving a sense of what this event means.
+      Roughly corresponds to SARIF v2.1.0 section 3.38.8.  */
+   enum class verb
+   {
+     unknown,
+ 
+     acquire,
+     release,
+     enter,
+     exit,
+     call,
+     return_,
+     branch,
+ 
+     danger
+   };
+   enum class noun
+   {
+     unknown,
+ 
+     taint,
+     sensitive, // this one isn't in SARIF v2.1.0; filed as https://github.com/oasis-tcs/sarif-spec/issues/530
+     function,
+     lock,
+     memory,
+     resource
+   };
+   enum class property
+   {
+     unknown,
+ 
+     true_,
+     false_
+   };
+   /* A bundle of such enums, allowing for descriptions of the meaning of
+      an event, such as
+      - "acquire memory": meaning (verb::acquire, noun::memory)
+      - "take true branch"": meaning (verb::branch, property::true)
+      - "return from function": meaning (verb::return, noun::function)
+      etc, as per SARIF's threadFlowLocation "kinds" property
+      (SARIF v2.1.0 section 3.38.8).  */
+   struct meaning
+   {
+     meaning ()
+     : m_verb (verb::unknown),
+       m_noun (noun::unknown),
+       m_property (property::unknown)
+     {
+     }
+     meaning (enum verb verb, enum noun noun)
+     : m_verb (verb), m_noun (noun), m_property (property::unknown)
+     {
+     }
+     meaning (enum verb verb, enum property property)
+     : m_verb (verb), m_noun (noun::unknown), m_property (property)
+     {
+     }
+ 
+     void dump_to_pp (pretty_printer *pp) const;
+ 
+     static const char *maybe_get_verb_str (enum verb);
+     static const char *maybe_get_noun_str (enum noun);
+     static const char *maybe_get_property_str (enum property);
+ 
+     enum verb m_verb;
+     enum noun m_noun;
+     enum property m_property;
+   };
+ 
+   virtual ~event () {}
+ 
+   virtual location_t get_location () const = 0;
+ 
+   /* Stack depth, so that consumers can visualize the interprocedural
+      calls, returns, and frame nesting.  */
+   virtual int get_stack_depth () const = 0;
+ 
+   /* Print a localized (and possibly colorized) description of this event.  */
+   virtual void print_desc (pretty_printer &pp) const = 0;
+ 
+   /* Get a logical location for this event, or null if there is none.  */
+   virtual logical_locations::key get_logical_location () const = 0;
+ 
+   virtual meaning get_meaning () const = 0;
+ 
+   /* True iff we should draw a line connecting this event to the
+      next event (e.g. to highlight control flow).  */
+   virtual bool connect_to_next_event_p () const = 0;
+ 
+   virtual thread_id_t get_thread_id () const = 0;
+ 
+   /* Hook for SARIF output to allow for adding diagnostic-specific
+      properties to the threadFlowLocation object's property bag.  */
+   virtual void
+   maybe_add_sarif_properties (sarif_builder &,
+ 			      sarif_object &/*thread_flow_loc_obj*/) const
+   {
+   }
+ 
+   /* Hook for capturing state at this event, potentially for visualizing
+      in HTML output, or for adding to SARIF.  */
+   virtual std::unique_ptr<digraphs::digraph>
+   maybe_make_diagnostic_state_graph (bool debug) const;
+ 
+   label_text get_desc (pretty_printer &ref_pp) const;
+ };
+ 
+ /* Abstract base class representing a thread of execution within
+    a diagnostics::paths::path.
+    Each event is associated with one thread.
+    Typically there is just one thread per diagnostics::paths::path. */
+ 
+ class thread
+ {
+ public:
+   virtual ~thread () {}
+   virtual label_text get_name (bool can_colorize) const = 0;
+ };
+ 
+ /* Abstract base class for getting at a sequence of events.  */
+ 
+ class path
+ {
+  public:
+   virtual ~path () {}
+   virtual unsigned num_events () const = 0;
+   virtual const event & get_event (int idx) const = 0;
+   virtual unsigned num_threads () const = 0;
+   virtual const thread &
+   get_thread (thread_id_t) const = 0;
+ 
+   /* Return true iff the two events are both within the same function,
+      or both outside of any function.  */
+   virtual bool
+   same_function_p (int event_idx_a,
+ 		   int event_idx_b) const = 0;
+ 
+   bool interprocedural_p () const;
+   bool multithreaded_p () const;
+ 
+   const logical_locations::manager &get_logical_location_manager () const
+   {
+     return m_logical_loc_mgr;
+   }
+ 
+ protected:
+   path (const logical_locations::manager &logical_loc_mgr)
+   : m_logical_loc_mgr (logical_loc_mgr)
+   {
+   }
+ 
+ private:
+   bool get_first_event_in_a_function (unsigned *out_idx) const;
+ 
+   const logical_locations::manager &m_logical_loc_mgr;
+ };
+ 
+ } // namespace paths
+ } // namespace diagnostics
+ 
+ /* Concrete subclasses of the above can be found in
+    simple-diagnostic-path.h.  */
+ 
+ extern void debug (diagnostics::paths::path *path);
+ 
+ #endif /* ! GCC_DIAGNOSTICS_PATHS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/sarif-sink.cc gcc-16-20250727/gcc/diagnostics/sarif-sink.cc
*** gcc-16-20250720/gcc/diagnostics/sarif-sink.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/sarif-sink.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,5077 ----
+ /* SARIF output for diagnostics
+    Copyright (C) 2018-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ 
+ #include "config.h"
+ #define INCLUDE_LIST
+ #define INCLUDE_MAP
+ #define INCLUDE_STRING
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "diagnostic.h"
+ #include "diagnostics/metadata.h"
+ #include "diagnostics/digraphs.h"
+ #include "diagnostics/state-graphs.h"
+ #include "diagnostics/paths.h"
+ #include "diagnostics/sink.h"
+ #include "diagnostics/buffering.h"
+ #include "json.h"
+ #include "cpplib.h"
+ #include "diagnostics/logical-locations.h"
+ #include "diagnostics/client-data-hooks.h"
+ #include "diagnostics/diagram.h"
+ #include "text-art/canvas.h"
+ #include "diagnostics/sarif-sink.h"
+ #include "diagnostics/text-sink.h"
+ #include "ordered-hash-map.h"
+ #include "sbitmap.h"
+ #include "selftest.h"
+ #include "diagnostics/selftest-context.h"
+ #include "diagnostics/selftest-source-printing.h"
+ #include "selftest-json.h"
+ #include "text-range-label.h"
+ #include "pretty-print-format-impl.h"
+ #include "pretty-print-urlifier.h"
+ #include "demangle.h"
+ #include "backtrace.h"
+ #include "xml.h"
+ 
+ namespace diagnostics {
+ 
+ /* A json::array where the values are "unique" as per
+    SARIF v2.1.0 section 3.7.3 ("Array properties with unique values").  */
+ 
+ template <typename JsonElementType>
+ class sarif_array_of_unique : public json::array
+ {
+  public:
+   size_t append_uniquely (std::unique_ptr<JsonElementType> val)
+   {
+     /* This should be O(log(n)) due to the std::map.  */
+     auto search = m_index_by_value.find (val.get ());
+     if (search != m_index_by_value.end())
+       return (*search).second;
+ 
+     const size_t insertion_idx = size ();
+     m_index_by_value.insert ({val.get (), insertion_idx});
+     append (std::move (val));
+     return insertion_idx;
+   }
+ 
+   /* For ease of reading output, add "index": idx to all
+      objects in the array.
+      We don't do this until we've added everything, since
+      the "index" property would otherwise confuse the
+      comparison against new elements.  */
+   void add_explicit_index_values ()
+   {
+     for (size_t idx = 0; idx < length (); ++idx)
+       if (json::object *obj = get (idx)->dyn_cast_object ())
+ 	obj->set_integer ("index", idx);
+   }
+ 
+ private:
+   struct comparator_t {
+     bool operator () (const json::value *a, const json::value *b) const
+     {
+       gcc_assert (a);
+       gcc_assert (b);
+       return json::value::compare (*a, *b) < 0;
+     }
+   };
+ 
+   // json::value * here is borrowed from m_elements
+   std::map<json::value *, int, comparator_t> m_index_by_value;
+ };
+ 
+ /* Forward decls.  */
+ class sarif_builder;
+ class content_renderer;
+   class escape_nonascii_renderer;
+ 
+ /* Subclasses of sarif_object.
+    Keep these in order of their descriptions in the specification.  */
+ class sarif_artifact_content; // 3.3
+ class sarif_artifact_location; // 3.4
+ class sarif_message; // 3.11
+ class sarif_multiformat_message_string; // 3.12
+ class sarif_log; // 3.13
+ class sarif_run; // 3.14
+ class sarif_tool; // 3.18
+ class sarif_tool_component; // 3.19
+ class sarif_invocation; // 3.20
+ class sarif_artifact; // 3.24
+ class sarif_location_manager; // not in the spec
+ class sarif_result; // 3.27
+ class sarif_location; // 3.28
+ class sarif_physical_location; // 3.29
+ class sarif_region; // 3.30
+ class sarif_logical_location; // 3.33
+ class sarif_location_relationship; // 3.34
+ class sarif_code_flow; // 3.36
+ class sarif_thread_flow; // 3.37
+ class sarif_thread_flow_location; // 3.38
+ class sarif_reporting_descriptor; // 3.49
+ class sarif_reporting_descriptor_reference; // 3.53
+ class sarif_tool_component_reference; // 3.54
+ class sarif_fix; // 3.55
+ class sarif_artifact_change; // 3.56
+ class sarif_replacement; // 3.57
+ class sarif_ice_notification; // 3.58
+ 
+ // Valid values for locationRelationship's "kinds" property (3.34.3)
+ 
+ enum class location_relationship_kind
+ {
+   includes,
+   is_included_by,
+   relevant,
+ 
+   NUM_KINDS
+ };
+ 
+ /* Declarations of subclasses of sarif_object.
+    Keep these in order of their descriptions in the specification.  */
+ 
+ /* Subclass of sarif_object for SARIF "artifactContent" objects
+    (SARIF v2.1.0 section 3.3).  */
+ 
+ class sarif_artifact_content : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "artifactLocation" objects
+    (SARIF v2.1.0 section 3.4).  */
+ 
+ class sarif_artifact_location : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "message" objects
+    (SARIF v2.1.0 section 3.11).  */
+ 
+ class sarif_message : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "multiformatMessageString" objects
+    (SARIF v2.1.0 section 3.12).  */
+ 
+ class sarif_multiformat_message_string : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "log" objects
+    (SARIF v2.1.0 section 3.13).  */
+ 
+ class sarif_log : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "run" objects
+    (SARIF v2.1.0 section 3.14).  */
+ 
+ class sarif_run : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "tool" objects
+    (SARIF v2.1.0 section 3.18).  */
+ 
+ class sarif_tool : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "toolComponent" objects
+    (SARIF v2.1.0 section 3.19).  */
+ 
+ class sarif_tool_component : public sarif_object {};
+ 
+ /* Make a JSON string for the current date and time.
+    See SARIF v2.1.0 section 3.9 "Date/time properties".
+    Given that we don't run at the very beginning/end of the
+    process, it doesn't make sense to be more accurate than
+    the current second.  */
+ 
+ static std::unique_ptr<json::string>
+ make_date_time_string_for_current_time ()
+ {
+   time_t t = time (nullptr);
+   struct tm *tm = gmtime (&t);
+   char buf[256];
+   snprintf (buf, sizeof (buf) - 1,
+ 	    ("%04i-%02i-%02iT"
+ 	     "%02i:%02i:%02iZ"),
+ 	    tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ 	    tm->tm_hour, tm->tm_min, tm->tm_sec);
+   return std::make_unique<json::string> (buf);
+ }
+ 
+ /* Subclass of sarif_object for SARIF "invocation" objects
+    (SARIF v2.1.0 section 3.20).  */
+ 
+ class sarif_invocation : public sarif_object
+ {
+ public:
+   sarif_invocation (sarif_builder &builder,
+ 		    const char * const *original_argv);
+ 
+   void add_notification_for_ice (const diagnostic_info &diagnostic,
+ 				 sarif_builder &builder,
+ 				 std::unique_ptr<json::object> backtrace);
+   void prepare_to_flush (sarif_builder &builder);
+ 
+ private:
+   std::unique_ptr<json::array> m_notifications_arr;
+   bool m_success;
+ };
+ 
+ /* Corresponds to values for the SARIF artifact objects "roles" property.
+    (SARIF v2.1.0 section 3.24.6).  */
+ 
+ enum class diagnostic_artifact_role
+ {
+   analysis_target, /* "analysisTarget".  */
+   debug_output_file, /* "debugOutputFile".  */
+   result_file, /* "resultFile".  */
+ 
+   /* "scannedFile" added in 2.2;
+      see https://github.com/oasis-tcs/sarif-spec/issues/459 */
+   scanned_file,
+ 
+   traced_file, /* "tracedFile".  */
+ 
+   NUM_ROLES
+ };
+ 
+ /* Subclass of sarif_object for SARIF artifact objects
+    (SARIF v2.1.0 section 3.24).  */
+ 
+ class sarif_artifact : public sarif_object
+ {
+ public:
+   sarif_artifact (const char *filename)
+   : m_filename (filename),
+     m_roles ((unsigned)diagnostic_artifact_role::NUM_ROLES),
+     m_embed_contents (false)
+   {
+     bitmap_clear (m_roles);
+   }
+ 
+   void add_role (enum diagnostic_artifact_role role,
+ 		 bool embed_contents);
+ 
+   bool embed_contents_p () const { return m_embed_contents; }
+   void populate_contents (sarif_builder &builder);
+   void populate_roles ();
+ 
+ private:
+   const char *m_filename;
+   auto_sbitmap m_roles;
+ 
+   /* Flag to track whether this artifact should have a "contents" property
+      (SARIF v2.1.0 section 3.24.8).
+      We only add the contents for those artifacts that have a location
+      referencing them (so that a consumer might want to quote the source).   */
+   bool m_embed_contents;
+ };
+ 
+ /* A class for sarif_objects that own a "namespace" of numeric IDs for
+    managing location objects within them.  Currently (SARIF v2.1.0)
+    this is just for sarif_result (section 3.28.2), but it will likely
+    eventually also be for notification objects; see
+    https://github.com/oasis-tcs/sarif-spec/issues/540
+ 
+    Consider locations with chains of include information e.g.
+ 
+    > include-chain-1.c:
+    >   #include "include-chain-1.h"
+ 
+    include-chain-1.h:
+      | // First set of decls, which will be referenced in notes
+      | #include "include-chain-1-1.h"
+      |
+      | // Second set of decls, which will trigger the errors
+      | #include "include-chain-1-2.h"
+ 
+    include-chain-1-1.h:
+      | int p;
+      | int q;
+ 
+    include-chain-1-1.h:
+      | char p;
+      | char q;
+ 
+    GCC's textual output emits:
+      |   In file included from PATH/include-chain-1.h:5,
+      |                    from PATH/include-chain-1.c:30:
+      |   PATH/include-chain-1-2.h:1:6: error: conflicting types for 'p'; have 'char'
+      |       1 | char p;
+      |         |      ^
+      |   In file included from PATH/include-chain-1.h:2:
+      |   PATH/include-chain-1-1.h:1:5: note: previous declaration of 'p' with type 'int'
+      |       1 | int p;
+      |         |     ^
+      |   PATH/include-chain-1-2.h:2:6: error: conflicting types for 'q'; have 'char'
+      |       2 | char q;
+      |         |      ^
+      |   PATH/include-chain-1-1.h:2:5: note: previous declaration of 'q' with type 'int'
+      |       2 | int q;
+      |         |     ^
+ 
+    Whenever a SARIF location is added for a location_t that
+    was #included from somewhere, we queue up the creation of a SARIF
+    location for the location of the #include.  The worklist of queued
+    locations is flushed when the result is finished, which lazily creates
+    any additional related locations for the include chain, and the
+    relationships between the locations.  Doing so can lead to further
+    include locations being processed.  The worklist approach allows us
+    to lazily explore the relevant part of the directed graph of location_t
+    values implicit in our line_maps structure, replicating it as a directed
+    graph of SARIF locations within the SARIF result object, like this:
+ 
+    [0]: error in include-chain-1-2.h ("conflicting types for 'p'; have 'char'")
+    [1]: #include "include-chain-1-2.h" in include-chain-1.h
+    [2]: note in include-chain-1-2.h ("previous declaration of 'p' with type 'int'")
+    [3]: #include "include-chain-1-1.h" in include-chain-1.h
+    [4]: #include "include-chain-1.h" in include-chain-1.c
+ 
+    where we want to capture this "includes" graph in SARIF form:
+    . +-----------------------------------+ +----------------------------------+
+    . |"id": 0                            | |"id": 2                           |
+    . | error: "conflicting types for 'p';| | note: previous declaration of 'p'|
+    . |  have 'char'"|                    | | with type 'int'")                |
+    . | in include-chain-1-2.h            | | in include-chain-1-1.h           |
+    . +-----------------------------------+ +----------------------------------+
+    .            ^         |                            ^         |
+    .   includes |         | included-by       includes |         | included-by
+    .            |         V                            |         V
+    .  +--------------------------------+    +--------------------------------+
+    .  |"id": 1                         |    |"id": 3                         |
+    .  | #include "include-chain-1-2.h" |    | #include "include-chain-1-1.h" |
+    .  | in include-chain-1.h           |    | in include-chain-1.h           |
+    .  +--------------------------------+    +--------------------------------+
+    .                   ^     |                       ^    |
+    .          includes |     | included-by  includes |    | included-by
+    .                   |     V                       |    V
+    .                  +------------------------------------+
+    .                  |"id": 4                             |
+    .                  | The  #include "include-chain-1.h"  |
+    .                  | in include-chain-1.c               |
+    .                  +------------------------------------+
+  */
+ 
+ class sarif_location_manager : public sarif_object
+ {
+ public:
+   /* A worklist of pending actions needed to fully process this object.
+ 
+      This lets us lazily walk our data structures to build the
+      directed graph of locations, whilst keeping "notes" at the top
+      of the "relatedLocations" array, and avoiding the need for
+      recursion.  */
+   struct worklist_item
+   {
+     enum class kind
+     {
+      /* Process a #include relationship where m_location_obj
+ 	was #included-d at m_where.  */
+      included_from,
+ 
+      /* Process a location_t that was added as a secondary location
+ 	to a rich_location without a label.  */
+      unlabelled_secondary_location
+     };
+ 
+     worklist_item (sarif_location &location_obj,
+ 		   enum kind kind,
+ 		   location_t where)
+       : m_location_obj (location_obj),
+ 	m_kind (kind),
+ 	m_where (where)
+     {
+     }
+ 
+     sarif_location &m_location_obj;
+     enum kind m_kind;
+     location_t m_where;
+   };
+ 
+   sarif_location_manager ()
+   : m_related_locations_arr (nullptr),
+     m_next_location_id (0)
+   {
+   }
+ 
+   unsigned allocate_location_id ()
+   {
+     return m_next_location_id++;
+   }
+ 
+   virtual void
+   add_related_location (std::unique_ptr<sarif_location> location_obj,
+ 			sarif_builder &builder);
+ 
+   void
+   add_relationship_to_worklist (sarif_location &location_obj,
+ 				enum worklist_item::kind kind,
+ 				location_t where);
+ 
+   void
+   process_worklist (sarif_builder &builder);
+ 
+   void
+   process_worklist_item (sarif_builder &builder,
+ 			 const worklist_item &item);
+ private:
+   json::array *m_related_locations_arr; // borrowed
+   unsigned m_next_location_id;
+ 
+   std::list<worklist_item> m_worklist;
+   std::map<location_t, sarif_location *> m_included_from_locations;
+   std::map<location_t, sarif_location *> m_unlabelled_secondary_locations;
+ };
+ 
+ /* Subclass of sarif_object for SARIF "result" objects
+    (SARIF v2.1.0 section 3.27).
+    Each SARIF result object has its own "namespace" of numeric IDs for
+    managing location objects (SARIF v2.1.0 section 3.28.2). */
+ 
+ class sarif_result : public sarif_location_manager
+ {
+ public:
+   sarif_result (unsigned idx_within_parent)
+   : m_idx_within_parent (idx_within_parent)
+   {}
+ 
+   unsigned get_index_within_parent () const { return m_idx_within_parent; }
+ 
+   void
+   on_nested_diagnostic (const diagnostic_info &diagnostic,
+ 			enum kind orig_diag_kind,
+ 			sarif_builder &builder);
+   void on_diagram (const diagram &d,
+ 		   sarif_builder &builder);
+ 
+ private:
+   const unsigned m_idx_within_parent;
+ };
+ 
+ /* Subclass of sarif_object for SARIF "location" objects
+    (SARIF v2.1.0 section 3.28).
+    A location object can have an "id" which must be unique within
+    the enclosing result, if any (see SARIF v2.1.0 section 3.28.2).  */
+ 
+ class sarif_location : public sarif_object
+ {
+ public:
+   long lazily_add_id (sarif_location_manager &loc_mgr);
+   long get_id () const;
+ 
+   void lazily_add_relationship (sarif_location &target,
+ 				enum location_relationship_kind kind,
+ 				sarif_location_manager &loc_mgr);
+ 
+ private:
+   sarif_location_relationship &
+   lazily_add_relationship_object (sarif_location &target,
+ 				  sarif_location_manager &loc_mgr);
+ 
+   json::array &lazily_add_relationships_array ();
+ 
+   std::map<sarif_location *,
+ 	   sarif_location_relationship *> m_relationships_map;
+ };
+ 
+ /* Subclass of sarif_object for SARIF "physicalLocation" objects
+    (SARIF v2.1.0 section 3.29).  */
+ 
+ class sarif_physical_location : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "region" objects
+    (SARIF v2.1.0 section 3.30).  */
+ 
+ class sarif_region : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "logicalLocation" objects
+    (SARIF v2.1.0 section 3.33).  */
+ 
+ class sarif_logical_location : public sarif_object
+ {
+ };
+ 
+ /* Subclass of sarif_object for SARIF "locationRelationship" objects
+    (SARIF v2.1.0 section 3.34).  */
+ 
+ class sarif_location_relationship : public sarif_object
+ {
+ public:
+   sarif_location_relationship (sarif_location &target,
+ 			       sarif_location_manager &loc_mgr);
+ 
+   long get_target_id () const;
+ 
+   void lazily_add_kind (enum location_relationship_kind kind);
+ 
+ private:
+   auto_sbitmap m_kinds;
+ };
+ 
+ /* Subclass of sarif_object for SARIF "codeFlow" objects
+    (SARIF v2.1.0 section 3.36).  */
+ 
+ class sarif_code_flow : public sarif_object
+ {
+ public:
+   sarif_code_flow (sarif_result &parent,
+ 		   unsigned idx_within_parent);
+ 
+   sarif_result &get_parent () const { return m_parent; }
+   unsigned get_index_within_parent () const { return m_idx_within_parent; }
+ 
+   sarif_thread_flow &
+   get_or_append_thread_flow (const paths::thread &thread,
+ 			     paths::thread_id_t thread_id);
+ 
+   sarif_thread_flow &
+   get_thread_flow (paths::thread_id_t thread_id);
+ 
+   void add_location (sarif_thread_flow_location &);
+ 
+   sarif_thread_flow_location &
+   get_thread_flow_loc_obj (paths::event_id_t event_id) const;
+ 
+ private:
+   sarif_result &m_parent;
+   const unsigned m_idx_within_parent;
+ 
+   hash_map<int_hash<paths::thread_id_t, -1, -2>,
+ 	   sarif_thread_flow *> m_thread_id_map; // borrowed ptr
+   json::array *m_thread_flows_arr; // borrowed
+ 
+   /* Vec of borrowed ptr, allowing for going easily from
+      an event_id to the corresponding threadFlowLocation object.  */
+   std::vector<sarif_thread_flow_location *> m_all_tfl_objs;
+ };
+ 
+ /* Subclass of sarif_object for SARIF "threadFlow" objects
+    (SARIF v2.1.0 section 3.37).  */
+ 
+ class sarif_thread_flow : public sarif_object
+ {
+ public:
+   sarif_thread_flow (sarif_code_flow &parent,
+ 		     const paths::thread &thread,
+ 		     unsigned idx_within_parent);
+ 
+   sarif_code_flow &get_parent () const { return m_parent; }
+   unsigned get_index_within_parent () const { return m_idx_within_parent; }
+ 
+   sarif_thread_flow_location &add_location ();
+ 
+ private:
+   sarif_code_flow &m_parent;
+   json::array *m_locations_arr; // borrowed
+   const unsigned m_idx_within_parent;
+ };
+ 
+ /* Subclass of sarif_object for SARIF "threadFlowLocation" objects
+    (SARIF v2.1.0 section 3.38).  */
+ 
+ class sarif_thread_flow_location : public sarif_object
+ {
+ public:
+   sarif_thread_flow_location (sarif_thread_flow &parent,
+ 			      unsigned idx_within_parent)
+   : m_parent (parent),
+     m_idx_within_parent (idx_within_parent)
+   {
+   }
+ 
+   sarif_thread_flow &get_parent () const { return m_parent; }
+   unsigned get_index_within_parent () const { return m_idx_within_parent; }
+ 
+ private:
+   sarif_thread_flow &m_parent;
+   const unsigned m_idx_within_parent;
+ };
+ 
+ /* Subclass of sarif_object for SARIF "reportingDescriptor" objects
+    (SARIF v2.1.0 section 3.49).  */
+ 
+ class sarif_reporting_descriptor : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "reportingDescriptorReference" objects
+    (SARIF v2.1.0 section 3.53).  */
+ 
+ class sarif_reporting_descriptor_reference : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "toolComponentReference" objects
+    (SARIF v2.1.0 section 3.54).  */
+ 
+ class sarif_tool_component_reference : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "fix" objects
+    (SARIF v2.1.0 section 3.55).  */
+ 
+ class sarif_fix : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "artifactChange" objects
+    (SARIF v2.1.0 section 3.56).  */
+ 
+ class sarif_artifact_change : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "replacement" objects
+    (SARIF v2.1.0 section 3.57).  */
+ 
+ class sarif_replacement : public sarif_object {};
+ 
+ /* Subclass of sarif_object for SARIF "notification" objects
+    (SARIF v2.1.0 section 3.58).
+ 
+    This subclass is specifically for notifying when an
+    internal compiler error occurs.  */
+ 
+ class sarif_ice_notification : public sarif_location_manager
+ {
+ public:
+   sarif_ice_notification (const diagnostic_info &diagnostic,
+ 			  sarif_builder &builder,
+ 			  std::unique_ptr<json::object> backtrace);
+ 
+   void
+   add_related_location (std::unique_ptr<sarif_location> location_obj,
+ 			sarif_builder &builder) final override;
+ };
+ 
+ /* Abstract base class for use when making an  "artifactContent"
+    object (SARIF v2.1.0 section 3.3): generate a value for the
+    3.3.4 "rendered" property.
+    Can return nullptr, for "no property".  */
+ 
+ class content_renderer
+ {
+ public:
+   virtual ~content_renderer () {}
+ 
+   virtual std::unique_ptr<sarif_multiformat_message_string>
+   render (const sarif_builder &builder) const = 0;
+ };
+ 
+ /* Concrete buffering implementation subclass for SARIF output.  */
+ 
+ class sarif_sink_buffer : public per_sink_buffer
+ {
+ public:
+   friend class sarif_sink;
+ 
+   sarif_sink_buffer (sarif_builder &builder)
+   : m_builder (builder)
+   {}
+ 
+   void dump (FILE *out, int indent) const final override;
+   bool empty_p () const final override;
+   void move_to (per_sink_buffer &dest) final override;
+   void clear () final override;
+   void flush () final override;
+ 
+   void add_result (std::unique_ptr<sarif_result> result)
+   {
+     m_results.push_back (std::move (result));
+   }
+ 
+   size_t num_results () const { return m_results.size (); }
+   sarif_result &get_result (size_t idx) { return *m_results[idx]; }
+ 
+ private:
+   sarif_builder &m_builder;
+   std::vector<std::unique_ptr<sarif_result>> m_results;
+ };
+ 
+ /* Classes for abstracting away JSON vs other serialization formats.  */
+ 
+ // class sarif_serialization_format_json : public sarif_serialization_format
+ 
+ void
+ sarif_serialization_format_json::write_to_file (FILE *outf,
+ 						const json::value &top)
+ {
+   top.dump (outf, m_formatted);
+   fprintf (outf, "\n");
+ }
+ 
+ /* A class for managing SARIF output (for -fdiagnostics-format=sarif-stderr
+    and -fdiagnostics-format=sarif-file).
+ 
+    As diagnostics occur, we build "result" JSON objects, and
+    accumulate state:
+    - which source files are referenced
+    - which warnings are emitted
+    - which CWEs are used
+ 
+    At the end of the compile, we use the above to build the full SARIF
+    object tree, adding the result objects to the correct place, and
+    creating objects for the various source files, warnings and CWEs
+    referenced.
+ 
+    Implemented:
+    - fix-it hints
+    - CWE metadata
+    - diagnostic groups (see limitations below)
+    - logical locations (e.g. cfun)
+    - labelled ranges (as annotations)
+    - secondary ranges without labels (as related locations)
+ 
+    Known limitations:
+    - GCC supports nesting of diagnostics (one-deep nesting via
+      auto_diagnostic_group, and arbitrary nesting via
+      auto_diagnostic_nesting_level).  These are captured in the SARIF
+      as related locations, and so we only capture location and message
+      information from such nested diagnostics (e.g. we ignore fix-it
+      hints on them).  Diagnostics within an auto_diagnostic_nesting_level
+      have their nesting level captured as a property.
+    - although we capture command-line arguments (section 3.20.2), we don't
+      yet capture response files.
+    - doesn't capture "artifact.encoding" property
+      (SARIF v2.1.0 section 3.24.9).
+    - doesn't capture hashes of the source files
+      ("artifact.hashes" property (SARIF v2.1.0 section 3.24.11).
+    - doesn't capture the "analysisTarget" property
+      (SARIF v2.1.0 section 3.27.13).
+    - doesn't capture -Werror cleanly
+    - doesn't capture inlining information (can SARIF handle this?)
+    - doesn't capture macro expansion information (can SARIF handle this?).
+    - doesn't capture any diagnostics::metadata::rules associated with
+      a diagnostic.  */
+ 
+ class sarif_builder
+ {
+ public:
+   friend class sarif_sink_buffer;
+ 
+   sarif_builder (diagnostics::context &dc,
+ 		 pretty_printer &printer,
+ 		 const line_maps *line_maps,
+ 		 std::unique_ptr<sarif_serialization_format> serialization_format,
+ 		 const sarif_generation_options &sarif_gen_opts);
+   ~sarif_builder ();
+ 
+   void set_printer (pretty_printer &printer)
+   {
+     m_printer = &printer;
+   }
+ 
+   const logical_locations::manager *
+   get_logical_location_manager () const
+   {
+     return m_logical_loc_mgr;
+   }
+ 
+   void
+   set_main_input_filename (const char *name);
+ 
+   void on_report_diagnostic (const diagnostic_info &diagnostic,
+ 			     enum kind orig_diag_kind,
+ 			     sarif_sink_buffer *buffer);
+   void emit_diagram (const diagram &d);
+   void end_group ();
+ 
+   void
+   report_global_digraph (const lazily_created<digraphs::digraph> &);
+ 
+   std::unique_ptr<sarif_result> take_current_result ()
+   {
+     return std::move (m_cur_group_result);
+   }
+ 
+   std::unique_ptr<sarif_log> flush_to_object ();
+   void flush_to_file (FILE *outf);
+ 
+   std::unique_ptr<json::array>
+   make_locations_arr (sarif_location_manager &loc_mgr,
+ 		      const diagnostic_info &diagnostic,
+ 		      enum diagnostic_artifact_role role);
+   std::unique_ptr<sarif_location>
+   make_location_object (sarif_location_manager *loc_mgr,
+ 			const rich_location &rich_loc,
+ 			logical_locations::key logical_loc,
+ 			enum diagnostic_artifact_role role);
+   std::unique_ptr<sarif_location>
+   make_location_object (sarif_location_manager &loc_mgr,
+ 			location_t where,
+ 			enum diagnostic_artifact_role role);
+   std::unique_ptr<sarif_message>
+   make_message_object (const char *msg) const;
+   std::unique_ptr<sarif_message>
+   make_message_object_for_diagram (const diagram &d);
+   std::unique_ptr<sarif_artifact_content>
+   maybe_make_artifact_content_object (const char *filename) const;
+ 
+   std::unique_ptr<sarif_artifact_location>
+   make_artifact_location_object (const char *filename);
+ 
+   const sarif_code_flow *
+   get_code_flow_for_event_ids () const
+   {
+     return m_current_code_flow;
+   }
+ 
+   diagnostics::context &get_context () const { return m_context; }
+   pretty_printer *get_printer () const { return m_printer; }
+   token_printer &get_token_printer () { return m_token_printer; }
+   enum sarif_version get_version () const { return m_sarif_gen_opts.m_version; }
+ 
+   size_t num_results () const { return m_results_array->size (); }
+   sarif_result &get_result (size_t idx)
+   {
+     auto element = (*m_results_array)[idx];
+     gcc_assert (element);
+     return *static_cast<sarif_result *> (element);
+   }
+ 
+   const sarif_generation_options &get_opts () const { return m_sarif_gen_opts; }
+ 
+   std::unique_ptr<sarif_logical_location>
+   make_minimal_sarif_logical_location (logical_locations::key);
+ 
+ private:
+   class sarif_token_printer : public token_printer
+   {
+   public:
+     sarif_token_printer (sarif_builder &builder)
+       : m_builder (builder)
+     {
+     }
+     void print_tokens (pretty_printer *pp,
+ 		       const pp_token_list &tokens) final override;
+   private:
+     sarif_builder &m_builder;
+   };
+ 
+   std::unique_ptr<sarif_result>
+   make_result_object (const diagnostic_info &diagnostic,
+ 		      enum kind orig_diag_kind,
+ 		      unsigned idx_within_parent);
+   void
+   add_any_include_chain (sarif_location_manager &loc_mgr,
+ 			 sarif_location &location_obj,
+ 			 location_t where);
+   void
+   set_any_logical_locs_arr (sarif_location &location_obj,
+ 			    logical_locations::key logical_loc);
+   std::unique_ptr<sarif_location>
+   make_location_object (sarif_location_manager &loc_mgr,
+ 			const paths::event &event,
+ 			enum diagnostic_artifact_role role);
+   std::unique_ptr<sarif_code_flow>
+   make_code_flow_object (sarif_result &result,
+ 			 unsigned idx_within_parent,
+ 			 const paths::path &path);
+   void
+   populate_thread_flow_location_object (sarif_result &result,
+ 					sarif_thread_flow_location &thread_flow_loc_obj,
+ 					const paths::event &event,
+ 					int event_execution_idx);
+   std::unique_ptr<json::array>
+   maybe_make_kinds_array (paths::event::meaning m) const;
+   std::unique_ptr<sarif_physical_location>
+   maybe_make_physical_location_object (location_t loc,
+ 				       enum diagnostic_artifact_role role,
+ 				       int column_override,
+ 				       const content_renderer *snippet_renderer);
+   std::unique_ptr<sarif_artifact_location>
+   make_artifact_location_object (location_t loc);
+   std::unique_ptr<sarif_artifact_location>
+   make_artifact_location_object_for_pwd () const;
+   std::unique_ptr<sarif_region>
+   maybe_make_region_object (location_t loc,
+ 			    int column_override) const;
+   std::unique_ptr<sarif_region>
+   maybe_make_region_object_for_context (location_t loc,
+ 					const content_renderer *snippet_renderer) const;
+   std::unique_ptr<sarif_region>
+   make_region_object_for_hint (const fixit_hint &hint) const;
+ 
+   int
+   ensure_sarif_logical_location_for (logical_locations::key k);
+ 
+   std::unique_ptr<sarif_multiformat_message_string>
+   make_multiformat_message_string (const char *msg) const;
+   std::unique_ptr<sarif_log>
+   make_top_level_object (std::unique_ptr<sarif_invocation> invocation_obj,
+ 			 std::unique_ptr<json::array> results);
+   std::unique_ptr<sarif_run>
+   make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
+ 		   std::unique_ptr<json::array> results);
+   std::unique_ptr<sarif_tool>
+   make_tool_object ();
+   std::unique_ptr<sarif_tool_component>
+   make_driver_tool_component_object ();
+   std::unique_ptr<json::array> maybe_make_taxonomies_array () const;
+   std::unique_ptr<sarif_tool_component>
+   maybe_make_cwe_taxonomy_object () const;
+   std::unique_ptr<sarif_tool_component_reference>
+   make_tool_component_reference_object_for_cwe () const;
+   std::unique_ptr<sarif_reporting_descriptor>
+   make_reporting_descriptor_object_for_warning (const diagnostic_info &diagnostic,
+ 						enum kind orig_diag_kind,
+ 						const char *option_text);
+   std::unique_ptr<sarif_reporting_descriptor>
+   make_reporting_descriptor_object_for_cwe_id (int cwe_id) const;
+   std::unique_ptr<sarif_reporting_descriptor_reference>
+   make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id);
+   sarif_artifact &
+   get_or_create_artifact (const char *filename,
+ 			  enum diagnostic_artifact_role role,
+ 			  bool embed_contents);
+   char *
+   get_source_lines (const char *filename,
+ 		    int start_line,
+ 		    int end_line) const;
+   std::unique_ptr<sarif_artifact_content>
+   maybe_make_artifact_content_object (const char *filename,
+ 				      int start_line,
+ 				      int end_line,
+ 				      const content_renderer *r) const;
+   std::unique_ptr<sarif_fix>
+   make_fix_object (const rich_location &rich_loc);
+   std::unique_ptr<sarif_artifact_change>
+   make_artifact_change_object (const rich_location &richloc);
+   std::unique_ptr<sarif_replacement>
+   make_replacement_object (const fixit_hint &hint) const;
+   std::unique_ptr<sarif_artifact_content>
+   make_artifact_content_object (const char *text) const;
+   int get_sarif_column (expanded_location exploc) const;
+ 
+   std::unique_ptr<json::object>
+   make_stack_from_backtrace ();
+ 
+   diagnostics::context &m_context;
+   pretty_printer *m_printer;
+   const line_maps *m_line_maps;
+   sarif_token_printer m_token_printer;
+ 
+   const logical_locations::manager *m_logical_loc_mgr;
+ 
+   /* The JSON object for the invocation object.  */
+   std::unique_ptr<sarif_invocation> m_invocation_obj;
+ 
+   /* The JSON array of pending diagnostics.  */
+   std::unique_ptr<json::array> m_results_array;
+ 
+   /* The JSON object for the result object (if any) in the current
+      diagnostic group.  */
+   std::unique_ptr<sarif_result> m_cur_group_result;
+ 
+   /* Ideally we'd use std::unique_ptr<sarif_artifact> here, but I had
+      trouble getting this to work when building with GCC 4.8.  */
+   ordered_hash_map <nofree_string_hash,
+ 		    sarif_artifact *> m_filename_to_artifact_map;
+ 
+   bool m_seen_any_relative_paths;
+   hash_set <free_string_hash> m_rule_id_set;
+   std::unique_ptr<json::array> m_rules_arr;
+ 
+   /* The set of all CWE IDs we've seen, if any.  */
+   hash_set <int_hash <int, 0, 1> > m_cwe_id_set;
+ 
+   std::unique_ptr<sarif_array_of_unique<sarif_logical_location>> m_cached_logical_locs;
+ 
+   std::unique_ptr<sarif_array_of_unique<sarif_graph>> m_run_graphs;
+ 
+   int m_tabstop;
+ 
+   std::unique_ptr<sarif_serialization_format> m_serialization_format;
+   const sarif_generation_options m_sarif_gen_opts;
+ 
+   unsigned m_next_result_idx;
+   sarif_code_flow *m_current_code_flow;
+ };
+ 
+ /* class sarif_object : public json::object.  */
+ 
+ sarif_property_bag &
+ sarif_object::get_or_create_properties ()
+ {
+   json::value *properties_val = get ("properties");
+   if (properties_val)
+     {
+       if (properties_val->get_kind () == json::JSON_OBJECT)
+ 	return *static_cast <sarif_property_bag *> (properties_val);
+     }
+ 
+   sarif_property_bag *bag = new sarif_property_bag ();
+   set ("properties", bag);
+   return *bag;
+ }
+ 
+ /* class sarif_invocation : public sarif_object.  */
+ 
+ sarif_invocation::sarif_invocation (sarif_builder &builder,
+ 				    const char * const *original_argv)
+ : m_notifications_arr (std::make_unique<json::array> ()),
+   m_success (true)
+ {
+   // "arguments" property (SARIF v2.1.0 section 3.20.2)
+   if (original_argv)
+     {
+       auto arguments_arr = std::make_unique<json::array> ();
+       for (size_t i = 0; original_argv[i]; ++i)
+ 	arguments_arr->append_string (original_argv[i]);
+       set<json::array> ("arguments", std::move (arguments_arr));
+     }
+ 
+   // "workingDirectory" property (SARIF v2.1.0 section 3.20.19)
+   if (const char *pwd = getpwd ())
+     set<sarif_artifact_location> ("workingDirectory",
+ 				  builder.make_artifact_location_object (pwd));
+ 
+   // "startTimeUtc" property (SARIF v2.1.0 section 3.20.7)
+   set<json::string> ("startTimeUtc",
+ 		     make_date_time_string_for_current_time ());
+ }
+ 
+ /* Handle an internal compiler error DIAGNOSTIC.
+    Add an object representing the ICE to the notifications array.  */
+ 
+ void
+ sarif_invocation::add_notification_for_ice (const diagnostic_info &diagnostic,
+ 					    sarif_builder &builder,
+ 					    std::unique_ptr<json::object> backtrace)
+ {
+   m_success = false;
+ 
+   auto notification
+     = std::make_unique<sarif_ice_notification> (diagnostic,
+ 						builder,
+ 						std::move (backtrace));
+ 
+   /* Support for related locations within a notification was added
+      in SARIF 2.2; see https://github.com/oasis-tcs/sarif-spec/issues/540  */
+   if (builder.get_version () >= sarif_version::v2_2_prerelease_2024_08_08)
+     notification->process_worklist (builder);
+ 
+   m_notifications_arr->append<sarif_ice_notification>
+     (std::move (notification));
+ }
+ 
+ void
+ sarif_invocation::prepare_to_flush (sarif_builder &builder)
+ {
+   const context &dc = builder.get_context ();
+ 
+   /* "executionSuccessful" property (SARIF v2.1.0 section 3.20.14).  */
+   if (dc.execution_failed_p ())
+     m_success = false;
+   set_bool ("executionSuccessful", m_success);
+ 
+   /* "toolExecutionNotifications" property (SARIF v2.1.0 section 3.20.21).  */
+   set ("toolExecutionNotifications", std::move (m_notifications_arr));
+ 
+   /* Call client hook, allowing it to create a custom property bag for
+      this object (SARIF v2.1.0 section 3.8) e.g. for recording time vars.  */
+   if (auto client_data_hooks = dc.get_client_data_hooks ())
+     client_data_hooks->add_sarif_invocation_properties (*this);
+ 
+   // "endTimeUtc" property (SARIF v2.1.0 section 3.20.8);
+   set<json::string> ("endTimeUtc",
+ 		     make_date_time_string_for_current_time ());
+ }
+ 
+ /* class sarif_artifact : public sarif_object.  */
+ 
+ /* Add ROLE to this artifact's roles.
+    If EMBED_CONTENTS is true, then flag that we will attempt to embed the
+    contents of this artifact when writing it out.  */
+ 
+ void
+ sarif_artifact::add_role (enum diagnostic_artifact_role role,
+ 			  bool embed_contents)
+ {
+   /* TODO(SARIF 2.2): "scannedFile" is to be added as a role in SARIF 2.2;
+      see https://github.com/oasis-tcs/sarif-spec/issues/459
+ 
+      For now, skip them.
+      Ultimately, we probably shouldn't bother embedding the contents
+      of such artifacts, just the snippets.  */
+   if (role == diagnostic_artifact_role::scanned_file)
+     return;
+ 
+   if (embed_contents)
+     m_embed_contents = true;
+ 
+   /* In SARIF v2.1.0 section 3.24.6 "roles" property:
+      "resultFile" is for an artifact
+      "which the analysis tool was not explicitly instructed to scan",
+      whereas "analysisTarget" is for one where the
+      "analysis tool was instructed to scan this artifact".
+      Hence the latter excludes the former.  */
+   if (role == diagnostic_artifact_role::result_file)
+     if (bitmap_bit_p (m_roles, (int)diagnostic_artifact_role::analysis_target))
+ 	return;
+ 
+   bitmap_set_bit (m_roles, (int)role);
+ }
+ 
+ /* Populate the "contents" property (SARIF v2.1.0 section 3.24.8).
+    We do this after initialization to
+    (a) ensure that any charset options have been set
+    (b) only populate it for artifacts that are referenced by a location.  */
+ 
+ void
+ sarif_artifact::populate_contents (sarif_builder &builder)
+ {
+   if (auto artifact_content_obj
+ 	= builder.maybe_make_artifact_content_object (m_filename))
+     set<sarif_artifact_content> ("contents", std::move (artifact_content_obj));
+ }
+ 
+ /* Get a string for ROLE corresponding to the
+    SARIF v2.1.0 section 3.24.6 "roles" property.  */
+ 
+ static const char *
+ get_artifact_role_string (enum diagnostic_artifact_role role)
+ {
+   switch (role)
+     {
+     default:
+       gcc_unreachable ();
+     case diagnostic_artifact_role::analysis_target:
+       return "analysisTarget";
+     case diagnostic_artifact_role::debug_output_file:
+       return "debugOutputFile";
+     case diagnostic_artifact_role::result_file:
+       return "resultFile";
+     case diagnostic_artifact_role::scanned_file:
+       return "scannedFile";
+     case diagnostic_artifact_role::traced_file:
+       return "tracedFile";
+     }
+ }
+ 
+ /* Populate the "roles" property of this sarif_artifact with a new
+    json::array for the artifact.roles property (SARIF v2.1.0 section 3.24.6)
+    containing strings such as "analysisTarget", "resultFile"
+    and/or "tracedFile".  */
+ 
+ void
+ sarif_artifact::populate_roles ()
+ {
+   if (bitmap_empty_p (m_roles))
+     return;
+   auto roles_arr (std::make_unique<json::array> ());
+   for (int i = 0; i < (int)diagnostic_artifact_role::NUM_ROLES; i++)
+     if (bitmap_bit_p (m_roles, i))
+       {
+ 	enum diagnostic_artifact_role role = (enum diagnostic_artifact_role)i;
+ 	roles_arr->append_string (get_artifact_role_string (role));
+       }
+   set<json::array> ("roles", std::move (roles_arr));
+ }
+ 
+ /* class sarif_location_manager : public sarif_object.  */
+ 
+ /* Base implementation of sarif_location_manager::add_related_location vfunc.
+ 
+    Add LOCATION_OBJ to this object's "relatedLocations" array,
+    creating it if it doesn't yet exist.  */
+ 
+ void
+ sarif_location_manager::
+ add_related_location (std::unique_ptr<sarif_location> location_obj,
+ 		      sarif_builder &)
+ {
+   if (!m_related_locations_arr)
+     {
+       m_related_locations_arr = new json::array ();
+       /* Give ownership of m_related_locations_arr to json::object;
+ 	 keep a borrowed ptr.  */
+       set ("relatedLocations", m_related_locations_arr);
+     }
+   m_related_locations_arr->append (std::move (location_obj));
+ }
+ 
+ void
+ sarif_location_manager::
+ add_relationship_to_worklist (sarif_location &location_obj,
+ 			      enum worklist_item::kind kind,
+ 			      location_t where)
+ {
+   m_worklist.push_back (worklist_item (location_obj,
+ 				       kind,
+ 				       where));
+ }
+ 
+ /* Process all items in this result's worklist.
+    Doing so may temporarily add new items to the end
+    of the worklist.
+    Handling any item should be "lazy", and thus we should
+    eventually drain the queue and terminate.  */
+ 
+ void
+ sarif_location_manager::process_worklist (sarif_builder &builder)
+ {
+   while (!m_worklist.empty ())
+     {
+       const worklist_item &item = m_worklist.front ();
+       process_worklist_item (builder, item);
+       m_worklist.pop_front ();
+     }
+ }
+ 
+ /* Process one item in this result's worklist, potentially
+    adding new items to the end of the worklist.  */
+ 
+ void
+ sarif_location_manager::process_worklist_item (sarif_builder &builder,
+ 					       const worklist_item &item)
+ {
+   switch (item.m_kind)
+     {
+     default:
+       gcc_unreachable ();
+     case worklist_item::kind::included_from:
+       {
+ 	sarif_location &included_loc_obj = item.m_location_obj;
+ 	sarif_location *includer_loc_obj = nullptr;
+ 	auto iter = m_included_from_locations.find (item.m_where);
+ 	if (iter != m_included_from_locations.end ())
+ 	  includer_loc_obj = iter->second;
+ 	else
+ 	  {
+ 	    std::unique_ptr<sarif_location> new_loc_obj
+ 	      = builder.make_location_object
+ 		  (*this,
+ 		   item.m_where,
+ 		   diagnostic_artifact_role::scanned_file);
+ 	    includer_loc_obj = new_loc_obj.get ();
+ 	    add_related_location (std::move (new_loc_obj), builder);
+ 	    auto kv
+ 	      = std::pair<location_t, sarif_location *> (item.m_where,
+ 							 includer_loc_obj);
+ 	    m_included_from_locations.insert (kv);
+ 	  }
+ 
+ 	includer_loc_obj->lazily_add_relationship
+ 	  (included_loc_obj,
+ 	   location_relationship_kind::includes,
+ 	   *this);
+ 	included_loc_obj.lazily_add_relationship
+ 	  (*includer_loc_obj,
+ 	   location_relationship_kind::is_included_by,
+ 	   *this);
+       }
+       break;
+     case worklist_item::kind::unlabelled_secondary_location:
+       {
+ 	sarif_location &primary_loc_obj = item.m_location_obj;
+ 	sarif_location *secondary_loc_obj = nullptr;
+ 	auto iter = m_unlabelled_secondary_locations.find (item.m_where);
+ 	if (iter != m_unlabelled_secondary_locations.end ())
+ 	  secondary_loc_obj = iter->second;
+ 	else
+ 	  {
+ 	    std::unique_ptr<sarif_location> new_loc_obj
+ 	      = builder.make_location_object
+ 		  (*this,
+ 		   item.m_where,
+ 		   diagnostic_artifact_role::scanned_file);
+ 	    secondary_loc_obj = new_loc_obj.get ();
+ 	    add_related_location (std::move (new_loc_obj), builder);
+ 	    auto kv
+ 	      = std::pair<location_t, sarif_location *> (item.m_where,
+ 							 secondary_loc_obj);
+ 	    m_unlabelled_secondary_locations.insert (kv);
+ 	  }
+ 	gcc_assert (secondary_loc_obj);
+ 	primary_loc_obj.lazily_add_relationship
+ 	  (*secondary_loc_obj,
+ 	   location_relationship_kind::relevant,
+ 	   *this);
+       }
+       break;
+     }
+ }
+ 
+ /* class sarif_result : public sarif_location_manager.  */
+ 
+ /* Handle secondary diagnostics that occur within a diagnostic group.
+    The closest SARIF seems to have to nested diagnostics is the
+    "relatedLocations" property of result objects (SARIF v2.1.0 section 3.27.22),
+    so we lazily set this property and populate the array if and when
+    secondary diagnostics occur (such as notes to a warning).  */
+ 
+ void
+ sarif_result::on_nested_diagnostic (const diagnostic_info &diagnostic,
+ 				    enum kind /*orig_diag_kind*/,
+ 				    sarif_builder &builder)
+ {
+   /* We don't yet generate meaningful logical locations for notes;
+      sometimes these will related to current_function_decl, but
+      often they won't.  */
+   auto location_obj
+     = builder.make_location_object (this, *diagnostic.m_richloc,
+ 				    logical_locations::key (),
+ 				    diagnostic_artifact_role::result_file);
+   auto message_obj
+     = builder.make_message_object (pp_formatted_text (builder.get_printer ()));
+   pp_clear_output_area (builder.get_printer ());
+   location_obj->set<sarif_message> ("message", std::move (message_obj));
+ 
+   /* Add nesting level, as per "P3358R0 SARIF for Structured Diagnostics"
+      https://wg21.link/P3358R0  */
+   sarif_property_bag &bag = location_obj->get_or_create_properties ();
+   bag.set_integer ("nestingLevel",
+ 		   builder.get_context ().get_diagnostic_nesting_level ());
+ 
+   add_related_location (std::move (location_obj), builder);
+ }
+ 
+ /* Handle diagrams that occur within a diagnostic group.
+    The closest thing in SARIF seems to be to add a location to the
+    "releatedLocations" property  (SARIF v2.1.0 section 3.27.22),
+    and to put the diagram into the "message" property of that location
+    (SARIF v2.1.0 section 3.28.5).  */
+ 
+ void
+ sarif_result::on_diagram (const diagram &d,
+ 			  sarif_builder &builder)
+ {
+   auto location_obj = std::make_unique<sarif_location> ();
+   auto message_obj = builder.make_message_object_for_diagram (d);
+   location_obj->set<sarif_message> ("message", std::move (message_obj));
+ 
+   add_related_location (std::move (location_obj), builder);
+ }
+ 
+ /* class sarif_location : public sarif_object.  */
+ 
+ /* Ensure this location has an "id" and return it.
+    Use LOC_MGR if an id needs to be allocated.
+ 
+    See the "id" property (3.28.2).
+ 
+    We use this to only assign ids to locations that are
+    referenced by another sarif object; others have no "id".   */
+ 
+ long
+ sarif_location::lazily_add_id (sarif_location_manager &loc_mgr)
+ {
+   long id = get_id ();
+   if (id != -1)
+     return id;
+   id = loc_mgr.allocate_location_id ();
+   set_integer ("id", id);
+   gcc_assert (id != -1);
+   return id;
+ }
+ 
+ /* Get the id of this location, or -1 if it doesn't have one.  */
+ 
+ long
+ sarif_location::get_id () const
+ {
+   json::value *id = get ("id");
+   if (!id)
+     return -1;
+   gcc_assert (id->get_kind () == json::JSON_INTEGER);
+   return static_cast <json::integer_number *> (id)->get ();
+ }
+ 
+ // 3.34.3 kinds property
+ static const char *
+ get_string_for_location_relationship_kind (enum location_relationship_kind kind)
+ {
+   switch (kind)
+     {
+     default:
+       gcc_unreachable ();
+     case location_relationship_kind::includes:
+       return "includes";
+     case location_relationship_kind::is_included_by:
+       return "isIncludedBy";
+     case location_relationship_kind::relevant:
+       return "relevant";
+     }
+ }
+ 
+ /* Lazily populate this location's "relationships" property (3.28.7)
+    with the relationship of KIND to TARGET, creating objects
+    as necessary.
+    Use LOC_MGR for any locations that need "id" values.  */
+ 
+ void
+ sarif_location::lazily_add_relationship (sarif_location &target,
+ 					 enum location_relationship_kind kind,
+ 					 sarif_location_manager &loc_mgr)
+ {
+   sarif_location_relationship &relationship_obj
+     = lazily_add_relationship_object (target, loc_mgr);
+ 
+   relationship_obj.lazily_add_kind (kind);
+ }
+ 
+ /* Lazily populate this location's "relationships" property (3.28.7)
+    with a location_relationship to TARGET, creating objects
+    as necessary.
+    Use LOC_MGR for any locations that need "id" values.  */
+ 
+ sarif_location_relationship &
+ sarif_location::lazily_add_relationship_object (sarif_location &target,
+ 						sarif_location_manager &loc_mgr)
+ {
+   /* See if THIS already has a locationRelationship referencing TARGET.  */
+   auto iter = m_relationships_map.find (&target);
+   if (iter != m_relationships_map.end ())
+     {
+       /* We already have a locationRelationship from THIS to TARGET.  */
+       sarif_location_relationship *relationship = iter->second;
+       gcc_assert (relationship->get_target_id() == target.get_id ());
+       return *relationship;
+     }
+ 
+   // Ensure that THIS has a "relationships" property (3.28.7).
+   json::array &relationships_arr = lazily_add_relationships_array ();
+ 
+   /* No existing locationRelationship from THIS to TARGET; make one,
+      record it, and add it to the "relationships" array.  */
+   auto relationship_obj
+     = std::make_unique<sarif_location_relationship> (target, loc_mgr);
+   sarif_location_relationship *relationship = relationship_obj.get ();
+   auto kv
+     = std::pair<sarif_location *,
+ 		sarif_location_relationship *> (&target, relationship);
+   m_relationships_map.insert (kv);
+ 
+   relationships_arr.append (std::move (relationship_obj));
+ 
+   return *relationship;
+ }
+ 
+ /* Ensure this location has a "relationships" array (3.28.7).  */
+ 
+ json::array &
+ sarif_location::lazily_add_relationships_array ()
+ {
+   const char *const property_name = "relationships";
+   if (json::value *relationships = get (property_name))
+     {
+       gcc_assert (relationships->get_kind () == json::JSON_ARRAY);
+       return *static_cast <json::array *> (relationships);
+     }
+   json::array *relationships_arr = new json::array ();
+   set (property_name, relationships_arr);
+   return *relationships_arr;
+ }
+ 
+ /* class sarif_ice_notification : public sarif_location_manager.  */
+ 
+ /* sarif_ice_notification's ctor.
+    DIAGNOSTIC is an internal compiler error.  */
+ 
+ sarif_ice_notification::
+ sarif_ice_notification (const diagnostic_info &diagnostic,
+ 			sarif_builder &builder,
+ 			std::unique_ptr<json::object> backtrace)
+ {
+   /* "locations" property (SARIF v2.1.0 section 3.58.4).  */
+   auto locations_arr
+     = builder.make_locations_arr (*this,
+ 				  diagnostic,
+ 				  diagnostic_artifact_role::result_file);
+   set<json::array> ("locations", std::move (locations_arr));
+ 
+   /* "message" property (SARIF v2.1.0 section 3.85.5).  */
+   auto message_obj
+     = builder.make_message_object (pp_formatted_text (builder.get_printer ()));
+   pp_clear_output_area (builder.get_printer ());
+   set<sarif_message> ("message", std::move (message_obj));
+ 
+   /* "level" property (SARIF v2.1.0 section 3.58.6).  */
+   set_string ("level", "error");
+ 
+   /* If we have backtrace information, add it as part of a property bag.  */
+   if (backtrace)
+     {
+       sarif_property_bag &bag = get_or_create_properties ();
+       bag.set ("gcc/backtrace", std::move (backtrace));
+     }
+ }
+ 
+ /* Implementation of sarif_location_manager::add_related_location vfunc
+    for notifications.  */
+ 
+ void
+ sarif_ice_notification::
+ add_related_location (std::unique_ptr<sarif_location> location_obj,
+ 		      sarif_builder &builder)
+ {
+   /* Support for related locations within a notification was added
+      in SARIF 2.2; see https://github.com/oasis-tcs/sarif-spec/issues/540  */
+   if (builder.get_version () >= sarif_version::v2_2_prerelease_2024_08_08)
+     sarif_location_manager::add_related_location (std::move (location_obj),
+ 						  builder);
+   /* Otherwise implicitly discard LOCATION_OBJ.  */
+ }
+ 
+ /* class sarif_location_relationship : public sarif_object.  */
+ 
+ sarif_location_relationship::
+ sarif_location_relationship (sarif_location &target,
+ 			     sarif_location_manager &loc_mgr)
+ : m_kinds ((unsigned)location_relationship_kind::NUM_KINDS)
+ {
+   bitmap_clear (m_kinds);
+   set_integer ("target", target.lazily_add_id (loc_mgr));
+ }
+ 
+ long
+ sarif_location_relationship::get_target_id () const
+ {
+   json::value *id = get ("id");
+   gcc_assert (id);
+   return static_cast <json::integer_number *> (id)->get ();
+ }
+ 
+ void
+ sarif_location_relationship::
+ lazily_add_kind (enum location_relationship_kind kind)
+ {
+   if (bitmap_bit_p (m_kinds, (int)kind))
+     return; // already have this kind
+   bitmap_set_bit (m_kinds, (int)kind);
+ 
+   // 3.34.3 kinds property
+   json::array *kinds_arr = nullptr;
+   if (json::value *kinds_val = get ("kinds"))
+     {
+       gcc_assert (kinds_val->get_kind () == json::JSON_ARRAY);
+     }
+   else
+     {
+       kinds_arr = new json::array ();
+       set ("kinds", kinds_arr);
+     }
+   const char *kind_str = get_string_for_location_relationship_kind (kind);
+   kinds_arr->append_string (kind_str);
+ }
+ 
+ /* class sarif_code_flow : public sarif_object.  */
+ 
+ sarif_code_flow::sarif_code_flow (sarif_result &parent,
+ 				  unsigned idx_within_parent)
+ : m_parent (parent),
+   m_idx_within_parent (idx_within_parent)
+ {
+   /* "threadFlows" property (SARIF v2.1.0 section 3.36.3).  */
+   auto thread_flows_arr = std::make_unique<json::array> ();
+   m_thread_flows_arr = thread_flows_arr.get (); // borrowed
+   set<json::array> ("threadFlows", std::move (thread_flows_arr));
+ }
+ 
+ sarif_thread_flow &
+ sarif_code_flow::get_or_append_thread_flow (const paths::thread &thread,
+ 					    paths::thread_id_t thread_id)
+ {
+   sarif_thread_flow **slot = m_thread_id_map.get (thread_id);
+   if (slot)
+     return **slot;
+ 
+   unsigned next_thread_flow_idx = m_thread_flows_arr->size ();
+   auto thread_flow_obj
+     = std::make_unique<sarif_thread_flow> (*this, thread, next_thread_flow_idx);
+   m_thread_id_map.put (thread_id, thread_flow_obj.get ()); // borrowed
+   sarif_thread_flow *result = thread_flow_obj.get ();
+   m_thread_flows_arr->append<sarif_thread_flow> (std::move (thread_flow_obj));
+   return *result;
+ }
+ 
+ sarif_thread_flow &
+ sarif_code_flow::get_thread_flow (paths::thread_id_t thread_id)
+ {
+   sarif_thread_flow **slot = m_thread_id_map.get (thread_id);
+   gcc_assert (slot); // it must already have one
+   return **slot;
+ }
+ 
+ void
+ sarif_code_flow::add_location (sarif_thread_flow_location &tfl_obj)
+ {
+   m_all_tfl_objs.push_back (&tfl_obj);
+ }
+ 
+ sarif_thread_flow_location &
+ sarif_code_flow::get_thread_flow_loc_obj (paths::event_id_t event_id) const
+ {
+   gcc_assert (event_id.known_p ());
+   gcc_assert ((size_t)event_id.zero_based () < m_all_tfl_objs.size ());
+   sarif_thread_flow_location *tfl_obj = m_all_tfl_objs[event_id.zero_based ()];
+   gcc_assert (tfl_obj);
+   return *tfl_obj;
+ }
+ 
+ /* class sarif_thread_flow : public sarif_object.  */
+ 
+ sarif_thread_flow::sarif_thread_flow (sarif_code_flow &parent,
+ 				      const paths::thread &thread,
+ 				      unsigned idx_within_parent)
+ : m_parent (parent),
+   m_idx_within_parent (idx_within_parent)
+ {
+   /* "id" property (SARIF v2.1.0 section 3.37.2).  */
+   label_text name (thread.get_name (false));
+   set_string ("id", name.get ());
+ 
+   /* "locations" property (SARIF v2.1.0 section 3.37.6).  */
+   m_locations_arr = new json::array ();
+ 
+   /* Give ownership of m_locations_arr to json::object;
+      keep a borrowed ptr.  */
+   set ("locations", m_locations_arr);
+ }
+ 
+ /* Add a sarif_thread_flow_location to this threadFlow object, but
+    don't populate it yet.  */
+ 
+ sarif_thread_flow_location &
+ sarif_thread_flow::add_location ()
+ {
+   const unsigned thread_flow_location_idx = m_locations_arr->size ();
+   sarif_thread_flow_location *thread_flow_loc_obj
+     = new sarif_thread_flow_location (*this, thread_flow_location_idx);
+   m_locations_arr->append (thread_flow_loc_obj);
+   m_parent.add_location (*thread_flow_loc_obj);
+   return *thread_flow_loc_obj;
+ }
+ 
+ /* class sarif_builder.  */
+ 
+ /* sarif_builder's ctor.  */
+ 
+ sarif_builder::sarif_builder (diagnostics::context &dc,
+ 			      pretty_printer &printer,
+ 			      const line_maps *line_maps,
+ 			      std::unique_ptr<sarif_serialization_format> serialization_format,
+ 			      const sarif_generation_options &sarif_gen_opts)
+ : m_context (dc),
+   m_printer (&printer),
+   m_line_maps (line_maps),
+   m_token_printer (*this),
+   m_logical_loc_mgr (nullptr),
+   m_invocation_obj
+     (std::make_unique<sarif_invocation> (*this,
+ 					 dc.get_original_argv ())),
+   m_results_array (new json::array ()),
+   m_cur_group_result (nullptr),
+   m_seen_any_relative_paths (false),
+   m_rule_id_set (),
+   m_rules_arr (new json::array ()),
+   m_cached_logical_locs
+     (std::make_unique<sarif_array_of_unique<sarif_logical_location>> ()),
+   m_run_graphs
+     (std::make_unique<sarif_array_of_unique<sarif_graph>> ()),
+   m_tabstop (dc.m_tabstop),
+   m_serialization_format (std::move (serialization_format)),
+   m_sarif_gen_opts (sarif_gen_opts),
+   m_next_result_idx (0),
+   m_current_code_flow (nullptr)
+ {
+   gcc_assert (m_line_maps);
+   gcc_assert (m_serialization_format);
+ 
+   if (auto client_data_hooks = dc.get_client_data_hooks ())
+     m_logical_loc_mgr = client_data_hooks->get_logical_location_manager ();
+ }
+ 
+ sarif_builder::~sarif_builder ()
+ {
+   /* Normally m_filename_to_artifact_map will have been emptied as part
+      of make_run_object, but this isn't run by all the selftests.
+      Ensure the artifact objects are cleaned up for such cases.  */
+   for (auto iter : m_filename_to_artifact_map)
+     {
+       sarif_artifact *artifact_obj = iter.second;
+       delete artifact_obj;
+     }
+ }
+ 
+ /* Functions at which to stop the backtrace print.  It's not
+    particularly helpful to print the callers of these functions.  */
+ 
+ static const char * const bt_stop[] =
+ {
+   "main",
+   "toplev::main",
+   "execute_one_pass",
+   "compile_file",
+ };
+ 
+ struct bt_closure
+ {
+   bt_closure (sarif_builder &builder,
+ 	      json::array *frames_arr)
+   : m_builder (builder),
+     m_frames_arr (frames_arr)
+   {
+   }
+ 
+   sarif_builder &m_builder;
+   json::array *m_frames_arr;
+ };
+ 
+ /* A callback function passed to the backtrace_full function.  */
+ 
+ static int
+ bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
+ 	     const char *function)
+ {
+   bt_closure *closure = (bt_closure *)data;
+ 
+   /* If we don't have any useful information, don't print
+      anything.  */
+   if (filename == nullptr && function == nullptr)
+     return 0;
+ 
+   /* Skip functions in context.cc or diagnostic-global-context.cc.  */
+   if (closure->m_frames_arr->size () == 0
+       && filename != nullptr
+       && (strcmp (lbasename (filename), "context.cc") == 0
+ 	  || strcmp (lbasename (filename),
+ 		     "diagnostic-global-context.cc") == 0))
+     return 0;
+ 
+   /* Print up to 20 functions.  We could make this a --param, but
+      since this is only for debugging just use a constant for now.  */
+   if (closure->m_frames_arr->size () >= 20)
+     {
+       /* Returning a non-zero value stops the backtrace.  */
+       return 1;
+     }
+ 
+   char *alc = nullptr;
+   if (function != nullptr)
+     {
+       char *str = cplus_demangle_v3 (function,
+ 				     (DMGL_VERBOSE | DMGL_ANSI
+ 				      | DMGL_GNU_V3 | DMGL_PARAMS));
+       if (str != nullptr)
+ 	{
+ 	  alc = str;
+ 	  function = str;
+ 	}
+ 
+       for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
+ 	{
+ 	  size_t len = strlen (bt_stop[i]);
+ 	  if (strncmp (function, bt_stop[i], len) == 0
+ 	      && (function[len] == '\0' || function[len] == '('))
+ 	    {
+ 	      if (alc != nullptr)
+ 		free (alc);
+ 	      /* Returning a non-zero value stops the backtrace.  */
+ 	      return 1;
+ 	    }
+ 	}
+     }
+ 
+   auto frame_obj = std::make_unique<json::object> ();
+ 
+   /* I tried using sarifStack and sarifStackFrame for this
+      but it's not a good fit e.g. PC information.  */
+   char buf[128];
+   snprintf (buf, sizeof (buf) - 1, "0x%lx", (unsigned long)pc);
+   frame_obj->set_string ("pc", buf);
+   if (function)
+     frame_obj->set_string ("function", function);
+   if (filename)
+     frame_obj->set_string ("filename", filename);
+   frame_obj->set_integer ("lineno", lineno);
+   closure->m_frames_arr->append (std::move (frame_obj));
+ 
+   if (alc != nullptr)
+     free (alc);
+ 
+   return 0;
+ }
+ 
+ /* Attempt to generate a JSON object representing a backtrace,
+    for adding to ICE notifications.  */
+ 
+ std::unique_ptr<json::object>
+ sarif_builder::make_stack_from_backtrace ()
+ {
+   auto frames_arr = std::make_unique<json::array> ();
+ 
+   backtrace_state *state = nullptr;
+   state = backtrace_create_state (nullptr, 0, nullptr, nullptr);
+   bt_closure closure (*this, frames_arr.get ());
+   const int frames_to_skip = 5;
+   if (state != nullptr)
+     backtrace_full (state, frames_to_skip, bt_callback, nullptr,
+ 		    (void *) &closure);
+ 
+   if (frames_arr->size () == 0)
+     return nullptr;
+ 
+   auto stack = std::make_unique<json::object> ();
+   stack->set ("frames", std::move (frames_arr));
+   return stack;
+ }
+ 
+ void
+ sarif_builder::set_main_input_filename (const char *name)
+ {
+   /* Mark NAME as the artifact that the tool was instructed to scan.
+      Only quote the contents if it gets referenced by physical locations,
+      since otherwise the "no diagnostics" case would quote the main input
+      file, and doing so noticeably bloated the output seen in analyzer
+      integration testing (build directory went from 20G -> 21G).  */
+   if (name)
+     get_or_create_artifact (name,
+ 			    diagnostic_artifact_role::analysis_target,
+ 			    false);
+ }
+ 
+ /* Implementation of "on_report_diagnostic" for SARIF output.  */
+ 
+ void
+ sarif_builder::on_report_diagnostic (const diagnostic_info &diagnostic,
+ 				     enum kind orig_diag_kind,
+ 				     sarif_sink_buffer *buffer)
+ {
+   pp_output_formatted_text (m_printer, m_context.get_urlifier ());
+ 
+   if (diagnostic.m_kind == kind::ice || diagnostic.m_kind == kind::ice_nobt)
+     {
+       std::unique_ptr<json::object> stack = make_stack_from_backtrace ();
+       m_invocation_obj->add_notification_for_ice (diagnostic, *this,
+ 						  std::move (stack));
+ 
+       /* Print a header for the remaining output to stderr, and
+ 	 return, attempting to print the usual ICE messages to
+ 	 stderr.  Hopefully this will be helpful to the user in
+ 	 indicating what's gone wrong (also for DejaGnu, for pruning
+ 	 those messages).   */
+       fnotice (stderr, "Internal compiler error:\n");
+ 
+       return;
+     }
+ 
+   if (buffer)
+     {
+       /* When buffering, we can only handle top-level results.  */
+       gcc_assert (!m_cur_group_result);
+       buffer->add_result (make_result_object (diagnostic, orig_diag_kind,
+ 					      m_next_result_idx++));
+       return;
+     }
+ 
+   if (m_cur_group_result)
+     /* Nested diagnostic.  */
+     m_cur_group_result->on_nested_diagnostic (diagnostic,
+ 					      orig_diag_kind,
+ 					      *this);
+   else
+     {
+       /* Top-level diagnostic.  */
+       m_cur_group_result = make_result_object (diagnostic, orig_diag_kind,
+ 					       m_next_result_idx++);
+     }
+ }
+ 
+ /* Implementation of diagnostics::context::m_diagrams.m_emission_cb
+    for SARIF output.  */
+ 
+ void
+ sarif_builder::emit_diagram (const diagram &d)
+ {
+   /* We must be within the emission of a top-level diagnostic.  */
+   gcc_assert (m_cur_group_result);
+   m_cur_group_result->on_diagram (d, *this);
+ }
+ 
+ /* Implementation of "end_group_cb" for SARIF output.  */
+ 
+ void
+ sarif_builder::end_group ()
+ {
+   if (m_cur_group_result)
+     {
+       m_cur_group_result->process_worklist (*this);
+       m_results_array->append<sarif_result> (std::move (m_cur_group_result));
+     }
+ }
+ 
+ void
+ sarif_builder::
+ report_global_digraph (const lazily_created<digraphs::digraph> &ldg)
+ {
+   auto &dg = ldg.get_or_create ();
+ 
+   /* Presumably the location manager must be nullptr; see
+      https://github.com/oasis-tcs/sarif-spec/issues/712  */
+   m_run_graphs->append (make_sarif_graph (dg, this, nullptr));
+ }
+ 
+ /* Create a top-level object, and add it to all the results
+    (and other entities) we've seen so far, moving ownership
+    to the object.  */
+ 
+ std::unique_ptr<sarif_log>
+ sarif_builder::flush_to_object ()
+ {
+   m_invocation_obj->prepare_to_flush (*this);
+   std::unique_ptr<sarif_log> top
+     = make_top_level_object (std::move (m_invocation_obj),
+ 			     std::move (m_results_array));
+   return top;
+ }
+ 
+ /* Create a top-level object, and add it to all the results
+    (and other entities) we've seen so far.
+ 
+    Flush it all to OUTF.  */
+ 
+ void
+ sarif_builder::flush_to_file (FILE *outf)
+ {
+   std::unique_ptr<sarif_log> top = flush_to_object ();
+   m_serialization_format->write_to_file (outf, *top);
+ }
+ 
+ /* Attempt to convert DIAG_KIND to a suitable value for the "level"
+    property (SARIF v2.1.0 section 3.27.10).
+ 
+    Return nullptr if there isn't one.  */
+ 
+ static const char *
+ maybe_get_sarif_level (enum kind diag_kind)
+ {
+   switch (diag_kind)
+     {
+     case kind::warning:
+       return "warning";
+     case kind::error:
+       return "error";
+     case kind::note:
+     case kind::anachronism:
+       return "note";
+     default:
+       return nullptr;
+     }
+ }
+ 
+ /* Make a string for DIAG_KIND suitable for use a ruleId
+    (SARIF v2.1.0 section 3.27.5) as a fallback for when we don't
+    have anything better to use.  */
+ 
+ static char *
+ make_rule_id_for_diagnostic_kind (enum kind diag_kind)
+ {
+   /* Lose the trailing ": ".  */
+   const char *kind_text = get_text_for_kind (diag_kind);
+   size_t len = strlen (kind_text);
+   gcc_assert (len > 2);
+   gcc_assert (kind_text[len - 2] == ':');
+   gcc_assert (kind_text[len - 1] == ' ');
+   char *rstrip = xstrdup (kind_text);
+   rstrip[len - 2] = '\0';
+   return rstrip;
+ }
+ 
+ /* Make a "result" object (SARIF v2.1.0 section 3.27) for DIAGNOSTIC.  */
+ 
+ std::unique_ptr<sarif_result>
+ sarif_builder::make_result_object (const diagnostic_info &diagnostic,
+ 				   enum kind orig_diag_kind,
+ 				   unsigned idx_within_parent)
+ {
+   auto result_obj = std::make_unique<sarif_result> (idx_within_parent);
+ 
+   /* "ruleId" property (SARIF v2.1.0 section 3.27.5).  */
+   /* Ideally we'd have an option_name for these.  */
+   if (char *option_text
+ 	= m_context.make_option_name (diagnostic.m_option_id,
+ 				      orig_diag_kind, diagnostic.m_kind))
+     {
+       /* Lazily create reportingDescriptor objects for and add to m_rules_arr.
+ 	 Set ruleId referencing them.  */
+       result_obj->set_string ("ruleId", option_text);
+       if (m_rule_id_set.contains (option_text))
+ 	free (option_text);
+       else
+ 	{
+ 	  /* This is the first time we've seen this ruleId.  */
+ 	  /* Add to set, taking ownership.  */
+ 	  m_rule_id_set.add (option_text);
+ 
+ 	  m_rules_arr->append<sarif_reporting_descriptor>
+ 	    (make_reporting_descriptor_object_for_warning (diagnostic,
+ 							   orig_diag_kind,
+ 							   option_text));
+ 	}
+     }
+   else
+     {
+       /* Otherwise, we have an "error" or a stray "note"; use the
+ 	 diagnostic kind as the ruleId, so that the result object at least
+ 	 has a ruleId.
+ 	 We don't bother creating reportingDescriptor objects for these.  */
+       char *rule_id = make_rule_id_for_diagnostic_kind (orig_diag_kind);
+       result_obj->set_string ("ruleId", rule_id);
+       free (rule_id);
+     }
+ 
+   if (diagnostic.m_metadata)
+     {
+       /* "taxa" property (SARIF v2.1.0 section 3.27.8).  */
+       if (int cwe_id = diagnostic.m_metadata->get_cwe ())
+ 	{
+ 	  auto taxa_arr = std::make_unique<json::array> ();
+ 	  taxa_arr->append<sarif_reporting_descriptor_reference>
+ 	    (make_reporting_descriptor_reference_object_for_cwe_id (cwe_id));
+ 	  result_obj->set<json::array> ("taxa", std::move (taxa_arr));
+ 	}
+ 
+       diagnostic.m_metadata->maybe_add_sarif_properties (*result_obj);
+ 
+       /* We don't yet support diagnostics::metadata::rule.  */
+     }
+ 
+   /* "level" property (SARIF v2.1.0 section 3.27.10).  */
+   if (const char *sarif_level = maybe_get_sarif_level (diagnostic.m_kind))
+     result_obj->set_string ("level", sarif_level);
+ 
+   /* "message" property (SARIF v2.1.0 section 3.27.11).  */
+   auto message_obj
+     = make_message_object (pp_formatted_text (m_printer));
+   pp_clear_output_area (m_printer);
+   result_obj->set<sarif_message> ("message", std::move (message_obj));
+ 
+   /* "locations" property (SARIF v2.1.0 section 3.27.12).  */
+   result_obj->set<json::array>
+     ("locations",
+      make_locations_arr (*result_obj.get (),
+ 			 diagnostic,
+ 			 diagnostic_artifact_role::result_file));
+ 
+   /* "codeFlows" property (SARIF v2.1.0 section 3.27.18).  */
+   if (const paths::path *path = diagnostic.m_richloc->get_path ())
+     {
+       auto code_flows_arr = std::make_unique<json::array> ();
+       const unsigned code_flow_index = 0;
+       code_flows_arr->append<sarif_code_flow>
+ 	(make_code_flow_object (*result_obj.get (),
+ 				code_flow_index,
+ 				*path));
+       result_obj->set<json::array> ("codeFlows", std::move (code_flows_arr));
+     }
+ 
+   // "graphs" property (SARIF v2.1.0 section 3.27.19).  */
+   if (diagnostic.m_metadata)
+     if (auto ldg = diagnostic.m_metadata->get_lazy_digraphs ())
+       {
+ 	auto &digraphs = ldg->get_or_create ();
+ 	auto graphs_arr = std::make_unique<json::array> ();
+ 	for (auto &iter : digraphs)
+ 	  graphs_arr->append (make_sarif_graph (*iter, this,
+ 						result_obj.get ()));
+ 	if (graphs_arr->size () > 0)
+ 	  result_obj->set<json::array> ("graphs", std::move (graphs_arr));
+       }
+ 
+   /* The "relatedLocations" property (SARIF v2.1.0 section 3.27.22) is
+      set up later, if any nested diagnostics occur within this diagnostic
+      group.  */
+ 
+   /* "fixes" property (SARIF v2.1.0 section 3.27.30).  */
+   const rich_location *richloc = diagnostic.m_richloc;
+   if (richloc->get_num_fixit_hints ())
+     {
+       auto fix_arr = std::make_unique<json::array> ();
+       fix_arr->append<sarif_fix> (make_fix_object (*richloc));
+       result_obj->set<json::array> ("fixes", std::move (fix_arr));
+     }
+ 
+   return result_obj;
+ }
+ 
+ /* Make a "reportingDescriptor" object (SARIF v2.1.0 section 3.49)
+    for a GCC warning.  */
+ 
+ std::unique_ptr<sarif_reporting_descriptor>
+ sarif_builder::
+ make_reporting_descriptor_object_for_warning (const diagnostic_info &diagnostic,
+ 					      enum kind /*orig_diag_kind*/,
+ 					      const char *option_text)
+ {
+   auto reporting_desc = std::make_unique<sarif_reporting_descriptor> ();
+ 
+   /* "id" property (SARIF v2.1.0 section 3.49.3).  */
+   reporting_desc->set_string ("id", option_text);
+ 
+   /* We don't implement "name" property (SARIF v2.1.0 section 3.49.7), since
+      it seems redundant compared to "id".  */
+ 
+   /* "helpUri" property (SARIF v2.1.0 section 3.49.12).  */
+   if (char *option_url = m_context.make_option_url (diagnostic.m_option_id))
+     {
+       reporting_desc->set_string ("helpUri", option_url);
+       free (option_url);
+     }
+ 
+   return reporting_desc;
+ }
+ 
+ /* Make a "reportingDescriptor" object (SARIF v2.1.0 section 3.49)
+    for CWE_ID, for use within the CWE taxa array.  */
+ 
+ std::unique_ptr<sarif_reporting_descriptor>
+ sarif_builder::make_reporting_descriptor_object_for_cwe_id (int cwe_id) const
+ {
+   auto reporting_desc = std::make_unique<sarif_reporting_descriptor> ();
+ 
+   /* "id" property (SARIF v2.1.0 section 3.49.3).  */
+   {
+     pretty_printer pp;
+     pp_printf (&pp, "%i", cwe_id);
+     reporting_desc->set_string ("id", pp_formatted_text (&pp));
+   }
+ 
+   /* "helpUri" property (SARIF v2.1.0 section 3.49.12).  */
+   {
+     char *url = get_cwe_url (cwe_id);
+     reporting_desc->set_string ("helpUri", url);
+     free (url);
+   }
+ 
+   return reporting_desc;
+ }
+ 
+ /* Make a "reportingDescriptorReference" object (SARIF v2.1.0 section 3.52)
+    referencing CWE_ID, for use within a result object.
+    Also, add CWE_ID to m_cwe_id_set.  */
+ 
+ std::unique_ptr<sarif_reporting_descriptor_reference>
+ sarif_builder::
+ make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id)
+ {
+   auto desc_ref_obj = std::make_unique<sarif_reporting_descriptor_reference> ();
+ 
+   /* "id" property (SARIF v2.1.0 section 3.52.4).  */
+   {
+     pretty_printer pp;
+     pp_printf (&pp, "%i", cwe_id);
+     desc_ref_obj->set_string ("id", pp_formatted_text (&pp));
+   }
+ 
+   /* "toolComponent" property (SARIF v2.1.0 section 3.52.7).  */
+   desc_ref_obj->set<sarif_tool_component_reference>
+     ("toolComponent", make_tool_component_reference_object_for_cwe ());
+ 
+   /* Add CWE_ID to our set.  */
+   gcc_assert (cwe_id > 0);
+   m_cwe_id_set.add (cwe_id);
+ 
+   return desc_ref_obj;
+ }
+ 
+ /* Make a "toolComponentReference" object (SARIF v2.1.0 section 3.54) that
+    references the CWE taxonomy.  */
+ 
+ std::unique_ptr<sarif_tool_component_reference>
+ sarif_builder::
+ make_tool_component_reference_object_for_cwe () const
+ {
+   auto comp_ref_obj = std::make_unique<sarif_tool_component_reference> ();
+ 
+   /* "name" property  (SARIF v2.1.0 section 3.54.3).  */
+   comp_ref_obj->set_string ("name", "cwe");
+ 
+   return comp_ref_obj;
+ }
+ 
+ /* Make an array suitable for use as the "locations" property of:
+    - a "result" object (SARIF v2.1.0 section 3.27.12), or
+    - a "notification" object (SARIF v2.1.0 section 3.58.4).
+    Use LOC_MGR for any locations that need "id" values.  */
+ 
+ std::unique_ptr<json::array>
+ sarif_builder::make_locations_arr (sarif_location_manager &loc_mgr,
+ 				   const diagnostic_info &diagnostic,
+ 				   enum diagnostic_artifact_role role)
+ {
+   auto locations_arr = std::make_unique<json::array> ();
+   logical_locations::key logical_loc;
+   if (auto client_data_hooks = m_context.get_client_data_hooks ())
+     logical_loc = client_data_hooks->get_current_logical_location ();
+ 
+   auto location_obj
+     = make_location_object (&loc_mgr, *diagnostic.m_richloc, logical_loc, role);
+   /* Don't add entirely empty location objects to the array.  */
+   if (!location_obj->is_empty ())
+     locations_arr->append<sarif_location> (std::move (location_obj));
+ 
+   return locations_arr;
+ }
+ 
+ /* If LOGICAL_LOC is non-null, use it to create a "logicalLocations" property
+    within LOCATION_OBJ (SARIF v2.1.0 section 3.28.4) with a minimal logical
+    location object referencing theRuns.logicalLocations (3.33.3).  */
+ 
+ void
+ sarif_builder::
+ set_any_logical_locs_arr (sarif_location &location_obj,
+ 			  logical_locations::key logical_loc)
+ {
+   if (!logical_loc)
+     return;
+   gcc_assert (m_logical_loc_mgr);
+   auto location_locs_arr = std::make_unique<json::array> ();
+ 
+   auto logical_loc_obj = make_minimal_sarif_logical_location (logical_loc);
+ 
+   location_locs_arr->append<sarif_logical_location>
+     (std::move (logical_loc_obj));
+ 
+   location_obj.set<json::array> ("logicalLocations",
+ 				 std::move (location_locs_arr));
+ }
+ 
+ /* Make a "location" object (SARIF v2.1.0 section 3.28) for RICH_LOC
+    and LOGICAL_LOC.
+    Use LOC_MGR for any locations that need "id" values, and for
+    any worklist items.
+    Note that we might not always have a LOC_MGR; see
+    https://github.com/oasis-tcs/sarif-spec/issues/712  */
+ 
+ std::unique_ptr<sarif_location>
+ sarif_builder::make_location_object (sarif_location_manager *loc_mgr,
+ 				     const rich_location &rich_loc,
+ 				     logical_locations::key logical_loc,
+ 				     enum diagnostic_artifact_role role)
+ {
+   class escape_nonascii_renderer : public content_renderer
+   {
+   public:
+     escape_nonascii_renderer (const rich_location &richloc,
+ 			      enum diagnostics_escape_format escape_format)
+     : m_richloc (richloc),
+       m_escape_format (escape_format)
+     {}
+ 
+     std::unique_ptr<sarif_multiformat_message_string>
+     render (const sarif_builder &builder) const final override
+     {
+       diagnostics::context dc;
+       diagnostic_initialize (&dc, 0);
+       auto &source_printing_opts = dc.get_source_printing_options ();
+       source_printing_opts.enabled = true;
+       source_printing_opts.colorize_source_p = false;
+       source_printing_opts.show_labels_p = true;
+       source_printing_opts.show_line_numbers_p = true;
+ 
+       rich_location my_rich_loc (m_richloc);
+       my_rich_loc.set_escape_on_output (true);
+ 
+       source_print_policy source_policy (dc);
+       dc.set_escape_format (m_escape_format);
+       text_sink text_output (dc);
+       source_policy.print (*text_output.get_printer (),
+ 			   my_rich_loc, kind::error, nullptr);
+ 
+       const char *buf = pp_formatted_text (text_output.get_printer ());
+       std::unique_ptr<sarif_multiformat_message_string> result
+ 	= builder.make_multiformat_message_string (buf);
+ 
+       diagnostic_finish (&dc);
+ 
+       return result;
+     }
+   private:
+     const rich_location &m_richloc;
+     enum diagnostics_escape_format m_escape_format;
+   } the_renderer (rich_loc,
+ 		  m_context.get_escape_format ());
+ 
+   auto location_obj = std::make_unique<sarif_location> ();
+ 
+   /* Get primary loc from RICH_LOC.  */
+   location_t loc = rich_loc.get_loc ();
+ 
+   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
+   const content_renderer *snippet_renderer
+     = rich_loc.escape_on_output_p () ? &the_renderer : nullptr;
+   if (auto phs_loc_obj
+ 	= maybe_make_physical_location_object (loc, role,
+ 					       rich_loc.get_column_override (),
+ 					       snippet_renderer))
+     location_obj->set<sarif_physical_location> ("physicalLocation",
+ 						std::move (phs_loc_obj));
+ 
+   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
+   set_any_logical_locs_arr (*location_obj, logical_loc);
+ 
+   /* Handle labelled ranges and/or secondary locations.  */
+   {
+     std::unique_ptr<json::array> annotations_arr = nullptr;
+     for (unsigned int i = 0; i < rich_loc.get_num_locations (); i++)
+       {
+ 	const location_range *range = rich_loc.get_range (i);
+ 	bool handled = false;
+ 	if (const range_label *label = range->m_label)
+ 	  {
+ 	    label_text text = label->get_text (i);
+ 	    if (text.get ())
+ 	      {
+ 		/* Create annotations for any labelled ranges.  */
+ 		location_t range_loc = rich_loc.get_loc (i);
+ 		auto region
+ 		  = maybe_make_region_object (range_loc,
+ 					      rich_loc.get_column_override ());
+ 		if (region)
+ 		  {
+ 		    if (!annotations_arr)
+ 		      annotations_arr = std::make_unique<json::array> ();
+ 		    region->set<sarif_message>
+ 		      ("message", make_message_object (text.get ()));
+ 		    annotations_arr->append<sarif_region> (std::move (region));
+ 		    handled = true;
+ 		  }
+ 	      }
+ 	  }
+ 
+ 	/* Add related locations for any secondary locations in RICH_LOC
+ 	   that don't have labels (and thus aren't added to "annotations"). */
+ 	if (loc_mgr && i > 0 && !handled)
+ 	  loc_mgr->add_relationship_to_worklist
+ 	    (*location_obj.get (),
+ 	     sarif_location_manager::worklist_item::kind::unlabelled_secondary_location,
+ 	     range->m_loc);
+       }
+     if (annotations_arr)
+       /* "annotations" property (SARIF v2.1.0 section 3.28.6).  */
+       location_obj->set<json::array> ("annotations",
+ 				      std::move (annotations_arr));
+   }
+ 
+   if (loc_mgr)
+     add_any_include_chain (*loc_mgr, *location_obj.get (), loc);
+ 
+   /* A flag for hinting that the diagnostic involves issues at the
+      level of character encodings (such as homoglyphs, or misleading
+      bidirectional control codes), and thus that it will be helpful
+      to the user if we show some representation of
+      how the characters in the pertinent source lines are encoded.  */
+   if (rich_loc.escape_on_output_p ())
+     {
+       sarif_property_bag &bag = location_obj->get_or_create_properties ();
+       bag.set_bool ("gcc/escapeNonAscii", rich_loc.escape_on_output_p ());
+     }
+ 
+   return location_obj;
+ }
+ 
+ /* If WHERE was #included from somewhere, add a worklist item
+    to LOC_MGR to lazily add a location for the #include location,
+    and relationships between it and the LOCATION_OBJ.
+    Compare with diagnostics::context::report_current_module, but rather
+    than iterating the current chain, we add the next edge and iterate
+    in the worklist, so that edges are only added once.  */
+ 
+ void
+ sarif_builder::add_any_include_chain (sarif_location_manager &loc_mgr,
+ 				      sarif_location &location_obj,
+ 				      location_t where)
+ {
+   if (where <= BUILTINS_LOCATION)
+     return;
+ 
+   const line_map_ordinary *map = nullptr;
+   linemap_resolve_location (m_line_maps, where,
+ 			    LRK_MACRO_DEFINITION_LOCATION,
+ 			    &map);
+ 
+   if (!map)
+     return;
+ 
+   location_t include_loc = linemap_included_from (map);
+   map = linemap_included_from_linemap (m_line_maps, map);
+   if (!map)
+     return;
+   loc_mgr.add_relationship_to_worklist
+     (location_obj,
+      sarif_result::worklist_item::kind::included_from,
+      include_loc);
+ }
+ 
+ /* Make a "location" object (SARIF v2.1.0 section 3.28) for WHERE
+    within an include chain.  */
+ 
+ std::unique_ptr<sarif_location>
+ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
+ 				     location_t loc,
+ 				     enum diagnostic_artifact_role role)
+ {
+   auto location_obj = std::make_unique<sarif_location> ();
+ 
+   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
+   if (auto phs_loc_obj
+       = maybe_make_physical_location_object (loc, role, 0, nullptr))
+     location_obj->set<sarif_physical_location> ("physicalLocation",
+ 						std::move (phs_loc_obj));
+ 
+   add_any_include_chain (loc_mgr, *location_obj.get (), loc);
+ 
+   return location_obj;
+ }
+ 
+ /* Make a "location" object (SARIF v2.1.0 section 3.28) for EVENT
+    within a paths::path.  */
+ 
+ std::unique_ptr<sarif_location>
+ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
+ 				     const paths::event &event,
+ 				     enum diagnostic_artifact_role role)
+ {
+   auto location_obj = std::make_unique<sarif_location> ();
+ 
+   /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3).  */
+   location_t loc = event.get_location ();
+   if (auto phs_loc_obj
+ 	= maybe_make_physical_location_object (loc, role, 0, nullptr))
+     location_obj->set<sarif_physical_location> ("physicalLocation",
+ 						std::move (phs_loc_obj));
+ 
+   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
+   logical_locations::key logical_loc = event.get_logical_location ();
+   set_any_logical_locs_arr (*location_obj, logical_loc);
+ 
+   /* "message" property (SARIF v2.1.0 section 3.28.5).  */
+   std::unique_ptr<pretty_printer> pp = get_printer ()->clone ();
+   event.print_desc (*pp);
+   location_obj->set<sarif_message>
+     ("message",
+      make_message_object (pp_formatted_text (pp.get ())));
+ 
+   add_any_include_chain (loc_mgr, *location_obj.get (), loc);
+ 
+   return location_obj;
+ }
+ 
+ /* Make a "physicalLocation" object (SARIF v2.1.0 section 3.29) for LOC.
+ 
+    If COLUMN_OVERRIDE is non-zero, then use it as the column number
+    if LOC has no column information.
+ 
+    Ensure that we have an artifact object for the file, adding ROLE to it,
+    and flagging that we will attempt to embed the contents of the artifact
+    when writing it out.  */
+ 
+ std::unique_ptr<sarif_physical_location>
+ sarif_builder::
+ maybe_make_physical_location_object (location_t loc,
+ 				     enum diagnostic_artifact_role role,
+ 				     int column_override,
+ 				     const content_renderer *snippet_renderer)
+ {
+   if (loc <= BUILTINS_LOCATION || LOCATION_FILE (loc) == nullptr)
+     return nullptr;
+ 
+   auto phys_loc_obj = std::make_unique<sarif_physical_location> ();
+ 
+   /* "artifactLocation" property (SARIF v2.1.0 section 3.29.3).  */
+   phys_loc_obj->set<sarif_artifact_location>
+     ("artifactLocation", make_artifact_location_object (loc));
+   get_or_create_artifact (LOCATION_FILE (loc), role, true);
+ 
+   /* "region" property (SARIF v2.1.0 section 3.29.4).  */
+   if (auto region_obj = maybe_make_region_object (loc, column_override))
+     phys_loc_obj->set<sarif_region> ("region", std::move (region_obj));
+ 
+   /* "contextRegion" property (SARIF v2.1.0 section 3.29.5).  */
+   if (auto context_region_obj
+ 	= maybe_make_region_object_for_context (loc, snippet_renderer))
+     phys_loc_obj->set<sarif_region> ("contextRegion",
+ 				     std::move (context_region_obj));
+ 
+   /* Instead, we add artifacts to the run as a whole,
+      with artifact.contents.
+      Could do both, though.  */
+ 
+   return phys_loc_obj;
+ }
+ 
+ /* Make an "artifactLocation" object (SARIF v2.1.0 section 3.4) for LOC,
+    or return nullptr.  */
+ 
+ std::unique_ptr<sarif_artifact_location>
+ sarif_builder::make_artifact_location_object (location_t loc)
+ {
+   return make_artifact_location_object (LOCATION_FILE (loc));
+ }
+ 
+ /* The ID value for use in "uriBaseId" properties (SARIF v2.1.0 section 3.4.4)
+    for when we need to express paths relative to PWD.  */
+ 
+ #define PWD_PROPERTY_NAME ("PWD")
+ 
+ /* Make an "artifactLocation" object (SARIF v2.1.0 section 3.4) for FILENAME,
+    or return nullptr.  */
+ 
+ std::unique_ptr<sarif_artifact_location>
+ sarif_builder::make_artifact_location_object (const char *filename)
+ {
+   auto artifact_loc_obj = std::make_unique<sarif_artifact_location> ();
+ 
+   /* "uri" property (SARIF v2.1.0 section 3.4.3).  */
+   artifact_loc_obj->set_string ("uri", filename);
+ 
+   if (filename[0] != '/')
+     {
+       /* If we have a relative path, set the "uriBaseId" property
+ 	 (SARIF v2.1.0 section 3.4.4).  */
+       artifact_loc_obj->set_string ("uriBaseId", PWD_PROPERTY_NAME);
+       m_seen_any_relative_paths = true;
+     }
+ 
+   return artifact_loc_obj;
+ }
+ 
+ /* Get the PWD, or nullptr, as an absolute file-based URI,
+    adding a trailing forward slash (as required by SARIF v2.1.0
+    section 3.14.14).  */
+ 
+ static char *
+ make_pwd_uri_str ()
+ {
+   /* The prefix of a file-based URI, up to, but not including the path. */
+ #define FILE_PREFIX ("file://")
+ 
+   const char *pwd = getpwd ();
+   if (!pwd)
+     return nullptr;
+   size_t len = strlen (pwd);
+   if (len == 0 || pwd[len - 1] != '/')
+     return concat (FILE_PREFIX, pwd, "/", nullptr);
+   else
+     {
+       gcc_assert (pwd[len - 1] == '/');
+       return concat (FILE_PREFIX, pwd, nullptr);
+     }
+ }
+ 
+ /* Make an "artifactLocation" object (SARIF v2.1.0 section 3.4) for the pwd,
+    for use in the "run.originalUriBaseIds" property (SARIF v2.1.0
+    section 3.14.14) when we have any relative paths.  */
+ 
+ std::unique_ptr<sarif_artifact_location>
+ sarif_builder::make_artifact_location_object_for_pwd () const
+ {
+   auto artifact_loc_obj = std::make_unique<sarif_artifact_location> ();
+ 
+   /* "uri" property (SARIF v2.1.0 section 3.4.3).  */
+   if (char *pwd = make_pwd_uri_str ())
+     {
+       gcc_assert (strlen (pwd) > 0);
+       gcc_assert (pwd[strlen (pwd) - 1] == '/');
+       artifact_loc_obj->set_string ("uri", pwd);
+       free (pwd);
+     }
+ 
+   return artifact_loc_obj;
+ }
+ 
+ /* Get the column number within EXPLOC.  */
+ 
+ int
+ sarif_builder::get_sarif_column (expanded_location exploc) const
+ {
+   cpp_char_column_policy policy (m_tabstop, cpp_wcwidth);
+   return location_compute_display_column (m_context.get_file_cache (),
+ 					  exploc, policy);
+ }
+ 
+ /* Make a "region" object (SARIF v2.1.0 section 3.30) for LOC,
+    or return nullptr.
+ 
+    If COLUMN_OVERRIDE is non-zero, then use it as the column number
+    if LOC has no column information.
+ 
+    We only support text properties of regions ("text regions"),
+    not binary properties ("binary regions"); see 3.30.1.  */
+ 
+ std::unique_ptr<sarif_region>
+ sarif_builder::maybe_make_region_object (location_t loc,
+ 					 int column_override) const
+ {
+   location_t caret_loc = get_pure_location (loc);
+ 
+   if (caret_loc <= BUILTINS_LOCATION)
+     return nullptr;
+ 
+   location_t start_loc = get_start (loc);
+   location_t finish_loc = get_finish (loc);
+ 
+   expanded_location exploc_caret = expand_location (caret_loc);
+   expanded_location exploc_start = expand_location (start_loc);
+   expanded_location exploc_finish = expand_location (finish_loc);
+ 
+   if (exploc_start.file !=exploc_caret.file)
+     return nullptr;
+   if (exploc_finish.file !=exploc_caret.file)
+     return nullptr;
+ 
+   /* We can have line == 0 in the presence of "#" lines.
+      SARIF requires lines > 0, so if we hit this case we don't have a
+      way of validly representing the region as SARIF; bail out.  */
+   if (exploc_start.line <= 0)
+     return nullptr;
+ 
+   auto region_obj = std::make_unique<sarif_region> ();
+ 
+   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
+   region_obj->set_integer ("startLine", exploc_start.line);
+ 
+   /* "startColumn" property (SARIF v2.1.0 section 3.30.6).
+ 
+      We use column == 0 to mean the whole line, so omit the column
+      information for this case, unless COLUMN_OVERRIDE is non-zero,
+      (for handling certain awkward lexer diagnostics)  */
+ 
+   if (exploc_start.column == 0 && column_override)
+     /* Use the provided column number.  */
+     exploc_start.column = column_override;
+ 
+   if (exploc_start.column > 0)
+     {
+       int start_column = get_sarif_column (exploc_start);
+       region_obj->set_integer ("startColumn", start_column);
+     }
+ 
+   /* "endLine" property (SARIF v2.1.0 section 3.30.7) */
+   if (exploc_finish.line != exploc_start.line
+       && exploc_finish.line > 0)
+     region_obj->set_integer ("endLine", exploc_finish.line);
+ 
+   /* "endColumn" property (SARIF v2.1.0 section 3.30.8).
+      This expresses the column immediately beyond the range.
+ 
+      We use column == 0 to mean the whole line, so omit the column
+      information for this case.  */
+   if (exploc_finish.column > 0)
+     {
+       int next_column = get_sarif_column (exploc_finish) + 1;
+       region_obj->set_integer ("endColumn", next_column);
+     }
+ 
+   return region_obj;
+ }
+ 
+ /* Make a "region" object (SARIF v2.1.0 section 3.30) for the "contextRegion"
+    property (SARIF v2.1.0 section 3.29.5) of a "physicalLocation".
+ 
+    This is similar to maybe_make_region_object, but ignores column numbers,
+    covering the line(s) as a whole, and including a "snippet" property
+    embedding those source lines, making it easier for consumers to show
+    the pertinent source.  */
+ 
+ std::unique_ptr<sarif_region>
+ sarif_builder::
+ maybe_make_region_object_for_context (location_t loc,
+ 				      const content_renderer *snippet_renderer)
+   const
+ {
+   location_t caret_loc = get_pure_location (loc);
+ 
+   if (caret_loc <= BUILTINS_LOCATION)
+     return nullptr;
+ 
+   location_t start_loc = get_start (loc);
+   location_t finish_loc = get_finish (loc);
+ 
+   expanded_location exploc_caret = expand_location (caret_loc);
+   expanded_location exploc_start = expand_location (start_loc);
+   expanded_location exploc_finish = expand_location (finish_loc);
+ 
+   if (exploc_start.file !=exploc_caret.file)
+     return nullptr;
+   if (exploc_finish.file !=exploc_caret.file)
+     return nullptr;
+ 
+   /* We can have line == 0 in the presence of "#" lines.
+      SARIF requires lines > 0, so if we hit this case we don't have a
+      way of validly representing the region as SARIF; bail out.  */
+   if (exploc_start.line <= 0)
+     return nullptr;
+ 
+   auto region_obj = std::make_unique<sarif_region> ();
+ 
+   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
+   region_obj->set_integer ("startLine", exploc_start.line);
+ 
+   /* "endLine" property (SARIF v2.1.0 section 3.30.7) */
+   if (exploc_finish.line != exploc_start.line
+       && exploc_finish.line > 0)
+     region_obj->set_integer ("endLine", exploc_finish.line);
+ 
+   /* "snippet" property (SARIF v2.1.0 section 3.30.13).  */
+   if (auto artifact_content_obj
+ 	= maybe_make_artifact_content_object (exploc_start.file,
+ 					      exploc_start.line,
+ 					      exploc_finish.line,
+ 					      snippet_renderer))
+     region_obj->set<sarif_artifact_content> ("snippet",
+ 					     std::move (artifact_content_obj));
+ 
+   return region_obj;
+ }
+ 
+ /* Make a "region" object (SARIF v2.1.0 section 3.30) for the deletion region
+    of HINT (as per SARIF v2.1.0 section 3.57.3).  */
+ 
+ std::unique_ptr<sarif_region>
+ sarif_builder::make_region_object_for_hint (const fixit_hint &hint) const
+ {
+   location_t start_loc = hint.get_start_loc ();
+   location_t next_loc = hint.get_next_loc ();
+ 
+   expanded_location exploc_start = expand_location (start_loc);
+   expanded_location exploc_next = expand_location (next_loc);
+ 
+   auto region_obj = std::make_unique<sarif_region> ();
+ 
+   /* "startLine" property (SARIF v2.1.0 section 3.30.5) */
+   region_obj->set_integer ("startLine", exploc_start.line);
+ 
+   /* "startColumn" property (SARIF v2.1.0 section 3.30.6) */
+   int start_col = get_sarif_column (exploc_start);
+   region_obj->set_integer ("startColumn", start_col);
+ 
+   /* "endLine" property (SARIF v2.1.0 section 3.30.7) */
+   if (exploc_next.line != exploc_start.line)
+     region_obj->set_integer ("endLine", exploc_next.line);
+ 
+   /* "endColumn" property (SARIF v2.1.0 section 3.30.8).
+      This expresses the column immediately beyond the range.  */
+   int next_col =  get_sarif_column (exploc_next);
+   region_obj->set_integer ("endColumn", next_col);
+ 
+   return region_obj;
+ }
+ 
+ /* Attempt to get a string for a logicalLocation's "kind" property
+    (SARIF v2.1.0 section 3.33.7).
+    Return nullptr if unknown.  */
+ 
+ static const char *
+ maybe_get_sarif_kind (enum logical_locations::kind kind)
+ {
+   using namespace logical_locations;
+ 
+   switch (kind)
+     {
+     default:
+       gcc_unreachable ();
+     case logical_locations::kind::unknown:
+       return nullptr;
+ 
+     /* Kinds within executable code.  */
+     case logical_locations::kind::function:
+       return "function";
+     case logical_locations::kind::member:
+       return "member";
+     case logical_locations::kind::module_:
+       return "module";
+     case logical_locations::kind::namespace_:
+       return "namespace";
+     case logical_locations::kind::type:
+       return "type";
+     case logical_locations::kind::return_type:
+       return "returnType";
+     case logical_locations::kind::parameter:
+       return "parameter";
+     case logical_locations::kind::variable:
+       return "variable";
+ 
+     /* Kinds within XML or HTML documents.  */
+     case logical_locations::kind::element:
+       return "element";
+     case logical_locations::kind::attribute:
+       return "attribute";
+     case logical_locations::kind::text:
+       return "text";
+     case logical_locations::kind::comment:
+       return "comment";
+     case logical_locations::kind::processing_instruction:
+       return "processingInstruction";
+     case logical_locations::kind::dtd:
+       return "dtd";
+     case logical_locations::kind::declaration:
+       return "declaration";
+ 
+     /* Kinds within JSON documents.  */
+     case logical_locations::kind::object:
+       return "object";
+     case logical_locations::kind::array:
+       return "array";
+     case logical_locations::kind::property:
+       return "property";
+     case logical_locations::kind::value:
+       return "value";
+     }
+ }
+ 
+ /* Set PROPERTY_NAME within this bag to a "logicalLocation" object (SARIF v2.1.0
+    section 3.33) for LOGICAL_LOC.  The object has an "index" property to refer to
+    theRuns.logicalLocations (3.33.3).  */
+ 
+ void
+ sarif_property_bag::set_logical_location (const char *property_name,
+ 					  sarif_builder &builder,
+ 					  logical_locations::key logical_loc)
+ {
+   set<sarif_logical_location>
+     (property_name,
+      builder.make_minimal_sarif_logical_location (logical_loc));
+ }
+ 
+ static void
+ copy_any_property_bag (const digraphs::object &input_obj,
+ 		       sarif_object &output_obj)
+ {
+   if (input_obj.get_property_bag ())
+     {
+       const json::object &old_bag = *input_obj.get_property_bag ();
+       sarif_property_bag &new_bag = output_obj.get_or_create_properties ();
+       for (size_t i = 0; i < old_bag.get_num_keys (); ++i)
+ 	{
+ 	  const char *key = old_bag.get_key (i);
+ 	  json::value *val = old_bag.get (key);
+ 	  new_bag.set (key, val->clone ());
+ 	}
+     }
+ }
+ 
+ std::unique_ptr<sarif_graph>
+ make_sarif_graph (const digraphs::digraph &g,
+ 		  sarif_builder *builder,
+ 		  sarif_location_manager *sarif_location_mgr)
+ {
+   auto result = std::make_unique<sarif_graph> ();
+ 
+   // 3.39.2 description property
+   if (const char *desc = g.get_description ())
+     if (builder)
+       result->set<sarif_message> ("description",
+ 				  builder->make_message_object (desc));
+ 
+   copy_any_property_bag (g, *result);
+ 
+   // 3.39.3 nodes property
+   auto nodes_arr = std::make_unique<json::array> ();
+   const int num_nodes = g.get_num_nodes ();
+   for (int i = 0; i < num_nodes; ++i)
+     nodes_arr->append (make_sarif_node (g.get_node (i),
+ 					builder,
+ 					sarif_location_mgr));
+   result->set ("nodes", std::move (nodes_arr));
+ 
+   // 3.39.4 edges property
+   auto edges_arr = std::make_unique<json::array> ();
+   const int num_edges = g.get_num_edges ();
+   for (int i = 0; i < num_edges; ++i)
+     edges_arr->append (make_sarif_edge (g.get_edge (i), builder));
+   result->set ("edges", std::move (edges_arr));
+ 
+   return result;
+ }
+ 
+ std::unique_ptr<sarif_node>
+ make_sarif_node (const digraphs::node &n,
+ 		 sarif_builder *builder,
+ 		 sarif_location_manager *sarif_location_mgr)
+ {
+   auto result = std::make_unique<sarif_node> ();
+ 
+   // 3.40.2 id property
+   result->set_string ("id", n.get_id ().c_str ());
+ 
+   copy_any_property_bag (n, *result);
+ 
+   // 3.40.3 label property
+   if (const char *label = n.get_label ())
+     if (builder)
+       result->set<sarif_message> ("label",
+ 				  builder->make_message_object (label));
+ 
+   // 3.40.4 location property
+   if (n.get_logical_loc ()
+       || n.get_physical_loc () != UNKNOWN_LOCATION)
+     if (builder)
+       {
+ 	rich_location rich_loc
+ 	  (line_table, n.get_physical_loc ());
+ 	auto loc_obj
+ 	  = builder->make_location_object
+ 	      (sarif_location_mgr,
+ 	       rich_loc,
+ 	       n.get_logical_loc (),
+ 	       diagnostic_artifact_role::scanned_file);
+ 	result->set<sarif_location> ("location",
+ 				     std::move (loc_obj));
+     }
+ 
+   // 3.40.5 children property
+   if (const int num_children = n.get_num_children ())
+     {
+       auto children_arr = std::make_unique<json::array> ();
+       for (int i = 0; i < num_children; ++i)
+ 	children_arr->append (make_sarif_node (n.get_child (i),
+ 					       builder,
+ 					       sarif_location_mgr));
+       result->set ("children", std::move (children_arr));
+     }
+ 
+   return result;
+ }
+ 
+ std::unique_ptr<sarif_edge>
+ make_sarif_edge (const digraphs::edge &e,
+ 		 sarif_builder *builder)
+ {
+   auto result = std::make_unique<sarif_edge> ();
+ 
+   // 3.41.2 id property
+   result->set_string ("id", e.get_id ().c_str ());
+ 
+   copy_any_property_bag (e, *result);
+ 
+   // 3.41.3 label property
+   if (const char *label = e.get_label ())
+     if (builder)
+       result->set<sarif_message> ("label",
+ 				  builder->make_message_object (label));
+ 
+   // 3.41.4 sourceNodeId property
+   result->set_string ("sourceNodeId", e.get_src_node ().get_id ().c_str ());
+ 
+   // 3.41.5 targetNodeId property
+   result->set_string ("targetNodeId", e.get_dst_node ().get_id ().c_str ());
+ 
+   return result;
+ }
+ 
+ void
+ sarif_property_bag::set_graph (const char *property_name,
+ 			       sarif_builder &builder,
+ 			       sarif_location_manager *sarif_location_mgr,
+ 			       const digraphs::digraph &g)
+ {
+   set<sarif_graph> (property_name,
+ 		    make_sarif_graph (g, &builder, sarif_location_mgr));
+ }
+ 
+ /* Ensure that m_cached_logical_locs has a "logicalLocation" object
+    (SARIF v2.1.0 section 3.33) for K, and return its index within the
+    array.  */
+ 
+ int
+ sarif_builder::
+ ensure_sarif_logical_location_for (logical_locations::key k)
+ {
+   gcc_assert (m_logical_loc_mgr);
+ 
+   auto sarif_logical_loc = std::make_unique<sarif_logical_location> ();
+ 
+   if (const char *short_name = m_logical_loc_mgr->get_short_name (k))
+     sarif_logical_loc->set_string ("name", short_name);
+ 
+   /* "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
+   if (const char *name_with_scope = m_logical_loc_mgr->get_name_with_scope (k))
+     sarif_logical_loc->set_string ("fullyQualifiedName", name_with_scope);
+ 
+   /* "decoratedName" property (SARIF v2.1.0 section 3.33.6).  */
+   if (const char *internal_name = m_logical_loc_mgr->get_internal_name (k))
+     sarif_logical_loc->set_string ("decoratedName", internal_name);
+ 
+   /* "kind" property (SARIF v2.1.0 section 3.33.7).  */
+   enum logical_locations::kind kind = m_logical_loc_mgr->get_kind (k);
+   if (const char *sarif_kind_str = maybe_get_sarif_kind (kind))
+     sarif_logical_loc->set_string ("kind", sarif_kind_str);
+ 
+   /* "parentIndex" property (SARIF v2.1.0 section 3.33.8).  */
+   if (auto parent_key = m_logical_loc_mgr->get_parent (k))
+     {
+       /* Recurse upwards.  */
+       int parent_index = ensure_sarif_logical_location_for (parent_key);
+       sarif_logical_loc->set_integer ("parentIndex", parent_index);
+     }
+ 
+   /* Consolidate if this logical location already exists.  */
+   int index
+     = m_cached_logical_locs->append_uniquely (std::move (sarif_logical_loc));
+ 
+   return index;
+ }
+ 
+ /* Ensure that theRuns.logicalLocations (3.14.17) has a "logicalLocation" object
+    (SARIF v2.1.0 section 3.33) for LOGICAL_LOC.
+    Create and return a minimal logicalLocation object referring to the
+    full object by index.  */
+ 
+ std::unique_ptr<sarif_logical_location>
+ sarif_builder::
+ make_minimal_sarif_logical_location (logical_locations::key logical_loc)
+ {
+   gcc_assert (m_logical_loc_mgr);
+ 
+   /* Ensure that m_cached_logical_locs has a "logicalLocation" object
+      (SARIF v2.1.0 section 3.33) for LOGICAL_LOC, and return its index within
+      the array.  */
+ 
+   auto sarif_logical_loc = std::make_unique <sarif_logical_location> ();
+ 
+   int index = ensure_sarif_logical_location_for (logical_loc);
+ 
+   // 3.33.3 index property
+   sarif_logical_loc->set_integer ("index", index);
+ 
+   /* "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
+   if (const char *name_with_scope
+         = m_logical_loc_mgr->get_name_with_scope (logical_loc))
+     sarif_logical_loc->set_string ("fullyQualifiedName", name_with_scope);
+ 
+   return sarif_logical_loc;
+ }
+ 
+ label_text
+ make_sarif_url_for_event (const sarif_code_flow *code_flow,
+ 			  paths::event_id_t event_id)
+ {
+   gcc_assert (event_id.known_p ());
+ 
+   if (!code_flow)
+     return label_text ();
+ 
+   const sarif_thread_flow_location &tfl_obj
+     = code_flow->get_thread_flow_loc_obj (event_id);
+   const int location_idx = tfl_obj.get_index_within_parent ();
+ 
+   const sarif_thread_flow &thread_flow_obj = tfl_obj.get_parent ();
+   const int thread_flow_idx = thread_flow_obj.get_index_within_parent ();
+ 
+   const sarif_code_flow &code_flow_obj = thread_flow_obj.get_parent ();
+   const int code_flow_idx = code_flow_obj.get_index_within_parent ();
+ 
+   const sarif_result &result_obj = code_flow_obj.get_parent ();
+   const int result_idx = result_obj.get_index_within_parent ();
+ 
+   /* We only support a single run object in the log.  */
+   const int run_idx = 0;
+ 
+   char *buf = xasprintf
+     ("sarif:/runs/%i/results/%i/codeFlows/%i/threadFlows/%i/locations/%i",
+      run_idx, result_idx, code_flow_idx, thread_flow_idx, location_idx);
+   return label_text::take (buf);
+ }
+ 
+ /* Make a "codeFlow" object (SARIF v2.1.0 section 3.36) for PATH.  */
+ 
+ std::unique_ptr<sarif_code_flow>
+ sarif_builder::make_code_flow_object (sarif_result &result,
+ 				      unsigned idx_within_parent,
+ 				      const paths::path &path)
+ {
+   auto code_flow_obj
+     = std::make_unique <sarif_code_flow> (result, idx_within_parent);
+ 
+   /* First pass:
+      Create threadFlows and threadFlowLocation objects within them,
+      effectively recording a mapping from event_id to threadFlowLocation
+      so that we can later go from an event_id to a URI within the
+      SARIF file.  */
+   for (unsigned i = 0; i < path.num_events (); i++)
+     {
+       const paths::event &event = path.get_event (i);
+       const paths::thread_id_t thread_id = event.get_thread_id ();
+ 
+       sarif_thread_flow &thread_flow_obj
+ 	= code_flow_obj->get_or_append_thread_flow (path.get_thread (thread_id),
+ 						    thread_id);
+       thread_flow_obj.add_location ();
+     }
+ 
+   /* Second pass: walk the events, populating the tfl objs.  */
+   m_current_code_flow = code_flow_obj.get ();
+   for (unsigned i = 0; i < path.num_events (); i++)
+     {
+       const paths::event &event = path.get_event (i);
+       sarif_thread_flow_location &thread_flow_loc_obj
+ 	= code_flow_obj->get_thread_flow_loc_obj (i);
+       populate_thread_flow_location_object (result,
+ 					    thread_flow_loc_obj,
+ 					    event,
+ 					    i);
+     }
+   m_current_code_flow = nullptr;
+ 
+   return code_flow_obj;
+ }
+ 
+ /* Populate TFL_OBJ, a "threadFlowLocation" object (SARIF v2.1.0 section 3.38)
+    based on EVENT.  */
+ 
+ void
+ sarif_builder::
+ populate_thread_flow_location_object (sarif_result &result,
+ 				      sarif_thread_flow_location &tfl_obj,
+ 				      const paths::event &ev,
+ 				      int event_execution_idx)
+ {
+   /* Give paths::event subclasses a chance to add custom properties
+      via a property bag.  */
+   ev.maybe_add_sarif_properties (*this, tfl_obj);
+ 
+   if (get_opts ().m_state_graph)
+     if (auto state_graph = ev.maybe_make_diagnostic_state_graph (true))
+       {
+ 	sarif_property_bag &props = tfl_obj.get_or_create_properties ();
+ 
+ #define PROPERTY_PREFIX "gcc/diagnostics/paths/event/"
+ 	props.set_graph (PROPERTY_PREFIX "state_graph",
+ 			 *this,
+ 			 /* Use RESULT for any related locations in the graph's
+ 			    nodes.
+ 			    It's not clear if this is correct; see:
+ 			    https://github.com/oasis-tcs/sarif-spec/issues/712
+ 			 */
+ 			 &result,
+ 			 *state_graph);
+ #undef PROPERTY_PREFIX
+       }
+ 
+   /* "location" property (SARIF v2.1.0 section 3.38.3).  */
+   tfl_obj.set<sarif_location>
+     ("location",
+      make_location_object (result, ev, diagnostic_artifact_role::traced_file));
+ 
+   /* "kinds" property (SARIF v2.1.0 section 3.38.8).  */
+   paths::event::meaning m = ev.get_meaning ();
+   if (auto kinds_arr = maybe_make_kinds_array (m))
+     tfl_obj.set<json::array> ("kinds", std::move (kinds_arr));
+ 
+   /* "nestingLevel" property (SARIF v2.1.0 section 3.38.10).  */
+   tfl_obj.set_integer ("nestingLevel", ev.get_stack_depth ());
+ 
+   /* "executionOrder" property (SARIF v2.1.0 3.38.11).
+      Offset by 1 to match the human-readable values emitted by %@.  */
+   tfl_obj.set_integer ("executionOrder", event_execution_idx + 1);
+ 
+   /* It might be nice to eventually implement the following for -fanalyzer:
+      - the "stack" property (SARIF v2.1.0 section 3.38.5)
+      - the "state" property (SARIF v2.1.0 section 3.38.9)
+      - the "importance" property (SARIF v2.1.0 section 3.38.13).  */
+ }
+ 
+ /* If M has any known meaning, make a json array suitable for the "kinds"
+    property of a "threadFlowLocation" object (SARIF v2.1.0 section 3.38.8).
+ 
+    Otherwise, return nullptr.  */
+ 
+ std::unique_ptr<json::array>
+ sarif_builder::
+ maybe_make_kinds_array (paths::event::meaning m) const
+ {
+   using namespace paths;
+ 
+   if (m.m_verb == event::verb::unknown
+       && m.m_noun == event::noun::unknown
+       && m.m_property == event::property::unknown)
+     return nullptr;
+ 
+   auto kinds_arr = std::make_unique<json::array> ();
+   if (const char *verb_str
+ 	= event::meaning::maybe_get_verb_str (m.m_verb))
+     kinds_arr->append_string (verb_str);
+   if (const char *noun_str
+ 	= event::meaning::maybe_get_noun_str (m.m_noun))
+     kinds_arr->append_string (noun_str);
+   if (const char *property_str
+ 	= event::meaning::maybe_get_property_str (m.m_property))
+     kinds_arr->append_string (property_str);
+   return kinds_arr;
+ }
+ 
+ /* In "3.11.5 Messages with placeholders":
+    "Within both plain text and formatted message strings, the characters
+    "{" and "}" SHALL be represented by the character sequences
+    "{{" and "}}" respectively."  */
+ 
+ static std::string
+ escape_braces (const char *text)
+ {
+   std::string result;
+   while (char ch = *text++)
+     switch (ch)
+       {
+       case '{':
+       case '}':
+ 	result += ch;
+ 	/* Fall through.  */
+       default:
+ 	result += ch;
+ 	break;
+       }
+   return result;
+ }
+ 
+ static void
+ set_string_property_escaping_braces (json::object &obj,
+ 				     const char *property_name,
+ 				     const char *value)
+ {
+   std::string escaped (escape_braces (value));
+   obj.set_string (property_name, escaped.c_str ());
+ }
+ 
+ /* Make a "message" object (SARIF v2.1.0 section 3.11) for MSG.  */
+ 
+ std::unique_ptr<sarif_message>
+ sarif_builder::make_message_object (const char *msg) const
+ {
+   auto message_obj = std::make_unique<sarif_message> ();
+ 
+   /* "text" property (SARIF v2.1.0 section 3.11.8).  */
+   set_string_property_escaping_braces (*message_obj,
+ 				       "text", msg);
+ 
+   return message_obj;
+ }
+ 
+ /* Make a "message" object (SARIF v2.1.0 section 3.11) for D.
+    We emit the diagram as a code block within the Markdown part
+    of the message.  */
+ 
+ std::unique_ptr<sarif_message>
+ sarif_builder::make_message_object_for_diagram (const diagram &d)
+ {
+   auto message_obj = std::make_unique<sarif_message> ();
+ 
+   /* "text" property (SARIF v2.1.0 section 3.11.8).  */
+   set_string_property_escaping_braces (*message_obj,
+ 				       "text", d.get_alt_text ());
+ 
+   pretty_printer *const pp = m_printer;
+   char *saved_prefix = pp_take_prefix (pp);
+   pp_set_prefix (pp, nullptr);
+ 
+   /* "To produce a code block in Markdown, simply indent every line of
+      the block by at least 4 spaces or 1 tab."
+      Here we use 4 spaces.  */
+   d.get_canvas ().print_to_pp (pp, "    ");
+   pp_set_prefix (pp, saved_prefix);
+ 
+   /* "markdown" property (SARIF v2.1.0 section 3.11.9).  */
+   set_string_property_escaping_braces (*message_obj,
+ 				       "markdown", pp_formatted_text (pp));
+ 
+   pp_clear_output_area (pp);
+ 
+   return message_obj;
+ }
+ 
+ /* Make a "multiformatMessageString object" (SARIF v2.1.0 section 3.12)
+    for MSG.  */
+ 
+ std::unique_ptr<sarif_multiformat_message_string>
+ sarif_builder::make_multiformat_message_string (const char *msg) const
+ {
+   auto message_obj = std::make_unique<sarif_multiformat_message_string> ();
+ 
+   /* "text" property (SARIF v2.1.0 section 3.12.3).  */
+   set_string_property_escaping_braces (*message_obj,
+ 				       "text", msg);
+ 
+   return message_obj;
+ }
+ 
+ /* Convert VERSION to a value for the "$schema" property
+    of a "sarifLog" object (SARIF v2.1.0 section 3.13.3).  */
+ 
+ static const char *
+ sarif_version_to_url (enum sarif_version version)
+ {
+   switch (version)
+     {
+     default:
+       gcc_unreachable ();
+     case sarif_version::v2_1_0:
+       return "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json";
+     case sarif_version::v2_2_prerelease_2024_08_08:
+       return "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/refs/tags/2.2-prerelease-2024-08-08/sarif-2.2/schema/sarif-2-2.schema.json";
+     }
+ }
+ 
+ /* Convert VERSION to a value for the "version" property
+    of a "sarifLog" object (SARIF v2.1.0 section 3.13.2).  */
+ 
+ static const char *
+ sarif_version_to_property (enum sarif_version version)
+ {
+   switch (version)
+     {
+     default:
+       gcc_unreachable ();
+     case sarif_version::v2_1_0:
+       return "2.1.0";
+     case sarif_version::v2_2_prerelease_2024_08_08:
+       /* I would have used "2.2-prerelease-2024-08-08",
+ 	 but the schema only accepts "2.2".  */
+       return "2.2";
+     }
+ }
+ 
+ /* Make a top-level "sarifLog" object (SARIF v2.1.0 section 3.13).  */
+ 
+ std::unique_ptr<sarif_log>
+ sarif_builder::
+ make_top_level_object (std::unique_ptr<sarif_invocation> invocation_obj,
+ 		       std::unique_ptr<json::array> results)
+ {
+   auto log_obj = std::make_unique<sarif_log> ();
+ 
+   /* "$schema" property (SARIF v2.1.0 section 3.13.3) .  */
+   log_obj->set_string ("$schema", sarif_version_to_url (get_version ()));
+ 
+   /* "version" property (SARIF v2.1.0 section 3.13.2).  */
+   log_obj->set_string ("version", sarif_version_to_property (get_version ()));
+ 
+   /* "runs" property (SARIF v2.1.0 section 3.13.4).  */
+   auto run_arr = std::make_unique<json::array> ();
+   auto run_obj = make_run_object (std::move (invocation_obj),
+ 				  std::move (results));
+   run_arr->append<sarif_run> (std::move (run_obj));
+   log_obj->set<json::array> ("runs", std::move (run_arr));
+ 
+   return log_obj;
+ }
+ 
+ /* Make a "run" object (SARIF v2.1.0 section 3.14).  */
+ 
+ std::unique_ptr<sarif_run>
+ sarif_builder::
+ make_run_object (std::unique_ptr<sarif_invocation> invocation_obj,
+ 		 std::unique_ptr<json::array> results)
+ {
+   auto run_obj = std::make_unique<sarif_run> ();
+ 
+   /* "tool" property (SARIF v2.1.0 section 3.14.6).  */
+   run_obj->set<sarif_tool> ("tool", make_tool_object ());
+ 
+   /* "taxonomies" property (SARIF v2.1.0 section 3.14.8).  */
+   if (auto taxonomies_arr = maybe_make_taxonomies_array ())
+     run_obj->set<json::array> ("taxonomies", std::move (taxonomies_arr));
+ 
+   /* "invocations" property (SARIF v2.1.0 section 3.14.11).  */
+   {
+     auto invocations_arr = std::make_unique<json::array> ();
+     invocations_arr->append (std::move (invocation_obj));
+     run_obj->set<json::array> ("invocations", std::move (invocations_arr));
+   }
+ 
+   /* "originalUriBaseIds (SARIF v2.1.0 section 3.14.14).  */
+   if (m_seen_any_relative_paths)
+     {
+       auto orig_uri_base_ids = std::make_unique<json::object> ();
+       orig_uri_base_ids->set<sarif_artifact_location>
+ 	(PWD_PROPERTY_NAME, make_artifact_location_object_for_pwd ());
+       run_obj->set<json::object> ("originalUriBaseIds",
+ 				  std::move (orig_uri_base_ids));
+     }
+ 
+   /* "artifacts" property (SARIF v2.1.0 section 3.14.15).  */
+   auto artifacts_arr = std::make_unique<json::array> ();
+   for (auto iter : m_filename_to_artifact_map)
+     {
+       sarif_artifact *artifact_obj = iter.second;
+       if (artifact_obj->embed_contents_p ())
+ 	artifact_obj->populate_contents (*this);
+       artifact_obj->populate_roles ();
+       artifacts_arr->append (artifact_obj);
+     }
+   run_obj->set<json::array> ("artifacts", std::move (artifacts_arr));
+   m_filename_to_artifact_map.empty ();
+ 
+   /* "results" property (SARIF v2.1.0 section 3.14.23).  */
+   run_obj->set<json::array> ("results", std::move (results));
+ 
+   /* "logicalLocations" property (SARIF v2.1.0 3.14.17). */
+   if (m_cached_logical_locs->size () > 0)
+     {
+       m_cached_logical_locs->add_explicit_index_values ();
+       run_obj->set<json::array> ("logicalLocations",
+ 				 std::move (m_cached_logical_locs));
+     }
+ 
+   // "graphs" property (SARIF v2.1.0 3.14.20)
+   if (m_run_graphs->size () > 0)
+     run_obj->set<json::array> ("graphs",
+ 			       std::move (m_run_graphs));
+ 
+   return run_obj;
+ }
+ 
+ /* Make a "tool" object (SARIF v2.1.0 section 3.18).  */
+ 
+ std::unique_ptr<sarif_tool>
+ sarif_builder::make_tool_object ()
+ {
+   auto tool_obj = std::make_unique<sarif_tool> ();
+ 
+   /* "driver" property (SARIF v2.1.0 section 3.18.2).  */
+   tool_obj->set<sarif_tool_component> ("driver",
+ 				       make_driver_tool_component_object ());
+ 
+   /* Report plugins via the "extensions" property
+      (SARIF v2.1.0 section 3.18.3).  */
+   if (auto client_data_hooks = m_context.get_client_data_hooks ())
+     if (const client_version_info *vinfo
+ 	  = client_data_hooks->get_any_version_info ())
+       {
+ 	class my_plugin_visitor : public client_version_info :: plugin_visitor
+ 	{
+ 	public:
+ 	  void
+ 	  on_plugin (const client_plugin_info &p) final override
+ 	  {
+ 	    /* Create a "toolComponent" object (SARIF v2.1.0 section 3.19)
+ 	       for the plugin.  */
+ 	    auto plugin_obj = std::make_unique<sarif_tool_component> ();
+ 
+ 	    /* "name" property (SARIF v2.1.0 section 3.19.8).  */
+ 	    if (const char *short_name = p.get_short_name ())
+ 	      plugin_obj->set_string ("name", short_name);
+ 
+ 	    /* "fullName" property (SARIF v2.1.0 section 3.19.9).  */
+ 	    if (const char *full_name = p.get_full_name ())
+ 	      plugin_obj->set_string ("fullName", full_name);
+ 
+ 	    /* "version" property (SARIF v2.1.0 section 3.19.13).  */
+ 	    if (const char *version = p.get_version ())
+ 	      plugin_obj->set_string ("version", version);
+ 
+ 	    m_plugin_objs.push_back (std::move (plugin_obj));
+ 	  }
+ 	  std::vector<std::unique_ptr<sarif_tool_component>> m_plugin_objs;
+ 	};
+ 	my_plugin_visitor v;
+ 	vinfo->for_each_plugin (v);
+ 	if (v.m_plugin_objs.size () > 0)
+ 	  {
+ 	    auto extensions_arr = std::make_unique<json::array> ();
+ 	    for (auto &iter : v.m_plugin_objs)
+ 	      extensions_arr->append<sarif_tool_component> (std::move (iter));
+ 	    tool_obj->set<json::array> ("extensions",
+ 					std::move (extensions_arr));
+ 	  }
+       }
+ 
+   /* Perhaps we could also show GMP, MPFR, MPC, isl versions as other
+      "extensions" (see toplev.cc: print_version).  */
+ 
+   return tool_obj;
+ }
+ 
+ /* Make a "toolComponent" object (SARIF v2.1.0 section 3.19) for what SARIF
+    calls the "driver" (see SARIF v2.1.0 section 3.18.1).  */
+ 
+ std::unique_ptr<sarif_tool_component>
+ sarif_builder::make_driver_tool_component_object ()
+ {
+   auto driver_obj = std::make_unique<sarif_tool_component> ();
+ 
+   if (auto client_data_hooks = m_context.get_client_data_hooks ())
+     if (const client_version_info *vinfo
+ 	  = client_data_hooks->get_any_version_info ())
+       {
+ 	/* "name" property (SARIF v2.1.0 section 3.19.8).  */
+ 	if (const char *name = vinfo->get_tool_name ())
+ 	  driver_obj->set_string ("name", name);
+ 
+ 	/* "fullName" property (SARIF v2.1.0 section 3.19.9).  */
+ 	if (char *full_name = vinfo->maybe_make_full_name ())
+ 	  {
+ 	    driver_obj->set_string ("fullName", full_name);
+ 	    free (full_name);
+ 	  }
+ 
+ 	/* "version" property (SARIF v2.1.0 section 3.19.13).  */
+ 	if (const char *version = vinfo->get_version_string ())
+ 	  driver_obj->set_string ("version", version);
+ 
+ 	/* "informationUri" property (SARIF v2.1.0 section 3.19.17).  */
+ 	if (char *version_url =  vinfo->maybe_make_version_url ())
+ 	  {
+ 	    driver_obj->set_string ("informationUri", version_url);
+ 	    free (version_url);
+ 	  }
+       }
+ 
+   /* "rules" property (SARIF v2.1.0 section 3.19.23).  */
+   driver_obj->set<json::array> ("rules", std::move (m_rules_arr));
+ 
+   return driver_obj;
+ }
+ 
+ /* If we've seen any CWE IDs, make an array for the "taxonomies" property
+    (SARIF v2.1.0 section 3.14.8) of a run object, containing a single
+    "toolComponent" (3.19) as per 3.19.3, representing the CWE.
+ 
+    Otherwise return nullptr.  */
+ 
+ std::unique_ptr<json::array>
+ sarif_builder::maybe_make_taxonomies_array () const
+ {
+   auto cwe_obj = maybe_make_cwe_taxonomy_object ();
+   if (!cwe_obj)
+     return nullptr;
+ 
+   /* "taxonomies" property (SARIF v2.1.0 section 3.14.8).  */
+   auto taxonomies_arr = std::make_unique<json::array> ();
+   taxonomies_arr->append<sarif_tool_component> (std::move (cwe_obj));
+   return taxonomies_arr;
+ }
+ 
+ /* If we've seen any CWE IDs, make a "toolComponent" object
+    (SARIF v2.1.0 section 3.19) representing the CWE taxonomy, as per 3.19.3.
+    Populate the "taxa" property with all of the CWE IDs in m_cwe_id_set.
+ 
+    Otherwise return nullptr.  */
+ 
+ std::unique_ptr<sarif_tool_component>
+ sarif_builder::maybe_make_cwe_taxonomy_object () const
+ {
+   if (m_cwe_id_set.is_empty ())
+     return nullptr;
+ 
+   auto taxonomy_obj = std::make_unique<sarif_tool_component> ();
+ 
+   /* "name" property (SARIF v2.1.0 section 3.19.8).  */
+   taxonomy_obj->set_string ("name", "CWE");
+ 
+   /* "version" property (SARIF v2.1.0 section 3.19.13).  */
+   taxonomy_obj->set_string ("version", "4.7");
+ 
+   /* "organization" property (SARIF v2.1.0 section 3.19.18).  */
+   taxonomy_obj->set_string ("organization", "MITRE");
+ 
+   /* "shortDescription" property (SARIF v2.1.0 section 3.19.19).  */
+   taxonomy_obj->set<sarif_multiformat_message_string>
+     ("shortDescription",
+      make_multiformat_message_string ("The MITRE"
+ 				      " Common Weakness Enumeration"));
+ 
+   /* "taxa" property (SARIF v2.1.0 3.section 3.19.25).  */
+   auto taxa_arr = std::make_unique<json::array> ();
+   for (auto cwe_id : m_cwe_id_set)
+     taxa_arr->append<sarif_reporting_descriptor>
+       (make_reporting_descriptor_object_for_cwe_id (cwe_id));
+   taxonomy_obj->set<json::array> ("taxa", std::move (taxa_arr));
+ 
+   return taxonomy_obj;
+ }
+ 
+ /* Ensure that we have an "artifact" object (SARIF v2.1.0 section 3.24)
+    for FILENAME, adding it to m_filename_to_artifact_map if not already
+    found, and adding ROLE to it.
+    If EMBED_CONTENTS is true, then flag that we will attempt to embed the
+    contents of this artifact when writing it out.  */
+ 
+ sarif_artifact &
+ sarif_builder::get_or_create_artifact (const char *filename,
+ 				       enum diagnostic_artifact_role role,
+ 				       bool embed_contents)
+ {
+   if (auto *slot = m_filename_to_artifact_map.get (filename))
+     {
+       (*slot)->add_role (role, embed_contents);
+       return **slot;
+     }
+ 
+   sarif_artifact *artifact_obj = new sarif_artifact (filename);
+   artifact_obj->add_role (role, embed_contents);
+   m_filename_to_artifact_map.put (filename, artifact_obj);
+ 
+   /* "location" property (SARIF v2.1.0 section 3.24.2).  */
+   artifact_obj->set<sarif_artifact_location>
+     ("location", make_artifact_location_object (filename));
+ 
+   /* "sourceLanguage" property (SARIF v2.1.0 section 3.24.10).  */
+   switch (role)
+     {
+     default:
+       gcc_unreachable ();
+     case diagnostic_artifact_role::analysis_target:
+     case diagnostic_artifact_role::result_file:
+     case diagnostic_artifact_role::scanned_file:
+     case diagnostic_artifact_role::traced_file:
+       /* Assume that these are in the source language.  */
+       if (auto client_data_hooks = m_context.get_client_data_hooks ())
+ 	if (const char *source_lang
+ 	    = client_data_hooks->maybe_get_sarif_source_language (filename))
+ 	  artifact_obj->set_string ("sourceLanguage", source_lang);
+       break;
+ 
+     case diagnostic_artifact_role::debug_output_file:
+       /* Assume that these are not in the source language.  */
+       break;
+     }
+ 
+   return *artifact_obj;
+ }
+ 
+ /* Make an "artifactContent" object (SARIF v2.1.0 section 3.3) for the
+    full contents of FILENAME.  */
+ 
+ std::unique_ptr<sarif_artifact_content>
+ sarif_builder::maybe_make_artifact_content_object (const char *filename) const
+ {
+   /* Let input.cc handle any charset conversion.  */
+   char_span utf8_content
+     = m_context.get_file_cache ().get_source_file_content (filename);
+   if (!utf8_content)
+     return nullptr;
+ 
+   /* Don't add it if it's not valid UTF-8.  */
+   if (!cpp_valid_utf8_p(utf8_content.get_buffer (), utf8_content.length ()))
+     return nullptr;
+ 
+   auto artifact_content_obj = std::make_unique<sarif_artifact_content> ();
+   artifact_content_obj->set<json::string>
+     ("text",
+      std::make_unique <json::string> (utf8_content.get_buffer (),
+ 				   utf8_content.length ()));
+   return artifact_content_obj;
+ }
+ 
+ /* Attempt to read the given range of lines from FILENAME; return
+    a freshly-allocated 0-terminated buffer containing them, or nullptr.  */
+ 
+ char *
+ sarif_builder::get_source_lines (const char *filename,
+ 				 int start_line,
+ 				 int end_line) const
+ {
+   auto_vec<char> result;
+ 
+   for (int line = start_line; line <= end_line; line++)
+     {
+       char_span line_content
+ 	= m_context.get_file_cache ().get_source_line (filename, line);
+       if (!line_content.get_buffer ())
+ 	return nullptr;
+       result.reserve (line_content.length () + 1);
+       for (size_t i = 0; i < line_content.length (); i++)
+ 	result.quick_push (line_content[i]);
+       result.quick_push ('\n');
+     }
+   result.safe_push ('\0');
+ 
+   return xstrdup (result.address ());
+ }
+ 
+ /* Make an "artifactContent" object (SARIF v2.1.0 section 3.3) for the given
+    run of lines within FILENAME (including the endpoints).
+    If R is non-NULL, use it to potentially set the "rendered"
+    property (3.3.4).  */
+ 
+ std::unique_ptr<sarif_artifact_content>
+ sarif_builder::
+ maybe_make_artifact_content_object (const char *filename,
+ 				    int start_line,
+ 				    int end_line,
+ 				    const content_renderer *r) const
+ {
+   char *text_utf8 = get_source_lines (filename, start_line, end_line);
+ 
+   if (!text_utf8)
+     return nullptr;
+ 
+   /* Don't add it if it's not valid UTF-8.  */
+   if (!cpp_valid_utf8_p(text_utf8, strlen(text_utf8)))
+     {
+       free (text_utf8);
+       return nullptr;
+     }
+ 
+   auto artifact_content_obj = std::make_unique<sarif_artifact_content> ();
+   artifact_content_obj->set_string ("text", text_utf8);
+   free (text_utf8);
+ 
+   /* 3.3.4 "rendered" property.  */
+   if (r)
+     if (std::unique_ptr<sarif_multiformat_message_string> rendered
+ 	  = r->render (*this))
+       artifact_content_obj->set ("rendered", std::move (rendered));
+ 
+   return artifact_content_obj;
+ }
+ 
+ /* Make a "fix" object (SARIF v2.1.0 section 3.55) for RICHLOC.  */
+ 
+ std::unique_ptr<sarif_fix>
+ sarif_builder::make_fix_object (const rich_location &richloc)
+ {
+   auto fix_obj = std::make_unique<sarif_fix> ();
+ 
+   /* "artifactChanges" property (SARIF v2.1.0 section 3.55.3).  */
+   /* We assume that all fix-it hints in RICHLOC affect the same file.  */
+   auto artifact_change_arr = std::make_unique<json::array> ();
+   artifact_change_arr->append<sarif_artifact_change>
+     (make_artifact_change_object (richloc));
+   fix_obj->set<json::array> ("artifactChanges",
+ 			     std::move (artifact_change_arr));
+ 
+   return fix_obj;
+ }
+ 
+ /* Make an "artifactChange" object (SARIF v2.1.0 section 3.56) for RICHLOC.  */
+ 
+ std::unique_ptr<sarif_artifact_change>
+ sarif_builder::make_artifact_change_object (const rich_location &richloc)
+ {
+   auto artifact_change_obj = std::make_unique<sarif_artifact_change> ();
+ 
+   /* "artifactLocation" property (SARIF v2.1.0 section 3.56.2).  */
+   artifact_change_obj->set<sarif_artifact_location>
+     ("artifactLocation",
+      make_artifact_location_object (richloc.get_loc ()));
+ 
+   /* "replacements" property (SARIF v2.1.0 section 3.56.3).  */
+   auto replacement_arr = std::make_unique<json::array> ();
+   for (unsigned int i = 0; i < richloc.get_num_fixit_hints (); i++)
+     {
+       const fixit_hint *hint = richloc.get_fixit_hint (i);
+       replacement_arr->append<sarif_replacement>
+ 	(make_replacement_object (*hint));
+     }
+   artifact_change_obj->set<json::array> ("replacements",
+ 					 std::move (replacement_arr));
+ 
+   return artifact_change_obj;
+ }
+ 
+ /* Make a "replacement" object (SARIF v2.1.0 section 3.57) for HINT.  */
+ 
+ std::unique_ptr<sarif_replacement>
+ sarif_builder::make_replacement_object (const fixit_hint &hint) const
+ {
+   auto replacement_obj = std::make_unique<sarif_replacement> ();
+ 
+   /* "deletedRegion" property (SARIF v2.1.0 section 3.57.3).  */
+   replacement_obj->set<sarif_region> ("deletedRegion",
+ 				      make_region_object_for_hint (hint));
+ 
+   /* "insertedContent" property (SARIF v2.1.0 section 3.57.4).  */
+   replacement_obj->set<sarif_artifact_content>
+     ("insertedContent",
+      make_artifact_content_object (hint.get_string ()));
+ 
+   return replacement_obj;
+ }
+ 
+ /* Make an "artifactContent" object (SARIF v2.1.0 section 3.3) for TEXT.  */
+ 
+ std::unique_ptr<sarif_artifact_content>
+ sarif_builder::make_artifact_content_object (const char *text) const
+ {
+   auto content_obj = std::make_unique<sarif_artifact_content> ();
+ 
+   /* "text" property (SARIF v2.1.0 section 3.3.2).  */
+   content_obj->set_string ("text", text);
+ 
+   return content_obj;
+ }
+ 
+ /* class sarif_sink_buffer : public per_sink_buffer.  */
+ 
+ void
+ sarif_sink_buffer::dump (FILE *out, int indent) const
+ {
+   fprintf (out, "%*ssarif_sink_buffer:\n", indent, "");
+   int idx = 0;
+   for (auto &result : m_results)
+     {
+       fprintf (out, "%*sresult[%i]:\n", indent + 2, "", idx);
+       result->dump (out, true);
+       fprintf (out, "\n");
+       ++idx;
+     }
+ }
+ 
+ bool
+ sarif_sink_buffer::empty_p () const
+ {
+   return m_results.empty ();
+ }
+ 
+ void
+ sarif_sink_buffer::move_to (per_sink_buffer &base)
+ {
+   sarif_sink_buffer &dest
+     = static_cast<sarif_sink_buffer &> (base);
+   for (auto &&result : m_results)
+     dest.m_results.push_back (std::move (result));
+   m_results.clear ();
+ }
+ 
+ void
+ sarif_sink_buffer::clear ()
+ {
+   m_results.clear ();
+ }
+ 
+ void
+ sarif_sink_buffer::flush ()
+ {
+   for (auto &&result : m_results)
+     {
+       result->process_worklist (m_builder);
+       m_builder.m_results_array->append<sarif_result> (std::move (result));
+     }
+   m_results.clear ();
+ }
+ 
+ class sarif_sink : public sink
+ {
+ public:
+   ~sarif_sink ()
+   {
+     /* Any sarifResult objects should have been handled by now.
+        If not, then something's gone wrong with diagnostic
+        groupings.  */
+     std::unique_ptr<sarif_result> pending_result
+       = m_builder.take_current_result ();
+     gcc_assert (!pending_result);
+   }
+ 
+   void dump (FILE *out, int indent) const override
+   {
+     fprintf (out, "%*ssarif_sink\n", indent, "");
+     sink::dump (out, indent);
+   }
+ 
+   void
+   set_main_input_filename (const char *name) final override
+   {
+     m_builder.set_main_input_filename (name);
+   }
+ 
+   std::unique_ptr<per_sink_buffer>
+   make_per_sink_buffer () final override
+   {
+     return std::make_unique<sarif_sink_buffer> (m_builder);
+   }
+   void set_buffer (per_sink_buffer *base_buffer) final override
+   {
+     sarif_sink_buffer *buffer
+       = static_cast<sarif_sink_buffer *> (base_buffer);
+     m_buffer = buffer;
+   }
+ 
+   bool follows_reference_printer_p () const final override
+   {
+     return false;
+   }
+ 
+   void update_printer () final override
+   {
+     m_printer = m_context.clone_printer ();
+ 
+     /* Don't colorize the text.  */
+     pp_show_color (m_printer.get ()) = false;
+ 
+     /* No textual URLs.  */
+     m_printer->set_url_format (URL_FORMAT_NONE);
+ 
+     /* Use builder's token printer.  */
+     get_printer ()->set_token_printer (&m_builder.get_token_printer ());
+ 
+     /* Update the builder to use the new printer.  */
+     m_builder.set_printer (*get_printer ());
+   }
+ 
+   void on_begin_group () final override
+   {
+     /* No-op,  */
+   }
+   void on_end_group () final override
+   {
+     m_builder.end_group ();
+   }
+   void
+   on_report_diagnostic (const diagnostic_info &diagnostic,
+ 			enum kind orig_diag_kind) final override
+   {
+     m_builder.on_report_diagnostic (diagnostic, orig_diag_kind, m_buffer);
+   }
+   void on_diagram (const diagram &d) final override
+   {
+     m_builder.emit_diagram (d);
+   }
+   void after_diagnostic (const diagnostic_info &) final override
+   {
+     /* No-op.  */
+   }
+ 
+   void
+   report_global_digraph (const lazily_created<digraphs::digraph> &ldg)
+     final override
+   {
+     m_builder.report_global_digraph (ldg);
+   }
+ 
+   sarif_builder &get_builder () { return m_builder; }
+ 
+   size_t num_results () const { return m_builder.num_results (); }
+   sarif_result &get_result (size_t idx) { return m_builder.get_result (idx); }
+ 
+ protected:
+   sarif_sink (context &dc,
+ 	      const line_maps *line_maps,
+ 	      std::unique_ptr<sarif_serialization_format> serialization_format,
+ 	      const sarif_generation_options &sarif_gen_opts)
+   : sink (dc),
+     m_builder (dc, *get_printer (), line_maps,
+ 	       std::move (serialization_format), sarif_gen_opts),
+     m_buffer (nullptr)
+   {}
+ 
+   sarif_builder m_builder;
+   sarif_sink_buffer *m_buffer;
+ };
+ 
+ class sarif_stream_sink : public sarif_sink
+ {
+ public:
+   sarif_stream_sink (context &dc,
+ 		     const line_maps *line_maps,
+ 		     std::unique_ptr<sarif_serialization_format> serialization_format,
+ 		     const sarif_generation_options &sarif_gen_opts,
+ 		     FILE *stream)
+   : sarif_sink (dc, line_maps,
+ 		std::move (serialization_format), sarif_gen_opts),
+     m_stream (stream)
+   {
+   }
+   ~sarif_stream_sink ()
+   {
+     m_builder.flush_to_file (m_stream);
+   }
+   bool machine_readable_stderr_p () const final override
+   {
+     return m_stream == stderr;
+   }
+ private:
+   FILE *m_stream;
+ };
+ 
+ class sarif_file_sink : public sarif_sink
+ {
+ public:
+   sarif_file_sink (context &dc,
+ 		   const line_maps *line_maps,
+ 		   std::unique_ptr<sarif_serialization_format> serialization_format,
+ 		   const sarif_generation_options &sarif_gen_opts,
+ 		   output_file output_file_)
+   : sarif_sink (dc, line_maps,
+ 		std::move (serialization_format),
+ 		sarif_gen_opts),
+     m_output_file (std::move (output_file_))
+   {
+     gcc_assert (m_output_file.get_open_file ());
+     gcc_assert (m_output_file.get_filename ());
+   }
+   ~sarif_file_sink ()
+   {
+     m_builder.flush_to_file (m_output_file.get_open_file ());
+   }
+   void dump (FILE *out, int indent) const override
+   {
+     fprintf (out, "%*ssarif_file_sink: %s\n",
+ 	     indent, "",
+ 	     m_output_file.get_filename ());
+     sink::dump (out, indent);
+   }
+   bool machine_readable_stderr_p () const final override
+   {
+     return false;
+   }
+ 
+ private:
+   output_file m_output_file;
+ };
+ 
+ /* Print the start of an embedded link to PP, as per 3.11.6.  */
+ 
+ static void
+ sarif_begin_embedded_link (pretty_printer *pp)
+ {
+   pp_character (pp, '[');
+ }
+ 
+ /* Print the end of an embedded link to PP, as per 3.11.6.  */
+ 
+ static void
+ sarif_end_embedded_link (pretty_printer *pp,
+ 			 const char *url)
+ {
+   pp_string (pp, "](");
+   /* TODO: does the URI need escaping?
+      See https://github.com/oasis-tcs/sarif-spec/issues/657 */
+   pp_string (pp, url);
+   pp_character (pp, ')');
+ }
+ 
+ /* class sarif_token_printer : public token_printer.  */
+ 
+ /* Implementation of pretty_printer::token_printer for SARIF output.
+    Emit URLs as per 3.11.6 ("Messages with embedded links").  */
+ 
+ void
+ sarif_builder::sarif_token_printer::print_tokens (pretty_printer *pp,
+ 						  const pp_token_list &tokens)
+ {
+   /* Convert to text, possibly with colorization, URLs, etc.  */
+   label_text current_url;
+   for (auto iter = tokens.m_first; iter; iter = iter->m_next)
+     switch (iter->m_kind)
+       {
+       default:
+ 	gcc_unreachable ();
+ 
+       case pp_token::kind::text:
+ 	{
+ 	  const pp_token_text *sub = as_a <const pp_token_text *> (iter);
+ 	  const char * const str = sub->m_value.get ();
+ 	  if (current_url.get ())
+ 	    {
+ 	      /* Write iter->m_value, but escaping any
+ 		 escaped link characters as per 3.11.6.  */
+ 	      for (const char *ptr = str; *ptr; ptr++)
+ 		{
+ 		  const char ch = *ptr;
+ 		  switch (ch)
+ 		    {
+ 		    default:
+ 		      pp_character (pp, ch);
+ 		      break;
+ 		    case '\\':
+ 		    case '[':
+ 		    case ']':
+ 		      pp_character (pp, '\\');
+ 		      pp_character (pp, ch);
+ 		      break;
+ 		    }
+ 		}
+ 	    }
+ 	  else
+ 	    /* TODO: is other escaping needed? (e.g. of '[')
+ 	       See https://github.com/oasis-tcs/sarif-spec/issues/658 */
+ 	    pp_string (pp, str);
+ 	}
+ 	break;
+ 
+       case pp_token::kind::begin_color:
+       case pp_token::kind::end_color:
+ 	/* These are no-ops.  */
+ 	break;
+ 
+       case pp_token::kind::begin_quote:
+ 	pp_begin_quote (pp, pp_show_color (pp));
+ 	break;
+       case pp_token::kind::end_quote:
+ 	pp_end_quote (pp, pp_show_color (pp));
+ 	break;
+ 
+       /* Emit URLs as per 3.11.6 ("Messages with embedded links").  */
+       case pp_token::kind::begin_url:
+ 	{
+ 	  pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter);
+ 	  sarif_begin_embedded_link (pp);
+ 	  current_url = std::move (sub->m_value);
+ 	}
+ 	break;
+       case pp_token::kind::end_url:
+ 	gcc_assert (current_url.get ());
+ 	sarif_end_embedded_link (pp, current_url.get ());
+ 	current_url = label_text::borrow (nullptr);
+ 	break;
+ 
+       case pp_token::kind::event_id:
+ 	{
+ 	  pp_token_event_id *sub = as_a <pp_token_event_id *> (iter);
+ 	  gcc_assert (sub->m_event_id.known_p ());
+ 	  const sarif_code_flow *code_flow
+ 	    = m_builder.get_code_flow_for_event_ids ();
+ 	  label_text url = make_sarif_url_for_event (code_flow,
+ 						     sub->m_event_id);
+ 	  if (url.get ())
+ 	    sarif_begin_embedded_link (pp);
+ 	  pp_character (pp, '(');
+ 	  pp_decimal_int (pp, sub->m_event_id.one_based ());
+ 	  pp_character (pp, ')');
+ 	  if (url.get ())
+ 	    sarif_end_embedded_link (pp, url.get ());
+ 	}
+ 	break;
+       }
+ }
+ 
+ /* Populate CONTEXT in preparation for SARIF output (either to stderr, or
+    to a file).
+    Return a reference to *FMT.  */
+ 
+ static sink &
+ init_sarif_sink (context &dc,
+ 		 std::unique_ptr<sarif_sink> fmt)
+ {
+   gcc_assert (fmt);
+   sink &out = *fmt;
+ 
+   fmt->update_printer ();
+ 
+   dc.set_sink (std::move (fmt));
+ 
+   return out;
+ }
+ 
+ /* Populate DC in preparation for SARIF output to stderr.
+    Return a reference to the new sink.  */
+ 
+ sink &
+ init_sarif_stderr (context &dc,
+ 		   const line_maps *line_maps,
+ 		   bool formatted)
+ {
+   gcc_assert (line_maps);
+   const sarif_generation_options sarif_gen_opts;
+   auto serialization
+     = std::make_unique<sarif_serialization_format_json> (formatted);
+   return init_sarif_sink
+     (dc,
+      std::make_unique<sarif_stream_sink> (dc,
+ 					  line_maps,
+ 					  std::move (serialization),
+ 					  sarif_gen_opts,
+ 					  stderr));
+ }
+ 
+ /* Attempt to open "BASE_FILE_NAME""EXTENSION" for writing.
+    Return a non-null output_file,
+    or return a null output_file and complain to DC
+    using LINE_MAPS.  */
+ 
+ output_file
+ output_file::try_to_open (context &dc,
+ 			  line_maps *line_maps,
+ 			  const char *base_file_name,
+ 			  const char *extension,
+ 			  bool is_binary)
+ {
+   gcc_assert (extension);
+   gcc_assert (extension[0] == '.');
+ 
+   if (!base_file_name)
+     {
+       rich_location richloc (line_maps, UNKNOWN_LOCATION);
+       dc.emit_diagnostic_with_group
+ 	(kind::error, richloc, nullptr, 0,
+ 	 "unable to determine filename for SARIF output");
+       return output_file ();
+     }
+ 
+   label_text filename = label_text::take (concat (base_file_name,
+ 						  extension,
+ 						  nullptr));
+   FILE *outf = fopen (filename.get (), is_binary ? "wb" : "w");
+   if (!outf)
+     {
+       rich_location richloc (line_maps, UNKNOWN_LOCATION);
+       dc.emit_diagnostic_with_group
+ 	(kind::error, richloc, nullptr, 0,
+ 	 "unable to open %qs for diagnostic output: %m",
+ 	 filename.get ());
+       return output_file ();
+     }
+   return output_file (outf, true, std::move (filename));
+ }
+ 
+ /* Attempt to open BASE_FILE_NAME.sarif for writing JSON.
+    Return a non-null output_file,
+    or return a null output_file and complain to DC
+    using LINE_MAPS.  */
+ 
+ output_file
+ open_sarif_output_file (context &dc,
+ 			line_maps *line_maps,
+ 			const char *base_file_name,
+ 			enum sarif_serialization_kind serialization_kind)
+ {
+   const char *suffix;
+   bool is_binary;
+   switch (serialization_kind)
+     {
+     default:
+       gcc_unreachable ();
+     case sarif_serialization_kind::json:
+       suffix = ".sarif";
+       is_binary = false;
+       break;
+     }
+ 
+   return output_file::try_to_open (dc,
+ 				   line_maps,
+ 				   base_file_name,
+ 				   suffix,
+ 				   is_binary);
+ }
+ 
+ /* Populate DC in preparation for SARIF output to a file named
+    BASE_FILE_NAME.sarif.
+    Return a reference to the new sink.  */
+ 
+ sink &
+ init_sarif_file (context &dc,
+ 		 line_maps *line_maps,
+ 		 bool formatted,
+ 		 const char *base_file_name)
+ {
+   gcc_assert (line_maps);
+ 
+   output_file output_file_
+     = open_sarif_output_file (dc,
+ 			      line_maps,
+ 			      base_file_name,
+ 			      sarif_serialization_kind::json);
+   auto serialization
+     = std::make_unique<sarif_serialization_format_json> (formatted);
+ 
+   const sarif_generation_options sarif_gen_opts;
+   return init_sarif_sink
+     (dc,
+      std::make_unique<sarif_file_sink> (dc,
+ 					line_maps,
+ 					std::move (serialization),
+ 					sarif_gen_opts,
+ 					std::move (output_file_)));
+ }
+ 
+ /* Populate DC in preparation for SARIF output to STREAM.
+    Return a reference to the new sink.  */
+ 
+ sink &
+ init_sarif_stream (context &dc,
+ 		   const line_maps *line_maps,
+ 		   bool formatted,
+ 		   FILE *stream)
+ {
+   gcc_assert (line_maps);
+   const sarif_generation_options sarif_gen_opts;
+   auto serialization
+     = std::make_unique<sarif_serialization_format_json> (formatted);
+   return init_sarif_sink
+     (dc,
+      std::make_unique<sarif_stream_sink> (dc,
+ 					  line_maps,
+ 					  std::move (serialization),
+ 					  sarif_gen_opts,
+ 					  stream));
+ }
+ 
+ std::unique_ptr<sink>
+ make_sarif_sink (context &dc,
+ 		 const line_maps &line_maps,
+ 		 std::unique_ptr<sarif_serialization_format> serialization,
+ 		 const sarif_generation_options &sarif_gen_opts,
+ 		 output_file output_file_)
+ {
+   auto sink
+     = std::make_unique<sarif_file_sink> (dc,
+ 					 &line_maps,
+ 					 std::move (serialization),
+ 					 sarif_gen_opts,
+ 					 std::move (output_file_));
+   sink->update_printer ();
+   return sink;
+ }
+ 
+ // struct sarif_generation_options
+ 
+ sarif_generation_options::sarif_generation_options ()
+ : m_version (sarif_version::v2_1_0),
+   m_state_graph (false)
+ {
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace selftest {
+ 
+ using auto_fix_quotes = ::selftest::auto_fix_quotes;
+ using line_table_case = ::selftest::line_table_case;
+ 
+ static void
+ test_sarif_array_of_unique_1 ()
+ {
+   sarif_array_of_unique<json::string> arr;
+ 
+   ASSERT_EQ (arr.length (), 0);
+ 
+   {
+     size_t idx = arr.append_uniquely (std::make_unique<json::string> ("foo"));
+     ASSERT_EQ (idx, 0);
+     ASSERT_EQ (arr.length (), 1);
+   }
+   {
+     size_t idx = arr.append_uniquely (std::make_unique<json::string> ("bar"));
+     ASSERT_EQ (idx, 1);
+     ASSERT_EQ (arr.length (), 2);
+   }
+ 
+   /* Try adding them again, should be idempotent.  */
+   {
+     size_t idx = arr.append_uniquely (std::make_unique<json::string> ("foo"));
+     ASSERT_EQ (idx, 0);
+     ASSERT_EQ (arr.length (), 2);
+   }
+   {
+     size_t idx = arr.append_uniquely (std::make_unique<json::string> ("bar"));
+     ASSERT_EQ (idx, 1);
+     ASSERT_EQ (arr.length (), 2);
+   }
+ }
+ 
+ static void
+ test_sarif_array_of_unique_2 ()
+ {
+   sarif_array_of_unique<json::object> arr;
+ 
+   ASSERT_EQ (arr.length (), 0);
+ 
+   {
+     auto obj0 = std::make_unique<json::object> ();
+     size_t idx = arr.append_uniquely (std::move (obj0));
+     ASSERT_EQ (idx, 0);
+     ASSERT_EQ (arr.length (), 1);
+ 
+     // Attempting to add another empty objects should be idempotent.
+     idx = arr.append_uniquely (std::make_unique<json::object> ());
+     ASSERT_EQ (idx, 0);
+     ASSERT_EQ (arr.length (), 1);
+   }
+   {
+     auto obj1 = std::make_unique<json::object> ();
+     obj1->set_string ("foo", "bar");
+     size_t idx = arr.append_uniquely (std::move (obj1));
+     ASSERT_EQ (idx, 1);
+     ASSERT_EQ (arr.length (), 2);
+ 
+     // Attempting to add an equivalent object should be idempotent.
+     auto other = std::make_unique<json::object> ();
+     other->set_string ("foo", "bar");
+     idx = arr.append_uniquely (std::move (other));
+     ASSERT_EQ (idx, 1);
+     ASSERT_EQ (arr.length (), 2);
+   }
+ 
+   // Verify behavior of add_explicit_index_values.
+   arr.add_explicit_index_values ();
+   ASSERT_JSON_INT_PROPERTY_EQ (arr[0], "index", 0);
+   ASSERT_JSON_INT_PROPERTY_EQ (arr[1], "index", 1);
+ }
+ 
+ /* A subclass of sarif_sink for writing selftests.
+    The JSON output is cached internally, rather than written
+    out to a file.  */
+ 
+ class test_sarif_diagnostic_context : public test_context
+ {
+ public:
+   test_sarif_diagnostic_context (const char *main_input_filename,
+ 				 const sarif_generation_options &sarif_gen_opts)
+   {
+     auto sink_ = std::make_unique<buffered_sink> (*this,
+ 						  line_table,
+ 						  true,
+ 						  sarif_gen_opts);
+     m_sink = sink_.get (); // borrowed
+     init_sarif_sink (*this, std::move (sink_));
+     m_sink->set_main_input_filename (main_input_filename);
+   }
+ 
+   std::unique_ptr<sarif_log> flush_to_object ()
+   {
+     return m_sink->flush_to_object ();
+   }
+ 
+   size_t num_results () const { return m_sink->num_results (); }
+   sarif_result &get_result (size_t idx) { return m_sink->get_result (idx); }
+ 
+ private:
+   class buffered_sink : public sarif_sink
+   {
+   public:
+     buffered_sink (context &dc,
+ 		   const line_maps *line_maps,
+ 		   bool formatted,
+ 		   const sarif_generation_options &sarif_gen_opts)
+     : sarif_sink (dc, line_maps,
+ 		  std::make_unique<sarif_serialization_format_json> (formatted),
+ 		  sarif_gen_opts)
+     {
+     }
+     bool machine_readable_stderr_p () const final override
+     {
+       return false;
+     }
+     std::unique_ptr<sarif_log> flush_to_object ()
+     {
+       return m_builder.flush_to_object ();
+     }
+   };
+ 
+   buffered_sink *m_sink; // borrowed
+ };
+ 
+ /* Test making a sarif_location for a complex rich_location
+    with labels and escape-on-output.  */
+ 
+ static void
+ test_make_location_object (const sarif_generation_options &sarif_gen_opts,
+ 			   const ::selftest::line_table_case &case_)
+ {
+   source_printing_fixture_one_liner_utf8 f (case_);
+   location_t line_end = linemap_position_for_column (line_table, 31);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   test_context dc;
+   pretty_printer pp;
+   sarif_builder builder
+     (dc, pp, line_table,
+      std::make_unique<sarif_serialization_format_json> (true),
+      sarif_gen_opts);
+ 
+   /* These "columns" are byte offsets, whereas later on the columns
+      in the generated SARIF use sarif_builder::get_sarif_column and
+      thus respect tabs, encoding.  */
+   const location_t foo
+     = make_location (linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 8));
+   const location_t bar
+     = make_location (linemap_position_for_column (line_table, 12),
+ 		     linemap_position_for_column (line_table, 12),
+ 		     linemap_position_for_column (line_table, 17));
+   const location_t field
+     = make_location (linemap_position_for_column (line_table, 19),
+ 		     linemap_position_for_column (line_table, 19),
+ 		     linemap_position_for_column (line_table, 30));
+ 
+   text_range_label label0 ("label0");
+   text_range_label label1 ("label1");
+   text_range_label label2 ("label2");
+ 
+   rich_location richloc (line_table, foo, &label0, nullptr);
+   richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+   richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+   richloc.set_escape_on_output (true);
+ 
+   sarif_result result (0);
+ 
+   std::unique_ptr<sarif_location> location_obj
+     = builder.make_location_object
+ 	(&result, richloc, logical_locations::key (),
+ 	 diagnostic_artifact_role::analysis_target);
+   ASSERT_NE (location_obj, nullptr);
+ 
+   auto physical_location
+     = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (location_obj.get (),
+ 					       "physicalLocation");
+   {
+     auto region
+       = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (physical_location, "region");
+     ASSERT_JSON_INT_PROPERTY_EQ (region, "startLine", 1);
+     ASSERT_JSON_INT_PROPERTY_EQ (region, "startColumn", 1);
+     ASSERT_JSON_INT_PROPERTY_EQ (region, "endColumn", 7);
+   }
+   {
+     auto context_region
+       = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (physical_location,
+ 						 "contextRegion");
+     ASSERT_JSON_INT_PROPERTY_EQ (context_region, "startLine", 1);
+ 
+     {
+       auto snippet
+ 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (context_region, "snippet");
+ 
+       /* We expect the snippet's "text" to be a copy of the content.  */
+       ASSERT_JSON_STRING_PROPERTY_EQ (snippet, "text",  f.m_content);
+ 
+       /* We expect the snippet to have a "rendered" whose "text" has a
+ 	 pure ASCII escaped copy of the line (with labels, etc).  */
+       {
+ 	auto rendered
+ 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (snippet, "rendered");
+ 	ASSERT_JSON_STRING_PROPERTY_EQ
+ 	  (rendered, "text",
+ 	   "1 | <U+1F602>_foo = <U+03C0>_bar.<U+1F602>_field<U+03C0>;\n"
+ 	   "  | ^~~~~~~~~~~~~   ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~\n"
+ 	   "  | |               |            |\n"
+ 	   "  | label0          label1       label2\n");
+       }
+     }
+   }
+   auto annotations
+     = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (location_obj.get (),
+ 					      "annotations");
+   ASSERT_EQ (annotations->size (), 3);
+   {
+     {
+       auto a0 = (*annotations)[0];
+       ASSERT_JSON_INT_PROPERTY_EQ (a0, "startLine", 1);
+       ASSERT_JSON_INT_PROPERTY_EQ (a0, "startColumn", 1);
+       ASSERT_JSON_INT_PROPERTY_EQ (a0, "endColumn", 7);
+       auto message
+ 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (a0, "message");
+       ASSERT_JSON_STRING_PROPERTY_EQ (message, "text", "label0");
+     }
+     {
+       auto a1 = (*annotations)[1];
+       ASSERT_JSON_INT_PROPERTY_EQ (a1, "startLine", 1);
+       ASSERT_JSON_INT_PROPERTY_EQ (a1, "startColumn", 10);
+       ASSERT_JSON_INT_PROPERTY_EQ (a1, "endColumn", 15);
+       auto message
+ 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (a1, "message");
+       ASSERT_JSON_STRING_PROPERTY_EQ (message, "text", "label1");
+     }
+     {
+       auto a2 = (*annotations)[2];
+       ASSERT_JSON_INT_PROPERTY_EQ (a2, "startLine", 1);
+       ASSERT_JSON_INT_PROPERTY_EQ (a2, "startColumn", 16);
+       ASSERT_JSON_INT_PROPERTY_EQ (a2, "endColumn", 25);
+       auto message
+ 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (a2, "message");
+       ASSERT_JSON_STRING_PROPERTY_EQ (message, "text", "label2");
+     }
+   }
+ }
+ 
+ /* Test of reporting a diagnostic at UNKNOWN_LOCATION to a
+    diagnostics::context and examining the generated sarif_log.
+    Verify various basic properties. */
+ 
+ static void
+ test_simple_log (const sarif_generation_options &sarif_gen_opts)
+ {
+   test_sarif_diagnostic_context dc ("MAIN_INPUT_FILENAME", sarif_gen_opts);
+ 
+   rich_location richloc (line_table, UNKNOWN_LOCATION);
+   dc.report (kind::error, richloc, nullptr, 0, "this is a test: %i", 42);
+ 
+   auto log_ptr = dc.flush_to_object ();
+ 
+   // 3.13 sarifLog:
+   auto log = log_ptr.get ();
+   const enum sarif_version version = sarif_gen_opts.m_version;
+   ASSERT_JSON_STRING_PROPERTY_EQ (log, "$schema",
+ 				  sarif_version_to_url (version));
+   ASSERT_JSON_STRING_PROPERTY_EQ (log, "version",
+ 				  sarif_version_to_property (version));
+ 
+   auto runs = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (log, "runs"); // 3.13.4
+   ASSERT_EQ (runs->size (), 1);
+ 
+   // 3.14 "run" object:
+   auto run = (*runs)[0];
+ 
+   {
+     // 3.14.6:
+     auto tool = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (run, "tool");
+ 
+     EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (tool, "driver"); // 3.18.2
+   }
+ 
+   {
+     // 3.14.11
+     auto invocations
+       = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "invocations");
+     ASSERT_EQ (invocations->size (), 1);
+ 
+     {
+       // 3.20 "invocation" object:
+       auto invocation = (*invocations)[0];
+ 
+       // 3.20.3 arguments property
+ 
+       // 3.20.7 startTimeUtc property
+       EXPECT_JSON_OBJECT_WITH_STRING_PROPERTY (invocation, "startTimeUtc");
+ 
+       // 3.20.8 endTimeUtc property
+       EXPECT_JSON_OBJECT_WITH_STRING_PROPERTY (invocation, "endTimeUtc");
+ 
+       // 3.20.19 workingDirectory property
+       {
+ 	auto wd_obj
+ 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (invocation,
+ 						     "workingDirectory");
+ 	EXPECT_JSON_OBJECT_WITH_STRING_PROPERTY (wd_obj, "uri");
+       }
+ 
+       // 3.20.21 toolExecutionNotifications property
+       auto notifications
+ 	= EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY
+ 	    (invocation, "toolExecutionNotifications");
+       ASSERT_EQ (notifications->size (), 0);
+     }
+   }
+ 
+   {
+     // 3.14.15:
+     auto artifacts = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "artifacts");
+     ASSERT_EQ (artifacts->size (), 1);
+ 
+     {
+       // 3.24 "artifact" object:
+       auto artifact = (*artifacts)[0];
+ 
+       // 3.24.2:
+       auto location
+ 	= EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (artifact, "location");
+       ASSERT_JSON_STRING_PROPERTY_EQ (location, "uri", "MAIN_INPUT_FILENAME");
+ 
+       // 3.24.6:
+       auto roles = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (artifact, "roles");
+       ASSERT_EQ (roles->size (), 1);
+       {
+ 	auto role = (*roles)[0];
+ 	ASSERT_JSON_STRING_EQ (role, "analysisTarget");
+       }
+     }
+   }
+ 
+   {
+     // 3.14.23:
+     auto results = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "results");
+     ASSERT_EQ (results->size (), 1);
+ 
+     {
+       // 3.27 "result" object:
+       auto result = (*results)[0];
+       ASSERT_JSON_STRING_PROPERTY_EQ (result, "ruleId", "error");
+       ASSERT_JSON_STRING_PROPERTY_EQ (result, "level", "error"); // 3.27.10
+ 
+       {
+ 	// 3.27.11:
+ 	auto message
+ 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (result, "message");
+ 	ASSERT_JSON_STRING_PROPERTY_EQ (message, "text",
+ 					"this is a test: 42");
+       }
+ 
+       // 3.27.12:
+       auto locations
+ 	= EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (result, "locations");
+       ASSERT_EQ (locations->size (), 0);
+     }
+   }
+ }
+ 
+ /* As above, but with a "real" location_t.  */
+ 
+ static void
+ test_simple_log_2 (const sarif_generation_options &sarif_gen_opts,
+ 		   const line_table_case &case_)
+ {
+   auto_fix_quotes fix_quotes;
+ 
+   const char *const content
+     /* 000000000111111
+        123456789012345.  */
+     = "unsinged int i;\n";
+   source_printing_fixture f (case_, content);
+   location_t line_end = linemap_position_for_column (line_table, 31);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   test_sarif_diagnostic_context dc (f.get_filename (), sarif_gen_opts);
+ 
+   const location_t typo_loc
+     = make_location (linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 8));
+ 
+   rich_location richloc (line_table, typo_loc);
+   dc.report (kind::error, richloc, nullptr, 0,
+ 	     "did you misspell %qs again?",
+ 	     "unsigned");
+ 
+   auto log_ptr = dc.flush_to_object ();
+ 
+   // 3.13 sarifLog:
+   auto log = log_ptr.get ();
+ 
+   auto runs = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (log, "runs"); // 3.13.4
+   ASSERT_EQ (runs->size (), 1);
+ 
+   // 3.14 "run" object:
+   auto run = (*runs)[0];
+ 
+   {
+     // 3.14.23:
+     auto results = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "results");
+     ASSERT_EQ (results->size (), 1);
+ 
+     {
+       // 3.27 "result" object:
+       auto result = (*results)[0];
+       ASSERT_JSON_STRING_PROPERTY_EQ (result, "ruleId", "error");
+       ASSERT_JSON_STRING_PROPERTY_EQ (result, "level", "error"); // 3.27.10
+ 
+       {
+ 	// 3.27.11:
+ 	auto message
+ 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (result, "message");
+ 	ASSERT_JSON_STRING_PROPERTY_EQ (message, "text",
+ 					"did you misspell `unsigned' again?");
+       }
+ 
+       // 3.27.12:
+       auto locations
+ 	= EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (result, "locations");
+       ASSERT_EQ (locations->size (), 1);
+ 
+       {
+ 	// 3.28 "location" object:
+ 	auto location = (*locations)[0];
+ 
+ 	auto physical_location
+ 	  = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (location,
+ 						     "physicalLocation");
+ 	{
+ 	  auto region
+ 	    = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (physical_location,
+ 						       "region");
+ 	  ASSERT_JSON_INT_PROPERTY_EQ (region, "startLine", 1);
+ 	  ASSERT_JSON_INT_PROPERTY_EQ (region, "startColumn", 1);
+ 	  ASSERT_JSON_INT_PROPERTY_EQ (region, "endColumn", 9);
+ 	}
+ 	{
+ 	  auto context_region
+ 	    = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (physical_location,
+ 						       "contextRegion");
+ 	  ASSERT_JSON_INT_PROPERTY_EQ (context_region, "startLine", 1);
+ 
+ 	  {
+ 	    auto snippet
+ 	      = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (context_region,
+ 							 "snippet");
+ 
+ 	    /* We expect the snippet's "text" to be a copy of the content.  */
+ 	    ASSERT_JSON_STRING_PROPERTY_EQ (snippet, "text",  f.m_content);
+ 	  }
+ 	}
+       }
+     }
+   }
+ }
+ 
+ /* Assuming that a single diagnostic has been emitted within
+    LOG, get a json::object for the result object.  */
+ 
+ static const json::object *
+ get_result_from_log (const sarif_log *log)
+ {
+   auto runs = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (log, "runs"); // 3.13.4
+   ASSERT_EQ (runs->size (), 1);
+ 
+   // 3.14 "run" object:
+   auto run = (*runs)[0];
+ 
+   // 3.14.23:
+   auto results = EXPECT_JSON_OBJECT_WITH_ARRAY_PROPERTY (run, "results");
+   ASSERT_EQ (results->size (), 1);
+ 
+   // 3.27 "result" object:
+   auto result = (*results)[0];
+   return expect_json_object (SELFTEST_LOCATION, result);
+ }
+ 
+ static const json::object *
+ get_message_from_result (const sarif_result &result)
+ {
+   // 3.27.11:
+   auto message_obj
+     = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (&result, "message");
+   return message_obj;
+ }
+ 
+ /* Assuming that a single diagnostic has been emitted to
+    DC, get a json::object for the messsage object within
+    the result.  */
+ 
+ static const json::object *
+ get_message_from_log (const sarif_log *log)
+ {
+   auto result_obj = get_result_from_log (log);
+ 
+   // 3.27.11:
+   auto message_obj
+     = EXPECT_JSON_OBJECT_WITH_OBJECT_PROPERTY (result_obj, "message");
+   return message_obj;
+ }
+ 
+ /* Tests of messages with embedded links; see SARIF v2.1.0 3.11.6.  */
+ 
+ static void
+ test_message_with_embedded_link (const sarif_generation_options &sarif_gen_opts)
+ {
+   auto_fix_quotes fix_quotes;
+   {
+     test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
+     rich_location richloc (line_table, UNKNOWN_LOCATION);
+     dc.report (kind::error, richloc, nullptr, 0,
+ 	       "before %{text%} after",
+ 	       "http://example.com");
+     std::unique_ptr<sarif_log> log = dc.flush_to_object ();
+ 
+     auto message_obj = get_message_from_log (log.get ());
+     ASSERT_JSON_STRING_PROPERTY_EQ
+       (message_obj, "text",
+        "before [text](http://example.com) after");
+   }
+ 
+   /* Escaping in message text.
+      This is "EXAMPLE 1" from 3.11.6.  */
+   {
+     test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
+     rich_location richloc (line_table, UNKNOWN_LOCATION);
+ 
+     /* Disable "unquoted sequence of 2 consecutive punctuation
+        characters `]\' in format" warning.  */
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic push
+ #  pragma GCC diagnostic ignored "-Wformat-diag"
+ #endif
+     dc.report (kind::error, richloc, nullptr, 0,
+ 	       "Prohibited term used in %{para[0]\\spans[2]%}.",
+ 	       "1");
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic pop
+ #endif
+ 
+     std::unique_ptr<sarif_log> log = dc.flush_to_object ();
+ 
+     auto message_obj = get_message_from_log (log.get ());
+     ASSERT_JSON_STRING_PROPERTY_EQ
+       (message_obj, "text",
+        "Prohibited term used in [para\\[0\\]\\\\spans\\[2\\]](1).");
+     /* This isn't exactly what EXAMPLE 1 of the spec has; reported as
+        https://github.com/oasis-tcs/sarif-spec/issues/656  */
+   }
+ 
+   /* Urlifier.  */
+   {
+     class test_urlifier : public urlifier
+     {
+     public:
+       char *
+       get_url_for_quoted_text (const char *p, size_t sz) const final override
+       {
+ 	if (!strncmp (p, "-foption", sz))
+ 	  return xstrdup ("http://example.com");
+ 	return nullptr;
+       }
+     };
+ 
+     test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
+     dc.push_owned_urlifier (std::make_unique<test_urlifier> ());
+     rich_location richloc (line_table, UNKNOWN_LOCATION);
+     dc.report (kind::error, richloc, nullptr, 0,
+ 	       "foo %<-foption%> %<unrecognized%> bar");
+     std::unique_ptr<sarif_log> log = dc.flush_to_object ();
+ 
+     auto message_obj = get_message_from_log (log.get ());
+     ASSERT_JSON_STRING_PROPERTY_EQ
+       (message_obj, "text",
+        "foo `[-foption](http://example.com)' `unrecognized' bar");
+   }
+ }
+ 
+ /* Verify that braces in messages get escaped, as per
+    3.11.5 ("Messages with placeholders").  */
+ 
+ static void
+ test_message_with_braces (const sarif_generation_options &sarif_gen_opts)
+ {
+   auto_fix_quotes fix_quotes;
+   {
+     test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
+     rich_location richloc (line_table, UNKNOWN_LOCATION);
+     dc.report (kind::error, richloc, nullptr, 0,
+ 	       "open brace: %qs close brace: %qs",
+ 	       "{", "}");
+     std::unique_ptr<sarif_log> log = dc.flush_to_object ();
+ 
+     auto message_obj = get_message_from_log (log.get ());
+     ASSERT_JSON_STRING_PROPERTY_EQ
+       (message_obj, "text",
+        "open brace: `{{' close brace: `}}'");
+   }
+ }
+ 
+ static void
+ test_buffering (const sarif_generation_options &sarif_gen_opts)
+ {
+   test_sarif_diagnostic_context dc ("test.c", sarif_gen_opts);
+ 
+   diagnostics::buffer buf_a (dc);
+   diagnostics::buffer buf_b (dc);
+ 
+   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+ 
+   ASSERT_EQ (dc.diagnostic_count (kind::error), 0);
+   ASSERT_EQ (buf_a.diagnostic_count (kind::error), 0);
+   ASSERT_EQ (buf_b.diagnostic_count (kind::error), 0);
+   ASSERT_EQ (dc.num_results (), 0);
+   ASSERT_TRUE (buf_a.empty_p ());
+   ASSERT_TRUE (buf_b.empty_p ());
+ 
+   /* Unbuffered diagnostic.  */
+   {
+     dc.report (kind::error, rich_loc, nullptr, 0,
+ 	       "message 1");
+ 
+     ASSERT_EQ (dc.diagnostic_count (kind::error), 1);
+     ASSERT_EQ (buf_a.diagnostic_count (kind::error), 0);
+     ASSERT_EQ (buf_b.diagnostic_count (kind::error), 0);
+     ASSERT_EQ (dc.num_results (), 1);
+     sarif_result &result_obj = dc.get_result (0);
+     auto message_obj = get_message_from_result (result_obj);
+     ASSERT_JSON_STRING_PROPERTY_EQ (message_obj, "text",
+ 				    "message 1");
+     ASSERT_TRUE (buf_a.empty_p ());
+     ASSERT_TRUE (buf_b.empty_p ());
+   }
+ 
+   /* Buffer diagnostic into buffer A.  */
+   {
+     dc.set_diagnostic_buffer (&buf_a);
+     dc.report (kind::error, rich_loc, nullptr, 0,
+ 	       "message in buffer a");
+     ASSERT_EQ (dc.diagnostic_count (kind::error), 1);
+     ASSERT_EQ (buf_a.diagnostic_count (kind::error), 1);
+     ASSERT_EQ (buf_b.diagnostic_count (kind::error), 0);
+     ASSERT_EQ (dc.num_results (), 1);
+     ASSERT_FALSE (buf_a.empty_p ());
+     ASSERT_TRUE (buf_b.empty_p ());
+   }
+ 
+   /* Buffer diagnostic into buffer B.  */
+   {
+     dc.set_diagnostic_buffer (&buf_b);
+     dc.report (kind::error, rich_loc, nullptr, 0,
+ 	       "message in buffer b");
+     ASSERT_EQ (dc.diagnostic_count (kind::error), 1);
+     ASSERT_EQ (buf_a.diagnostic_count (kind::error), 1);
+     ASSERT_EQ (buf_b.diagnostic_count (kind::error), 1);
+     ASSERT_EQ (dc.num_results (), 1);
+     ASSERT_FALSE (buf_a.empty_p ());
+     ASSERT_FALSE (buf_b.empty_p ());
+   }
+ 
+   /* Flush buffer B to dc.  */
+   {
+     dc.flush_diagnostic_buffer (buf_b);
+     ASSERT_EQ (dc.diagnostic_count (kind::error), 2);
+     ASSERT_EQ (buf_a.diagnostic_count (kind::error), 1);
+     ASSERT_EQ (buf_b.diagnostic_count (kind::error), 0);
+     ASSERT_EQ (dc.num_results (), 2);
+     sarif_result &result_1_obj = dc.get_result (1);
+     auto message_1_obj = get_message_from_result (result_1_obj);
+     ASSERT_JSON_STRING_PROPERTY_EQ (message_1_obj, "text",
+ 				    "message in buffer b");
+     ASSERT_FALSE (buf_a.empty_p ());
+     ASSERT_TRUE (buf_b.empty_p ());
+   }
+ 
+   /* Clear buffer A.  */
+   {
+     dc.clear_diagnostic_buffer (buf_a);
+     ASSERT_EQ (dc.diagnostic_count (kind::error), 2);
+     ASSERT_EQ (buf_a.diagnostic_count (kind::error), 0);
+     ASSERT_EQ (buf_b.diagnostic_count (kind::error), 0);
+     ASSERT_EQ (dc.num_results (), 2);
+     ASSERT_TRUE (buf_a.empty_p ());
+     ASSERT_TRUE (buf_b.empty_p ());
+   }
+ }
+ 
+ template <class ...ArgTypes>
+ static void
+ for_each_sarif_gen_option (void (*callback) (const sarif_generation_options &,
+ 					     ArgTypes ...),
+ 			   ArgTypes ...args)
+ {
+   sarif_generation_options sarif_gen_opts;
+   for (int version_idx = 0;
+        version_idx < (int)sarif_version::num_versions;
+        ++version_idx)
+     {
+       sarif_gen_opts.m_version = static_cast<enum sarif_version> (version_idx);
+ 
+       callback (sarif_gen_opts, args...);
+     }
+ }
+ 
+ static void
+ run_line_table_case_tests_per_version (const line_table_case &case_)
+ {
+   for_each_sarif_gen_option<const line_table_case &>
+     (test_make_location_object, case_);
+ 
+   for_each_sarif_gen_option<const line_table_case &>
+     (test_simple_log_2, case_);
+ }
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ sarif_sink_cc_tests ()
+ {
+   test_sarif_array_of_unique_1 ();
+   test_sarif_array_of_unique_2 ();
+ 
+   for_each_sarif_gen_option (test_simple_log);
+   for_each_sarif_gen_option (test_message_with_embedded_link);
+   for_each_sarif_gen_option (test_message_with_braces);
+   for_each_sarif_gen_option (test_buffering);
+ 
+   /* Run tests per (SARIF gen-option, line-table-case) pair.  */
+   for_each_line_table_case (run_line_table_case_tests_per_version);
+ }
+ 
+ } // namespace diagnostics::selftest
+ } // namespace diagnostics
+ 
+ #endif /* CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/sarif-sink.h gcc-16-20250727/gcc/diagnostics/sarif-sink.h
*** gcc-16-20250720/gcc/diagnostics/sarif-sink.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/sarif-sink.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,189 ----
+ /* SARIF output for diagnostics.
+    Copyright (C) 2023-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_SARIF_SINK_H
+ #define GCC_DIAGNOSTICS_SARIF_SINK_H
+ 
+ #include "json.h"
+ #include "diagnostics/sink.h"
+ #include "diagnostics/output-file.h"
+ #include "diagnostics/logical-locations.h"
+ 
+ namespace diagnostics {
+ 
+ namespace digraphs {
+   class digraph;
+   class node;
+   class edge;
+ }
+ 
+ /* Enum for choosing what format to serializing the generated SARIF into.  */
+ 
+ enum class sarif_serialization_kind
+ {
+    json,
+ 
+    num_values
+ };
+ 
+ extern output_file
+ open_sarif_output_file (context &dc,
+ 			line_maps *line_maps,
+ 			const char *base_file_name,
+ 			enum sarif_serialization_kind serialization_kind);
+ 
+ extern sink &
+ init_sarif_stderr (context &dc,
+ 		   const line_maps *line_maps,
+ 		   bool formatted);
+ extern sink &
+ init_sarif_file (context &dc,
+ 		 line_maps *line_maps,
+ 		 bool formatted,
+ 		 const char *base_file_name);
+ extern sink &
+ init_sarif_stream (context &dc,
+ 		   const line_maps *line_maps,
+ 		   bool formatted,
+ 		   FILE *stream);
+ 
+ /* Abstract base class for handling JSON output vs other kinds of
+    serialization of the json tree.  */
+ 
+ class sarif_serialization_format
+ {
+ public:
+   virtual ~sarif_serialization_format () {}
+   virtual void write_to_file (FILE *outf,
+ 			      const json::value &top) = 0;
+ };
+ 
+ /* Concrete subclass for serializing SARIF as JSON.  */
+ 
+ class sarif_serialization_format_json : public sarif_serialization_format
+ {
+ public:
+   sarif_serialization_format_json (bool formatted)
+   : m_formatted (formatted)
+   {
+   }
+   void write_to_file (FILE *outf, const json::value &top) final override;
+ 
+ private:
+   bool m_formatted;
+ };
+ 
+ /* Control of SARIF generation.  */
+ 
+ enum class sarif_version
+ {
+   v2_1_0,
+   v2_2_prerelease_2024_08_08,
+ 
+   num_versions
+ };
+ 
+ /* A bundle of state for controlling what to put in SARIF output,
+    such as which version of SARIF to generate
+    (as opposed to SARIF *serialization* options, such as formatting).  */
+ 
+ struct sarif_generation_options
+ {
+   sarif_generation_options ();
+ 
+   enum sarif_version m_version;
+   bool m_state_graph;
+ };
+ 
+ extern std::unique_ptr<sink>
+ make_sarif_sink (context &dc,
+ 		 const line_maps &line_maps,
+ 		 std::unique_ptr<sarif_serialization_format> serialization_format,
+ 		 const sarif_generation_options &sarif_gen_opts,
+ 		 output_file output_file_);
+ 
+ class sarif_builder;
+ class sarif_location_manager;
+ 
+ /* Concrete subclass of json::object for SARIF property bags
+    (SARIF v2.1.0 section 3.8).  */
+ 
+ class sarif_property_bag : public json::object
+ {
+ public:
+   void set_logical_location (const char *property_name,
+ 			     sarif_builder &,
+ 			     logical_locations::key logical_loc);
+   void set_graph (const char *property_name,
+ 		  sarif_builder &,
+ 		  sarif_location_manager *sarif_location_mgr,
+ 		  const digraphs::digraph &g);
+ };
+ 
+ /* Concrete subclass of json::object for SARIF objects that can
+    contain property bags (as per SARIF v2.1.0 section 3.8.1, which has:
+    "In addition to those properties that are explicitly documented, every
+    object defined in this document MAY contain a property named properties
+    whose value is a property bag.")  */
+ 
+ class sarif_object : public json::object
+ {
+ public:
+   sarif_property_bag &get_or_create_properties ();
+ };
+ 
+ /* Subclass of sarif_object for SARIF "graph" objects
+    (SARIF v2.1.0 section 3.39).  */
+ 
+ class sarif_graph : public sarif_object
+ {
+ };
+ 
+ /* Subclass of sarif_object for SARIF "node" objects
+    (SARIF v2.1.0 section 3.40).  */
+ 
+ class sarif_node : public sarif_object
+ {
+ };
+ 
+ /* Subclass of sarif_object for SARIF "edge" objects
+    (SARIF v2.1.0 section 3.41).  */
+ 
+ class sarif_edge : public sarif_object
+ {
+ };
+ 
+ extern std::unique_ptr<sarif_graph>
+ make_sarif_graph (const digraphs::digraph &g,
+ 		  sarif_builder *builder,
+ 		  sarif_location_manager *sarif_location_mgr);
+ 
+ extern std::unique_ptr<sarif_node>
+ make_sarif_node (const digraphs::node &n,
+ 		 sarif_builder *builder,
+ 		 sarif_location_manager *sarif_location_mgr);
+ 
+ extern std::unique_ptr<sarif_edge>
+ make_sarif_edge (const digraphs::edge &e,
+ 		 sarif_builder *builder);
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_SARIF_SINK_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/selftest-context.cc gcc-16-20250727/gcc/diagnostics/selftest-context.cc
*** gcc-16-20250720/gcc/diagnostics/selftest-context.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/selftest-context.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,104 ----
+ /* Selftest support for diagnostics.
+    Copyright (C) 2016-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "diagnostic.h"
+ #include "diagnostics/sink.h"
+ #include "selftest.h"
+ #include "diagnostics/selftest-context.h"
+ 
+ /* The selftest code should entirely disappear in a production
+    configuration, hence we guard all of it with #if CHECKING_P.  */
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace selftest {
+ 
+ /* Implementation of class diagnostics::selftest::test_context.  */
+ 
+ test_context::test_context ()
+ {
+   diagnostic_initialize (this, 0);
+   pp_show_color (get_reference_printer ()) = false;
+ 
+   auto &source_printing_opts = get_source_printing_options ();
+   source_printing_opts.enabled = true;
+   source_printing_opts.show_labels_p = true;
+   m_show_column = true;
+   start_span (this) = start_span_cb;
+   source_printing_opts.min_margin_width = 6;
+   source_printing_opts.max_width = 80;
+   pp_buffer (get_sink (0).get_printer ())->m_flush_p = false;
+ }
+ 
+ test_context::~test_context ()
+ {
+   diagnostic_finish (this);
+ }
+ 
+ /* Implementation of diagnostics::start_span_fn, hiding the
+    real filename (to avoid printing the names of tempfiles).  */
+ 
+ void
+ test_context::
+ start_span_cb (const location_print_policy &loc_policy,
+ 	       to_text &html_or_text,
+ 	       expanded_location exploc)
+ {
+   exploc.file = "FILENAME";
+   default_start_span_fn<to_text>
+     (loc_policy, html_or_text, exploc);
+ }
+ 
+ bool
+ test_context::report (enum kind kind,
+ 		      rich_location &richloc,
+ 		      const metadata *metadata_,
+ 		      option_id opt_id,
+ 		      const char * fmt, ...)
+ {
+   va_list ap;
+   va_start (ap, fmt);
+   begin_group ();
+   bool result = diagnostic_impl (&richloc, metadata_, opt_id, fmt, &ap, kind);
+   end_group ();
+   va_end (ap);
+   return result;
+ }
+ 
+ /* Print RICHLOC's source and annotations to this context's m_printer.
+    Return the text buffer from the printer.  */
+ 
+ const char *
+ test_context::test_show_locus (rich_location &richloc)
+ {
+   pretty_printer *pp = get_reference_printer ();
+   gcc_assert (pp);
+   source_print_policy source_policy (*this);
+   source_policy.print (*pp, richloc, kind::error, nullptr);
+   return pp_formatted_text (pp);
+ }
+ 
+ } // namespace selftest
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/selftest-context.h gcc-16-20250727/gcc/diagnostics/selftest-context.h
*** gcc-16-20250720/gcc/diagnostics/selftest-context.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/selftest-context.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,93 ----
+ /* Selftest support for diagnostics.
+    Copyright (C) 2016-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_SELFTEST_CONTEXT_H
+ #define GCC_DIAGNOSTICS_SELFTEST_CONTEXT_H
+ 
+ /* The selftest code should entirely disappear in a production
+    configuration, hence we guard all of it with #if CHECKING_P.  */
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace selftest {
+ 
+ /* Convenience subclass of diagnostics::context for testing
+    the diagnostic subsystem.  */
+ 
+ class test_context : public context
+ {
+  public:
+   test_context ();
+   ~test_context ();
+ 
+   /* Implementation of diagnostics::start_span_fn, hiding the
+      real filename (to avoid printing the names of tempfiles).  */
+   static void
+   start_span_cb (const location_print_policy &,
+ 		 to_text &sink,
+ 		 expanded_location exploc);
+ 
+   /* Report a diagnostic to this context.  For a selftest, this
+      should only be called on a context that uses a non-standard formatter
+      that e.g. gathers the results in memory, rather than emits to stderr.  */
+   bool
+   report (enum kind kind,
+ 	  rich_location &richloc,
+ 	  const metadata *,
+ 	  option_id opt_id,
+ 	  const char * fmt, ...) ATTRIBUTE_GCC_DIAG(6,7);
+ 
+   const char *test_show_locus (rich_location &richloc);
+ 
+   /* Setters for the context's source_printing_options
+      for use in selftests.  */
+   void colorize_source (bool val)
+   {
+     get_source_printing_options ().colorize_source_p = val;
+   }
+   void show_labels (bool val)
+   {
+     get_source_printing_options ().show_labels_p = val;
+   }
+   void show_line_numbers (bool val)
+   {
+     get_source_printing_options ().show_line_numbers_p = val;
+   }
+   void show_ruler (bool val)
+   {
+     get_source_printing_options ().show_ruler_p = val;
+   }
+   void show_event_links (bool val)
+   {
+     get_source_printing_options ().show_event_links_p = val;
+   }
+   void set_caret_char (unsigned idx, char ch)
+   {
+     gcc_assert (idx < rich_location::STATICALLY_ALLOCATED_RANGES);
+     get_source_printing_options ().caret_chars[idx] = ch;
+   }
+ };
+ 
+ } // namespace selftest
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
+ 
+ #endif /* GCC_DIAGNOSTICS_SELFTEST_CONTEXT_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/selftest-logical-locations.cc gcc-16-20250727/gcc/diagnostics/selftest-logical-locations.cc
*** gcc-16-20250720/gcc/diagnostics/selftest-logical-locations.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/selftest-logical-locations.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,122 ----
+ /* Concrete subclass of logical_locations::manager for use in selftests.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "selftest.h"
+ #include "diagnostics/selftest-logical-locations.h"
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace logical_locations {
+ namespace selftest {
+ 
+ /* class test_manager : public manager.  */
+ 
+ test_manager::~test_manager ()
+ {
+   for (auto iter : m_name_to_item_map)
+     delete iter.second;
+ }
+ 
+ const char *
+ test_manager::get_short_name (key k) const
+ {
+   auto item = item_from_key (k);
+   if (!item)
+     return nullptr;
+   return item->m_name;
+ }
+ 
+ const char *
+ test_manager::get_name_with_scope (key k) const
+ {
+   auto item = item_from_key (k);
+   return item->m_name;
+ }
+ 
+ const char *
+ test_manager::get_internal_name (key k) const
+ {
+   auto item = item_from_key (k);
+   return item->m_name;
+ }
+ 
+ enum diagnostics::logical_locations::kind
+ test_manager::get_kind (key k) const
+ {
+   auto item = item_from_key (k);
+   return item->m_kind;
+ }
+ 
+ label_text
+ test_manager::get_name_for_path_output (key k) const
+ {
+   auto item = item_from_key (k);
+   return label_text::borrow (item->m_name);
+ }
+ 
+ diagnostics::logical_locations::key
+ test_manager::
+ logical_location_from_funcname (const char *funcname)
+ {
+   const item *i = item_from_funcname (funcname);
+   return key::from_ptr (i);
+ }
+ 
+ const test_manager::item *
+ test_manager::item_from_funcname (const char *funcname)
+ {
+   if (!funcname)
+     return nullptr;
+ 
+   if (item **slot = m_name_to_item_map.get (funcname))
+     return *slot;
+ 
+   item *i = new item (kind::function, funcname);
+   m_name_to_item_map.put (funcname, i);
+   return i;
+ }
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ selftest_logical_locations_cc_tests ()
+ {
+   test_manager mgr;
+ 
+   ASSERT_FALSE (mgr.logical_location_from_funcname (nullptr));
+ 
+   key loc_foo = mgr.logical_location_from_funcname ("foo");
+   key loc_bar = mgr.logical_location_from_funcname ("bar");
+ 
+   ASSERT_NE (loc_foo, loc_bar);
+ 
+   ASSERT_STREQ (mgr.get_short_name (loc_foo), "foo");
+   ASSERT_STREQ (mgr.get_short_name (loc_bar), "bar");
+ }
+ 
+ } // namespace diagnostics::logical_locations::selftest
+ } // namespace diagnostics::logical_locations
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/selftest-logical-locations.h gcc-16-20250727/gcc/diagnostics/selftest-logical-locations.h
*** gcc-16-20250720/gcc/diagnostics/selftest-logical-locations.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/selftest-logical-locations.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,86 ----
+ /* Concrete subclass of logical_locations::manager for use in selftests.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_SELFTEST_LOGICAL_LOCATIONS_H
+ #define GCC_DIAGNOSTICS_SELFTEST_LOGICAL_LOCATIONS_H
+ 
+ #include "diagnostics/logical-locations.h"
+ 
+ /* The selftest code should entirely disappear in a production
+    configuration, hence we guard all of it with #if CHECKING_P.  */
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace logical_locations {
+ namespace selftest {
+ 
+ /* Concrete subclass of logical_locations::manager for use in selftests.  */
+ 
+ class test_manager : public manager
+ {
+ public:
+   ~test_manager ();
+ 
+   const char *get_short_name (key) const final override;
+   const char *get_name_with_scope (key) const final override;
+   const char *get_internal_name (key) const final override;
+   kind get_kind (key) const final override;
+   label_text get_name_for_path_output (key) const final override;
+   key get_parent (key) const final override
+   {
+     return key ();
+   }
+ 
+   key
+   logical_location_from_funcname (const char *funcname);
+ 
+ private:
+   struct item
+   {
+     item (kind kind_,
+ 	  const char *name)
+     : m_kind (kind_),
+       m_name (name)
+     {
+     }
+ 
+     kind m_kind;
+     const char *m_name;
+   };
+ 
+   const item *
+   item_from_funcname (const char *funcname);
+ 
+   static const item *item_from_key (key k)
+   {
+     return k.cast_to<const item *> ();
+   }
+ 
+   hash_map<nofree_string_hash, item *> m_name_to_item_map;
+ };
+ 
+ } // namespace diagnostics::logical_locations::selftest
+ } // namespace diagnostics::logical_locations::
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
+ 
+ #endif /* GCC_DIAGNOSTICS_SELFTEST_LOGICAL_LOCATIONS_H.  */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/selftest-paths.cc gcc-16-20250727/gcc/diagnostics/selftest-paths.cc
*** gcc-16-20250720/gcc/diagnostics/selftest-paths.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/selftest-paths.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,247 ----
+ /* Concrete classes for selftests involving diagnostic paths.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ 
+ #include "config.h"
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "version.h"
+ #include "diagnostic.h"
+ #include "diagnostics/selftest-paths.h"
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace paths {
+ namespace selftest {
+ 
+ /* class test_path : public diagnostics::paths::path.  */
+ 
+ test_path::
+ test_path (logical_locations::selftest::test_manager &logical_loc_mgr,
+ 	   pretty_printer *event_pp)
+ : path (logical_loc_mgr),
+   m_test_logical_loc_mgr (logical_loc_mgr),
+   m_event_pp (event_pp)
+ {
+   add_thread ("main");
+ }
+ 
+ /* Implementation of path::num_events vfunc for
+    test_path: simply get the number of events in the vec.  */
+ 
+ unsigned
+ test_path::num_events () const
+ {
+   return m_events.length ();
+ }
+ 
+ /* Implementation of path::get_event vfunc for
+    test_path: simply return the event in the vec.  */
+ 
+ const event &
+ test_path::get_event (int idx) const
+ {
+   return *m_events[idx];
+ }
+ 
+ unsigned
+ test_path::num_threads () const
+ {
+   return m_threads.length ();
+ }
+ 
+ const thread &
+ test_path::get_thread (thread_id_t idx) const
+ {
+   return *m_threads[idx];
+ }
+ 
+ bool
+ test_path::same_function_p (int event_idx_a,
+ 			    int event_idx_b) const
+ {
+   return (m_events[event_idx_a]->get_logical_location ()
+ 	  == m_events[event_idx_b]->get_logical_location ());
+ }
+ 
+ thread_id_t
+ test_path::add_thread (const char *name)
+ {
+   m_threads.safe_push (new test_thread (name));
+   return m_threads.length () - 1;
+ }
+ 
+ /* Add an event to this path at LOC within function FNDECL at
+    stack depth DEPTH.
+ 
+    Use m_context's printer to format FMT, as the text of the new
+    event.
+ 
+    Return the id of the new event.  */
+ 
+ event_id_t
+ test_path::add_event (location_t loc,
+ 		      const char *funcname,
+ 		      int depth,
+ 		      const char *fmt, ...)
+ {
+   pretty_printer *pp = m_event_pp;
+   pp_clear_output_area (pp);
+ 
+   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+ 
+   va_list ap;
+ 
+   va_start (ap, fmt);
+ 
+   /* No localization is done on FMT.  */
+   text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
+   pp_format (pp, &ti);
+   pp_output_formatted_text (pp);
+ 
+   va_end (ap);
+ 
+   test_event *new_event
+     = new test_event (loc,
+ 		      logical_location_from_funcname (funcname),
+ 		      depth,
+ 		      pp_formatted_text (pp));
+   m_events.safe_push (new_event);
+ 
+   pp_clear_output_area (pp);
+ 
+   return event_id_t (m_events.length () - 1);
+ }
+ 
+ event_id_t
+ test_path::add_thread_event (thread_id_t thread_id,
+ 			     location_t loc,
+ 			     const char *funcname,
+ 			     int depth,
+ 			     const char *fmt, ...)
+ {
+   pretty_printer *pp = m_event_pp;
+   pp_clear_output_area (pp);
+ 
+   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+ 
+   va_list ap;
+ 
+   va_start (ap, fmt);
+ 
+   /* No localization is done on FMT.  */
+   text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
+ 
+   pp_format (pp, &ti);
+   pp_output_formatted_text (pp);
+ 
+   va_end (ap);
+ 
+   test_event *new_event
+     = new test_event (loc,
+ 		      logical_location_from_funcname (funcname),
+ 		      depth,
+ 		      pp_formatted_text (pp),
+ 		      thread_id);
+   m_events.safe_push (new_event);
+ 
+   pp_clear_output_area (pp);
+ 
+   return event_id_t (m_events.length () - 1);
+ }
+ 
+ /* Mark the most recent event on this path (which must exist) as being
+    connected to the next one to be added.  */
+ 
+ void
+ test_path::connect_to_next_event ()
+ {
+   gcc_assert (m_events.length () > 0);
+   m_events[m_events.length () - 1]->connect_to_next_event ();
+ }
+ 
+ void
+ test_path::add_entry (const char *callee_name,
+ 		      int stack_depth,
+ 		      thread_id_t thread_id)
+ {
+   add_thread_event (thread_id, UNKNOWN_LOCATION, callee_name, stack_depth,
+ 		    "entering %qs", callee_name);
+ }
+ 
+ void
+ test_path::add_return (const char *caller_name,
+ 		       int stack_depth,
+ 		       thread_id_t thread_id)
+ {
+   add_thread_event (thread_id, UNKNOWN_LOCATION, caller_name, stack_depth,
+ 		    "returning to %qs", caller_name);
+ }
+ 
+ void
+ test_path::add_call (const char *caller_name,
+ 		     int caller_stack_depth,
+ 		     const char *callee_name,
+ 		     thread_id_t thread_id)
+ {
+   add_thread_event (thread_id, UNKNOWN_LOCATION,
+ 		    caller_name, caller_stack_depth,
+ 		    "calling %qs", callee_name);
+   add_entry (callee_name, caller_stack_depth + 1, thread_id);
+ }
+ 
+ logical_locations::key
+ test_path::logical_location_from_funcname (const char *funcname)
+ {
+   return m_test_logical_loc_mgr.logical_location_from_funcname (funcname);
+ }
+ 
+ /* struct test_event.  */
+ 
+ /* test_event's ctor.  */
+ 
+ test_event::
+ test_event (location_t loc,
+ 	    logical_location logical_loc,
+ 	    int depth,
+ 	    const char *desc,
+ 	    thread_id_t thread_id)
+ : m_loc (loc),
+   m_logical_loc (logical_loc),
+   m_depth (depth), m_desc (xstrdup (desc)),
+   m_connected_to_next_event (false),
+   m_thread_id (thread_id)
+ {
+ }
+ 
+ /* test_event's dtor.  */
+ 
+ test_event::~test_event ()
+ {
+   free (m_desc);
+ }
+ 
+ } // namespace diagnostics::paths::selftest
+ } // namespace diagnostics::paths
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/selftest-paths.h gcc-16-20250727/gcc/diagnostics/selftest-paths.h
*** gcc-16-20250720/gcc/diagnostics/selftest-paths.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/selftest-paths.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,169 ----
+ /* Concrete classes for selftests involving diagnostic paths.
+    Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_SELFTEST_PATHS_H
+ #define GCC_DIAGNOSTICS_SELFTEST_PATHS_H
+ 
+ #include "diagnostics/paths.h"
+ #include "diagnostics/selftest-logical-locations.h"
+ 
+ /* The selftest code should entirely disappear in a production
+    configuration, hence we guard all of it with #if CHECKING_P.  */
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace paths {
+ namespace selftest {
+ 
+ /* Concrete subclasses of the abstract base classes
+    declared in diagnostic-path.h for use in selftests.
+ 
+    This code should have no dependency on "tree".  */
+ 
+ /* An implementation of diagnostics::paths::event.  */
+ 
+ class test_event : public event
+ {
+  public:
+   using logical_location = logical_locations::key;
+   using thread_id_t = paths::thread_id_t;
+ 
+   test_event (location_t loc,
+ 	      logical_location logical_loc,
+ 	      int depth,
+ 	      const char *desc,
+ 	      thread_id_t thread_id = 0);
+   ~test_event ();
+ 
+   location_t get_location () const final override { return m_loc; }
+   int get_stack_depth () const final override { return m_depth; }
+   void print_desc (pretty_printer &pp) const final override
+   {
+     pp_string (&pp, m_desc);
+   }
+   logical_location get_logical_location () const final override
+   {
+     return m_logical_loc;
+   }
+   meaning get_meaning () const final override
+   {
+     return meaning ();
+   }
+   bool connect_to_next_event_p () const final override
+   {
+     return m_connected_to_next_event;
+   }
+   thread_id_t get_thread_id () const final override
+   {
+     return m_thread_id;
+   }
+ 
+   void connect_to_next_event ()
+   {
+     m_connected_to_next_event = true;
+   }
+ 
+  private:
+   location_t m_loc;
+   logical_location m_logical_loc;
+   int m_depth;
+   char *m_desc; // has been formatted; doesn't get i18n-ed
+   bool m_connected_to_next_event;
+   thread_id_t m_thread_id;
+ };
+ 
+ /* A simple implementation of diagnostics::paths::thread.  */
+ 
+ class test_thread : public thread
+ {
+ public:
+   test_thread (const char *name) : m_name (name) {}
+   label_text get_name (bool) const final override
+   {
+     return label_text::borrow (m_name);
+   }
+ 
+ private:
+   const char *m_name; // has been i18n-ed and formatted
+ };
+ 
+ /* A concrete subclass of diagnostics::paths::path for implementing selftests
+    - a vector of test_event instances
+    - adds member functions for adding test event
+    - does no translation of its events
+    - has no dependency on "tree".  */
+ 
+ class test_path : public path
+ {
+  public:
+   test_path (logical_locations::selftest::test_manager &logical_loc_mgr,
+ 	     pretty_printer *event_pp);
+ 
+   unsigned num_events () const final override;
+   const event & get_event (int idx) const final override;
+   unsigned num_threads () const final override;
+   const thread &
+   get_thread (thread_id_t) const final override;
+   bool
+   same_function_p (int event_idx_a,
+ 		   int event_idx_b) const final override;
+ 
+   thread_id_t add_thread (const char *name);
+ 
+   event_id_t add_event (location_t loc, const char *funcname, int depth,
+ 			const char *fmt, ...)
+     ATTRIBUTE_GCC_DIAG(5,6);
+   event_id_t
+   add_thread_event (thread_id_t thread_id,
+ 		    location_t loc, const char *funcname, int depth,
+ 		    const char *fmt, ...)
+     ATTRIBUTE_GCC_DIAG(6,7);
+ 
+   void connect_to_next_event ();
+ 
+   void add_entry (const char *callee_name, int stack_depth,
+ 		  thread_id_t thread_id = 0);
+   void add_return (const char *caller_name, int stack_depth,
+ 		   thread_id_t thread_id = 0);
+   void add_call (const char *caller_name,
+ 		 int caller_stack_depth,
+ 		 const char *callee_name,
+ 		 thread_id_t thread_id = 0);
+ 
+  private:
+   logical_locations::key
+   logical_location_from_funcname (const char *funcname);
+ 
+   logical_locations::selftest::test_manager &m_test_logical_loc_mgr;
+   auto_delete_vec<test_thread> m_threads;
+   auto_delete_vec<test_event> m_events;
+ 
+   /* (for use by add_event).  */
+   pretty_printer *m_event_pp;
+ };
+ 
+ } // namespace diagnostics::paths::selftest
+ } // namespace diagnostics::paths
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
+ 
+ #endif /* ! GCC_DIAGNOSTICS_SELFTEST_PATHS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/selftest-source-printing.h gcc-16-20250727/gcc/diagnostics/selftest-source-printing.h
*** gcc-16-20250720/gcc/diagnostics/selftest-source-printing.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/selftest-source-printing.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,85 ----
+ /* Support for selftests involving diagnostic_show_locus.
+    Copyright (C) 1999-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_SELFTEST_SOURCE_PRINTING_H
+ #define GCC_DIAGNOSTICS_SELFTEST_SOURCE_PRINTING_H
+ 
+ #include "selftest.h"
+ #include "diagnostics/file-cache.h"
+ 
+ /* The selftest code should entirely disappear in a production
+    configuration, hence we guard all of it with #if CHECKING_P.  */
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace selftest {
+ 
+ /* RAII class for use in selftests involving diagnostic_show_locus.
+ 
+    Manages creating and cleaning up the following:
+    - writing out a temporary .c file containing CONTENT
+    - temporarily override the global "line_table" (using CASE_) and
+      push a line_map starting at the first line of the temporary file
+    - provide a file_cache.  */
+ 
+ struct source_printing_fixture
+ {
+   source_printing_fixture (const ::selftest::line_table_case &case_,
+ 			   const char *content);
+ 
+   const char *get_filename () const
+   {
+     return m_tmp_source_file.get_filename ();
+   }
+ 
+   const char *m_content;
+   ::selftest::temp_source_file m_tmp_source_file;
+   ::selftest::line_table_test m_ltt;
+   file_cache m_fc;
+ };
+ 
+ /* Fixture for one-liner tests exercising multibyte awareness.  For
+    simplicity we stick to using two multibyte characters in the test, U+1F602
+    == "\xf0\x9f\x98\x82", which uses 4 bytes and 2 display columns, and U+03C0
+    == "\xcf\x80", which uses 2 bytes and 1 display column.
+ 
+    This works with the following 1-line source file:
+ 
+      .0000000001111111111222222   display
+      .1234567890123456789012345   columns
+      "SS_foo = P_bar.SS_fieldP;\n"
+      .0000000111111111222222223   byte
+      .1356789012456789134567891   columns
+ 
+    Here SS represents the two display columns for the U+1F602 emoji and
+    P represents the one display column for the U+03C0 pi symbol.  */
+ 
+ struct source_printing_fixture_one_liner_utf8
+   : public source_printing_fixture
+ {
+   source_printing_fixture_one_liner_utf8 (const ::selftest::line_table_case &case_);
+ };
+ 
+ } // namespace diagnostics::selftest
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
+ 
+ #endif /* GCC_DIAGNOSTICS_SELFTEST_SOURCE_PRINTING_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/sink.h gcc-16-20250727/gcc/diagnostics/sink.h
*** gcc-16-20250720/gcc/diagnostics/sink.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/sink.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,110 ----
+ /* Declarations for managing different output formats for diagnostics.
+    Copyright (C) 2023-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_SINK_H
+ #define GCC_DIAGNOSTICS_SINK_H
+ 
+ #include "diagnostic.h"
+ 
+ namespace diagnostics {
+ 
+ class per_sink_buffer;
+ 
+ /* Abstract base class for a particular output format for diagnostics;
+    each value of -fdiagnostics-output-format= will have its own
+    implementation.  */
+ 
+ class sink
+ {
+ public:
+   virtual ~sink () {}
+ 
+   virtual void dump (FILE *out, int indent) const;
+ 
+   /* Vfunc for notifying this format what the primary input file is,
+      e.g. for titles of HTML, for SARIF's artifact metadata.  */
+   virtual void set_main_input_filename (const char *) {}
+ 
+   /* Vfunc for making an appropriate per_sink_buffer
+      subclass for this format.  */
+   virtual std::unique_ptr<per_sink_buffer>
+   make_per_sink_buffer () = 0;
+ 
+   /* Vfunc to be called when call a diagnostics::buffer is set on
+      a diagnostics::context, to update this format.  The per_sink_buffer
+      will be one created by make_per_sink_buffer above and thus be
+      of the correct subclass.  */
+   virtual void set_buffer (per_sink_buffer *) = 0;
+ 
+   virtual void on_begin_group () = 0;
+   virtual void on_end_group () = 0;
+ 
+   /* Vfunc with responsibility for phase 3 of formatting the message
+      and "printing" the result.  */
+   virtual void on_report_diagnostic (const diagnostic_info &,
+ 				     enum kind orig_diag_kind) = 0;
+ 
+   virtual void on_report_verbatim (text_info &);
+ 
+   virtual void on_diagram (const diagram &diag) = 0;
+   virtual void after_diagnostic (const diagnostic_info &) = 0;
+   virtual bool machine_readable_stderr_p () const = 0;
+   virtual bool follows_reference_printer_p () const = 0;
+ 
+   /* Vfunc called when the diagnostics::context changes its
+      reference printer (either to a new subclass of pretty_printer
+      or when color/url options change).
+      Subclasses should update their m_printer accordingly.  */
+   virtual void update_printer () = 0;
+ 
+   virtual void
+   report_global_digraph (const lazily_created<digraphs::digraph> &) = 0;
+ 
+   context &get_context () const { return m_context; }
+   pretty_printer *get_printer () const { return m_printer.get (); }
+ 
+   text_art::theme *get_diagram_theme () const
+   {
+     return m_context.get_diagram_theme ();
+   }
+ 
+   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
+ 
+ protected:
+   sink (context &dc)
+   : m_context (dc),
+     m_printer (dc.clone_printer ())
+   {}
+ 
+ protected:
+   context &m_context;
+   std::unique_ptr<pretty_printer> m_printer;
+ };
+ 
+ extern void
+ output_format_init (context &,
+ 		    const char *main_input_filename_,
+ 		    const char *base_file_name,
+ 		    enum diagnostics_output_format,
+ 		    bool json_formatting);
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_SINK_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/source-printing-effects.h gcc-16-20250727/gcc/diagnostics/source-printing-effects.h
*** gcc-16-20250720/gcc/diagnostics/source-printing-effects.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/source-printing-effects.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,62 ----
+ /* Classes for adding special effects when quoting source code.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ 
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_SOURCE_PRINTING_EFFECTS_H
+ #define GCC_DIAGNOSTICS_SOURCE_PRINTING_EFFECTS_H
+ 
+ namespace diagnostics {
+ 
+ /* Abstract base class for describing special effects when printing
+    a label when quoting source code.  */
+ 
+ class label_effects
+ {
+ public:
+   virtual ~label_effects () {}
+ 
+   /* Adding links between labels, e.g. for visualizing control flow
+      in execution paths.  */
+   virtual bool has_in_edge (unsigned range_idx) const = 0;
+   virtual bool has_out_edge (unsigned range_idx) const = 0;
+ };
+ 
+ /* A class to hold state when quoting a run of lines of source code.  */
+ 
+ class source_effect_info
+ {
+ public:
+   source_effect_info ()
+   : m_leading_in_edge_column (-1),
+     m_trailing_out_edge_column (-1)
+   {
+   }
+ 
+   /* The column for an incoming link to the first label,
+      or -1 if no such link.  */
+   int m_leading_in_edge_column;
+ 
+   /* The column for an outgoing link from the final label,
+      or -1 if no such link.  */
+   int m_trailing_out_edge_column;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif /* GCC_DIAGNOSTICS_SOURCE_PRINTING_EFFECTS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/source-printing.cc gcc-16-20250727/gcc/diagnostics/source-printing.cc
*** gcc-16-20250720/gcc/diagnostics/source-printing.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/source-printing.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,7052 ----
+ /* Diagnostic subroutines for printing source-code
+    Copyright (C) 1999-2025 Free Software Foundation, Inc.
+    Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #define INCLUDE_MAP
+ #define INCLUDE_STRING
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "version.h"
+ #include "intl.h"
+ #include "diagnostic.h"
+ #include "diagnostics/color.h"
+ #include "gcc-rich-location.h"
+ #include "text-range-label.h"
+ #include "selftest.h"
+ #include "diagnostics/selftest-context.h"
+ #include "diagnostics/selftest-source-printing.h"
+ #include "cpplib.h"
+ #include "text-art/types.h"
+ #include "text-art/theme.h"
+ #include "diagnostics/source-printing-effects.h"
+ #include "diagnostics/file-cache.h"
+ #include "xml.h"
+ #include "xml-printer.h"
+ 
+ #ifdef HAVE_TERMIOS_H
+ # include <termios.h>
+ #endif
+ 
+ #ifdef GWINSZ_IN_SYS_IOCTL
+ # include <sys/ioctl.h>
+ #endif
+ 
+ /* Disable warnings about quoting issues in the pp_xxx calls below
+    that (intentionally) don't follow GCC diagnostic conventions.  */
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic push
+ #  pragma GCC diagnostic ignored "-Wformat-diag"
+ #endif
+ 
+ /* Classes for rendering source code and diagnostics, within an
+    anonymous namespace.
+    The work is done by "class layout", which embeds and uses
+    "class colorizer" and "class layout_range" to get things done.  */
+ 
+ namespace {
+ 
+ /* The state at a given point of the source code, assuming that we're
+    in a range: which range are we in, and whether we should draw a caret at
+    this point.  */
+ 
+ struct point_state
+ {
+   int range_idx;
+   bool draw_caret_p;
+ };
+ 
+ /* A class to inject colorization codes when printing the diagnostic locus
+    as text.
+ 
+    It has one kind of colorization for each of:
+      - normal text
+      - range 0 (the "primary location")
+      - range 1
+      - range 2
+ 
+    The class caches the lookup of the color codes for the above.
+ 
+    The class also has responsibility for tracking which of the above is
+    active, filtering out unnecessary changes.  This allows
+    layout_printer::print_source_line and layout_printer::print_annotation_line
+    to simply request a colorization code for *every* character they print,
+    via this class, and have the filtering be done for them here.  */
+ 
+ class colorizer
+ {
+  public:
+   colorizer (pretty_printer &pp,
+ 	     const rich_location &richloc,
+ 	     enum diagnostics::kind diagnostic_kind);
+   ~colorizer ();
+ 
+   void set_range (int range_idx)
+   {
+     /* If we have a specific highlight color for the range, use it.  */
+     if (pp_show_highlight_colors (&m_pp))
+       {
+ 	const location_range *const loc_range = m_richloc.get_range (range_idx);
+ 	if (loc_range->m_highlight_color)
+ 	  {
+ 	    set_named_color (loc_range->m_highlight_color);
+ 	    return;
+ 	  }
+       }
+ 
+     /* Otherwise, we emphasize the primary location, then alternate between
+        two colors for the secondary locations.
+        But if we're printing a run of events in a diagnostic path, that
+        makes no sense, so print all of them with the same colorization.  */
+     if (m_diagnostic_kind == diagnostics::kind::path)
+       set_state (0);
+     else
+       set_state (range_idx);
+   }
+   void set_cfg_edge () { set_state (0); }
+   void set_normal_text () { set_state (STATE_NORMAL_TEXT); }
+   void set_fixit_insert () { set_state (STATE_FIXIT_INSERT); }
+   void set_fixit_delete () { set_state (STATE_FIXIT_DELETE); }
+   void set_named_color (const char *color);
+ 
+  private:
+   void set_state (int state);
+   void begin_state (int state);
+   void finish_state (int state);
+   const char *get_color_by_name (const char *);
+ 
+  private:
+   static const int STATE_NORMAL_TEXT = -1;
+   static const int STATE_FIXIT_INSERT  = -2;
+   static const int STATE_FIXIT_DELETE  = -3;
+   static const int STATE_NAMED_COLOR  = -4;
+ 
+   pretty_printer &m_pp;
+   const rich_location &m_richloc;
+   enum diagnostics::kind m_diagnostic_kind;
+   int m_current_state;
+   const char *m_range1;
+   const char *m_range2;
+   const char *m_fixit_insert;
+   const char *m_fixit_delete;
+   const char *m_stop_color;
+   std::string m_current_named_color;
+ };
+ 
+ /* In order to handle multibyte sources properly, all of this logic needs to be
+    aware of the distinction between the number of bytes and the number of
+    display columns occupied by a character, which are not the same for non-ASCII
+    characters.  For example, the Unicode pi symbol, U+03C0, is encoded in UTF-8
+    as "\xcf\x80", and thus occupies 2 bytes of space while only occupying 1
+    display column when it is output.  A typical emoji, such as U+1F602 (in
+    UTF-8, "\xf0\x9f\x98\x82"), requires 4 bytes and has a display width of 2.
+ 
+    The below example line, which is also used for selftests below, shows how the
+    display column and byte column are related:
+ 
+      0000000001111111111222222   display
+      1234567890123456789012345   columns
+      SS_foo = P_bar.SS_fieldP;
+      0000000111111111222222223   byte
+      1356789012456789134567891   columns
+ 
+    Here SS represents the two display columns for the U+1F602 emoji, and P
+    represents the one display column for the U+03C0 pi symbol.  As an example, a
+    diagnostic pointing to the final P on this line is at byte column 29 and
+    display column 24.  This reflects the fact that the three extended characters
+    before the final P occupy cumulatively 5 more bytes than they do display
+    columns (a difference of 2 for each of the two SSs, and one for the other P).
+ 
+    One or the other of the two column units is more useful depending on the
+    context.  For instance, in order to output the caret at the correct location,
+    we need to count display columns; in order to colorize a source line, we need
+    to count the bytes.  All locations are provided to us as byte counts, which
+    we augment with the display column on demand so that it can be used when
+    needed.  This is not the most efficient way to do things since it requires
+    looping over the whole line each time, but it should be fine for the purpose
+    of outputting diagnostics.
+ 
+    In order to keep straight which units (byte or display) are in use at a
+    given time, the following enum lets us specify that explicitly.  */
+ 
+ enum column_unit {
+   /* Measured in raw bytes.  */
+   CU_BYTES = 0,
+ 
+   /* Measured in display units.  */
+   CU_DISPLAY_COLS,
+ 
+   /* For arrays indexed by column_unit.  */
+   CU_NUM_UNITS
+ };
+ 
+ /* Utility class to augment an exploc with the corresponding display column.  */
+ 
+ class exploc_with_display_col : public expanded_location
+ {
+  public:
+   exploc_with_display_col (diagnostics::file_cache &fc,
+ 			   const expanded_location &exploc,
+ 			   const cpp_char_column_policy &policy,
+ 			   enum location_aspect aspect)
+   : expanded_location (exploc),
+     m_display_col (location_compute_display_column (fc, exploc, policy))
+   {
+     if (exploc.column > 0)
+       {
+ 	/* m_display_col is now the final column of the byte.
+ 	   If escaping has happened, we may want the first column instead.  */
+ 	if (aspect != LOCATION_ASPECT_FINISH)
+ 	  {
+ 	    expanded_location prev_exploc (exploc);
+ 	    prev_exploc.column--;
+ 	    int prev_display_col
+ 	      = (location_compute_display_column (fc, prev_exploc, policy));
+ 	    m_display_col = prev_display_col + 1;
+ 	  }
+       }
+   }
+ 
+   int m_display_col;
+ };
+ 
+ 
+ /* A point within a layout_range; similar to an exploc_with_display_col,
+    but after filtering on file.  */
+ 
+ class layout_point
+ {
+  public:
+   layout_point (const exploc_with_display_col &exploc)
+     : m_line (exploc.line)
+   {
+     m_columns[CU_BYTES] = exploc.column;
+     m_columns[CU_DISPLAY_COLS] = exploc.m_display_col;
+   }
+ 
+   linenum_type m_line;
+   int m_columns[CU_NUM_UNITS];
+ };
+ 
+ /* A class for use by "class layout" below: a filtered location_range.  */
+ 
+ class layout_range
+ {
+  public:
+   layout_range (const exploc_with_display_col &start_exploc,
+ 		const exploc_with_display_col &finish_exploc,
+ 		enum range_display_kind range_display_kind,
+ 		const exploc_with_display_col &caret_exploc,
+ 		unsigned original_idx,
+ 		const range_label *label);
+ 
+   bool contains_point (linenum_type row, int column,
+ 		       enum column_unit col_unit) const;
+   bool intersects_line_p (linenum_type row) const;
+ 
+   bool has_in_edge () const;
+   bool has_out_edge () const;
+ 
+   layout_point m_start;
+   layout_point m_finish;
+   enum range_display_kind m_range_display_kind;
+   layout_point m_caret;
+   unsigned m_original_idx;
+   const range_label *m_label;
+ };
+ 
+ /* A struct for use by layout::print_source_line for telling
+    layout::print_annotation_line the extents of the source line that
+    it printed, so that underlines can be clipped appropriately.  Units
+    are 1-based display columns.  */
+ 
+ struct line_bounds
+ {
+   int m_first_non_ws_disp_col;
+   int m_last_non_ws_disp_col;
+ 
+   line_bounds ()
+   {
+     m_first_non_ws_disp_col = INT_MAX;
+     m_last_non_ws_disp_col = 0;
+   }
+ };
+ 
+ /* A range of contiguous source lines within a layout (e.g. "lines 5-10"
+    or "line 23").  During the layout ctor, layout::calculate_line_spans
+    splits the pertinent source lines into a list of disjoint line_span
+    instances (e.g. lines 5-10, lines 15-20, line 23).  */
+ 
+ class line_span
+ {
+ public:
+   line_span (linenum_type first_line, linenum_type last_line)
+     : m_first_line (first_line), m_last_line (last_line)
+   {
+     gcc_assert (first_line <= last_line);
+   }
+   linenum_type get_first_line () const { return m_first_line; }
+   linenum_type get_last_line () const { return m_last_line; }
+ 
+   bool contains_line_p (linenum_type line) const
+   {
+     return line >= m_first_line && line <= m_last_line;
+   }
+ 
+   static int comparator (const void *p1, const void *p2)
+   {
+     const line_span *ls1 = (const line_span *)p1;
+     const line_span *ls2 = (const line_span *)p2;
+     int first_line_cmp = compare (ls1->m_first_line, ls2->m_first_line);
+     if (first_line_cmp)
+       return first_line_cmp;
+     return compare (ls1->m_last_line, ls2->m_last_line);
+   }
+ 
+   linenum_type m_first_line;
+   linenum_type m_last_line;
+ };
+ 
+ #if CHECKING_P
+ 
+ /* Selftests for line_span.  */
+ 
+ static void
+ test_line_span ()
+ {
+   line_span line_one (1, 1);
+   ASSERT_EQ (1, line_one.get_first_line ());
+   ASSERT_EQ (1, line_one.get_last_line ());
+   ASSERT_FALSE (line_one.contains_line_p (0));
+   ASSERT_TRUE (line_one.contains_line_p (1));
+   ASSERT_FALSE (line_one.contains_line_p (2));
+ 
+   line_span lines_1_to_3 (1, 3);
+   ASSERT_EQ (1, lines_1_to_3.get_first_line ());
+   ASSERT_EQ (3, lines_1_to_3.get_last_line ());
+   ASSERT_TRUE (lines_1_to_3.contains_line_p (1));
+   ASSERT_TRUE (lines_1_to_3.contains_line_p (3));
+ 
+   ASSERT_EQ (0, line_span::comparator (&line_one, &line_one));
+   ASSERT_GT (line_span::comparator (&lines_1_to_3, &line_one), 0);
+   ASSERT_LT (line_span::comparator (&line_one, &lines_1_to_3), 0);
+ 
+   /* A linenum > 2^31.  */
+   const linenum_type LARGEST_LINE = 0xffffffff;
+   line_span largest_line (LARGEST_LINE, LARGEST_LINE);
+   ASSERT_EQ (LARGEST_LINE, largest_line.get_first_line ());
+   ASSERT_EQ (LARGEST_LINE, largest_line.get_last_line ());
+ 
+   ASSERT_GT (line_span::comparator (&largest_line, &line_one), 0);
+   ASSERT_LT (line_span::comparator (&line_one, &largest_line), 0);
+ }
+ 
+ #endif /* #if CHECKING_P */
+ 
+ /* A bundle of information containing how to print unicode
+    characters and bytes when quoting source code.
+ 
+    Provides a unified place to support escaping some subset
+    of characters to some format.
+ 
+    Extends char_column_policy; printing is split out to avoid
+    libcpp having to know about pretty_printer.  */
+ 
+ struct char_display_policy : public cpp_char_column_policy
+ {
+  public:
+   char_display_policy (int tabstop,
+ 		       int (*width_cb) (cppchar_t c),
+ 		       void (*print_text_cb) (diagnostics::to_text &text_out,
+ 					      const cpp_decoded_char &cp),
+ 		       void (*print_html_cb) (diagnostics::to_html &html_out,
+ 					      const cpp_decoded_char &cp))
+   : cpp_char_column_policy (tabstop, width_cb),
+     m_print_text_cb (print_text_cb),
+     m_print_html_cb (print_html_cb)
+   {
+   }
+ 
+   void (*m_print_text_cb) (diagnostics::to_text &text_out,
+ 			   const cpp_decoded_char &cp);
+   void (*m_print_html_cb) (diagnostics::to_html &html_out,
+ 			   const cpp_decoded_char &cp);
+ };
+ 
+ template <typename TextOrHtml> class layout_printer;
+ 
+ } // anonymous namespace
+ 
+ namespace diagnostics {
+ 
+ /* This code is written generically to write either:
+    - text, to a pretty_printer, potentially with colorization codes, or
+    - html, to an xml::printer, with nested HTML tags.
+ 
+    This is handled via a "TextOrHtml" template, which is either to_text
+    or to_html.  */
+ 
+ /* Writing text output.  */
+ 
+ struct to_text
+ {
+   friend class layout_printer<to_text>;
+ 
+   // This is a RAII class for HTML, but is a no-op for text.
+   struct auto_check_tag_nesting
+   {
+     auto_check_tag_nesting (to_text &) {}
+   };
+ 
+   to_text (pretty_printer &pp,
+ 	   colorizer &colorizer)
+   : m_pp (pp),
+     m_colorizer (&colorizer)
+   {
+     m_saved_rule = pp_prefixing_rule (&m_pp);
+     pp_prefixing_rule (&m_pp) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+   }
+   to_text (pretty_printer &pp,
+ 	   colorizer *colorizer)
+   : m_pp (pp),
+     m_colorizer (colorizer)
+   {
+     m_saved_rule = pp_prefixing_rule (&m_pp);
+     pp_prefixing_rule (&m_pp) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+   }
+   ~to_text ()
+   {
+ 
+     pp_prefixing_rule (&m_pp) = m_saved_rule;
+   }
+ 
+   static bool is_text () { return true; }
+   static bool is_html () { return false; }
+ 
+   void emit_text_prefix ()
+   {
+     pp_emit_prefix (&m_pp);
+   }
+ 
+   void push_html_tag (std::string, bool)
+   {
+     // no-op for text
+   }
+   void push_html_tag_with_class (std::string, std::string, bool)
+   {
+     // no-op for text
+   }
+   void pop_html_tag (const char *)
+   {
+     // no-op for text
+   }
+ 
+   void add_html_tag_with_class (std::string, std::string, bool)
+   {
+     // no-op for text
+   }
+ 
+   void add_space ()
+   {
+     pp_space (&m_pp);
+   }
+ 
+   void add_character (cppchar_t ch)
+   {
+     pp_unicode_character (&m_pp, ch);
+   }
+ 
+   void add_utf8_byte (char b)
+   {
+     pp_character (&m_pp, b);
+   }
+ 
+   void add_text (const char *text)
+   {
+     pp_string (&m_pp, text);
+   }
+ 
+   void print_decoded_char (const char_display_policy &char_policy,
+ 			   cpp_decoded_char cp)
+   {
+     char_policy.m_print_text_cb (*this, cp);
+   }
+ 
+   void colorize_text_ensure_normal ()
+   {
+     gcc_assert (m_colorizer);
+     m_colorizer->set_normal_text ();
+   }
+ 
+   void colorize_text_for_range_idx (int range_idx)
+   {
+     gcc_assert (m_colorizer);
+     m_colorizer->set_range (range_idx);
+   }
+ 
+   void colorize_text_for_cfg_edge ()
+   {
+     gcc_assert (m_colorizer);
+     m_colorizer->set_cfg_edge ();
+   }
+ 
+   void colorize_text_for_fixit_insert ()
+   {
+     gcc_assert (m_colorizer);
+     m_colorizer->set_fixit_insert ();
+   }
+ 
+   void colorize_text_for_fixit_delete ()
+   {
+     gcc_assert (m_colorizer);
+     m_colorizer->set_fixit_delete ();
+   }
+ 
+   void
+   invoke_start_span_fn (const source_print_policy &source_policy,
+ 			const location_print_policy &loc_policy,
+ 			const expanded_location &exploc)
+   {
+     source_policy.get_text_start_span_fn () (loc_policy, *this, exploc);
+   }
+ 
+   // Text-specific functions
+   void add_newline ()
+   {
+     pp_newline (&m_pp);
+   }
+ 
+   pretty_printer &m_pp;
+ private:
+   colorizer *m_colorizer;
+   diagnostic_prefixing_rule_t m_saved_rule;
+ };
+ 
+ /* Writing HTML output.  */
+ 
+ struct to_html
+ {
+   friend class layout_printer<to_html>;
+ 
+   // RAII class for ensuring that the tags nested correctly
+   struct auto_check_tag_nesting : public xml::auto_check_tag_nesting
+   {
+   public:
+     auto_check_tag_nesting (to_html &out)
+     : xml::auto_check_tag_nesting (out.m_xp)
+     {
+     }
+   };
+ 
+   to_html (xml::printer &xp,
+ 	   const rich_location *richloc,
+ 	   html_label_writer *html_label_writer)
+   : m_xp (xp),
+     m_richloc (richloc),
+     m_html_label_writer (html_label_writer)
+   {}
+ 
+   static bool is_text () { return false; }
+   static bool is_html () { return true; }
+ 
+   void emit_text_prefix ()
+   {
+     // no-op for HTML
+   }
+ 
+   void push_html_tag (std::string name,
+ 		      bool preserve_whitespace)
+   {
+     m_xp.push_tag (std::move (name), preserve_whitespace);
+   }
+ 
+   void push_html_tag_with_class (std::string name,
+ 				 std::string class_,
+ 				 bool preserve_whitespace)
+   {
+     m_xp.push_tag_with_class (std::move (name),
+ 			      std::move (class_),
+ 			      preserve_whitespace);
+   }
+ 
+   void pop_html_tag (const char *expected_name)
+   {
+     m_xp.pop_tag (expected_name);
+   }
+ 
+   void add_html_tag_with_class (std::string name,
+ 				std::string class_,
+ 				bool preserve_whitespace)
+   {
+     auto element = std::make_unique<xml::element> (std::move (name),
+ 						   preserve_whitespace);
+     element->set_attr ("class", std::move (class_));
+     m_xp.append (std::move (element));
+   }
+ 
+   void add_raw_html (const char *src)
+   {
+     m_xp.add_raw (src);
+   }
+ 
+   void add_space ()
+   {
+     m_xp.add_text (" ");
+   }
+ 
+   void add_character (cppchar_t ch)
+   {
+     pp_clear_output_area (&m_scratch_pp);
+     pp_unicode_character (&m_scratch_pp, ch);
+     m_xp.add_text_from_pp (m_scratch_pp);
+   }
+ 
+   void add_utf8_byte (char b)
+   {
+     m_xp.add_text (std::string (1, b));
+   }
+ 
+   void add_text (const char *text)
+   {
+     m_xp.add_text (text);
+   }
+ 
+   void print_decoded_char (const char_display_policy &char_policy,
+ 			   cpp_decoded_char cp)
+   {
+     char_policy.m_print_html_cb (*this, cp);
+   }
+ 
+   void colorize_text_ensure_normal ()
+   {
+     // no-op for HTML
+   }
+ 
+   void colorize_text_for_cfg_edge ()
+   {
+     // no-op for HTML
+   }
+ 
+   void colorize_text_for_fixit_insert ()
+   {
+     // no-op for HTML
+   }
+ 
+   void colorize_text_for_fixit_delete ()
+   {
+     // no-op for HTML
+   }
+ 
+   void
+   invoke_start_span_fn (const source_print_policy &source_policy,
+ 			const location_print_policy &loc_policy,
+ 			const expanded_location &exploc)
+   {
+     source_policy.get_html_start_span_fn () (loc_policy, *this, exploc);
+   }
+ 
+   const location_range *
+   get_location_range_by_idx (int range_idx)
+   {
+     if (!m_richloc)
+       return nullptr;
+     return m_richloc->get_range (range_idx);
+   }
+ 
+   const char *
+   get_highlight_color_for_range_idx (int range_idx)
+   {
+     const location_range *const loc_range
+       = get_location_range_by_idx (range_idx);
+     if (!loc_range)
+       return nullptr;
+     return loc_range->m_highlight_color;
+   }
+ 
+   xml::printer &m_xp;
+   const rich_location *m_richloc;
+ private:
+   html_label_writer *m_html_label_writer;
+   pretty_printer m_scratch_pp;
+ };
+ 
+ void
+ location_print_policy::
+ print_text_span_start (const diagnostics::context &dc,
+ 		       pretty_printer &pp,
+ 		       const expanded_location &exploc)
+ {
+   to_text out (pp, nullptr);
+   source_print_policy source_policy (dc);
+   source_policy.get_text_start_span_fn () (*this, out, exploc);
+ }
+ 
+ void
+ location_print_policy::
+ print_html_span_start (const diagnostics::context &dc,
+ 		       xml::printer &xp,
+ 		       const expanded_location &exploc)
+ {
+   to_html out (xp, nullptr, nullptr);
+   source_print_policy source_policy (dc);
+   source_policy.get_html_start_span_fn () (*this, out, exploc);
+ }
+ 
+ pretty_printer *
+ get_printer (to_text &out)
+ {
+   return &out.m_pp;
+ }
+ 
+ template<>
+ void
+ default_start_span_fn<to_text> (const location_print_policy &loc_policy,
+ 				to_text &out,
+ 				expanded_location exploc)
+ {
+   const column_policy &column_policy_ = loc_policy.get_column_policy ();
+   label_text text
+     = column_policy_.get_location_text (exploc,
+ 					loc_policy.show_column_p (),
+ 					pp_show_color (&out.m_pp));
+   pp_string (&out.m_pp, text.get ());
+   pp_newline (&out.m_pp);
+ }
+ 
+ template<>
+ void
+ default_start_span_fn<to_html> (const location_print_policy &loc_policy,
+ 				to_html &out,
+ 				expanded_location exploc)
+ {
+   const column_policy &column_policy_
+     = loc_policy.get_column_policy ();
+   label_text text
+     = column_policy_.get_location_text (exploc,
+ 					loc_policy.show_column_p (),
+ 					false);
+   out.m_xp.push_tag_with_class ("span", "location", true);
+   out.m_xp.add_text (text.get ());
+   out.m_xp.pop_tag ("span");
+ }
+ 
+ } // namespace diagnostics
+ 
+ namespace {
+ 
+ /* A class to control the overall layout when printing a diagnostic.
+ 
+    The layout is determined within the constructor.
+ 
+    Printing the layout is handled by class layout_printer.  This separation
+    is to avoid depending on the pretty_printer in the layout.
+ 
+    We assume we have disjoint ranges.  */
+ 
+ class layout
+ {
+  public:
+   friend class layout_printer<diagnostics::to_text>;
+   friend class layout_printer<diagnostics::to_html>;
+ 
+   layout (const diagnostics::source_print_policy &source_policy,
+ 	  const rich_location &richloc,
+ 	  diagnostics::source_effect_info *effect_info = nullptr);
+ 
+   bool maybe_add_location_range (const location_range *loc_range,
+ 				 unsigned original_idx,
+ 				 bool restrict_to_current_line_spans);
+ 
+   int get_num_line_spans () const { return m_line_spans.length (); }
+   const line_span *get_line_span (int idx) const { return &m_line_spans[idx]; }
+ 
+   int get_linenum_width () const { return m_linenum_width; }
+   int get_x_offset_display () const { return m_x_offset_display; }
+ 
+   bool print_heading_for_line_span_index_p (int line_span_idx) const;
+ 
+   expanded_location get_expanded_location (const line_span *) const;
+ 
+   void on_bad_codepoint (const char *ptr, cppchar_t ch, size_t ch_sz);
+ 
+  private:
+   bool will_show_line_p (linenum_type row) const;
+   bool should_print_annotation_line_p (linenum_type row) const;
+ 
+   bool annotation_line_showed_range_p (linenum_type line, int start_column,
+ 				       int finish_column) const;
+   bool validate_fixit_hint_p (const fixit_hint *hint);
+ 
+   void calculate_line_spans ();
+   void calculate_linenum_width ();
+   void calculate_x_offset_display ();
+ 
+   bool
+   get_state_at_point (/* Inputs.  */
+ 		      linenum_type row, int column,
+ 		      int first_non_ws, int last_non_ws,
+ 		      enum column_unit col_unit,
+ 		      /* Outputs.  */
+ 		      point_state *out_state) const;
+ 
+   int
+   get_x_bound_for_row (linenum_type row, int caret_column,
+ 		       int last_non_ws) const;
+ 
+  private:
+   bool compatible_locations_p (location_t loc_a, location_t loc_b) const;
+ 
+   const diagnostics::source_printing_options &m_options;
+   const line_maps *m_line_table;
+   diagnostics::file_cache &m_file_cache;
+   const text_art::ascii_theme m_fallback_theme;
+   const text_art::theme &m_theme;
+   diagnostics::source_effect_info *m_effect_info;
+   char_display_policy m_char_policy;
+   location_t m_primary_loc;
+   exploc_with_display_col m_exploc;
+   auto_vec <layout_range> m_layout_ranges;
+   auto_vec <const fixit_hint *> m_fixit_hints;
+   auto_vec <line_span> m_line_spans;
+   int m_linenum_width;
+   int m_x_offset_display;
+   bool m_escape_on_output;
+ };
+ 
+ class line_label;
+ 
+ enum class margin_kind
+ {
+   normal,
+   insertion,
+   ruler
+ };
+ 
+ /* A bundle of state for printing a particular layout
+    to a particular TextOrHtml (either to_text or to_html).  */
+ template <typename TextOrHtml>
+ class layout_printer
+ {
+ public:
+   layout_printer (TextOrHtml &text_or_html,
+ 		  const layout &layout,
+ 		  bool is_diagnostic_path);
+ 
+   void print (const diagnostics::source_print_policy &source_policy);
+ 
+ private:
+   const diagnostics::source_printing_options &
+   get_options () const { return m_layout.m_options; }
+ 
+   const text_art::theme &
+   get_theme () const { return m_layout.m_theme; }
+ 
+   void show_ruler (int max_column);
+   void print_gap_in_line_numbering ();
+   void print_leading_fixits (linenum_type row);
+   void print_line (linenum_type row);
+   line_bounds print_source_line (linenum_type row, const char *line,
+ 				 int line_bytes);
+   void print_leftmost_column ();
+   void start_annotation_line (enum margin_kind);
+   void end_line ();
+   void print_annotation_line (linenum_type row, const line_bounds lbounds);
+   void print_any_labels (linenum_type row);
+   void begin_label (int state_idx, bool is_label_text);
+   void end_label (int state_idx, bool is_label_text);
+   void print_trailing_fixits (linenum_type row);
+ 
+   void
+   move_to_column (int *column, int dest_column, bool add_left_margin);
+ 
+   void print_any_right_to_left_edge_lines ();
+ 
+   void set_in_range (int range_idx);
+   void set_outside_range ();
+ 
+ private:
+   TextOrHtml &m_text_or_html;
+   const layout &m_layout;
+   bool m_is_diagnostic_path;
+ 
+   bool m_was_in_range_p;
+   int m_last_range_idx;
+ 
+   /* Fields for handling links between labels (e.g. for showing CFG edges
+      in execution paths).
+      Note that the logic for printing such links makes various simplifying
+      assumptions about the set of labels in the rich_location, and users
+      of this code will need to split up labels into separate rich_location
+      instances to respect these assumptions, or the output will look wrong.
+      See the diagnostic_path-printing code for more information.  */
+ 
+   /* An enum for describing the state of the leftmost column,
+      used for showing links between labels.
+      Consider e.g.
+      .x0000000001111111111222222222233333333334444444444.
+      .x1234567890123456789012345678901234567890123456789.
+      |      |                                    <- none
+      |      (9) following ‘false’ branch... ->-+ <- none
+      |                                         | <- none
+      |                                         | <- none
+      |+----------------------------------------+ <- rewinding to lhs
+      ||  result->i = i;                          <- at lhs
+      ||  ~~~~~~~~~~^~~                           <- at lhs
+      ||            |                             <- at lhs
+      |+----------->(10) ...to here               <- indenting to dest
+      ^^
+      ||
+      |leftmost column ("x" above).
+      "margin".  */
+   enum class link_lhs_state {
+     none,
+     rewinding_to_lhs,
+     at_lhs,
+     indenting_to_dest
+   } m_link_lhs_state;
+ 
+   /* The column of the current link on the RHS, if any, or
+      -1 if there is none.
+      Consider e.g.
+      .x0000000001111111111222222222233333333334444444444.
+      .x1234567890123456789012345678901234567890123456789.
+      |      |                                     <- -1
+      |      (10) following ‘false’ branch... ->-+ <- 42
+      |                                          | <- 42
+      |                                          | <- 42
+      |+-----------------------------------------+ <- 42
+      ||  result->i = i;                           <- -1
+      ||  ~~~~~~~~~~^~~                            <- -1
+      ||            |                              <- -1
+      |+----------->(11) ...to here                <- -1.  */
+   int m_link_rhs_column;
+ };
+ 
+ /* Implementation of "class colorizer".  */
+ 
+ /* The constructor for "colorizer".  Lookup and store color codes for the
+    different kinds of things we might need to print.  */
+ 
+ colorizer::colorizer (pretty_printer &pp,
+ 		      const rich_location &richloc,
+ 		      enum diagnostics::kind diagnostic_kind) :
+   m_pp (pp),
+   m_richloc (richloc),
+   m_diagnostic_kind (diagnostic_kind),
+   m_current_state (STATE_NORMAL_TEXT)
+ {
+   m_range1 = get_color_by_name ("range1");
+   m_range2 = get_color_by_name ("range2");
+   m_fixit_insert = get_color_by_name ("fixit-insert");
+   m_fixit_delete = get_color_by_name ("fixit-delete");
+   m_stop_color = colorize_stop (pp_show_color (&m_pp));
+ }
+ 
+ /* The destructor for "colorize".  If colorization is on, print a code to
+    turn it off.  */
+ 
+ colorizer::~colorizer ()
+ {
+   finish_state (m_current_state);
+ }
+ 
+ /* Update state, changing to the specific named color and printing its
+    color codes.  */
+ 
+ void
+ colorizer::set_named_color (const char *color)
+ {
+   if (m_current_state == STATE_NAMED_COLOR
+       && color == m_current_named_color)
+     return;
+   finish_state (m_current_state);
+   m_current_state = STATE_NAMED_COLOR;
+   pp_string (&m_pp, colorize_start (pp_show_color (&m_pp), color));
+   m_current_named_color = color;
+ }
+ 
+ /* Update state, printing color codes if necessary if there's a state
+    change.  */
+ 
+ void
+ colorizer::set_state (int new_state)
+ {
+   if (m_current_state != new_state)
+     {
+       finish_state (m_current_state);
+       m_current_state = new_state;
+       begin_state (new_state);
+     }
+ }
+ 
+ /* Turn on any colorization for STATE.  */
+ 
+ void
+ colorizer::begin_state (int state)
+ {
+   switch (state)
+     {
+     case STATE_NORMAL_TEXT:
+       break;
+ 
+     case STATE_FIXIT_INSERT:
+       pp_string (&m_pp, m_fixit_insert);
+       break;
+ 
+     case STATE_FIXIT_DELETE:
+       pp_string (&m_pp, m_fixit_delete);
+       break;
+ 
+     case STATE_NAMED_COLOR:
+       /* Should be handled by colorizer::set_named_color.  */
+       gcc_unreachable ();
+ 
+     case 0:
+       /* Make range 0 be the same color as the "kind" text
+ 	 (error vs warning vs note).  */
+       pp_string
+ 	(&m_pp,
+ 	 colorize_start (pp_show_color (&m_pp),
+ 			 get_color_for_kind (m_diagnostic_kind)));
+       break;
+ 
+     case 1:
+       pp_string (&m_pp, m_range1);
+       break;
+ 
+     case 2:
+       pp_string (&m_pp, m_range2);
+       break;
+ 
+     default:
+       /* For ranges beyond 2, alternate between color 1 and color 2.  */
+       {
+ 	gcc_assert (state > 2);
+ 	pp_string (&m_pp,
+ 		   state % 2 ? m_range1 : m_range2);
+       }
+       break;
+     }
+ }
+ 
+ /* Turn off any colorization for STATE.  */
+ 
+ void
+ colorizer::finish_state (int state)
+ {
+   if (state != STATE_NORMAL_TEXT)
+     pp_string (&m_pp, m_stop_color);
+ }
+ 
+ /* Get the color code for NAME (or the empty string if
+    colorization is disabled).  */
+ 
+ const char *
+ colorizer::get_color_by_name (const char *name)
+ {
+   return colorize_start (pp_show_color (&m_pp), name);
+ }
+ 
+ /* Implementation of class layout_range.  */
+ 
+ /* The constructor for class layout_range.
+    Initialize various layout_point fields from expanded_location
+    equivalents; we've already filtered on file.  */
+ 
+ layout_range::layout_range (const exploc_with_display_col &start_exploc,
+ 			    const exploc_with_display_col &finish_exploc,
+ 			    enum range_display_kind range_display_kind,
+ 			    const exploc_with_display_col &caret_exploc,
+ 			    unsigned original_idx,
+ 			    const range_label *label)
+ : m_start (start_exploc),
+   m_finish (finish_exploc),
+   m_range_display_kind (range_display_kind),
+   m_caret (caret_exploc),
+   m_original_idx (original_idx),
+   m_label (label)
+ {
+ }
+ 
+ /* Is (column, row) within the given range?
+    We've already filtered on the file.
+ 
+    Ranges are closed (both limits are within the range).
+ 
+    Example A: a single-line range:
+      start:  (col=22, line=2)
+      finish: (col=38, line=2)
+ 
+   |00000011111111112222222222333333333344444444444
+   |34567890123456789012345678901234567890123456789
+ --+-----------------------------------------------
+ 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+ 02|bbbbbbbbbbbbbbbbbbbSwwwwwwwwwwwwwwwFaaaaaaaaaaa
+ 03|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ 
+    Example B: a multiline range with
+      start:  (col=14, line=3)
+      finish: (col=08, line=5)
+ 
+   |00000011111111112222222222333333333344444444444
+   |34567890123456789012345678901234567890123456789
+ --+-----------------------------------------------
+ 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+ 02|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+ 03|bbbbbbbbbbbSwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
+ 04|wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
+ 05|wwwwwFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ 06|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ --+-----------------------------------------------
+ 
+    Legend:
+    - 'b' indicates a point *before* the range
+    - 'S' indicates the start of the range
+    - 'w' indicates a point within the range
+    - 'F' indicates the finish of the range (which is
+ 	 within it).
+    - 'a' indicates a subsequent point *after* the range.
+ 
+    COL_UNIT controls whether we check the byte column or
+    the display column; one or the other is more convenient
+    depending on the context.  */
+ 
+ bool
+ layout_range::contains_point (linenum_type row, int column,
+ 			      enum column_unit col_unit) const
+ {
+   gcc_assert (m_start.m_line <= m_finish.m_line);
+   /* ...but the equivalent isn't true for the columns;
+      consider example B in the comment above.  */
+ 
+   if (row < m_start.m_line)
+     /* Points before the first line of the range are
+        outside it (corresponding to line 01 in example A
+        and lines 01 and 02 in example B above).  */
+     return false;
+ 
+   if (row == m_start.m_line)
+     /* On same line as start of range (corresponding
+        to line 02 in example A and line 03 in example B).  */
+     {
+       if (column < m_start.m_columns[col_unit])
+ 	/* Points on the starting line of the range, but
+ 	   before the column in which it begins.  */
+ 	return false;
+ 
+       if (row < m_finish.m_line)
+ 	/* This is a multiline range; the point
+ 	   is within it (corresponds to line 03 in example B
+ 	   from column 14 onwards) */
+ 	return true;
+       else
+ 	{
+ 	  /* This is a single-line range.  */
+ 	  gcc_assert (row == m_finish.m_line);
+ 	  return column <= m_finish.m_columns[col_unit];
+ 	}
+     }
+ 
+   /* The point is in a line beyond that containing the
+      start of the range: lines 03 onwards in example A,
+      and lines 04 onwards in example B.  */
+   gcc_assert (row > m_start.m_line);
+ 
+   if (row > m_finish.m_line)
+     /* The point is beyond the final line of the range
+        (lines 03 onwards in example A, and lines 06 onwards
+        in example B).  */
+     return false;
+ 
+   if (row < m_finish.m_line)
+     {
+       /* The point is in a line that's fully within a multiline
+ 	 range (e.g. line 04 in example B).  */
+       gcc_assert (m_start.m_line < m_finish.m_line);
+       return true;
+     }
+ 
+   gcc_assert (row ==  m_finish.m_line);
+ 
+   return column <= m_finish.m_columns[col_unit];
+ }
+ 
+ /* Does this layout_range contain any part of line ROW?  */
+ 
+ bool
+ layout_range::intersects_line_p (linenum_type row) const
+ {
+   gcc_assert (m_start.m_line <= m_finish.m_line);
+   if (row < m_start.m_line)
+     return false;
+   if (row > m_finish.m_line)
+     return false;
+   return true;
+ }
+ 
+ /* Return true if this layout_range should have an in-edge.  */
+ 
+ bool
+ layout_range::has_in_edge () const
+ {
+   if (!m_label)
+     return false;
+   const diagnostics::label_effects *effects
+     = m_label->get_effects (m_original_idx);
+   if (!effects)
+     return false;
+ 
+   return effects->has_in_edge (m_original_idx);
+ }
+ 
+ /* Return true if this layout_range should have an out-edge.  */
+ 
+ bool
+ layout_range::has_out_edge () const
+ {
+   if (!m_label)
+     return false;
+   const diagnostics::label_effects *effects
+     = m_label->get_effects (m_original_idx);
+   if (!effects)
+     return false;
+ 
+   return effects->has_out_edge (m_original_idx);
+ }
+ 
+ #if CHECKING_P
+ 
+ /* Default for when we don't care what the tab expansion is set to.  */
+ static const int def_tabstop = 8;
+ 
+ static cpp_char_column_policy def_policy ()
+ {
+   return cpp_char_column_policy (def_tabstop, cpp_wcwidth);
+ }
+ 
+ /* Create some expanded locations for testing layout_range.  The filename
+    member of the explocs is set to the empty string.  This member will only be
+    inspected by the calls to location_compute_display_column() made from the
+    layout_point constructors.  That function will check for an empty filename
+    argument and not attempt to open it, rather treating the non-existent data
+    as if the display width were the same as the byte count.  Tests exercising a
+    real difference between byte count and display width are performed later,
+    e.g. in test_diagnostic_show_locus_one_liner_utf8().  */
+ 
+ static layout_range
+ make_range (diagnostics::file_cache &fc,
+ 	    int start_line, int start_col, int end_line, int end_col)
+ {
+   const expanded_location start_exploc
+     = {"", start_line, start_col, nullptr, false};
+   const expanded_location finish_exploc
+     = {"", end_line, end_col, nullptr, false};
+   return layout_range (exploc_with_display_col (fc,
+ 						start_exploc, def_policy (),
+ 						LOCATION_ASPECT_START),
+ 		       exploc_with_display_col (fc,
+ 						finish_exploc, def_policy (),
+ 						LOCATION_ASPECT_FINISH),
+ 		       SHOW_RANGE_WITHOUT_CARET,
+ 		       exploc_with_display_col (fc,
+ 						start_exploc, def_policy (),
+ 						LOCATION_ASPECT_CARET),
+ 		       0, nullptr);
+ }
+ 
+ /* Selftests for layout_range::contains_point and
+    layout_range::intersects_line_p.  */
+ 
+ /* Selftest for layout_range, where the layout_range
+    is a range with start==end i.e. a single point.  */
+ 
+ static void
+ test_layout_range_for_single_point ()
+ {
+   diagnostics::file_cache fc;
+   layout_range point = make_range (fc, 7, 10, 7, 10);
+ 
+   /* Tests for layout_range::contains_point.  */
+ 
+   for (int i = 0; i != CU_NUM_UNITS; ++i)
+     {
+       const enum column_unit col_unit = (enum column_unit) i;
+ 
+       /* Before the line.  */
+       ASSERT_FALSE (point.contains_point (6, 1, col_unit));
+ 
+       /* On the line, but before start.  */
+       ASSERT_FALSE (point.contains_point (7, 9, col_unit));
+ 
+       /* At the point.  */
+       ASSERT_TRUE (point.contains_point (7, 10, col_unit));
+ 
+       /* On the line, after the point.  */
+       ASSERT_FALSE (point.contains_point (7, 11, col_unit));
+ 
+       /* After the line.  */
+       ASSERT_FALSE (point.contains_point (8, 1, col_unit));
+     }
+ 
+   /* Tests for layout_range::intersects_line_p.  */
+   ASSERT_FALSE (point.intersects_line_p (6));
+   ASSERT_TRUE (point.intersects_line_p (7));
+   ASSERT_FALSE (point.intersects_line_p (8));
+ }
+ 
+ /* Selftest for layout_range, where the layout_range
+    is the single-line range shown as "Example A" above.  */
+ 
+ static void
+ test_layout_range_for_single_line ()
+ {
+   diagnostics::file_cache fc;
+   layout_range example_a = make_range (fc, 2, 22, 2, 38);
+ 
+   /* Tests for layout_range::contains_point.  */
+ 
+   for (int i = 0; i != CU_NUM_UNITS; ++i)
+     {
+       const enum column_unit col_unit = (enum column_unit) i;
+ 
+       /* Before the line.  */
+       ASSERT_FALSE (example_a.contains_point (1, 1, col_unit));
+ 
+       /* On the line, but before start.  */
+       ASSERT_FALSE (example_a.contains_point (2, 21, col_unit));
+ 
+       /* On the line, at the start.  */
+       ASSERT_TRUE (example_a.contains_point (2, 22, col_unit));
+ 
+       /* On the line, within the range.  */
+       ASSERT_TRUE (example_a.contains_point (2, 23, col_unit));
+ 
+       /* On the line, at the end.  */
+       ASSERT_TRUE (example_a.contains_point (2, 38, col_unit));
+ 
+       /* On the line, after the end.  */
+       ASSERT_FALSE (example_a.contains_point (2, 39, col_unit));
+ 
+       /* After the line.  */
+       ASSERT_FALSE (example_a.contains_point (2, 39, col_unit));
+     }
+ 
+   /* Tests for layout_range::intersects_line_p.  */
+   ASSERT_FALSE (example_a.intersects_line_p (1));
+   ASSERT_TRUE (example_a.intersects_line_p (2));
+   ASSERT_FALSE (example_a.intersects_line_p (3));
+ }
+ 
+ /* Selftest for layout_range, where the layout_range
+    is the multi-line range shown as "Example B" above.  */
+ 
+ static void
+ test_layout_range_for_multiple_lines ()
+ {
+   diagnostics::file_cache fc;
+   layout_range example_b = make_range (fc, 3, 14, 5, 8);
+ 
+   /* Tests for layout_range::contains_point.  */
+ 
+   for (int i = 0; i != CU_NUM_UNITS; ++i)
+     {
+       const enum column_unit col_unit = (enum column_unit) i;
+ 
+       /* Before first line.  */
+       ASSERT_FALSE (example_b.contains_point (1, 1, col_unit));
+ 
+       /* On the first line, but before start.  */
+       ASSERT_FALSE (example_b.contains_point (3, 13, col_unit));
+ 
+       /* At the start.  */
+       ASSERT_TRUE (example_b.contains_point (3, 14, col_unit));
+ 
+       /* On the first line, within the range.  */
+       ASSERT_TRUE (example_b.contains_point (3, 15, col_unit));
+ 
+       /* On an interior line.
+ 	 The column number should not matter; try various boundary
+ 	 values.  */
+       ASSERT_TRUE (example_b.contains_point (4, 1, col_unit));
+       ASSERT_TRUE (example_b.contains_point (4, 7, col_unit));
+       ASSERT_TRUE (example_b.contains_point (4, 8, col_unit));
+       ASSERT_TRUE (example_b.contains_point (4, 9, col_unit));
+       ASSERT_TRUE (example_b.contains_point (4, 13, col_unit));
+       ASSERT_TRUE (example_b.contains_point (4, 14, col_unit));
+       ASSERT_TRUE (example_b.contains_point (4, 15, col_unit));
+ 
+       /* On the final line, before the end.  */
+       ASSERT_TRUE (example_b.contains_point (5, 7, col_unit));
+ 
+       /* On the final line, at the end.  */
+       ASSERT_TRUE (example_b.contains_point (5, 8, col_unit));
+ 
+       /* On the final line, after the end.  */
+       ASSERT_FALSE (example_b.contains_point (5, 9, col_unit));
+ 
+       /* After the line.  */
+       ASSERT_FALSE (example_b.contains_point (6, 1, col_unit));
+     }
+ 
+   /* Tests for layout_range::intersects_line_p.  */
+   ASSERT_FALSE (example_b.intersects_line_p (2));
+   ASSERT_TRUE (example_b.intersects_line_p (3));
+   ASSERT_TRUE (example_b.intersects_line_p (4));
+   ASSERT_TRUE (example_b.intersects_line_p (5));
+   ASSERT_FALSE (example_b.intersects_line_p (6));
+ }
+ 
+ #endif /* #if CHECKING_P */
+ 
+ /* Given a source line LINE of length LINE_BYTES bytes, determine the length
+    (still in bytes, not display cols) without any trailing whitespace.  */
+ 
+ static int
+ get_line_bytes_without_trailing_whitespace (const char *line, int line_bytes)
+ {
+   int result = line_bytes;
+   while (result > 0)
+     {
+       char ch = line[result - 1];
+       if (ch == ' ' || ch == '\t' || ch == '\r')
+ 	result--;
+       else
+ 	break;
+     }
+   gcc_assert (result >= 0);
+   gcc_assert (result <= line_bytes);
+   gcc_assert (result == 0 ||
+ 	      (line[result - 1] != ' '
+ 	       && line[result -1] != '\t'
+ 	       && line[result -1] != '\r'));
+   return result;
+ }
+ 
+ #if CHECKING_P
+ 
+ /* A helper function for testing get_line_bytes_without_trailing_whitespace.  */
+ 
+ static void
+ assert_eq (const char *line, int expected_bytes)
+ {
+   int actual_value
+     = get_line_bytes_without_trailing_whitespace (line, strlen (line));
+   ASSERT_EQ (actual_value, expected_bytes);
+ }
+ 
+ /* Verify that get_line_bytes_without_trailing_whitespace is sane for
+    various inputs.  It is not required to handle newlines.  */
+ 
+ static void
+ test_get_line_bytes_without_trailing_whitespace ()
+ {
+   assert_eq ("", 0);
+   assert_eq (" ", 0);
+   assert_eq ("\t", 0);
+   assert_eq ("\r", 0);
+   assert_eq ("hello world", 11);
+   assert_eq ("hello world     ", 11);
+   assert_eq ("hello world     \t\t  ", 11);
+   assert_eq ("hello world\r", 11);
+ }
+ 
+ #endif /* #if CHECKING_P */
+ 
+ /* Helper function for layout's ctor, for sanitizing locations relative
+    to the primary location within a diagnostic.
+ 
+    Compare LOC_A and LOC_B to see if it makes sense to print underlines
+    connecting their expanded locations.  Doing so is only guaranteed to
+    make sense if the locations share the same macro expansion "history"
+    i.e. they can be traced through the same macro expansions, eventually
+    reaching an ordinary map.
+ 
+    This may be too strong a condition, but it effectively sanitizes
+    PR c++/70105, which has an example of printing an expression where the
+    final location of the expression is in a different macro, which
+    erroneously was leading to hundreds of lines of irrelevant source
+    being printed.  */
+ 
+ bool
+ layout::compatible_locations_p (location_t loc_a, location_t loc_b) const
+ {
+   if (IS_ADHOC_LOC (loc_a))
+     loc_a = get_location_from_adhoc_loc (m_line_table, loc_a);
+   if (IS_ADHOC_LOC (loc_b))
+     loc_b = get_location_from_adhoc_loc (m_line_table, loc_b);
+ 
+   /* If either location is one of the special locations outside of a
+      linemap, they are only compatible if they are equal.  */
+   if (loc_a < RESERVED_LOCATION_COUNT
+       || loc_b < RESERVED_LOCATION_COUNT)
+     return loc_a == loc_b;
+ 
+   const line_map *map_a = linemap_lookup (m_line_table, loc_a);
+   linemap_assert (map_a);
+ 
+   const line_map *map_b = linemap_lookup (m_line_table, loc_b);
+   linemap_assert (map_b);
+ 
+   /* Are they within the same map?  */
+   if (map_a == map_b)
+     {
+       /* Are both within the same macro expansion?  */
+       if (linemap_macro_expansion_map_p (map_a))
+ 	{
+ 	  /* If so, then they're only compatible if either both are
+ 	     from the macro definition, or both from the macro arguments.  */
+ 	  bool loc_a_from_defn
+ 	    = linemap_location_from_macro_definition_p (m_line_table, loc_a);
+ 	  bool loc_b_from_defn
+ 	    = linemap_location_from_macro_definition_p (m_line_table, loc_b);
+ 	  if (loc_a_from_defn != loc_b_from_defn)
+ 	    return false;
+ 
+ 	  /* Expand each location towards the spelling location, and
+ 	     recurse.  */
+ 	  const line_map_macro *macro_map = linemap_check_macro (map_a);
+ 	  location_t loc_a_toward_spelling
+ 	    = linemap_macro_map_loc_unwind_toward_spelling (m_line_table,
+ 							    macro_map,
+ 							    loc_a);
+ 	  location_t loc_b_toward_spelling
+ 	    = linemap_macro_map_loc_unwind_toward_spelling (m_line_table,
+ 							    macro_map,
+ 							    loc_b);
+ 	  return compatible_locations_p (loc_a_toward_spelling,
+ 					 loc_b_toward_spelling);
+ 	}
+ 
+       /* Otherwise they are within the same ordinary map.  */
+       return true;
+     }
+   else
+     {
+       /* Within different maps.  */
+ 
+       /* If either is within a macro expansion, they are incompatible.  */
+       if (linemap_macro_expansion_map_p (map_a)
+ 	  || linemap_macro_expansion_map_p (map_b))
+ 	return false;
+ 
+       /* Within two different ordinary maps; they are compatible iff they
+ 	 are in the same file.  */
+       const line_map_ordinary *ord_map_a = linemap_check_ordinary (map_a);
+       const line_map_ordinary *ord_map_b = linemap_check_ordinary (map_b);
+       return ord_map_a->to_file == ord_map_b->to_file;
+     }
+ }
+ 
+ /* Comparator for sorting fix-it hints.  */
+ 
+ static int
+ fixit_cmp (const void *p_a, const void *p_b)
+ {
+   const fixit_hint * hint_a = *static_cast<const fixit_hint * const *> (p_a);
+   const fixit_hint * hint_b = *static_cast<const fixit_hint * const *> (p_b);
+   return hint_a->get_start_loc () - hint_b->get_start_loc ();
+ }
+ 
+ /* Callbacks for use when not escaping the source.  */
+ 
+ /* The default callback for char_column_policy::m_width_cb is cpp_wcwidth.  */
+ 
+ /* Callback for char_display_policy::m_print_cb for printing source chars
+    when not escaping the source.  */
+ 
+ template <class TextOrHtml>
+ static void
+ default_print_decoded_ch (TextOrHtml &text_or_html,
+ 			  const cpp_decoded_char &decoded_ch)
+ {
+   for (const char *ptr = decoded_ch.m_start_byte;
+        ptr != decoded_ch.m_next_byte; ptr++)
+     {
+       if (*ptr == '\0' || *ptr == '\r')
+ 	{
+ 	  text_or_html.add_space ();
+ 	  continue;
+ 	}
+ 
+       text_or_html.add_utf8_byte (*ptr);
+     }
+ }
+ 
+ /* Callbacks for use with DIAGNOSTICS_ESCAPE_FORMAT_BYTES.  */
+ 
+ static const int width_per_escaped_byte = 4;
+ 
+ /* Callback for char_column_policy::m_width_cb for determining the
+    display width when escaping with DIAGNOSTICS_ESCAPE_FORMAT_BYTES.  */
+ 
+ static int
+ escape_as_bytes_width (cppchar_t ch)
+ {
+   if (ch < 0x80 && ISPRINT (ch))
+     return cpp_wcwidth (ch);
+   else
+     {
+       if (ch <=   0x7F) return 1 * width_per_escaped_byte;
+       if (ch <=  0x7FF) return 2 * width_per_escaped_byte;
+       if (ch <= 0xFFFF) return 3 * width_per_escaped_byte;
+       return 4 * width_per_escaped_byte;
+     }
+ }
+ 
+ /* Callback for char_display_policy::m_print_cb for printing source chars
+    when escaping with DIAGNOSTICS_ESCAPE_FORMAT_BYTES.  */
+ 
+ template <typename TextOrHtml>
+ static void
+ escape_as_bytes_print (TextOrHtml &text_or_html,
+ 		       const cpp_decoded_char &decoded_ch)
+ {
+   if (!decoded_ch.m_valid_ch)
+     {
+       for (const char *iter = decoded_ch.m_start_byte;
+ 	   iter != decoded_ch.m_next_byte; ++iter)
+ 	{
+ 	  char buf[16];
+ 	  sprintf (buf, "<%02x>", (unsigned char)*iter);
+ 	  text_or_html.add_text (buf);
+ 	}
+       return;
+     }
+ 
+   cppchar_t ch = decoded_ch.m_ch;
+   if (ch < 0x80 && ISPRINT (ch))
+     text_or_html.add_character (ch);
+   else
+     {
+       for (const char *iter = decoded_ch.m_start_byte;
+ 	   iter < decoded_ch.m_next_byte; ++iter)
+ 	{
+ 	  char buf[16];
+ 	  sprintf (buf, "<%02x>", (unsigned char)*iter);
+ 	  text_or_html.add_text (buf);
+ 	}
+     }
+ }
+ 
+ /* Callbacks for use with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE.  */
+ 
+ /* Callback for char_column_policy::m_width_cb for determining the
+    display width when escaping with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE.  */
+ 
+ static int
+ escape_as_unicode_width (cppchar_t ch)
+ {
+   if (ch < 0x80 && ISPRINT (ch))
+     return cpp_wcwidth (ch);
+   else
+     {
+       // Width of "<U+%04x>"
+       if (ch > 0xfffff)
+ 	return 10;
+       else if (ch > 0xffff)
+ 	return 9;
+       else
+ 	return 8;
+     }
+ }
+ 
+ /* Callback for char_display_policy::m_print_cb for printing source chars
+    when escaping with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE.  */
+ 
+ template <typename TextOrHtml>
+ static void
+ escape_as_unicode_print (TextOrHtml &text_or_html,
+ 			 const cpp_decoded_char &decoded_ch)
+ {
+   if (!decoded_ch.m_valid_ch)
+     {
+       escape_as_bytes_print<TextOrHtml> (text_or_html, decoded_ch);
+       return;
+     }
+ 
+   cppchar_t ch = decoded_ch.m_ch;
+   if (ch < 0x80 && ISPRINT (ch))
+     text_or_html.add_character (ch);
+   else
+     {
+       char buf[16];
+       sprintf (buf, "<U+%04X>", ch);
+       text_or_html.add_text (buf);
+     }
+ }
+ 
+ /* Populate a char_display_policy based on SOURCE_POLICY and RICHLOC.  */
+ 
+ static char_display_policy
+ make_char_policy (const diagnostics::source_print_policy &source_policy,
+ 		  const rich_location &richloc)
+ {
+   /* The default is to not escape non-ASCII bytes.  */
+   char_display_policy result
+     (source_policy.get_column_policy ().get_tabstop (),
+      cpp_wcwidth,
+      default_print_decoded_ch<diagnostics::to_text>,
+      default_print_decoded_ch<diagnostics::to_html>);
+ 
+   /* If the diagnostic suggests escaping non-ASCII bytes, then
+      use policy from user-supplied options.  */
+   if (richloc.escape_on_output_p ())
+     {
+       result.m_undecoded_byte_width = width_per_escaped_byte;
+       switch (source_policy.get_escape_format ())
+ 	{
+ 	default:
+ 	  gcc_unreachable ();
+ 	case DIAGNOSTICS_ESCAPE_FORMAT_UNICODE:
+ 	  result.m_width_cb = escape_as_unicode_width;
+ 	  result.m_print_text_cb
+ 	    = escape_as_unicode_print<diagnostics::to_text>;
+ 	  result.m_print_html_cb
+ 	    = escape_as_unicode_print<diagnostics::to_html>;
+ 	  break;
+ 	case DIAGNOSTICS_ESCAPE_FORMAT_BYTES:
+ 	  result.m_width_cb = escape_as_bytes_width;
+ 	  result.m_print_text_cb = escape_as_bytes_print<diagnostics::to_text>;
+ 	  result.m_print_html_cb = escape_as_bytes_print<diagnostics::to_html>;
+ 	  break;
+ 	}
+     }
+ 
+   return result;
+ }
+ 
+ /* Implementation of class layout.  */
+ 
+ /* Constructor for class layout.
+ 
+    Filter the ranges from the rich_location to those that we can
+    sanely print, populating m_layout_ranges and m_fixit_hints.
+    Determine the range of lines that we will print, splitting them
+    up into an ordered list of disjoint spans of contiguous line numbers.
+    Determine m_x_offset_display, to ensure that the primary caret
+    will fit within the max_width provided by the diagnostics::context.  */
+ 
+ layout::layout (const diagnostics::source_print_policy &source_policy,
+ 		const rich_location &richloc,
+ 		diagnostics::source_effect_info *effect_info)
+ : m_options (source_policy.get_options ()),
+   m_line_table (richloc.get_line_table ()),
+   m_file_cache (source_policy.get_file_cache ()),
+   /* Ensure we have a non-null m_theme. */
+   m_theme (source_policy.get_diagram_theme ()
+ 	   ? *source_policy.get_diagram_theme ()
+ 	   : *static_cast <const text_art::theme *> (&m_fallback_theme)),
+   m_effect_info (effect_info),
+   m_char_policy (make_char_policy (source_policy, richloc)),
+   m_primary_loc (richloc.get_range (0)->m_loc),
+   m_exploc (m_file_cache,
+ 	    richloc.get_expanded_location (0), m_char_policy,
+ 	    LOCATION_ASPECT_CARET),
+   m_layout_ranges (richloc.get_num_locations ()),
+   m_fixit_hints (richloc.get_num_fixit_hints ()),
+   m_line_spans (1 + richloc.get_num_locations ()),
+   m_linenum_width (0),
+   m_x_offset_display (0),
+   m_escape_on_output (richloc.escape_on_output_p ())
+ {
+   for (unsigned int idx = 0; idx < richloc.get_num_locations (); idx++)
+     {
+       /* This diagnostic printer can only cope with "sufficiently sane" ranges.
+ 	 Ignore any ranges that are awkward to handle.  */
+       const location_range *loc_range = richloc.get_range (idx);
+       maybe_add_location_range (loc_range, idx, false);
+     }
+ 
+   /* Populate m_fixit_hints, filtering to only those that are in the
+      same file.  */
+   for (unsigned int i = 0; i < richloc.get_num_fixit_hints (); i++)
+     {
+       const fixit_hint *hint = richloc.get_fixit_hint (i);
+       if (validate_fixit_hint_p (hint))
+ 	m_fixit_hints.safe_push (hint);
+     }
+ 
+   /* Sort m_fixit_hints.  */
+   m_fixit_hints.qsort (fixit_cmp);
+ 
+   /* Populate the indicated members.  */
+   calculate_line_spans ();
+   calculate_linenum_width ();
+   calculate_x_offset_display ();
+ }
+ 
+ 
+ /* Attempt to add LOC_RANGE to m_layout_ranges, filtering them to
+    those that we can sanely print.
+ 
+    ORIGINAL_IDX is the index of LOC_RANGE within its rich_location,
+    (for use as extrinsic state by label ranges).
+ 
+    If RESTRICT_TO_CURRENT_LINE_SPANS is true, then LOC_RANGE is also
+    filtered against this layout instance's current line spans: it
+    will only be added if the location is fully within the lines
+    already specified by other locations.
+ 
+    Return true iff LOC_RANGE was added.  */
+ 
+ bool
+ layout::maybe_add_location_range (const location_range *loc_range,
+ 				  unsigned original_idx,
+ 				  bool restrict_to_current_line_spans)
+ {
+   gcc_assert (loc_range);
+ 
+   /* Split the "range" into caret and range information.  */
+   source_range src_range = get_range_from_loc (m_line_table, loc_range->m_loc);
+ 
+   /* Expand the various locations.  */
+   expanded_location start
+     = linemap_client_expand_location_to_spelling_point
+     (m_line_table, src_range.m_start, LOCATION_ASPECT_START);
+   expanded_location finish
+     = linemap_client_expand_location_to_spelling_point
+     (m_line_table, src_range.m_finish, LOCATION_ASPECT_FINISH);
+   expanded_location caret
+     = linemap_client_expand_location_to_spelling_point
+     (m_line_table, loc_range->m_loc, LOCATION_ASPECT_CARET);
+ 
+   /* If any part of the range isn't in the same file as the primary
+      location of this diagnostic, ignore the range.  */
+   if (start.file != m_exploc.file)
+     return false;
+   if (finish.file != m_exploc.file)
+     return false;
+   if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
+     if (caret.file != m_exploc.file)
+       return false;
+ 
+   /* Sanitize the caret location for non-primary ranges.  */
+   if (m_layout_ranges.length () > 0)
+     if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
+       if (!compatible_locations_p (loc_range->m_loc, m_primary_loc))
+ 	/* Discard any non-primary ranges that can't be printed
+ 	   sanely relative to the primary location.  */
+ 	return false;
+ 
+   /* If there's no column information, then don't try to print
+      annotation lines for this range.  */
+   enum range_display_kind range_display_kind
+     = loc_range->m_range_display_kind;
+   if (start.column == 0
+       || finish.column == 0
+       || caret.column == 0)
+     range_display_kind = SHOW_LINES_WITHOUT_RANGE;
+ 
+   /* Everything is now known to be in the correct source file,
+      but it may require further sanitization.  */
+   layout_range ri (exploc_with_display_col (m_file_cache,
+ 					    start, m_char_policy,
+ 					    LOCATION_ASPECT_START),
+ 		   exploc_with_display_col (m_file_cache,
+ 					    finish, m_char_policy,
+ 					    LOCATION_ASPECT_FINISH),
+ 		   range_display_kind,
+ 		   exploc_with_display_col (m_file_cache,
+ 					    caret, m_char_policy,
+ 					    LOCATION_ASPECT_CARET),
+ 		   original_idx, loc_range->m_label);
+ 
+   /* If we have a range that finishes before it starts (perhaps
+      from something built via macro expansion), printing the
+      range is likely to be nonsensical.  Also, attempting to do so
+      breaks assumptions within the printing code  (PR c/68473).
+      Similarly, don't attempt to print ranges if one or both ends
+      of the range aren't sane to print relative to the
+      primary location (PR c++/70105).  */
+   if (start.line > finish.line
+       || !compatible_locations_p (src_range.m_start, m_primary_loc)
+       || !compatible_locations_p (src_range.m_finish, m_primary_loc))
+     {
+       /* Is this the primary location?  */
+       if (m_layout_ranges.length () == 0)
+ 	{
+ 	  /* We want to print the caret for the primary location, but
+ 	     we must sanitize away m_start and m_finish.  */
+ 	  ri.m_start = ri.m_caret;
+ 	  ri.m_finish = ri.m_caret;
+ 	}
+       else
+ 	/* This is a non-primary range; ignore it.  */
+ 	return false;
+     }
+ 
+   /* Potentially filter to just the lines already specified by other
+      locations.  This is for use by gcc_rich_location::add_location_if_nearby.
+      The layout ctor doesn't use it, and can't because m_line_spans
+      hasn't been set up at that point.  */
+   if (restrict_to_current_line_spans)
+     {
+       if (!will_show_line_p (start.line))
+ 	return false;
+       if (!will_show_line_p (finish.line))
+ 	return false;
+       if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
+ 	if (!will_show_line_p (caret.line))
+ 	  return false;
+     }
+ 
+   /* Passed all the tests; add the range to m_layout_ranges so that
+      it will be printed.  */
+   m_layout_ranges.safe_push (ri);
+   return true;
+ }
+ 
+ /* Return true iff ROW is within one of the line spans for this layout.  */
+ 
+ bool
+ layout::will_show_line_p (linenum_type row) const
+ {
+   for (int line_span_idx = 0; line_span_idx < get_num_line_spans ();
+        line_span_idx++)
+     {
+       const line_span *line_span = get_line_span (line_span_idx);
+       if (line_span->contains_line_p (row))
+ 	return true;
+     }
+   return false;
+ }
+ 
+ /* Print a line showing a gap in the line numbers, for showing the boundary
+    between two line spans.  */
+ 
+ template<>
+ void
+ layout_printer<diagnostics::to_text>::print_gap_in_line_numbering ()
+ {
+   gcc_assert (m_layout.m_options.show_line_numbers_p);
+ 
+   m_text_or_html.emit_text_prefix ();
+ 
+   for (int i = 0; i < m_layout.get_linenum_width () + 1; i++)
+     m_text_or_html.add_character ('.');
+ 
+   m_text_or_html.add_newline ();
+ }
+ 
+ template<>
+ void
+ layout_printer<diagnostics::to_html>::print_gap_in_line_numbering ()
+ {
+   gcc_assert (m_layout.m_options.show_line_numbers_p);
+ 
+   m_text_or_html.add_raw_html
+     ("<tbody class=\"line-span-jump\">\n"
+      "<tr class=\"line-span-jump-row\">"
+      "<td class=\"linenum-gap\">[...]</td>"
+      "<td class=\"source-gap\"/></tr>\n"
+      "</tbody>\n");
+ }
+ 
+ /* Return true iff we should print a heading when starting the
+    line span with the given index.  */
+ 
+ bool
+ layout::print_heading_for_line_span_index_p (int line_span_idx) const
+ {
+   /* We print a heading for every change of line span, hence for every
+      line span after the initial one.  */
+   if (line_span_idx > 0)
+     return true;
+ 
+   /* We also do it for the initial span if the primary location of the
+      diagnostic is in a different span.  */
+   if (m_exploc.line > (int)get_line_span (0)->m_last_line)
+     return true;
+ 
+   return false;
+ }
+ 
+ /* Get an expanded_location for the first location of interest within
+    the given line_span.
+    Used when printing a heading to indicate a new line span.  */
+ 
+ expanded_location
+ layout::get_expanded_location (const line_span *line_span) const
+ {
+   /* Whenever possible, use the caret location.  */
+   if (line_span->contains_line_p (m_exploc.line))
+     return m_exploc;
+ 
+   /* Otherwise, use the start of the first range that's present
+      within the line_span.  */
+   for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
+     {
+       const layout_range *lr = &m_layout_ranges[i];
+       if (line_span->contains_line_p (lr->m_start.m_line))
+ 	{
+ 	  expanded_location exploc = m_exploc;
+ 	  exploc.line = lr->m_start.m_line;
+ 	  exploc.column = lr->m_start.m_columns[CU_BYTES];
+ 	  return exploc;
+ 	}
+     }
+ 
+   /* Otherwise, use the location of the first fixit-hint present within
+      the line_span.  */
+   for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
+     {
+       const fixit_hint *hint = m_fixit_hints[i];
+       location_t loc = hint->get_start_loc ();
+       expanded_location exploc = expand_location (loc);
+       if (line_span->contains_line_p (exploc.line))
+ 	return exploc;
+     }
+ 
+   /* It should not be possible to have a line span that didn't
+      contain any of the layout_range or fixit_hint instances.  */
+   gcc_unreachable ();
+   return m_exploc;
+ }
+ 
+ /* Determine if HINT is meaningful to print within this layout.  */
+ 
+ bool
+ layout::validate_fixit_hint_p (const fixit_hint *hint)
+ {
+   if (LOCATION_FILE (hint->get_start_loc ()) != m_exploc.file)
+     return false;
+   if (LOCATION_FILE (hint->get_next_loc ()) != m_exploc.file)
+     return false;
+ 
+   return true;
+ }
+ 
+ /* Determine the range of lines affected by HINT.
+    This assumes that HINT has already been filtered by
+    validate_fixit_hint_p, and so affects the correct source file.  */
+ 
+ static line_span
+ get_line_span_for_fixit_hint (const fixit_hint *hint)
+ {
+   gcc_assert (hint);
+ 
+   int start_line = LOCATION_LINE (hint->get_start_loc ());
+ 
+   /* For line-insertion fix-it hints, add the previous line to the
+      span, to give the user more context on the proposed change.  */
+   if (hint->ends_with_newline_p ())
+     if (start_line > 1)
+       start_line--;
+ 
+   return line_span (start_line,
+ 		    LOCATION_LINE (hint->get_next_loc ()));
+ }
+ 
+ /* We want to print the pertinent source code at a diagnostic.  The
+    rich_location can contain multiple locations.  This will have been
+    filtered into m_exploc (the caret for the primary location) and
+    m_layout_ranges, for those ranges within the same source file.
+ 
+    We will print a subset of the lines within the source file in question,
+    as a collection of "spans" of lines.
+ 
+    This function populates m_line_spans with an ordered, disjoint list of
+    the line spans of interest.
+ 
+    Printing a gap between line spans takes one line, so, when printing
+    line numbers, we allow a gap of up to one line between spans when
+    merging, since it makes more sense to print the source line rather than a
+    "gap-in-line-numbering" line.  When not printing line numbers, it's
+    better to be more explicit about what's going on, so keeping them as
+    separate spans is preferred.
+ 
+    For example, if the primary range is on lines 8-10, with secondary ranges
+    covering lines 5-6 and lines 13-15:
+ 
+      004
+      005                   |RANGE 1
+      006                   |RANGE 1
+      007
+      008  |PRIMARY RANGE
+      009  |PRIMARY CARET
+      010  |PRIMARY RANGE
+      011
+      012
+      013                                |RANGE 2
+      014                                |RANGE 2
+      015                                |RANGE 2
+      016
+ 
+    With line numbering on, we want two spans: lines 5-10 and lines 13-15.
+ 
+    With line numbering off (with span headers), we want three spans: lines 5-6,
+    lines 8-10, and lines 13-15.  */
+ 
+ void
+ layout::calculate_line_spans ()
+ {
+   /* This should only be called once, by the ctor.  */
+   gcc_assert (m_line_spans.length () == 0);
+ 
+   /* Populate tmp_spans with individual spans, for each of
+      m_exploc, and for m_layout_ranges.  */
+   auto_vec<line_span> tmp_spans (1 + m_layout_ranges.length ());
+   tmp_spans.safe_push (line_span (m_exploc.line, m_exploc.line));
+   for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
+     {
+       const layout_range *lr = &m_layout_ranges[i];
+       gcc_assert (lr->m_start.m_line <= lr->m_finish.m_line);
+       tmp_spans.safe_push (line_span (lr->m_start.m_line,
+ 				      lr->m_finish.m_line));
+     }
+ 
+   /* Also add spans for any fix-it hints, in case they cover other lines.  */
+   for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
+     {
+       const fixit_hint *hint = m_fixit_hints[i];
+       gcc_assert (hint);
+       tmp_spans.safe_push (get_line_span_for_fixit_hint (hint));
+     }
+ 
+   /* Sort them.  */
+   tmp_spans.qsort(line_span::comparator);
+ 
+   /* Now iterate through tmp_spans, copying into m_line_spans, and
+      combining where possible.  */
+   gcc_assert (tmp_spans.length () > 0);
+   m_line_spans.safe_push (tmp_spans[0]);
+   for (unsigned int i = 1; i < tmp_spans.length (); i++)
+     {
+       line_span *current = &m_line_spans[m_line_spans.length () - 1];
+       const line_span *next = &tmp_spans[i];
+       gcc_assert (next->m_first_line >= current->m_first_line);
+       const int merger_distance = m_options.show_line_numbers_p ? 1 : 0;
+       if ((linenum_arith_t)next->m_first_line
+ 	  <= (linenum_arith_t)current->m_last_line + 1 + merger_distance)
+ 	{
+ 	  /* We can merge them. */
+ 	  if (next->m_last_line > current->m_last_line)
+ 	    current->m_last_line = next->m_last_line;
+ 	}
+       else
+ 	{
+ 	  /* No merger possible.  */
+ 	  m_line_spans.safe_push (*next);
+ 	}
+     }
+ 
+   /* Verify the result, in m_line_spans.  */
+   gcc_assert (m_line_spans.length () > 0);
+   for (unsigned int i = 1; i < m_line_spans.length (); i++)
+     {
+       const line_span *prev = &m_line_spans[i - 1];
+       const line_span *next = &m_line_spans[i];
+       /* The individual spans must be sane.  */
+       gcc_assert (prev->m_first_line <= prev->m_last_line);
+       gcc_assert (next->m_first_line <= next->m_last_line);
+       /* The spans must be ordered.  */
+       gcc_assert (prev->m_first_line < next->m_first_line);
+       /* There must be a gap of at least one line between separate spans.  */
+       gcc_assert ((prev->m_last_line + 1) < next->m_first_line);
+     }
+ }
+ 
+ /* Determine how many display columns need to be reserved for line numbers,
+    based on the largest line number that will be needed, and populate
+    m_linenum_width.  */
+ 
+ void
+ layout::calculate_linenum_width ()
+ {
+   gcc_assert (m_line_spans.length () > 0);
+   const line_span *last_span = &m_line_spans[m_line_spans.length () - 1];
+   int highest_line = last_span->m_last_line;
+   if (highest_line < 0)
+     highest_line = 0;
+   m_linenum_width = diagnostics::num_digits (highest_line);
+   /* If we're showing jumps in the line-numbering, allow at least 3 chars.  */
+   if (m_line_spans.length () > 1)
+     m_linenum_width = MAX (m_linenum_width, 3);
+   /* If there's a minimum margin width, apply it (subtracting 1 for the space
+      after the line number.  */
+   m_linenum_width = MAX (m_linenum_width, m_options.min_margin_width - 1);
+ }
+ 
+ /* Calculate m_x_offset_display, which improves readability in case the source
+    line of interest is longer than the user's display.  All lines output will be
+    shifted to the left (so that their beginning is no longer displayed) by
+    m_x_offset_display display columns, so that the caret is in a reasonable
+    location.  */
+ 
+ void
+ layout::calculate_x_offset_display ()
+ {
+   m_x_offset_display = 0;
+ 
+   const int max_width = m_options.max_width;
+   if (!max_width)
+     {
+       /* Nothing to do, the width is not capped.  */
+       return;
+     }
+ 
+   const diagnostics::char_span line
+     = m_file_cache.get_source_line (m_exploc.file,
+ 				    m_exploc.line);
+   if (!line)
+     {
+       /* Nothing to do, we couldn't find the source line.  */
+       return;
+     }
+   int caret_display_column = m_exploc.m_display_col;
+   const int line_bytes
+     = get_line_bytes_without_trailing_whitespace (line.get_buffer (),
+ 						  line.length ());
+   int eol_display_column
+     = cpp_display_width (line.get_buffer (), line_bytes, m_char_policy);
+   if (caret_display_column > eol_display_column
+       || !caret_display_column)
+     {
+       /* This does not make sense, so don't try to do anything in this case.  */
+       return;
+     }
+ 
+   /* Adjust caret and eol positions to include the left margin.  If we are
+      outputting line numbers, then the left margin is equal to m_linenum_width
+      plus three for the " | " which follows it.  Otherwise the left margin width
+      is equal to 1, because layout::print_source_line() will prefix each line
+      with a space.  */
+   const int source_display_cols = eol_display_column;
+   int left_margin_size = 1;
+   if (m_options.show_line_numbers_p)
+       left_margin_size = m_linenum_width + 3;
+   caret_display_column += left_margin_size;
+   eol_display_column += left_margin_size;
+ 
+   if (eol_display_column <= max_width)
+     {
+       /* Nothing to do, everything fits in the display.  */
+       return;
+     }
+ 
+   /* The line is too long for the display.  Calculate an offset such that the
+      caret is not too close to the right edge of the screen.  It will be
+      CARET_LINE_MARGIN display columns from the right edge, unless it is closer
+      than that to the end of the source line anyway.  */
+   int right_margin_size = CARET_LINE_MARGIN;
+   right_margin_size = MIN (eol_display_column - caret_display_column,
+ 			   right_margin_size);
+   if (right_margin_size + left_margin_size >= max_width)
+     {
+       /* The max_width is very small, so anything we try to do will not be very
+ 	 effective; just punt in this case and output with no offset.  */
+       return;
+     }
+   const int max_caret_display_column = max_width - right_margin_size;
+   if (caret_display_column > max_caret_display_column)
+     {
+       m_x_offset_display = caret_display_column - max_caret_display_column;
+       /* Make sure we don't offset the line into oblivion.  */
+       static const int min_cols_visible = 2;
+       if (source_display_cols - m_x_offset_display < min_cols_visible)
+ 	m_x_offset_display = 0;
+     }
+ }
+ 
+ /* Print line ROW of source code, potentially colorized at any ranges, and
+    return the line bounds.  LINE is the source line (not necessarily
+    0-terminated) and LINE_BYTES is its length in bytes.  In order to handle both
+    colorization and tab expansion, this function tracks the line position in
+    both byte and display column units.  */
+ 
+ template<typename TextOrHtml>
+ line_bounds
+ layout_printer<TextOrHtml>::print_source_line (linenum_type row,
+ 					 const char *line,
+ 					 int line_bytes)
+ {
+   m_text_or_html.colorize_text_ensure_normal ();
+   m_text_or_html.push_html_tag ("tr", true);
+   m_text_or_html.emit_text_prefix ();
+   if (m_layout.m_options.show_line_numbers_p)
+     {
+       m_text_or_html.push_html_tag_with_class ("td", "linenum", true);
+       int width = diagnostics::num_digits (row);
+       for (int i = 0; i < m_layout.get_linenum_width () - width; i++)
+ 	m_text_or_html.add_space ();
+       char buf[20];
+       sprintf (buf, "%i", row);
+       m_text_or_html.add_text (buf);
+       if (TextOrHtml::is_text ())
+ 	m_text_or_html.add_text (" |");
+       m_text_or_html.pop_html_tag ("td");
+     }
+ 
+   m_text_or_html.push_html_tag_with_class ("td", "left-margin", true);
+   print_leftmost_column ();
+   m_text_or_html.pop_html_tag ("td");
+ 
+   /* We will stop printing the source line at any trailing whitespace.  */
+   line_bytes = get_line_bytes_without_trailing_whitespace (line,
+ 							   line_bytes);
+ 
+   /* This object helps to keep track of which display column we are at, which is
+      necessary for computing the line bounds in display units, for doing
+      tab expansion, and for implementing m_x_offset_display.  */
+   cpp_display_width_computation dw (line, line_bytes, m_layout.m_char_policy);
+ 
+   m_text_or_html.push_html_tag_with_class ("td", "source", true);
+ 
+   /* Skip the first m_x_offset_display display columns.  In case the leading
+      portion that will be skipped ends with a character with wcwidth > 1, then
+      it is possible we skipped too much, so account for that by padding with
+      spaces.  Note that this does the right thing too in case a tab was the last
+      character to be skipped over; the tab is effectively replaced by the
+      correct number of trailing spaces needed to offset by the desired number of
+      display columns.  */
+   for (int skipped_display_cols
+ 	 = dw.advance_display_cols (m_layout.m_x_offset_display);
+        skipped_display_cols > m_layout.m_x_offset_display; --skipped_display_cols)
+     m_text_or_html.add_space ();
+ 
+   /* Print the line and compute the line_bounds.  */
+   line_bounds lbounds;
+   while (!dw.done ())
+     {
+       /* Assuming colorization is enabled for the caret and underline
+ 	 characters, we may also colorize the associated characters
+ 	 within the source line.
+ 
+ 	 For frontends that generate range information, we color the
+ 	 associated characters in the source line the same as the
+ 	 carets and underlines in the annotation line, to make it easier
+ 	 for the reader to see the pertinent code.
+ 
+ 	 For frontends that only generate carets, we don't colorize the
+ 	 characters above them, since this would look strange (e.g.
+ 	 colorizing just the first character in a token).  */
+       if (m_layout.m_options.colorize_source_p)
+ 	{
+ 	  bool in_range_p;
+ 	  point_state state;
+ 	  const int start_byte_col = dw.bytes_processed () + 1;
+ 	  in_range_p = m_layout.get_state_at_point (row, start_byte_col,
+ 						    0, INT_MAX,
+ 						    CU_BYTES,
+ 						    &state);
+ 	  if (in_range_p)
+ 	    set_in_range (state.range_idx);
+ 	  else
+ 	    set_outside_range ();
+ 	}
+ 
+       /* Get the display width of the next character to be output, expanding
+ 	 tabs and replacing some control bytes with spaces as necessary.  */
+       const char *c = dw.next_byte ();
+       const int start_disp_col = dw.display_cols_processed () + 1;
+       cpp_decoded_char cp;
+       const int this_display_width = dw.process_next_codepoint (&cp);
+       if (*c == '\t')
+ 	{
+ 	  /* The returned display width is the number of spaces into which the
+ 	     tab should be expanded.  */
+ 	  for (int i = 0; i != this_display_width; ++i)
+ 	    m_text_or_html.add_space ();
+ 	  continue;
+ 	}
+ 
+       /* We have a (possibly multibyte) character to output; update the line
+ 	 bounds if it is not whitespace.  */
+       if (*c != ' ')
+ 	{
+ 	  lbounds.m_last_non_ws_disp_col = dw.display_cols_processed ();
+ 	  if (lbounds.m_first_non_ws_disp_col == INT_MAX)
+ 	    lbounds.m_first_non_ws_disp_col = start_disp_col;
+ 	}
+ 
+       /* Output the character.  */
+       m_text_or_html.print_decoded_char (m_layout.m_char_policy, cp);
+       c = dw.next_byte ();
+     }
+   set_outside_range ();
+   end_line ();
+   return lbounds;
+ }
+ 
+ /* Determine if we should print an annotation line for ROW.
+    i.e. if any of m_layout_ranges contains ROW.  */
+ 
+ bool
+ layout::should_print_annotation_line_p (linenum_type row) const
+ {
+   layout_range *range;
+   int i;
+   FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+     {
+       if (range->m_range_display_kind == SHOW_LINES_WITHOUT_RANGE)
+ 	return false;
+       if (range->intersects_line_p (row))
+ 	return true;
+     }
+   return false;
+ }
+ 
+ /* Print the leftmost column after the margin, which is used for showing
+    links between labels (e.g. for CFG edges in execution paths).  */
+ 
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::print_leftmost_column ()
+ {
+   if (!get_options ().show_event_links_p)
+     gcc_assert (m_link_lhs_state == link_lhs_state::none);
+ 
+   switch (m_link_lhs_state)
+     {
+     default:
+       gcc_unreachable ();
+     case link_lhs_state::none:
+       m_text_or_html.add_space ();
+       break;
+     case link_lhs_state::rewinding_to_lhs:
+       {
+ 	m_text_or_html.colorize_text_for_cfg_edge ();
+ 	const cppchar_t ch = get_theme ().get_cppchar
+ 	  (text_art::theme::cell_kind::CFG_FROM_LEFT_TO_DOWN);
+ 	m_text_or_html.add_character (ch);
+ 	m_text_or_html.colorize_text_ensure_normal ();
+       }
+       break;
+     case link_lhs_state::at_lhs:
+       {
+ 	m_text_or_html.colorize_text_for_cfg_edge ();
+ 	const cppchar_t ch = get_theme ().get_cppchar
+ 	  (text_art::theme::cell_kind::CFG_DOWN);
+ 	m_text_or_html.add_character (ch);
+ 	m_text_or_html.colorize_text_ensure_normal ();
+       }
+       break;
+     case link_lhs_state::indenting_to_dest:
+       {
+ 	m_text_or_html.colorize_text_for_cfg_edge ();
+ 	const cppchar_t ch = get_theme ().get_cppchar
+ 	  (text_art::theme::cell_kind::CFG_FROM_DOWN_TO_RIGHT);
+ 	m_text_or_html.add_character (ch);
+ 	m_text_or_html.colorize_text_ensure_normal ();
+       }
+       break;
+     }
+ }
+ 
+ /* Begin an annotation line for either text or html output
+ 
+    If m_show_line_numbers_p, print the left margin, which is empty
+    for annotation lines.
+    After any left margin, print a leftmost column, which is used for
+    showing links between labels (e.g. for CFG edges in execution paths).
+ 
+    For text output, this also first prints the text prefix.
+    For html output, this also pushes <tr> and <td> open tags, where the
+    <td> is for the coming annotations.  */
+ 
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::start_annotation_line (enum margin_kind margin)
+ {
+   m_text_or_html.emit_text_prefix ();
+   m_text_or_html.push_html_tag ("tr", true);
+ 
+   char margin_char = (margin == margin_kind::insertion
+ 		      ? '+'
+ 		      : ' ');
+ 
+   if (get_options ().show_line_numbers_p)
+     {
+       /* Print the margin.  If MARGIN_CHAR != ' ', then print up to 3
+ 	 of it, right-aligned, padded with spaces.  */
+       m_text_or_html.push_html_tag_with_class ("td", "linenum", true);
+       int i;
+       for (i = 0; i < m_layout.m_linenum_width - 3; i++)
+ 	m_text_or_html.add_space ();
+       for (; i < m_layout.m_linenum_width; i++)
+ 	m_text_or_html.add_character (margin_char);
+       if (TextOrHtml::is_text ())
+ 	m_text_or_html.add_text (" |");
+       m_text_or_html.pop_html_tag ("td");
+     }
+ 
+   m_text_or_html.push_html_tag_with_class ("td", "left-margin", true);
+   if (margin == margin_kind::insertion)
+     m_text_or_html.add_character (margin_char);
+   else
+     print_leftmost_column ();
+   m_text_or_html.pop_html_tag ("td");
+ 
+   m_text_or_html.push_html_tag_with_class ("td",
+ 					   (margin == margin_kind::ruler
+ 					    ? "ruler"
+ 					    : "annotation"),
+ 					   true);
+ }
+ 
+ /* End a source or annotation line: text implementation.
+    Reset any colorization and emit a newline.  */
+ 
+ template<>
+ void
+ layout_printer<diagnostics::to_text>::end_line ()
+ {
+   m_text_or_html.colorize_text_ensure_normal ();
+   m_text_or_html.add_newline ();
+ }
+ 
+ /* End a source or annotation line: HTML implementation.
+    Close the <td> and <tr> tags.  */
+ 
+ template<>
+ void
+ layout_printer<diagnostics::to_html>::end_line ()
+ {
+   m_text_or_html.pop_html_tag ("td");
+   m_text_or_html.pop_html_tag ("tr");
+ }
+ 
+ /* Handle the various transitions between being-in-range and
+    not-being-in-a-range, and between ranges.  */
+ 
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::set_in_range (int range_idx)
+ {
+   if (m_was_in_range_p)
+     {
+       if (m_last_range_idx != range_idx)
+ 	{
+ 	  /* transition between ranges.  */
+ 	  end_label (m_last_range_idx, false);
+ 	  begin_label (range_idx, false);
+ 	}
+     }
+   else
+     {
+       /* transition from "not in a range" to "in a range".  */
+       begin_label (range_idx, false);
+       m_was_in_range_p = true;
+     }
+   m_last_range_idx = range_idx;
+ }
+ 
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::set_outside_range ()
+ {
+   if (m_was_in_range_p)
+     /* transition from "in a range" to "not in a range".  */
+     end_label (m_last_range_idx, false);
+   m_was_in_range_p = false;
+ }
+ 
+ /* Print a line consisting of the caret/underlines for the given
+    source line.  */
+ 
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::print_annotation_line (linenum_type row,
+ 					     const line_bounds lbounds)
+ {
+   int x_bound = m_layout.get_x_bound_for_row (row,
+ 					      m_layout.m_exploc.m_display_col,
+ 					      lbounds.m_last_non_ws_disp_col);
+ 
+   start_annotation_line (margin_kind::normal);
+ 
+   for (int column = 1 + m_layout.m_x_offset_display; column < x_bound; column++)
+     {
+       bool in_range_p;
+       point_state state;
+       in_range_p = m_layout.get_state_at_point (row, column,
+ 						lbounds.m_first_non_ws_disp_col,
+ 						lbounds.m_last_non_ws_disp_col,
+ 						CU_DISPLAY_COLS,
+ 						&state);
+       if (in_range_p)
+ 	set_in_range (state.range_idx);
+       else
+ 	set_outside_range ();
+ 
+       if (in_range_p)
+ 	{
+ 	  /* Within a range.  Draw either the caret or an underline.  */
+ 	  if (state.draw_caret_p)
+ 	    {
+ 	      /* Draw the caret.  */
+ 	      char caret_char;
+ 	      if (state.range_idx < rich_location::STATICALLY_ALLOCATED_RANGES)
+ 		caret_char = get_options ().caret_chars[state.range_idx];
+ 	      else
+ 		caret_char = '^';
+ 	      m_text_or_html.add_character (caret_char);
+ 	    }
+ 	  else
+ 	    m_text_or_html.add_character ('~');
+ 	}
+       else
+ 	{
+ 	  /* Not in a range.  */
+ 	  m_text_or_html.add_character (' ');
+ 	}
+     }
+ 
+   set_outside_range ();
+ 
+   end_line ();
+ }
+ 
+ /* A version of label_text that can live inside a vec.
+    Requires manual cleanup via maybe_free.  */
+ 
+ struct pod_label_text
+ {
+   pod_label_text ()
+   : m_buffer (nullptr), m_caller_owned (false)
+   {}
+ 
+   pod_label_text (label_text &&other)
+   : m_buffer (const_cast<char*> (other.get ())),
+     m_caller_owned (other.is_owner ())
+   {
+     other.release ();
+   }
+ 
+   void maybe_free ()
+   {
+     if (m_caller_owned)
+       free (m_buffer);
+   }
+ 
+   char *m_buffer;
+   bool m_caller_owned;
+ };
+ 
+ /* Implementation detail of layout::print_any_labels.
+ 
+    A label within the given row of source.  */
+ 
+ class line_label
+ {
+ public:
+   line_label (unsigned original_range_idx,
+ 	      int state_idx, int column,
+ 	      label_text text,
+ 	      bool has_in_edge,
+ 	      bool has_out_edge)
+   : m_original_range_idx (original_range_idx),
+     m_state_idx (state_idx), m_column (column),
+     m_text (std::move (text)), m_label_line (0), m_has_vbar (true),
+     m_has_in_edge (has_in_edge),
+     m_has_out_edge (has_out_edge)
+   {
+     /* Using styled_string rather than cpp_display_width here
+        lets us skip SGR formatting characters for color and URLs.
+        It doesn't handle tabs and unicode escaping, but we don't
+        expect to see either of those in labels.  */
+     text_art::style_manager sm;
+     text_art::styled_string str (sm, m_text.m_buffer);
+     m_display_width = str.calc_canvas_width ();
+   }
+ 
+   /* Sorting is primarily by column, then by state index.  */
+   static int comparator (const void *p1, const void *p2)
+   {
+     const line_label *ll1 = (const line_label *)p1;
+     const line_label *ll2 = (const line_label *)p2;
+     int column_cmp = compare (ll1->m_column, ll2->m_column);
+     if (column_cmp)
+       return column_cmp;
+     /* Order by reverse state index, so that labels are printed
+        in order of insertion into the rich_location when the
+        sorted list is walked backwards.  */
+     return -compare (ll1->m_state_idx, ll2->m_state_idx);
+   }
+ 
+   unsigned m_original_range_idx;
+   int m_state_idx;
+   int m_column;
+   pod_label_text m_text;
+   size_t m_display_width;
+   int m_label_line;
+   bool m_has_vbar;
+   bool m_has_in_edge;
+   bool m_has_out_edge;
+ };
+ 
+ /* Implementations of layout_printer::{begin,end}_label for
+    to_text and to_html.
+ 
+    RANGE_IDX is the index of the range within the rich_location.
+ 
+    IS_LABEL_TEXT is true for the text of the label,
+    false when quoting the source code, underlining the source
+    code, and for the vertical bars connecting the underlines
+    to the text of the label.  */
+ 
+ template<>
+ void
+ layout_printer<diagnostics::to_text>::begin_label (int range_idx,
+ 						   bool is_label_text)
+ {
+   /* Colorize the text, unless it's for labels for events in a
+      diagnostic path.  */
+   if (is_label_text && m_is_diagnostic_path)
+     return;
+ 
+   gcc_assert (m_text_or_html.m_colorizer);
+   m_text_or_html.m_colorizer->set_range (range_idx);
+ }
+ 
+ template<>
+ void
+ layout_printer<diagnostics::to_html>::begin_label (int range_idx,
+ 						   bool is_label_text)
+ {
+   if (is_label_text && m_text_or_html.m_html_label_writer)
+     m_text_or_html.m_html_label_writer->begin_label ();
+ 
+   if (const char *highlight_color
+ 	= m_text_or_html.get_highlight_color_for_range_idx (range_idx))
+     m_text_or_html.m_xp.push_tag_with_class ("span", highlight_color);
+ }
+ 
+ template<>
+ void
+ layout_printer<diagnostics::to_text>::end_label (int, bool)
+ {
+   m_text_or_html.colorize_text_ensure_normal ();
+ }
+ 
+ template<>
+ void
+ layout_printer<diagnostics::to_html>::end_label (int range_idx,
+ 						 bool is_label_text)
+ {
+   if (m_text_or_html.get_highlight_color_for_range_idx (range_idx))
+     m_text_or_html.m_xp.pop_tag ("span");
+ 
+   if (is_label_text && m_text_or_html.m_html_label_writer)
+     m_text_or_html.m_html_label_writer->end_label ();
+ }
+ 
+ /* Print any labels in this row.  */
+ template <typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::print_any_labels (linenum_type row)
+ {
+   int i;
+   auto_vec<line_label> labels;
+ 
+   /* Gather the labels that are to be printed into "labels".  */
+   {
+     layout_range *range;
+     FOR_EACH_VEC_ELT (m_layout.m_layout_ranges, i, range)
+       {
+ 	/* Most ranges don't have labels, so reject this first.  */
+ 	if (range->m_label == nullptr)
+ 	  continue;
+ 
+ 	/* The range's caret must be on this line.  */
+ 	if (range->m_caret.m_line != row)
+ 	  continue;
+ 
+ 	/* Reject labels that aren't fully visible due to clipping
+ 	   by m_x_offset_display.  */
+ 	const int disp_col = range->m_caret.m_columns[CU_DISPLAY_COLS];
+ 	if (disp_col <= m_layout.m_x_offset_display)
+ 	  continue;
+ 
+ 	label_text text;
+ 	text = range->m_label->get_text (range->m_original_idx);
+ 
+ 	/* Allow for labels that return nullptr from their get_text
+ 	   implementation (so e.g. such labels can control their own
+ 	   visibility).  */
+ 	if (text.get () == nullptr)
+ 	  continue;
+ 
+ 	labels.safe_push (line_label (range->m_original_idx,
+ 				      i, disp_col, std::move (text),
+ 				      range->has_in_edge (),
+ 				      range->has_out_edge ()));
+       }
+   }
+ 
+   /* Bail out if there are no labels on this row.  */
+   if (labels.length () == 0)
+     return;
+ 
+   /* Sort them.  */
+   labels.qsort(line_label::comparator);
+ 
+   /* Figure out how many "label lines" we need, and which
+      one each label is printed in.
+ 
+      For example, if the labels aren't too densely packed,
+      we can fit them on the same line, giving two "label lines":
+ 
+        foo + bar
+        ~~~   ~~~
+        |     |        : label line 0
+        l0    l1       : label line 1
+ 
+      If they would touch each other or overlap, then we need
+      additional "label lines":
+ 
+        foo + bar
+        ~~~   ~~~
+        |     |             : label line 0
+        |     label 1       : label line 1
+        label 0             : label line 2
+ 
+      Place the final label on label line 1, and work backwards, adding
+      label lines as needed.
+ 
+      If multiple labels are at the same place, put them on separate
+      label lines:
+ 
+        foo + bar
+            ^               : label line 0
+            |               : label line 1
+            label 0         : label line 2
+            label 1         : label line 3.  */
+ 
+   int max_label_line = 1;
+   int label_line_with_in_edge = -1;
+   {
+     int next_column = INT_MAX;
+     line_label *label;
+     FOR_EACH_VEC_ELT_REVERSE (labels, i, label)
+       {
+ 	/* Would this label "touch" or overlap the next label?  */
+ 	if (label->m_column + label->m_display_width >= (size_t)next_column)
+ 	  {
+ 	    max_label_line++;
+ 
+ 	    /* If we've already seen labels with the same column, suppress the
+ 	       vertical bar for subsequent ones in this backwards iteration;
+ 	       hence only the one with the highest label_line has m_has_vbar set.  */
+ 	    if (label->m_column == next_column)
+ 	      label->m_has_vbar = false;
+ 	  }
+ 
+ 	label->m_label_line = max_label_line;
+ 	if (get_options ().show_event_links_p)
+ 	  if (label->m_has_in_edge)
+ 	    label_line_with_in_edge = max_label_line;
+ 	next_column = label->m_column;
+       }
+   }
+ 
+   gcc_assert (labels.length () > 0);
+ 
+   /* Print the "label lines".  For each label within the line, print
+      either a vertical bar ('|') for the labels that are lower down, or the
+      labels themselves once we've reached their line.  */
+   {
+     for (int label_line = 0; label_line <= max_label_line; label_line++)
+       {
+ 	if (label_line == label_line_with_in_edge)
+ 	  {
+ 	    gcc_assert (get_options ().show_event_links_p);
+ 	    m_link_lhs_state = link_lhs_state::indenting_to_dest;
+ 	  }
+ 	start_annotation_line (margin_kind::normal);
+ 
+ 	int column = 1 + m_layout.m_x_offset_display;
+ 	line_label *label;
+ 	FOR_EACH_VEC_ELT (labels, i, label)
+ 	  {
+ 	    if (label_line > label->m_label_line)
+ 	      /* We've printed all the labels for this label line.  */
+ 	      break;
+ 
+ 	    if (label_line == label->m_label_line)
+ 	      {
+ 		gcc_assert (column <= label->m_column);
+ 
+ 		if (label_line == label_line_with_in_edge)
+ 		  {
+ 		    /* Print a prefix showing an incoming
+ 		       link from another label.
+ 		       .|+----------->(10) ...to here
+ 		       . ^~~~~~~~~~~~~
+ 		       . this text.  */
+ 		    gcc_assert (get_options ().show_event_links_p);
+ 		    m_text_or_html.colorize_text_for_cfg_edge ();
+ 		    const cppchar_t right= get_theme ().get_cppchar
+ 		      (text_art::theme::cell_kind::CFG_RIGHT);
+ 		    while (column < label->m_column - 1)
+ 		      {
+ 			m_text_or_html.add_character (right);
+ 			column++;
+ 		      }
+ 		    if (column == label->m_column - 1)
+ 		      {
+ 			m_text_or_html.add_character ('>');
+ 			column++;
+ 		      }
+ 		    m_text_or_html.colorize_text_ensure_normal ();
+ 		    m_link_lhs_state = link_lhs_state::none;
+ 		    label_line_with_in_edge = -1;
+ 		  }
+ 		else
+ 		  move_to_column (&column, label->m_column, true);
+ 		gcc_assert (column == label->m_column);
+ 
+ 		begin_label (label->m_state_idx, true);
+ 		m_text_or_html.add_text (label->m_text.m_buffer);
+ 		end_label (label->m_state_idx, true);
+ 
+ 		column += label->m_display_width;
+ 		if (get_options ().show_event_links_p && label->m_has_out_edge)
+ 		  {
+ 		    /* Print a suffix showing the start of a linkage
+ 		       to another label e.g. " ->-+" which will be the
+ 		       first part of e.g.
+ 		       .      (9) following ‘false’ branch... ->-+ <- HERE
+ 		       .                                         |
+ 		       .                                         |
+ 		       .  */
+ 		    const cppchar_t right= get_theme ().get_cppchar
+ 		      (text_art::theme::cell_kind::CFG_RIGHT);
+ 		    const cppchar_t from_right_to_down= get_theme ().get_cppchar
+ 		      (text_art::theme::cell_kind::CFG_FROM_RIGHT_TO_DOWN);
+ 		    m_text_or_html.colorize_text_for_cfg_edge ();
+ 		    m_text_or_html.add_space ();
+ 		    m_text_or_html.add_character (right);
+ 		    m_text_or_html.add_character ('>');
+ 		    m_text_or_html.add_character (right);
+ 		    m_text_or_html.add_character (from_right_to_down);
+ 		    m_text_or_html.colorize_text_ensure_normal ();
+ 		    column += 5;
+ 		    m_link_rhs_column = column - 1;
+ 		  }
+ 	      }
+ 	    else if (label->m_has_vbar)
+ 	      {
+ 		gcc_assert (column <= label->m_column);
+ 		move_to_column (&column, label->m_column, true);
+ 		begin_label (label->m_state_idx, false);
+ 		m_text_or_html.add_character ('|');
+ 		end_label (label->m_state_idx, false);
+ 		column++;
+ 	      }
+ 	  }
+ 
+ 	/* If we have a vertical link line on the RHS, print the
+ 	   '|' on this annotation line after the labels.  */
+ 	if (m_link_rhs_column != -1 && column < m_link_rhs_column)
+ 	  {
+ 	    move_to_column (&column, m_link_rhs_column, true);
+ 	    m_text_or_html.colorize_text_for_cfg_edge ();
+ 	    const cppchar_t down= get_theme ().get_cppchar
+ 	      (text_art::theme::cell_kind::CFG_DOWN);
+ 	    m_text_or_html.add_character (down);
+ 	    m_text_or_html.colorize_text_ensure_normal ();
+ 	  }
+ 
+ 	end_line ();
+       }
+     }
+ 
+   /* If we have a vertical link line on the RHS, print a trailing
+      annotation line showing the vertical line.  */
+   if (m_link_rhs_column != -1)
+     {
+       int column = 1 + m_layout.m_x_offset_display;
+       start_annotation_line (margin_kind::normal);
+       move_to_column (&column, m_link_rhs_column, true);
+       m_text_or_html.colorize_text_for_cfg_edge ();
+       const cppchar_t down= get_theme ().get_cppchar
+ 	(text_art::theme::cell_kind::CFG_DOWN);
+       m_text_or_html.add_character (down);
+       end_line ();
+     }
+ 
+   /* Clean up.  */
+   {
+     line_label *label;
+     FOR_EACH_VEC_ELT (labels, i, label)
+       label->m_text.maybe_free ();
+   }
+ }
+ 
+ /* If there are any fixit hints inserting new lines before source line ROW,
+    print them.
+ 
+    They are printed on lines of their own, before the source line
+    itself, with a leading '+'.  */
+ 
+ template <typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::print_leading_fixits (linenum_type row)
+ {
+   for (unsigned int i = 0; i < m_layout.m_fixit_hints.length (); i++)
+     {
+       const fixit_hint *hint = m_layout.m_fixit_hints[i];
+ 
+       if (!hint->ends_with_newline_p ())
+ 	/* Not a newline fixit; print it in print_trailing_fixits.  */
+ 	continue;
+ 
+       gcc_assert (hint->insertion_p ());
+ 
+       if (hint->affects_line_p (m_layout.m_line_table,
+ 				m_layout.m_exploc.file,
+ 				row))
+ 	{
+ 	  /* Printing the '+' with normal colorization
+ 	     and the inserted line with "insert" colorization
+ 	     helps them stand out from each other, and from
+ 	     the surrounding text.  */
+ 	  m_text_or_html.colorize_text_ensure_normal ();
+ 	  start_annotation_line (margin_kind::insertion);
+ 	  m_text_or_html.colorize_text_for_fixit_insert ();
+ 	  /* Print all but the trailing newline of the fix-it hint.
+ 	     We have to print the newline separately to avoid
+ 	     getting additional pp prefixes printed.  */
+ 	  for (size_t i = 0; i < hint->get_length () - 1; i++)
+ 	    m_text_or_html.add_character (hint->get_string ()[i]);
+ 	  end_line ();
+ 	}
+     }
+ }
+ 
+ /* Subroutine of layout::print_trailing_fixits.
+ 
+    Determine if the annotation line printed for LINE contained
+    the exact range from START_COLUMN to FINISH_COLUMN (in display units).  */
+ 
+ bool
+ layout::annotation_line_showed_range_p (linenum_type line, int start_column,
+ 					int finish_column) const
+ {
+   layout_range *range;
+   int i;
+   FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+     if (range->m_start.m_line == line
+ 	&& range->m_start.m_columns[CU_DISPLAY_COLS] == start_column
+ 	&& range->m_finish.m_line == line
+ 	&& range->m_finish.m_columns[CU_DISPLAY_COLS] == finish_column)
+       return true;
+   return false;
+ }
+ 
+ /* Classes for printing trailing fix-it hints i.e. those that
+    don't add new lines.
+ 
+    For insertion, these can look like:
+ 
+      new_text
+ 
+    For replacement, these can look like:
+ 
+      ------------- : underline showing affected range
+      new_text
+ 
+    For deletion, these can look like:
+ 
+      ------------- : underline showing affected range
+ 
+    This can become confusing if they overlap, and so we need
+    to do some preprocessing to decide what to print.
+    We use the list of fixit_hint instances affecting the line
+    to build a list of "correction" instances, and print the
+    latter.
+ 
+    For example, consider a set of fix-its for converting
+    a C-style cast to a C++ const_cast.
+ 
+    Given:
+ 
+    ..000000000111111111122222222223333333333.
+    ..123456789012345678901234567890123456789.
+      foo *f = (foo *)ptr->field;
+                           ^~~~~
+ 
+    and the fix-it hints:
+      - replace col 10 (the open paren) with "const_cast<"
+      - replace col 16 (the close paren) with "> ("
+      - insert ")" before col 27
+ 
+    then we would get odd-looking output:
+ 
+      foo *f = (foo *)ptr->field;
+                           ^~~~~
+               -
+               const_cast<
+                     -
+                     > (        )
+ 
+    It would be better to detect when fixit hints are going to
+    overlap (those that require new lines), and to consolidate
+    the printing of such fixits, giving something like:
+ 
+      foo *f = (foo *)ptr->field;
+                           ^~~~~
+               -----------------
+               const_cast<foo *> (ptr->field)
+ 
+    This works by detecting when the printing would overlap, and
+    effectively injecting no-op replace hints into the gaps between
+    such fix-its, so that the printing joins up.
+ 
+    In the above example, the overlap of:
+      - replace col 10 (the open paren) with "const_cast<"
+    and:
+      - replace col 16 (the close paren) with "> ("
+    is fixed by injecting a no-op:
+      - replace cols 11-15 with themselves ("foo *")
+    and consolidating these, making:
+      - replace cols 10-16 with "const_cast<" + "foo *" + "> ("
+    i.e.:
+      - replace cols 10-16 with "const_cast<foo *> ("
+ 
+    This overlaps with the final fix-it hint:
+      - insert ")" before col 27
+    and so we repeat the consolidation process, by injecting
+    a no-op:
+      - replace cols 17-26 with themselves ("ptr->field")
+    giving:
+      - replace cols 10-26 with "const_cast<foo *> (" + "ptr->field" + ")"
+    i.e.:
+      - replace cols 10-26 with "const_cast<foo *> (ptr->field)"
+ 
+    and is thus printed as desired.  */
+ 
+ /* A range of (byte or display) columns within a line.  */
+ 
+ class column_range
+ {
+ public:
+   column_range (int start_, int finish_) : start (start_), finish (finish_)
+   {
+     gcc_assert (valid_p (start, finish));
+   }
+ 
+   bool operator== (const column_range &other) const
+   {
+     return start == other.start && finish == other.finish;
+   }
+ 
+   static bool valid_p (int start, int finish)
+   {
+     /* We must have either a range, or an insertion.  */
+     return (start <= finish || finish == start - 1);
+   }
+ 
+   int start;
+   int finish;
+ };
+ 
+ /* Get the range of bytes or display columns that HINT would affect.  */
+ static column_range
+ get_affected_range (diagnostics::file_cache &fc,
+ 		    const cpp_char_column_policy &policy,
+ 		    const fixit_hint *hint, enum column_unit col_unit)
+ {
+   expanded_location exploc_start = expand_location (hint->get_start_loc ());
+   expanded_location exploc_finish = expand_location (hint->get_next_loc ());
+   --exploc_finish.column;
+ 
+   int start_column;
+   int finish_column;
+   if (col_unit == CU_DISPLAY_COLS)
+     {
+       start_column = location_compute_display_column (fc, exploc_start, policy);
+       if (hint->insertion_p ())
+ 	finish_column = start_column - 1;
+       else
+ 	finish_column
+ 	  = location_compute_display_column (fc, exploc_finish, policy);
+     }
+   else
+     {
+       start_column = exploc_start.column;
+       finish_column = exploc_finish.column;
+     }
+   return column_range (start_column, finish_column);
+ }
+ 
+ /* Get the range of display columns that would be printed for HINT.  */
+ 
+ static column_range
+ get_printed_columns (diagnostics::file_cache &fc,
+ 		     const cpp_char_column_policy &policy,
+ 		     const fixit_hint *hint)
+ {
+   expanded_location exploc = expand_location (hint->get_start_loc ());
+   int start_column = location_compute_display_column (fc, exploc, policy);
+   int hint_width = cpp_display_width (hint->get_string (), hint->get_length (),
+ 				      policy);
+   int final_hint_column = start_column + hint_width - 1;
+   if (hint->insertion_p ())
+     {
+       return column_range (start_column, final_hint_column);
+     }
+   else
+     {
+       exploc = expand_location (hint->get_next_loc ());
+       --exploc.column;
+       int finish_column = location_compute_display_column (fc, exploc, policy);
+       return column_range (start_column,
+ 			   MAX (finish_column, final_hint_column));
+     }
+ }
+ 
+ /* A correction on a particular line.
+    This describes a plan for how to print one or more fixit_hint
+    instances that affected the line, potentially consolidating hints
+    into corrections to make the result easier for the user to read.  */
+ 
+ class correction
+ {
+ public:
+   correction (column_range affected_bytes,
+ 	      column_range affected_columns,
+ 	      column_range printed_columns,
+ 	      const char *new_text, size_t new_text_len,
+ 	      const cpp_char_column_policy &policy)
+   : m_affected_bytes (affected_bytes),
+     m_affected_columns (affected_columns),
+     m_printed_columns (printed_columns),
+     m_text (xstrdup (new_text)),
+     m_byte_length (new_text_len),
+     m_policy (policy),
+     m_alloc_sz (new_text_len + 1)
+   {
+     compute_display_cols ();
+   }
+ 
+   ~correction () { free (m_text); }
+ 
+   bool insertion_p () const
+   {
+     return m_affected_bytes.start == m_affected_bytes.finish + 1;
+   }
+ 
+   void ensure_capacity (size_t len);
+   void ensure_terminated ();
+ 
+   void compute_display_cols ()
+   {
+     m_display_cols = cpp_display_width (m_text, m_byte_length, m_policy);
+   }
+ 
+   void overwrite (int dst_offset, const diagnostics::char_span &src_span)
+   {
+     gcc_assert (dst_offset >= 0);
+     gcc_assert (dst_offset + src_span.length () < m_alloc_sz);
+     memcpy (m_text + dst_offset, src_span.get_buffer (),
+ 	    src_span.length ());
+   }
+ 
+   /* If insert, then start: the column before which the text
+      is to be inserted, and finish is offset by the length of
+      the replacement.
+      If replace, then the range of columns affected.  */
+   column_range m_affected_bytes;
+   column_range m_affected_columns;
+ 
+   /* If insert, then start: the column before which the text
+      is to be inserted, and finish is offset by the length of
+      the replacement.
+      If replace, then the range of columns affected.  */
+   column_range m_printed_columns;
+ 
+   /* The text to be inserted/used as replacement.  */
+   char *m_text;
+   size_t m_byte_length; /* Not including null-terminator.  */
+   int m_display_cols;
+   const cpp_char_column_policy &m_policy;
+   size_t m_alloc_sz;
+ };
+ 
+ /* Ensure that m_text can hold a string of length LEN
+    (plus 1 for 0-termination).  */
+ 
+ void
+ correction::ensure_capacity (size_t len)
+ {
+   /* Allow 1 extra byte for 0-termination.  */
+   if (m_alloc_sz < (len + 1))
+     {
+       size_t new_alloc_sz = (len + 1) * 2;
+       m_text = (char *)xrealloc (m_text, new_alloc_sz);
+       m_alloc_sz = new_alloc_sz;
+     }
+ }
+ 
+ /* Ensure that m_text is 0-terminated.  */
+ 
+ void
+ correction::ensure_terminated ()
+ {
+   /* 0-terminate the buffer.  */
+   gcc_assert (m_byte_length < m_alloc_sz);
+   m_text[m_byte_length] = '\0';
+ }
+ 
+ /* A list of corrections affecting a particular line.
+    This is used by layout::print_trailing_fixits for planning
+    how to print the fix-it hints affecting the line.  */
+ 
+ class line_corrections
+ {
+ public:
+   line_corrections (diagnostics::file_cache &fc,
+ 		    const char_display_policy &policy,
+ 		    const char *filename,
+ 		    linenum_type row)
+   : m_file_cache (fc),
+     m_policy (policy), m_filename (filename), m_row (row)
+   {}
+   ~line_corrections ();
+ 
+   void add_hint (const fixit_hint *hint);
+ 
+   diagnostics::file_cache &m_file_cache;
+   const char_display_policy &m_policy;
+   const char *m_filename;
+   linenum_type m_row;
+   auto_vec <correction *> m_corrections;
+ };
+ 
+ /* struct line_corrections.  */
+ 
+ line_corrections::~line_corrections ()
+ {
+   unsigned i;
+   correction *c;
+   FOR_EACH_VEC_ELT (m_corrections, i, c)
+     delete c;
+ }
+ 
+ /* A struct wrapping a particular source line, allowing
+    run-time bounds-checking of accesses in a checked build.  */
+ 
+ class source_line
+ {
+ public:
+   source_line (diagnostics::file_cache &fc, const char *filename, int line);
+ 
+   diagnostics::char_span as_span ()
+   {
+     return diagnostics::char_span (chars, width);
+   }
+ 
+   const char *chars;
+   int width;
+ };
+ 
+ /* source_line's ctor.  */
+ 
+ source_line::source_line (diagnostics::file_cache &fc,
+ 			  const char *filename,
+ 			  int line)
+ {
+   diagnostics::char_span span = fc.get_source_line (filename, line);
+   chars = span.get_buffer ();
+   width = span.length ();
+ }
+ 
+ /* Add HINT to the corrections for this line.
+    Attempt to consolidate nearby hints so that they will not
+    overlap with printed.  */
+ 
+ void
+ line_corrections::add_hint (const fixit_hint *hint)
+ {
+   column_range affected_bytes
+     = get_affected_range (m_file_cache, m_policy, hint, CU_BYTES);
+   column_range affected_columns
+     = get_affected_range (m_file_cache, m_policy, hint, CU_DISPLAY_COLS);
+   column_range printed_columns
+     = get_printed_columns (m_file_cache, m_policy, hint);
+ 
+   /* Potentially consolidate.  */
+   if (!m_corrections.is_empty ())
+     {
+       correction *last_correction
+ 	= m_corrections[m_corrections.length () - 1];
+ 
+       /* The following consolidation code assumes that the fix-it hints
+ 	 have been sorted by start (done within layout's ctor).  */
+       gcc_assert (affected_bytes.start
+ 		  >= last_correction->m_affected_bytes.start);
+       gcc_assert (printed_columns.start
+ 		  >= last_correction->m_printed_columns.start);
+ 
+       if (printed_columns.start <= last_correction->m_printed_columns.finish
+ 	  && column_range::valid_p (last_correction->m_affected_bytes.finish + 1,
+ 				    affected_bytes.start - 1))
+ 	{
+ 	  /* We have two hints for which the printed forms of the hints
+ 	     would touch or overlap, so we need to consolidate them to avoid
+ 	     confusing the user.
+ 	     Attempt to inject a "replace" correction from immediately
+ 	     after the end of the last hint to immediately before the start
+ 	     of the next hint.  */
+ 	  column_range between (last_correction->m_affected_bytes.finish + 1,
+ 				affected_bytes.start - 1);
+ 
+ 	  /* Try to read the source.  */
+ 	  source_line line (m_file_cache, m_filename, m_row);
+ 	  if (line.chars && between.finish < line.width)
+ 	    {
+ 	      /* Consolidate into the last correction:
+ 		 add a no-op "replace" of the "between" text, and
+ 		 add the text from the new hint.  */
+ 	      int old_byte_len = last_correction->m_byte_length;
+ 	      gcc_assert (old_byte_len >= 0);
+ 	      int between_byte_len = between.finish + 1 - between.start;
+ 	      gcc_assert (between_byte_len >= 0);
+ 	      int new_byte_len
+ 		= old_byte_len + between_byte_len + hint->get_length ();
+ 	      gcc_assert (new_byte_len >= 0);
+ 	      last_correction->ensure_capacity (new_byte_len);
+ 	      last_correction->overwrite
+ 		(old_byte_len,
+ 		 line.as_span ().subspan (between.start - 1,
+ 					  between.finish + 1 - between.start));
+ 	      last_correction->overwrite
+ 		(old_byte_len + between_byte_len,
+ 		 diagnostics::char_span (hint->get_string (),
+ 					 hint->get_length ()));
+ 	      last_correction->m_byte_length = new_byte_len;
+ 	      last_correction->ensure_terminated ();
+ 	      last_correction->m_affected_bytes.finish
+ 		= affected_bytes.finish;
+ 	      last_correction->m_affected_columns.finish
+ 		= affected_columns.finish;
+ 	      int prev_display_cols = last_correction->m_display_cols;
+ 	      last_correction->compute_display_cols ();
+ 	      last_correction->m_printed_columns.finish
+ 		+= last_correction->m_display_cols - prev_display_cols;
+ 	      return;
+ 	    }
+ 	}
+     }
+ 
+   /* If no consolidation happened, add a new correction instance.  */
+   m_corrections.safe_push (new correction (affected_bytes,
+ 					   affected_columns,
+ 					   printed_columns,
+ 					   hint->get_string (),
+ 					   hint->get_length (),
+ 					   m_policy));
+ }
+ 
+ /* If there are any fixit hints on source line ROW, print them.
+    They are printed in order, attempting to combine them onto lines, but
+    starting new lines if necessary.
+    Fix-it hints that insert new lines are handled separately,
+    in layout::print_leading_fixits.  */
+ 
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::print_trailing_fixits (linenum_type row)
+ {
+   typename TextOrHtml::auto_check_tag_nesting sentinel (m_text_or_html);
+ 
+   /* Build a list of correction instances for the line,
+      potentially consolidating hints (for the sake of readability).  */
+   line_corrections corrections (m_layout.m_file_cache, m_layout.m_char_policy,
+ 				m_layout.m_exploc.file, row);
+   for (unsigned int i = 0; i < m_layout.m_fixit_hints.length (); i++)
+     {
+       const fixit_hint *hint = m_layout.m_fixit_hints[i];
+ 
+       /* Newline fixits are handled by layout::print_leading_fixits.  */
+       if (hint->ends_with_newline_p ())
+ 	continue;
+ 
+       if (hint->affects_line_p (m_layout.m_line_table,
+ 				m_layout.m_exploc.file,
+ 				row))
+ 	corrections.add_hint (hint);
+     }
+ 
+   /* Now print the corrections.  */
+   unsigned i;
+   correction *c;
+   int column = 1 + m_layout.m_x_offset_display;
+ 
+   if (!corrections.m_corrections.is_empty ())
+     start_annotation_line (margin_kind::normal);
+ 
+   FOR_EACH_VEC_ELT (corrections.m_corrections, i, c)
+     {
+       /* For now we assume each fixit hint can only touch one line.  */
+       if (c->insertion_p ())
+ 	{
+ 	  /* This assumes the insertion just affects one line.  */
+ 	  int start_column = c->m_printed_columns.start;
+ 	  move_to_column (&column, start_column, true);
+ 	  m_text_or_html.colorize_text_for_fixit_insert ();
+ 	  m_text_or_html.add_text (c->m_text);
+ 	  m_text_or_html.colorize_text_ensure_normal ();
+ 	  column += c->m_display_cols;
+ 	}
+       else
+ 	{
+ 	  /* If the range of the replacement wasn't printed in the
+ 	     annotation line, then print an extra underline to
+ 	     indicate exactly what is being replaced.
+ 	     Always show it for removals.  */
+ 	  int start_column = c->m_affected_columns.start;
+ 	  int finish_column = c->m_affected_columns.finish;
+ 	  if (!m_layout.annotation_line_showed_range_p (row, start_column,
+ 							finish_column)
+ 	      || c->m_byte_length == 0)
+ 	    {
+ 	      move_to_column (&column, start_column, true);
+ 	      m_text_or_html.colorize_text_for_fixit_delete ();
+ 	      for (; column <= finish_column; column++)
+ 		m_text_or_html.add_character ('-');
+ 	      m_text_or_html.colorize_text_ensure_normal ();
+ 	    }
+ 	  /* Print the replacement text.  REPLACE also covers
+ 	     removals, so only do this extra work (potentially starting
+ 	     a new line) if we have actual replacement text.  */
+ 	  if (c->m_byte_length > 0)
+ 	    {
+ 	      move_to_column (&column, start_column, true);
+ 	      m_text_or_html.colorize_text_for_fixit_insert ();
+ 	      m_text_or_html.add_text (c->m_text);
+ 	      m_text_or_html.colorize_text_ensure_normal ();
+ 	      column += c->m_display_cols;
+ 	    }
+ 	}
+     }
+ 
+   /* Add a trailing newline, if necessary.  */
+   move_to_column (&column, 1 + m_layout.m_x_offset_display, false);
+ }
+ 
+ /* Return true if (ROW/COLUMN) is within a range of the layout.
+    If it returns true, OUT_STATE is written to, with the
+    range index, and whether we should draw the caret at
+    (ROW/COLUMN) (as opposed to an underline).  COL_UNIT controls
+    whether all inputs and outputs are in bytes or display column units.  */
+ 
+ bool
+ layout::get_state_at_point (/* Inputs.  */
+ 			    linenum_type row, int column,
+ 			    int first_non_ws, int last_non_ws,
+ 			    enum column_unit col_unit,
+ 			    /* Outputs.  */
+ 			    point_state *out_state) const
+ {
+   layout_range *range;
+   int i;
+   FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+     {
+       if (range->m_range_display_kind == SHOW_LINES_WITHOUT_RANGE)
+ 	/* Bail out early, so that such ranges don't affect underlining or
+ 	   source colorization.  */
+ 	continue;
+ 
+       if (range->contains_point (row, column, col_unit))
+ 	{
+ 	  out_state->range_idx = i;
+ 
+ 	  /* Are we at the range's caret?  is it visible? */
+ 	  out_state->draw_caret_p = false;
+ 	  if (range->m_range_display_kind == SHOW_RANGE_WITH_CARET
+ 	      && row == range->m_caret.m_line
+ 	      && column == range->m_caret.m_columns[col_unit])
+ 	    out_state->draw_caret_p = true;
+ 
+ 	  /* Within a multiline range, don't display any underline
+ 	     in any leading or trailing whitespace on a line.
+ 	     We do display carets, however.  */
+ 	  if (!out_state->draw_caret_p)
+ 	    if (column < first_non_ws || column > last_non_ws)
+ 	      return false;
+ 
+ 	  /* We are within a range.  */
+ 	  return true;
+ 	}
+     }
+ 
+   return false;
+ }
+ 
+ /* Helper function for use by layout::print_line when printing the
+    annotation line under the source line.
+    Get the display column beyond the rightmost one that could contain a caret
+    or range marker, given that we stop rendering at trailing whitespace.
+    ROW is the source line within the given file.
+    CARET_COLUMN is the display column of range 0's caret.
+    LAST_NON_WS_COLUMN is the last display column containing a non-whitespace
+    character of source (as determined when printing the source line).  */
+ 
+ int
+ layout::get_x_bound_for_row (linenum_type row, int caret_column,
+ 			     int last_non_ws_column) const
+ {
+   int result = caret_column + 1;
+ 
+   layout_range *range;
+   int i;
+   FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+     {
+       if (row >= range->m_start.m_line)
+ 	{
+ 	  if (range->m_finish.m_line == row)
+ 	    {
+ 	      /* On the final line within a range; ensure that
+ 		 we render up to the end of the range.  */
+ 	      const int disp_col = range->m_finish.m_columns[CU_DISPLAY_COLS];
+ 	      if (result <= disp_col)
+ 		result = disp_col + 1;
+ 	    }
+ 	  else if (row < range->m_finish.m_line)
+ 	    {
+ 	      /* Within a multiline range; ensure that we render up to the
+ 		 last non-whitespace column.  */
+ 	      if (result <= last_non_ws_column)
+ 		result = last_non_ws_column + 1;
+ 	    }
+ 	}
+     }
+ 
+   return result;
+ }
+ 
+ /* Given *COLUMN as an x-coordinate, print spaces to position
+    successive output at DEST_COLUMN, printing a newline if necessary,
+    and updating *COLUMN.  If ADD_LEFT_MARGIN, then print the (empty)
+    left margin after any newline.  */
+ 
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::move_to_column (int *column,
+ 				      int dest_column,
+ 				      bool add_left_margin)
+ {
+   /* Start a new line if we need to.  */
+   if (*column > dest_column)
+     {
+       end_line ();
+       if (add_left_margin)
+ 	start_annotation_line (margin_kind::normal);
+       *column = 1 + m_layout.m_x_offset_display;
+     }
+ 
+   while (*column < dest_column)
+     {
+       /* For debugging column issues, it can be helpful to replace this
+ 	 add_space call with
+ 	   m_text_or_html.add_character ('0' + (*column % 10));
+ 	 to visualize the changing value of "*column".  */
+       m_text_or_html.add_space ();
+       (*column)++;
+     }
+ }
+ 
+ /* For debugging layout issues, render a ruler giving column numbers
+    (after the 1-column indent).  */
+ 
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::show_ruler (int max_column)
+ {
+   m_text_or_html.push_html_tag_with_class("thead", "ruler", false);
+ 
+   /* Hundreds.  */
+   if (max_column > 99)
+     {
+       start_annotation_line (margin_kind::ruler);
+       for (int column = 1 + m_layout.m_x_offset_display;
+ 	   column <= max_column;
+ 	   ++column)
+ 	if (column % 10 == 0)
+ 	  m_text_or_html.add_character ('0' + (column / 100) % 10);
+ 	else
+ 	  m_text_or_html.add_space ();
+       end_line ();
+     }
+ 
+   /* Tens.  */
+   start_annotation_line (margin_kind::ruler);
+   for (int column = 1 + m_layout.m_x_offset_display;
+        column <= max_column;
+        ++column)
+     if (column % 10 == 0)
+       m_text_or_html.add_character ('0' + (column / 10) % 10);
+     else
+       m_text_or_html.add_space ();
+   end_line ();
+ 
+   /* Units.  */
+   start_annotation_line (margin_kind::ruler);
+   for (int column = 1 + m_layout.m_x_offset_display;
+        column <= max_column;
+        ++column)
+     m_text_or_html.add_character ('0' + (column % 10));
+   end_line ();
+ 
+   m_text_or_html.pop_html_tag("thead"); // thead
+ }
+ 
+ /* Print leading fix-its (for new lines inserted before the source line)
+    then the source line, followed by an annotation line
+    consisting of any caret/underlines, then any fixits.
+    If the source line can't be read, print nothing.  */
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::print_line (linenum_type row)
+ {
+   typename TextOrHtml::auto_check_tag_nesting sentinel (m_text_or_html);
+ 
+   diagnostics::char_span line
+     = m_layout.m_file_cache.get_source_line (m_layout.m_exploc.file, row);
+   if (!line)
+     return;
+ 
+   print_any_right_to_left_edge_lines ();
+   print_leading_fixits (row);
+   const line_bounds lbounds
+     = print_source_line (row, line.get_buffer (), line.length ());
+   if (m_layout.should_print_annotation_line_p (row))
+     print_annotation_line (row, lbounds);
+   if (get_options ().show_labels_p)
+     print_any_labels (row);
+   print_trailing_fixits (row);
+ }
+ 
+ /* If there's a link column in the RHS, print something like this:
+    "                                           │\n"
+    "┌──────────────────────────────────────────┘\n"
+    showing the link entering at the top right and emerging
+    at the bottom left.  */
+ 
+ template<typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::print_any_right_to_left_edge_lines ()
+ {
+   if (m_link_rhs_column == -1)
+     /* Can also happen if the out-edge had UNKNOWN_LOCATION.  */
+     return;
+ 
+   gcc_assert (get_options ().show_event_links_p);
+ 
+   /* Print the line with "|".  */
+   start_annotation_line (margin_kind::normal);
+ 
+   int column = 1 + m_layout.m_x_offset_display;
+   move_to_column (&column, m_link_rhs_column, true);
+   m_text_or_html.colorize_text_for_cfg_edge ();
+   const cppchar_t down= get_theme ().get_cppchar
+     (text_art::theme::cell_kind::CFG_DOWN);
+   m_text_or_html.add_character (down);
+   end_line ();
+ 
+   /* Print the line with "┌──────────────────────────────────────────┘".  */
+   m_link_lhs_state = link_lhs_state::rewinding_to_lhs;
+   start_annotation_line (margin_kind::normal);
+   m_text_or_html.colorize_text_for_cfg_edge ();
+   const cppchar_t left= get_theme ().get_cppchar
+     (text_art::theme::cell_kind::CFG_LEFT);
+   for (int column = 1 + m_layout.m_x_offset_display;
+        column < m_link_rhs_column;
+        ++column)
+     m_text_or_html.add_character (left);
+   const cppchar_t from_down_to_left = get_theme ().get_cppchar
+     (text_art::theme::cell_kind::CFG_FROM_DOWN_TO_LEFT);
+   m_text_or_html.add_character (from_down_to_left);
+   end_line ();
+ 
+   /* We now have a link line on the LHS,
+      and no longer have one on the RHS.  */
+   m_link_lhs_state = link_lhs_state::at_lhs;
+   m_link_rhs_column = -1;
+ }
+ 
+ template<typename TextOrHtml>
+ layout_printer<TextOrHtml>::layout_printer (TextOrHtml &text_or_html,
+ 				      const layout &layout,
+ 				      bool is_diagnostic_path)
+ : m_text_or_html (text_or_html),
+   m_layout (layout),
+   m_is_diagnostic_path (is_diagnostic_path),
+   m_was_in_range_p (false),
+   m_last_range_idx (0),
+   m_link_lhs_state (link_lhs_state::none),
+   m_link_rhs_column (-1)
+ {
+   if (get_options ().show_event_links_p)
+     if (auto effect_info = m_layout.m_effect_info)
+       if (effect_info->m_leading_in_edge_column)
+ 	m_link_rhs_column = effect_info->m_leading_in_edge_column;
+ }
+ 
+ } /* End of anonymous namespace.  */
+ 
+ /* If LOC is within the spans of lines that will already be printed for
+    this gcc_rich_location, then add it as a secondary location and return true.
+ 
+    Otherwise return false.
+ 
+    Use POLICY for determining how spans of lines would be printed.  */
+ 
+ bool
+ gcc_rich_location::
+ add_location_if_nearby (const diagnostics::source_print_policy &policy,
+ 			location_t loc,
+ 			bool restrict_to_current_line_spans,
+ 			const range_label *label)
+ {
+   /* Use the layout location-handling logic to sanitize LOC,
+      filtering it to the current line spans within a temporary
+      layout instance.  */
+ 
+   layout layout (policy, *this);
+   location_range loc_range;
+   loc_range.m_loc = loc;
+   loc_range.m_range_display_kind = SHOW_RANGE_WITHOUT_CARET;
+   loc_range.m_label = nullptr;
+   if (!layout.maybe_add_location_range (&loc_range, 0,
+ 					restrict_to_current_line_spans))
+     return false;
+ 
+   add_range (loc, SHOW_RANGE_WITHOUT_CARET, label);
+   return true;
+ }
+ 
+ bool
+ gcc_rich_location::
+ add_location_if_nearby (const diagnostics::context &dc,
+ 			location_t loc,
+ 			bool restrict_to_current_line_spans,
+ 			const range_label *label)
+ {
+   diagnostics::source_print_policy
+     source_policy (dc,
+ 		   dc.get_source_printing_options ());
+   return add_location_if_nearby (source_policy, loc,
+ 				 restrict_to_current_line_spans, label);
+ }
+ 
+ namespace diagnostics {
+ 
+ /* As per diagnostics::source_print_policy::print, but don't print anything
+    if source printing is disabled, or if the location hasn't changed.  */
+ 
+ void
+ context::maybe_show_locus (const rich_location &richloc,
+ 			   const source_printing_options &opts,
+ 			   enum kind diagnostic_kind,
+ 			   pretty_printer &pp,
+ 			   source_effect_info *effects)
+ {
+   const location_t loc = richloc.get_loc ();
+   /* Do nothing if source-printing has been disabled.  */
+   if (!opts.enabled)
+     return;
+ 
+   /* Don't attempt to print source for UNKNOWN_LOCATION and for builtins.  */
+   if (loc <= BUILTINS_LOCATION)
+     return;
+ 
+   /* Don't print the same source location twice in a row, unless we have
+      fix-it hints, or multiple locations, or a label.  */
+   if (loc == m_last_location
+       && richloc.get_num_fixit_hints () == 0
+       && richloc.get_num_locations () == 1
+       && richloc.get_range (0)->m_label == nullptr)
+     return;
+ 
+   m_last_location = loc;
+ 
+   source_print_policy source_policy (*this, opts);
+   source_policy.print (pp, richloc, diagnostic_kind, effects);
+ }
+ 
+ /* As above, but print in HTML form to XP.
+    If non-null, use LABEL_WRITER when writing labelled ranges.  */
+ 
+ void
+ context::maybe_show_locus_as_html (const rich_location &richloc,
+ 				   const source_printing_options &opts,
+ 				   enum kind diagnostic_kind,
+ 				   xml::printer &xp,
+ 				   source_effect_info *effects,
+ 				   html_label_writer *label_writer)
+ {
+   const location_t loc = richloc.get_loc ();
+   /* Do nothing if source-printing has been disabled.  */
+   if (!opts.enabled)
+     return;
+ 
+   /* Don't attempt to print source for UNKNOWN_LOCATION and for builtins.  */
+   if (loc <= BUILTINS_LOCATION)
+     return;
+ 
+   /* Don't print the same source location twice in a row, unless we have
+      fix-it hints, or multiple locations, or a label.  */
+   if (loc == m_last_location
+       && richloc.get_num_fixit_hints () == 0
+       && richloc.get_num_locations () == 1
+       && richloc.get_range (0)->m_label == nullptr)
+     return;
+ 
+   m_last_location = loc;
+ 
+   source_print_policy source_policy (*this, opts);
+   source_policy.print_as_html (xp, richloc, diagnostic_kind, effects,
+ 			       label_writer);
+ }
+ 
+ source_print_policy::
+ source_print_policy (const context &dc)
+ : m_options (dc.m_source_printing),
+   m_location_policy (dc),
+   m_text_start_span_cb (dc.m_text_callbacks.m_text_start_span),
+   m_html_start_span_cb (dc.m_text_callbacks.m_html_start_span),
+   m_file_cache (dc.get_file_cache ()),
+   m_diagram_theme (dc.get_diagram_theme ()),
+   m_escape_format (dc.get_escape_format ())
+ {
+ }
+ 
+ source_print_policy::source_print_policy (const context &dc,
+ 					  const source_printing_options &opts)
+ : m_options (opts),
+   m_location_policy (dc),
+   m_text_start_span_cb (dc.m_text_callbacks.m_text_start_span),
+   m_html_start_span_cb (dc.m_text_callbacks.m_html_start_span),
+   m_file_cache (dc.get_file_cache ()),
+   m_diagram_theme (dc.get_diagram_theme ()),
+   m_escape_format (dc.get_escape_format ())
+ {
+ }
+ 
+ /* Print to PP the physical source code corresponding to the location(s)
+    in RICHLOC, with additional annotations, as if for a diagnostic of the
+    given DIAGNOSTIC_KIND.
+    If EFFECTS is non-null, then use and update it.  */
+ 
+ void
+ source_print_policy::print (pretty_printer &pp,
+ 			    const rich_location &richloc,
+ 			    enum kind diagnostic_kind,
+ 			    source_effect_info *effects) const
+ {
+   layout layout (*this, richloc, effects);
+   colorizer col (pp, richloc, diagnostic_kind);
+   to_text text_or_html (pp, col);
+   layout_printer<to_text> lp (text_or_html, layout,
+ 			      diagnostic_kind == diagnostics::kind::path);
+   lp.print (*this);
+ }
+ 
+ /* As above, but print in HTML form to XP.
+    If non-null, use LABEL_WRITER when writing labelled ranges.  */
+ 
+ void
+ source_print_policy::print_as_html (xml::printer &xp,
+ 				    const rich_location &richloc,
+ 				    enum kind diagnostic_kind,
+ 				    source_effect_info *effects,
+ 				    html_label_writer *label_writer) const
+ {
+   layout layout (*this, richloc, effects);
+   to_html text_or_html (xp, &richloc, label_writer);
+   layout_printer<to_html> lp (text_or_html, layout,
+ 			      diagnostic_kind == diagnostics::kind::path);
+   xml::auto_check_tag_nesting sentinel (xp);
+   lp.print (*this);
+ }
+ 
+ } // namespace diagnostics
+ 
+ template <typename TextOrHtml>
+ void
+ layout_printer<TextOrHtml>::
+ print (const diagnostics::source_print_policy &source_policy)
+ {
+   typename TextOrHtml::auto_check_tag_nesting sentinel (m_text_or_html);
+ 
+   m_text_or_html.push_html_tag_with_class ("table", "locus", false);
+ 
+   if (get_options ().show_ruler_p)
+     show_ruler (m_layout.m_x_offset_display + get_options ().max_width);
+ 
+   for (int line_span_idx = 0; line_span_idx < m_layout.get_num_line_spans ();
+        line_span_idx++)
+     {
+       const line_span *line_span = m_layout.get_line_span (line_span_idx);
+       if (get_options ().show_line_numbers_p)
+ 	{
+ 	  /* With line numbers, we should show whenever the line-numbering
+ 	     "jumps".  */
+ 	  if (line_span_idx > 0)
+ 	    print_gap_in_line_numbering ();
+ 	}
+       else
+ 	{
+ 	  /* Without line numbers, we print headings for some line spans.  */
+ 	  if (m_layout.print_heading_for_line_span_index_p (line_span_idx))
+ 	    {
+ 	      expanded_location exploc
+ 		= m_layout.get_expanded_location (line_span);
+ 	      const diagnostics::location_print_policy &
+ 		loc_policy = source_policy.get_location_policy ();
+ 	      m_text_or_html.invoke_start_span_fn (source_policy, loc_policy, exploc);
+ 	    }
+ 	}
+ 
+       m_text_or_html.push_html_tag_with_class ("tbody", "line-span", false);
+ 
+       /* Iterate over the lines within this span (using linenum_arith_t to
+ 	 avoid overflow with 0xffffffff causing an infinite loop).  */
+       linenum_arith_t last_line = line_span->get_last_line ();
+       for (linenum_arith_t row = line_span->get_first_line ();
+ 	   row <= last_line; row++)
+ 	print_line (row);
+ 
+       m_text_or_html.pop_html_tag ("tbody");
+     }
+ 
+   if (auto effect_info = m_layout.m_effect_info)
+     effect_info->m_trailing_out_edge_column = m_link_rhs_column;
+ 
+   m_text_or_html.pop_html_tag ("table");
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace selftest {
+ 
+ using test_context = diagnostics::selftest::test_context;
+ 
+ using line_table_case = ::selftest::line_table_case;
+ using line_table_test = ::selftest::line_table_test;
+ using temp_source_file = ::selftest::temp_source_file;
+ 
+ static std::unique_ptr<xml::node>
+ make_element_for_locus (const rich_location &rich_loc,
+ 			enum kind kind,
+ 			diagnostics::context &dc)
+ {
+   dc.m_last_location = UNKNOWN_LOCATION;
+ 
+   xml::element wrapper ("wrapper", false);
+   xml::printer xp (wrapper);
+   dc.maybe_show_locus_as_html (rich_loc,
+ 			       dc.get_source_printing_options (),
+ 			       kind,
+ 			       xp,
+ 			       nullptr,
+ 			       nullptr); // label_writer
+   if (wrapper.m_children.size () > 0)
+     return std::move (wrapper.m_children[0]);
+   else
+     return nullptr;
+ }
+ 
+ static label_text
+ make_raw_html_for_locus (const rich_location &rich_loc,
+ 			 enum kind kind,
+ 			 diagnostics::context &dc)
+ {
+   auto node = make_element_for_locus (rich_loc, kind, dc);
+   pretty_printer pp;
+   if (node)
+     node->write_as_xml (&pp, 0, true);
+   return label_text::take (xstrdup (pp_formatted_text (&pp)));
+ }
+ 
+ /* Selftests for diagnostic_show_locus.  */
+ 
+ source_printing_fixture::
+ source_printing_fixture (const line_table_case &case_,
+ 			 const char *content)
+ : m_content (content),
+   m_tmp_source_file (SELFTEST_LOCATION, ".c", content),
+   m_ltt (case_),
+   m_fc ()
+ {
+   linemap_add (line_table, LC_ENTER, false,
+ 	       m_tmp_source_file.get_filename (), 1);
+ }
+ 
+ /* Populate a char_display_policy based on DC and RICHLOC.  */
+ 
+ static char_display_policy
+ make_char_policy (const diagnostics::context &dc,
+ 		  const rich_location &richloc)
+ {
+   diagnostics::source_print_policy source_policy (dc);
+   return ::make_char_policy (source_policy, richloc);
+ }
+ 
+ /* Verify that cpp_display_width correctly handles escaping.  */
+ 
+ static void
+ test_display_widths ()
+ {
+   gcc_rich_location richloc (UNKNOWN_LOCATION);
+ 
+   /* U+03C0 "GREEK SMALL LETTER PI".  */
+   const char *pi = "\xCF\x80";
+   /* U+1F642 "SLIGHTLY SMILING FACE".  */
+   const char *emoji = "\xF0\x9F\x99\x82";
+   /* Stray trailing byte of a UTF-8 character.  */
+   const char *stray = "\xBF";
+   /* U+10FFFF.  */
+   const char *max_codepoint = "\xF4\x8F\xBF\xBF";
+ 
+   /* No escaping.  */
+   {
+     test_context dc;
+     char_display_policy policy (make_char_policy (dc, richloc));
+     ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 1);
+     ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 2);
+     ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 1);
+     /* Don't check width of U+10FFFF; it's in a private use plane.  */
+   }
+ 
+   richloc.set_escape_on_output (true);
+ 
+   {
+     test_context dc;
+     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
+     char_display_policy policy (make_char_policy (dc, richloc));
+     ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
+     ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 9);
+     ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 4);
+     ASSERT_EQ (cpp_display_width (max_codepoint, strlen (max_codepoint),
+ 				  policy),
+ 	       strlen ("<U+10FFFF>"));
+   }
+ 
+   {
+     test_context dc;
+     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
+     char_display_policy policy (make_char_policy (dc, richloc));
+     ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
+     ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 16);
+     ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 4);
+     ASSERT_EQ (cpp_display_width (max_codepoint, strlen (max_codepoint),
+ 				  policy),
+ 	       16);
+   }
+ }
+ 
+ /* For precise tests of the layout, make clear where the source line will
+    start.  test_left_margin sets the total byte count from the left side of the
+    screen to the start of source lines, after the line number and the separator,
+    which consists of the three characters " | ".  */
+ static const int test_linenum_sep = 3;
+ static const int test_left_margin = 7;
+ 
+ /* Helper function for test_layout_x_offset_display_utf8().  */
+ static void
+ test_offset_impl (int caret_byte_col, int max_width,
+ 		  int expected_x_offset_display,
+ 		  int left_margin = test_left_margin)
+ {
+   test_context dc;
+   auto &source_printing_opts = dc.get_source_printing_options ();
+   source_printing_opts.max_width = max_width;
+   /* min_margin_width sets the minimum space reserved for
+      the line number plus one space after.  */
+   source_printing_opts.min_margin_width = left_margin - test_linenum_sep + 1;
+   dc.show_line_numbers (true);
+   diagnostics::source_print_policy source_policy (dc);
+   rich_location richloc (line_table,
+ 			 linemap_position_for_column (line_table,
+ 						      caret_byte_col));
+   layout test_layout (source_policy, richloc, nullptr);
+   ASSERT_EQ (left_margin - test_linenum_sep,
+ 	     test_layout.get_linenum_width ());
+   ASSERT_EQ (expected_x_offset_display,
+ 	     test_layout.get_x_offset_display ());
+ }
+ 
+ /* Test that layout::calculate_x_offset_display() works.  */
+ static void
+ test_layout_x_offset_display_utf8 (const line_table_case &case_)
+ {
+ 
+   const char *content
+     = "This line is very long, so that we can use it to test the logic for "
+       "clipping long lines.  Also this: \xf0\x9f\x98\x82\xf0\x9f\x98\x82 is a "
+       "pair of emojis that occupies 8 bytes and 4 display columns, starting at "
+       "column #102.\n";
+ 
+   /* Number of bytes in the line, subtracting one to remove the newline.  */
+   const int line_bytes = strlen (content) - 1;
+ 
+   /* Number of display columns occupied by the line; each of the 2 emojis
+      takes up 2 fewer display columns than it does bytes.  */
+   const int line_display_cols = line_bytes - 2*2;
+ 
+   /* The column of the first emoji.  Byte or display is the same as there are
+      no multibyte characters earlier on the line.  */
+   const int emoji_col = 102;
+ 
+   source_printing_fixture f (case_, content);
+ 
+   linemap_add (line_table, LC_ENTER, false, f.get_filename (), 1);
+ 
+   location_t line_end = linemap_position_for_column (line_table, line_bytes);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   ASSERT_STREQ (f.get_filename (), LOCATION_FILE (line_end));
+   ASSERT_EQ (1, LOCATION_LINE (line_end));
+   ASSERT_EQ (line_bytes, LOCATION_COLUMN (line_end));
+ 
+   diagnostics::char_span lspan = f.m_fc.get_source_line (f.get_filename (), 1);
+   ASSERT_EQ (line_display_cols,
+ 	     cpp_display_width (lspan.get_buffer (), lspan.length (),
+ 				def_policy ()));
+   ASSERT_EQ (line_display_cols,
+ 	     location_compute_display_column (f.m_fc,
+ 					      expand_location (line_end),
+ 					      def_policy ()));
+   ASSERT_EQ (0, memcmp (lspan.get_buffer () + (emoji_col - 1),
+ 			"\xf0\x9f\x98\x82\xf0\x9f\x98\x82", 8));
+ 
+   /* (caret_byte, max_width, expected_x_offset_display, [left_margin])  */
+ 
+   /* No constraint on the width -> no offset.  */
+   test_offset_impl (emoji_col, 0, 0);
+ 
+   /* Caret is before the beginning -> no offset.  */
+   test_offset_impl (0, 100, 0);
+ 
+   /* Caret is past the end of the line -> no offset.  */
+   test_offset_impl (line_bytes+1, 100, 0);
+ 
+   /* Line fits in the display -> no offset.  */
+   test_offset_impl (line_bytes, line_display_cols + test_left_margin, 0);
+   test_offset_impl (emoji_col, line_display_cols + test_left_margin, 0);
+ 
+   /* Line is too long for the display but caret location is OK
+      anyway -> no offset.  */
+   static const int small_width = 24;
+   test_offset_impl (1, small_width, 0);
+ 
+   /* Width constraint is very small -> no offset.  */
+   test_offset_impl (emoji_col, CARET_LINE_MARGIN, 0);
+ 
+   /* Line would be offset, but due to large line numbers, offsetting
+      would remove the whole line -> no offset.  */
+   static const int huge_left_margin = 100;
+   test_offset_impl (emoji_col, huge_left_margin, 0, huge_left_margin);
+ 
+   /* Line is the same length as the display, but the line number makes it too
+      long, so offset is required.  Caret is at the end so padding on the right
+      is not in effect.  */
+   for (int excess = 1; excess <= 3; ++excess)
+     test_offset_impl (line_bytes, line_display_cols + test_left_margin - excess,
+ 		      excess);
+ 
+   /* Line is much too long for the display, caret is near the end ->
+      offset should be such that the line fits in the display and caret
+      remains the same distance from the end that it was.  */
+   for (int caret_offset = 0, max_offset = MIN (CARET_LINE_MARGIN, 10);
+        caret_offset <= max_offset; ++caret_offset)
+     test_offset_impl (line_bytes - caret_offset, small_width,
+ 		      line_display_cols + test_left_margin - small_width);
+ 
+   /* As previous case but caret is closer to the middle; now we want it to end
+      up CARET_LINE_MARGIN bytes from the end.  */
+   ASSERT_GT (line_display_cols - emoji_col, CARET_LINE_MARGIN);
+   test_offset_impl (emoji_col, small_width,
+ 		    emoji_col + test_left_margin
+ 		    - (small_width - CARET_LINE_MARGIN));
+ 
+   /* Test that the source line is offset as expected when printed.  */
+   {
+     test_context dc;
+     auto &source_printing_opts = dc.get_source_printing_options ();
+     source_printing_opts.max_width = small_width - 6;
+     source_printing_opts.min_margin_width
+       = test_left_margin - test_linenum_sep + 1;
+     dc.show_line_numbers (true);
+     dc.show_ruler (true);
+     diagnostics::source_print_policy policy (dc);
+     rich_location richloc (line_table,
+ 			   linemap_position_for_column (line_table,
+ 							emoji_col));
+     layout test_layout (policy, richloc, nullptr);
+     colorizer col (*dc.get_reference_printer (),
+ 		   richloc, diagnostics::kind::error);
+     diagnostics::to_text text_or_html (*dc.get_reference_printer (), col);
+     layout_printer<diagnostics::to_text> lp (text_or_html, test_layout, false);
+     lp.print (policy);
+     ASSERT_STREQ ("     |         1         \n"
+ 		  "     |         1         \n"
+ 		  "     | 234567890123456789\n"
+ 		  "   1 | \xf0\x9f\x98\x82\xf0\x9f\x98\x82 is a pair of emojis "
+ 		  "that occupies 8 bytes and 4 display columns, starting at "
+ 		  "column #102.\n"
+ 		  "     | ^\n",
+ 		  pp_formatted_text (dc.get_reference_printer ()));
+   }
+ 
+   /* Similar to the previous example, but now the offset called for would split
+      the first emoji in the middle of the UTF-8 sequence.  Check that we replace
+      it with a padding space in this case.  */
+   {
+     test_context dc;
+     auto &source_printing_opts = dc.get_source_printing_options ();
+     source_printing_opts.max_width = small_width - 5;
+     source_printing_opts.min_margin_width
+       = test_left_margin - test_linenum_sep + 1;
+     dc.show_line_numbers (true);
+     dc.show_ruler (true);
+     diagnostics::source_print_policy policy (dc);
+     rich_location richloc (line_table,
+ 			   linemap_position_for_column (line_table,
+ 							emoji_col + 2));
+     layout test_layout (dc, richloc, nullptr);
+     colorizer col (*dc.get_reference_printer (),
+ 		   richloc, diagnostics::kind::error);
+     diagnostics::to_text text_or_html (*dc.get_reference_printer (), col);
+     layout_printer<diagnostics::to_text> lp (text_or_html, test_layout, false);
+     lp.print (policy);
+     ASSERT_STREQ ("     |        1         1 \n"
+ 		  "     |        1         2 \n"
+ 		  "     | 3456789012345678901\n"
+ 		  "   1 |  \xf0\x9f\x98\x82 is a pair of emojis "
+ 		  "that occupies 8 bytes and 4 display columns, starting at "
+ 		  "column #102.\n"
+ 		  "     |  ^\n",
+ 		  pp_formatted_text (dc.get_reference_printer ()));
+   }
+ 
+ }
+ 
+ static void
+ test_layout_x_offset_display_tab (const line_table_case &case_)
+ {
+   const char *content
+     = "This line is very long, so that we can use it to test the logic for "
+       "clipping long lines.  Also this: `\t' is a tab that occupies 1 byte and "
+       "a variable number of display columns, starting at column #103.\n";
+ 
+   /* Number of bytes in the line, subtracting one to remove the newline.  */
+   const int line_bytes = strlen (content) - 1;
+ 
+  /* The column where the tab begins.  Byte or display is the same as there are
+     no multibyte characters earlier on the line.  */
+   const int tab_col = 103;
+ 
+   /* Effective extra size of the tab beyond what a single space would have taken
+      up, indexed by tabstop.  */
+   static const int num_tabstops = 11;
+   int extra_width[num_tabstops];
+   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
+     {
+       const int this_tab_size = tabstop - (tab_col - 1) % tabstop;
+       extra_width[tabstop] = this_tab_size - 1;
+     }
+   /* Example of this calculation: if tabstop is 10, the tab starting at column
+      #103 has to expand into 8 spaces, covering columns 103-110, so that the
+      next character is at column #111.  So it takes up 7 more columns than
+      a space would have taken up.  */
+   ASSERT_EQ (7, extra_width[10]);
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+   diagnostics::file_cache fc;
+   line_table_test ltt (case_);
+ 
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+ 
+   location_t line_end = linemap_position_for_column (line_table, line_bytes);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Check that cpp_display_width handles the tabs as expected.  */
+   diagnostics::char_span lspan = fc.get_source_line (tmp.get_filename (), 1);
+   ASSERT_EQ ('\t', *(lspan.get_buffer () + (tab_col - 1)));
+   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
+     {
+       cpp_char_column_policy policy (tabstop, cpp_wcwidth);
+       ASSERT_EQ (line_bytes + extra_width[tabstop],
+ 		 cpp_display_width (lspan.get_buffer (), lspan.length (),
+ 				    policy));
+       ASSERT_EQ (line_bytes + extra_width[tabstop],
+ 		 location_compute_display_column (fc,
+ 						  expand_location (line_end),
+ 						  policy));
+     }
+ 
+   /* Check that the tab is expanded to the expected number of spaces.  */
+   rich_location richloc (line_table,
+ 			 linemap_position_for_column (line_table,
+ 						      tab_col + 1));
+   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
+     {
+       test_context dc;
+       dc.m_tabstop = tabstop;
+       diagnostics::source_print_policy policy (dc);
+       layout test_layout (policy, richloc, nullptr);
+       colorizer col (*dc.get_reference_printer (),
+ 		     richloc, diagnostics::kind::error);
+       diagnostics::to_text text_or_html (*dc.get_reference_printer (), col);
+       layout_printer<diagnostics::to_text> lp
+ 	(text_or_html, test_layout, false);
+       lp.print (policy);
+       const char *out = pp_formatted_text (dc.get_reference_printer ());
+       ASSERT_EQ (nullptr, strchr (out, '\t'));
+       const char *left_quote = strchr (out, '`');
+       const char *right_quote = strchr (out, '\'');
+       ASSERT_NE (nullptr, left_quote);
+       ASSERT_NE (nullptr, right_quote);
+       ASSERT_EQ (right_quote - left_quote, extra_width[tabstop] + 2);
+     }
+ 
+   /* Check that the line is offset properly and that the tab is broken up
+      into the expected number of spaces when it is the last character skipped
+      over.  */
+   for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
+     {
+       test_context dc;
+       dc.m_tabstop = tabstop;
+       static const int small_width = 24;
+       auto &source_printing_opts = dc.get_source_printing_options ();
+       source_printing_opts.max_width = small_width - 4;
+       source_printing_opts.min_margin_width
+ 	= test_left_margin - test_linenum_sep + 1;
+       dc.show_line_numbers (true);
+       diagnostics::source_print_policy policy (dc);
+       layout test_layout (policy, richloc, nullptr);
+       colorizer col (*dc.get_reference_printer (),
+ 		     richloc, diagnostics::kind::error);
+       diagnostics::to_text text_or_html (*dc.get_reference_printer (), col);
+       layout_printer<diagnostics::to_text> lp
+ 	(text_or_html, test_layout, false);
+       lp.print (policy);
+ 
+       /* We have arranged things so that two columns will be printed before
+ 	 the caret.  If the tab results in more than one space, this should
+ 	 produce two spaces in the output; otherwise, it will be a single space
+ 	 preceded by the opening quote before the tab character.  */
+       const char *output1
+ 	= "   1 |   ' is a tab that occupies 1 byte and a variable number of "
+ 	  "display columns, starting at column #103.\n"
+ 	  "     |   ^\n";
+       const char *output2
+ 	= "   1 | ` ' is a tab that occupies 1 byte and a variable number of "
+ 	  "display columns, starting at column #103.\n"
+ 	  "     |   ^\n";
+       const char *expected_output = (extra_width[tabstop] ? output1 : output2);
+       ASSERT_STREQ (expected_output, pp_formatted_text (dc.get_reference_printer ()));
+     }
+ }
+ 
+ 
+ /* Verify that diagnostic_show_locus works sanely on UNKNOWN_LOCATION.  */
+ 
+ static void
+ test_diagnostic_show_locus_unknown_location ()
+ {
+   test_context dc;
+   rich_location richloc (line_table, UNKNOWN_LOCATION);
+   ASSERT_STREQ ("", dc.test_show_locus (richloc));
+ }
+ 
+ /* Verify that diagnostic_show_locus works sanely for various
+    single-line cases.
+ 
+    All of these work on the following 1-line source file:
+      .0000000001111111
+      .1234567890123456
+      "foo = bar.field;\n"
+    which is set up by test_diagnostic_show_locus_one_liner and calls
+    them.  */
+ 
+ /* Just a caret.  */
+ 
+ static void
+ test_one_liner_simple_caret ()
+ {
+   test_context dc;
+   location_t caret = linemap_position_for_column (line_table, 10);
+   rich_location richloc (line_table, caret);
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		"          ^\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* No column information (column == 0).
+    No annotation line should be printed.  */
+ 
+ static void
+ test_one_liner_no_column ()
+ {
+   test_context dc;
+   location_t caret = linemap_position_for_column (line_table, 0);
+   rich_location richloc (line_table, caret);
+   ASSERT_STREQ (" foo = bar.field;\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Caret and range.  */
+ 
+ static void
+ test_one_liner_caret_and_range ()
+ {
+   test_context dc;
+   location_t caret = linemap_position_for_column (line_table, 10);
+   location_t start = linemap_position_for_column (line_table, 7);
+   location_t finish = linemap_position_for_column (line_table, 15);
+   location_t loc = make_location (caret, start, finish);
+   rich_location richloc (line_table, loc);
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		"       ~~~^~~~~~\n",
+ 		dc.test_show_locus (richloc));
+ 
+   {
+     test_context dc;
+     auto out = make_raw_html_for_locus (richloc, diagnostics::kind::error, dc);
+      ASSERT_STREQ
+        ("<table class=\"locus\">\n"
+ 	"  <tbody class=\"line-span\">\n"
+ 	"    <tr><td class=\"left-margin\"> </td><td class=\"source\">foo = bar.field;</td></tr>\n"
+ 	"    <tr><td class=\"left-margin\"> </td><td class=\"annotation\">      ~~~^~~~~~</td></tr>\n"
+ 	"  </tbody>\n"
+ 	"</table>\n",
+ 	out.get ());
+   }
+   {
+     test_context dc;
+     dc.show_line_numbers (true);
+     auto out = make_raw_html_for_locus (richloc, diagnostics::kind::error, dc);
+      ASSERT_STREQ
+        ("<table class=\"locus\">\n"
+ 	"  <tbody class=\"line-span\">\n"
+ 	"    <tr><td class=\"linenum\">    1</td><td class=\"left-margin\"> </td><td class=\"source\">foo = bar.field;</td></tr>\n"
+ 	"    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">      ~~~^~~~~~</td></tr>\n"
+ 	"  </tbody>\n"
+ 	"</table>\n",
+ 	out.get ());
+   }
+ }
+ 
+ /* Multiple ranges and carets.  */
+ 
+ static void
+ test_one_liner_multiple_carets_and_ranges ()
+ {
+   test_context dc;
+   location_t foo
+     = make_location (linemap_position_for_column (line_table, 2),
+ 		     linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 3));
+   dc.set_caret_char (0, 'A');
+ 
+   location_t bar
+     = make_location (linemap_position_for_column (line_table, 8),
+ 		     linemap_position_for_column (line_table, 7),
+ 		     linemap_position_for_column (line_table, 9));
+   dc.set_caret_char (1, 'B');
+ 
+   location_t field
+     = make_location (linemap_position_for_column (line_table, 13),
+ 		     linemap_position_for_column (line_table, 11),
+ 		     linemap_position_for_column (line_table, 15));
+   dc.set_caret_char (2, 'C');
+ 
+   rich_location richloc (line_table, foo);
+   richloc.add_range (bar, SHOW_RANGE_WITH_CARET);
+   richloc.add_range (field, SHOW_RANGE_WITH_CARET);
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		" ~A~   ~B~ ~~C~~\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Insertion fix-it hint: adding an "&" to the front of "bar.field". */
+ 
+ static void
+ test_one_liner_fixit_insert_before ()
+ {
+   test_context dc;
+   location_t caret = linemap_position_for_column (line_table, 7);
+   rich_location richloc (line_table, caret);
+   richloc.add_fixit_insert_before ("&");
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		"       ^\n"
+ 		"       &\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Insertion fix-it hint: adding a "[0]" after "foo". */
+ 
+ static void
+ test_one_liner_fixit_insert_after ()
+ {
+   test_context dc;
+   location_t start = linemap_position_for_column (line_table, 1);
+   location_t finish = linemap_position_for_column (line_table, 3);
+   location_t foo = make_location (start, start, finish);
+   rich_location richloc (line_table, foo);
+   richloc.add_fixit_insert_after ("[0]");
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		" ^~~\n"
+ 		"    [0]\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Removal fix-it hint: removal of the ".field".
+    Also verify the interaction of pp_set_prefix with rulers and
+    fix-it hints.  */
+ 
+ static void
+ test_one_liner_fixit_remove ()
+ {
+   location_t start = linemap_position_for_column (line_table, 10);
+   location_t finish = linemap_position_for_column (line_table, 15);
+   location_t dot = make_location (start, start, finish);
+   rich_location richloc (line_table, dot);
+   richloc.add_fixit_remove ();
+ 
+   /* Normal.  */
+   {
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  "          ^~~~~~\n"
+ 		  "          ------\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Test of adding a prefix.  */
+   {
+     test_context dc;
+     pp_prefixing_rule (dc.get_reference_printer ()) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+     pp_set_prefix (dc.get_reference_printer (), xstrdup ("TEST PREFIX:"));
+     ASSERT_STREQ ("TEST PREFIX: foo = bar.field;\n"
+ 		  "TEST PREFIX:          ^~~~~~\n"
+ 		  "TEST PREFIX:          ------\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Normal, with ruler.  */
+   {
+     test_context dc;
+     auto &source_printing_opts = dc.get_source_printing_options ();
+     dc.show_ruler (true);
+     source_printing_opts.max_width = 104;
+     ASSERT_STREQ ("          0         0         0         0         0         0         0         0         0         1    \n"
+ 		  "          1         2         3         4         5         6         7         8         9         0    \n"
+ 		  " 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234\n"
+ 		  " foo = bar.field;\n"
+ 		  "          ^~~~~~\n"
+ 		  "          ------\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Test of adding a prefix, with ruler.  */
+   {
+     test_context dc;
+     auto &source_printing_opts = dc.get_source_printing_options ();
+     dc.show_ruler (true);
+     source_printing_opts.max_width = 50;
+     pp_prefixing_rule (dc.get_reference_printer ()) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+     pp_set_prefix (dc.get_reference_printer (), xstrdup ("TEST PREFIX:"));
+     ASSERT_STREQ ("TEST PREFIX:          1         2         3         4         5\n"
+ 		  "TEST PREFIX: 12345678901234567890123456789012345678901234567890\n"
+ 		  "TEST PREFIX: foo = bar.field;\n"
+ 		  "TEST PREFIX:          ^~~~~~\n"
+ 		  "TEST PREFIX:          ------\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Test of adding a prefix, with ruler and line numbers.  */
+   {
+     test_context dc;
+     auto &source_printing_opts = dc.get_source_printing_options ();
+     dc.show_ruler (true);
+     source_printing_opts.max_width = 50;
+     dc.show_line_numbers (true);
+     pp_prefixing_rule (dc.get_reference_printer ()) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+     pp_set_prefix (dc.get_reference_printer (), xstrdup ("TEST PREFIX:"));
+     ASSERT_STREQ ("TEST PREFIX:      |          1         2         3         4         5\n"
+ 		  "TEST PREFIX:      | 12345678901234567890123456789012345678901234567890\n"
+ 		  "TEST PREFIX:    1 | foo = bar.field;\n"
+ 		  "TEST PREFIX:      |          ^~~~~~\n"
+ 		  "TEST PREFIX:      |          ------\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Replace fix-it hint: replacing "field" with "m_field". */
+ 
+ static void
+ test_one_liner_fixit_replace ()
+ {
+   test_context dc;
+   location_t start = linemap_position_for_column (line_table, 11);
+   location_t finish = linemap_position_for_column (line_table, 15);
+   location_t field = make_location (start, start, finish);
+   rich_location richloc (line_table, field);
+   richloc.add_fixit_replace ("m_field");
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		"           ^~~~~\n"
+ 		"           m_field\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Replace fix-it hint: replacing "field" with "m_field",
+    but where the caret was elsewhere.  */
+ 
+ static void
+ test_one_liner_fixit_replace_non_equal_range ()
+ {
+   test_context dc;
+   location_t equals = linemap_position_for_column (line_table, 5);
+   location_t start = linemap_position_for_column (line_table, 11);
+   location_t finish = linemap_position_for_column (line_table, 15);
+   rich_location richloc (line_table, equals);
+   source_range range;
+   range.m_start = start;
+   range.m_finish = finish;
+   richloc.add_fixit_replace (range, "m_field");
+   /* The replacement range is not indicated in the annotation line, so
+      it should be indicated via an additional underline.  */
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		"     ^\n"
+ 		"           -----\n"
+ 		"           m_field\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Replace fix-it hint: replacing "field" with "m_field",
+    where the caret was elsewhere, but where a secondary range
+    exactly covers "field".  */
+ 
+ static void
+ test_one_liner_fixit_replace_equal_secondary_range ()
+ {
+   test_context dc;
+   location_t equals = linemap_position_for_column (line_table, 5);
+   location_t start = linemap_position_for_column (line_table, 11);
+   location_t finish = linemap_position_for_column (line_table, 15);
+   rich_location richloc (line_table, equals);
+   location_t field = make_location (start, start, finish);
+   richloc.add_range (field);
+   richloc.add_fixit_replace (field, "m_field");
+   /* The replacement range is indicated in the annotation line,
+      so it shouldn't be indicated via an additional underline.  */
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		"     ^     ~~~~~\n"
+ 		"           m_field\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Verify that we can use ad-hoc locations when adding fixits to a
+    rich_location.  */
+ 
+ static void
+ test_one_liner_fixit_validation_adhoc_locations ()
+ {
+   /* Generate a range that's too long to be packed, so must
+      be stored as an ad-hoc location (given the defaults
+      of 5 or 7 bits or 0 bits of packed range); 150 columns > 2**7.  */
+   const location_t c7 = linemap_position_for_column (line_table, 7);
+   const location_t c157 = linemap_position_for_column (line_table, 157);
+   const location_t loc = make_location (c7, c7, c157);
+ 
+   if (c157 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   ASSERT_TRUE (IS_ADHOC_LOC (loc));
+ 
+   /* Insert.  */
+   {
+     rich_location richloc (line_table, loc);
+     richloc.add_fixit_insert_before (loc, "test");
+     /* It should not have been discarded by the validator.  */
+     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  "       ^~~~~~~~~~                               "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          \n"
+ 		  "       test\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Remove.  */
+   {
+     rich_location richloc (line_table, loc);
+     source_range range = source_range::from_locations (loc, c157);
+     richloc.add_fixit_remove (range);
+     /* It should not have been discarded by the validator.  */
+     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  "       ^~~~~~~~~~                               "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          \n"
+ 		  "       -----------------------------------------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Replace.  */
+   {
+     rich_location richloc (line_table, loc);
+     source_range range = source_range::from_locations (loc, c157);
+     richloc.add_fixit_replace (range, "test");
+     /* It should not have been discarded by the validator.  */
+     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  "       ^~~~~~~~~~                               "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          \n"
+ 		  "       test\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Test of consolidating insertions at the same location.  */
+ 
+ static void
+ test_one_liner_many_fixits_1 ()
+ {
+   test_context dc;
+   location_t equals = linemap_position_for_column (line_table, 5);
+   rich_location richloc (line_table, equals);
+   for (int i = 0; i < 19; i++)
+     richloc.add_fixit_insert_before ("a");
+   ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		"     ^\n"
+ 		"     aaaaaaaaaaaaaaaaaaa\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Ensure that we can add an arbitrary number of fix-it hints to a
+    rich_location, even if they are not consolidated.  */
+ 
+ static void
+ test_one_liner_many_fixits_2 ()
+ {
+   test_context dc;
+   location_t equals = linemap_position_for_column (line_table, 5);
+   rich_location richloc (line_table, equals);
+   for (int i = 0; i < 19; i++)
+     {
+       location_t loc = linemap_position_for_column (line_table, (i * 2) + 1);
+       richloc.add_fixit_insert_before (loc, "a");
+     }
+   ASSERT_EQ (19, richloc.get_num_fixit_hints ());
+   ASSERT_STREQ (" foo = bar.field;\n"
+ 		"     ^\n"
+ 		" a a a a a a a a a a a a a a a a a a a\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Test of labeling the ranges within a rich_location.  */
+ 
+ static void
+ test_one_liner_labels ()
+ {
+   location_t foo
+     = make_location (linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 3));
+   location_t bar
+     = make_location (linemap_position_for_column (line_table, 7),
+ 		     linemap_position_for_column (line_table, 7),
+ 		     linemap_position_for_column (line_table, 9));
+   location_t field
+     = make_location (linemap_position_for_column (line_table, 11),
+ 		     linemap_position_for_column (line_table, 11),
+ 		     linemap_position_for_column (line_table, 15));
+ 
+   /* Example where all the labels fit on one line.  */
+   {
+     text_range_label label0 ("0");
+     text_range_label label1 ("1");
+     text_range_label label2 ("2");
+     gcc_rich_location richloc (foo, &label0, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+ 
+     {
+       test_context dc;
+       ASSERT_STREQ (" foo = bar.field;\n"
+ 		    " ^~~   ~~~ ~~~~~\n"
+ 		    " |     |   |\n"
+ 		    " 0     1   2\n",
+ 		    dc.test_show_locus (richloc));
+     }
+ 
+     /* Verify that we can disable label-printing.  */
+     {
+       test_context dc;
+       dc.show_labels (false);
+       ASSERT_STREQ (" foo = bar.field;\n"
+ 		    " ^~~   ~~~ ~~~~~\n",
+ 		    dc.test_show_locus (richloc));
+     }
+   }
+ 
+   /* Example where the labels need extra lines.  */
+   {
+     text_range_label label0 ("label 0");
+     text_range_label label1 ("label 1");
+     text_range_label label2 ("label 2");
+     gcc_rich_location richloc (foo, &label0, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+ 
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  " ^~~   ~~~ ~~~~~\n"
+ 		  " |     |   |\n"
+ 		  " |     |   label 2\n"
+ 		  " |     label 1\n"
+ 		  " label 0\n",
+ 		  dc.test_show_locus (richloc));
+ 
+     {
+       test_context dc;
+       dc.show_line_numbers (true);
+       auto out
+ 	= make_raw_html_for_locus (richloc, diagnostics::kind::error, dc);
+       ASSERT_STREQ
+ 	("<table class=\"locus\">\n"
+ 	 "  <tbody class=\"line-span\">\n"
+ 	 "    <tr><td class=\"linenum\">    1</td><td class=\"left-margin\"> </td><td class=\"source\">foo = bar.field;</td></tr>\n"
+ 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">^~~   ~~~ ~~~~~</td></tr>\n"
+ 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">|     |   |</td></tr>\n"
+ 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">|     |   label 2</td></tr>\n"
+ 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">|     label 1</td></tr>\n"
+ 	 "    <tr><td class=\"linenum\">     </td><td class=\"left-margin\"> </td><td class=\"annotation\">label 0</td></tr>\n"
+ 	 "  </tbody>\n"
+ 	 "</table>\n",
+ 	 out.get ());
+     }
+   }
+ 
+   /* Example of boundary conditions: label 0 and 1 have just enough clearance,
+      but label 1 just touches label 2.  */
+   {
+     text_range_label label0 ("aaaaa");
+     text_range_label label1 ("bbbb");
+     text_range_label label2 ("c");
+     gcc_rich_location richloc (foo, &label0, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+ 
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  " ^~~   ~~~ ~~~~~\n"
+ 		  " |     |   |\n"
+ 		  " |     |   c\n"
+ 		  " aaaaa bbbb\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of out-of-order ranges (thus requiring a sort).  */
+   {
+     text_range_label label0 ("0");
+     text_range_label label1 ("1");
+     text_range_label label2 ("2");
+     gcc_rich_location richloc (field, &label0, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+     richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label2);
+ 
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  " ~~~   ~~~ ^~~~~\n"
+ 		  " |     |   |\n"
+ 		  " 2     1   0\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Ensure we don't ICE if multiple ranges with labels are on
+      the same point.  */
+   {
+     text_range_label label0 ("label 0");
+     text_range_label label1 ("label 1");
+     text_range_label label2 ("label 2");
+     gcc_rich_location richloc (bar, &label0, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label2);
+ 
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  "       ^~~\n"
+ 		  "       |\n"
+ 		  "       label 0\n"
+ 		  "       label 1\n"
+ 		  "       label 2\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of out-of-order ranges (thus requiring a sort), where
+      they overlap, and there are multiple ranges on the same point.  */
+   {
+     text_range_label label_0a ("label 0a");
+     text_range_label label_1a ("label 1a");
+     text_range_label label_2a ("label 2a");
+     text_range_label label_0b ("label 0b");
+     text_range_label label_1b ("label 1b");
+     text_range_label label_2b ("label 2b");
+     text_range_label label_0c ("label 0c");
+     text_range_label label_1c ("label 1c");
+     text_range_label label_2c ("label 2c");
+     gcc_rich_location richloc (field, &label_0a, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1a);
+     richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2a);
+ 
+     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label_0b);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1b);
+     richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2b);
+ 
+     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label_0c);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1c);
+     richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2c);
+ 
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  " ~~~   ~~~ ^~~~~\n"
+ 		  " |     |   |\n"
+ 		  " |     |   label 0a\n"
+ 		  " |     |   label 0b\n"
+ 		  " |     |   label 0c\n"
+ 		  " |     label 1a\n"
+ 		  " |     label 1b\n"
+ 		  " |     label 1c\n"
+ 		  " label 2a\n"
+ 		  " label 2b\n"
+ 		  " label 2c\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Verify that a nullptr result from range_label::get_text is
+      handled gracefully.  */
+   {
+     text_range_label label (nullptr);
+     gcc_rich_location richloc (bar, &label, nullptr);
+ 
+     test_context dc;
+     ASSERT_STREQ (" foo = bar.field;\n"
+ 		  "       ^~~\n",
+ 		  dc.test_show_locus (richloc));
+    }
+ 
+   /* TODO: example of formatted printing (needs to be in
+      gcc-rich-location.cc due to Makefile.in issues).  */
+ }
+ 
+ /* Run the various one-liner tests.  */
+ 
+ static void
+ test_diagnostic_show_locus_one_liner (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      ....................0000000001111111.
+      ....................1234567890123456.  */
+   const char *content = "foo = bar.field;\n";
+ 
+   source_printing_fixture f (case_, content);
+ 
+   location_t line_end = linemap_position_for_column (line_table, 16);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   ASSERT_STREQ (f.get_filename (), LOCATION_FILE (line_end));
+   ASSERT_EQ (1, LOCATION_LINE (line_end));
+   ASSERT_EQ (16, LOCATION_COLUMN (line_end));
+ 
+   test_one_liner_simple_caret ();
+   test_one_liner_no_column ();
+   test_one_liner_caret_and_range ();
+   test_one_liner_multiple_carets_and_ranges ();
+   test_one_liner_fixit_insert_before ();
+   test_one_liner_fixit_insert_after ();
+   test_one_liner_fixit_remove ();
+   test_one_liner_fixit_replace ();
+   test_one_liner_fixit_replace_non_equal_range ();
+   test_one_liner_fixit_replace_equal_secondary_range ();
+   test_one_liner_fixit_validation_adhoc_locations ();
+   test_one_liner_many_fixits_1 ();
+   test_one_liner_many_fixits_2 ();
+   test_one_liner_labels ();
+ }
+ 
+ /* Version of all one-liner tests exercising multibyte awareness.
+    These are all called from test_diagnostic_show_locus_one_liner,
+    which uses source_printing_fixture_one_liner_utf8 to create
+    the test file; see the notes in diagnostic-show-locus-selftest.h.
+ 
+    Note: all of the below asserts would be easier to read if we used UTF-8
+    directly in the string constants, but it seems better not to demand the
+    host compiler support this, when it isn't otherwise necessary.  Instead,
+    whenever an extended character appears in a string, we put a line break
+    after it so that all succeeding characters can appear visually at the
+    correct display column.  */
+ 
+ /* Just a caret.  */
+ 
+ static void
+ test_one_liner_simple_caret_utf8 ()
+ {
+   test_context dc;
+   location_t caret = linemap_position_for_column (line_table, 18);
+   rich_location richloc (line_table, caret);
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		"               ^\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Caret and range.  */
+ static void
+ test_one_liner_caret_and_range_utf8 ()
+ {
+   test_context dc;
+   location_t caret = linemap_position_for_column (line_table, 18);
+   location_t start = linemap_position_for_column (line_table, 12);
+   location_t finish = linemap_position_for_column (line_table, 30);
+   location_t loc = make_location (caret, start, finish);
+   rich_location richloc (line_table, loc);
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		"          ~~~~~^~~~~~~~~~\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Multiple ranges and carets.  */
+ 
+ static void
+ test_one_liner_multiple_carets_and_ranges_utf8 ()
+ {
+   test_context dc;
+   location_t foo
+     = make_location (linemap_position_for_column (line_table, 7),
+ 		     linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 8));
+   dc.set_caret_char (0, 'A');
+ 
+   location_t bar
+     = make_location (linemap_position_for_column (line_table, 16),
+ 		     linemap_position_for_column (line_table, 12),
+ 		     linemap_position_for_column (line_table, 17));
+   dc.set_caret_char (1, 'B');
+ 
+   location_t field
+     = make_location (linemap_position_for_column (line_table, 26),
+ 		     linemap_position_for_column (line_table, 19),
+ 		     linemap_position_for_column (line_table, 30));
+   dc.set_caret_char (2, 'C');
+   rich_location richloc (line_table, foo);
+   richloc.add_range (bar, SHOW_RANGE_WITH_CARET);
+   richloc.add_range (field, SHOW_RANGE_WITH_CARET);
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		" ~~~~A~   ~~~B~ ~~~~~C~~~\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Insertion fix-it hint: adding an "&" to the front of "P_bar.field". */
+ 
+ static void
+ test_one_liner_fixit_insert_before_utf8 ()
+ {
+   test_context dc;
+   location_t caret = linemap_position_for_column (line_table, 12);
+   rich_location richloc (line_table, caret);
+   richloc.add_fixit_insert_before ("&");
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		"          ^\n"
+ 		"          &\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Insertion fix-it hint: adding a "[0]" after "SS_foo". */
+ 
+ static void
+ test_one_liner_fixit_insert_after_utf8 ()
+ {
+   test_context dc;
+   location_t start = linemap_position_for_column (line_table, 1);
+   location_t finish = linemap_position_for_column (line_table, 8);
+   location_t foo = make_location (start, start, finish);
+   rich_location richloc (line_table, foo);
+   richloc.add_fixit_insert_after ("[0]");
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		" ^~~~~~\n"
+ 		"       [0]\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Removal fix-it hint: removal of the ".SS_fieldP". */
+ 
+ static void
+ test_one_liner_fixit_remove_utf8 ()
+ {
+   test_context dc;
+   location_t start = linemap_position_for_column (line_table, 18);
+   location_t finish = linemap_position_for_column (line_table, 30);
+   location_t dot = make_location (start, start, finish);
+   rich_location richloc (line_table, dot);
+   richloc.add_fixit_remove ();
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		"               ^~~~~~~~~~\n"
+ 		"               ----------\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Replace fix-it hint: replacing "SS_fieldP" with "m_SSfieldP". */
+ 
+ static void
+ test_one_liner_fixit_replace_utf8 ()
+ {
+   test_context dc;
+   location_t start = linemap_position_for_column (line_table, 19);
+   location_t finish = linemap_position_for_column (line_table, 30);
+   location_t field = make_location (start, start, finish);
+   rich_location richloc (line_table, field);
+   richloc.add_fixit_replace ("m_\xf0\x9f\x98\x82_field\xcf\x80");
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		"                ^~~~~~~~~\n"
+ 		"                m_\xf0\x9f\x98\x82"
+ 				    "_field\xcf\x80\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Replace fix-it hint: replacing "SS_fieldP" with "m_SSfieldP",
+    but where the caret was elsewhere.  */
+ 
+ static void
+ test_one_liner_fixit_replace_non_equal_range_utf8 ()
+ {
+   test_context dc;
+   location_t equals = linemap_position_for_column (line_table, 10);
+   location_t start = linemap_position_for_column (line_table, 19);
+   location_t finish = linemap_position_for_column (line_table, 30);
+   rich_location richloc (line_table, equals);
+   source_range range;
+   range.m_start = start;
+   range.m_finish = finish;
+   richloc.add_fixit_replace (range, "m_\xf0\x9f\x98\x82_field\xcf\x80");
+   /* The replacement range is not indicated in the annotation line, so
+      it should be indicated via an additional underline.  */
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		"        ^\n"
+ 		"                ---------\n"
+ 		"                m_\xf0\x9f\x98\x82"
+ 				    "_field\xcf\x80\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Replace fix-it hint: replacing "SS_fieldP" with "m_SSfieldP",
+    where the caret was elsewhere, but where a secondary range
+    exactly covers "field".  */
+ 
+ static void
+ test_one_liner_fixit_replace_equal_secondary_range_utf8 ()
+ {
+   test_context dc;
+   location_t equals = linemap_position_for_column (line_table, 10);
+   location_t start = linemap_position_for_column (line_table, 19);
+   location_t finish = linemap_position_for_column (line_table, 30);
+   rich_location richloc (line_table, equals);
+   location_t field = make_location (start, start, finish);
+   richloc.add_range (field);
+   richloc.add_fixit_replace (field, "m_\xf0\x9f\x98\x82_field\xcf\x80");
+   /* The replacement range is indicated in the annotation line,
+      so it shouldn't be indicated via an additional underline.  */
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		"        ^       ~~~~~~~~~\n"
+ 		"                m_\xf0\x9f\x98\x82"
+ 				    "_field\xcf\x80\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Verify that we can use ad-hoc locations when adding fixits to a
+    rich_location.  */
+ 
+ static void
+ test_one_liner_fixit_validation_adhoc_locations_utf8 ()
+ {
+   /* Generate a range that's too long to be packed, so must
+      be stored as an ad-hoc location (given the defaults
+      of 5 bits or 7 bits or 0 bits of packed range); 150 columns > 2**7.  */
+   const location_t c12 = linemap_position_for_column (line_table, 12);
+   const location_t c162 = linemap_position_for_column (line_table, 162);
+   const location_t loc = make_location (c12, c12, c162);
+ 
+   if (c162 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   ASSERT_TRUE (IS_ADHOC_LOC (loc));
+ 
+   /* Insert.  */
+   {
+     rich_location richloc (line_table, loc);
+     richloc.add_fixit_insert_before (loc, "test");
+     /* It should not have been discarded by the validator.  */
+     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 
+     test_context dc;
+     ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		     "_foo = \xcf\x80"
+ 			     "_bar.\xf0\x9f\x98\x82"
+ 				    "_field\xcf\x80"
+ 					   ";\n"
+ 		  "          ^~~~~~~~~~~~~~~~                     "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          \n"
+ 		  "          test\n",
+ 		dc.test_show_locus (richloc));
+   }
+ 
+   /* Remove.  */
+   {
+     rich_location richloc (line_table, loc);
+     source_range range = source_range::from_locations (loc, c162);
+     richloc.add_fixit_remove (range);
+     /* It should not have been discarded by the validator.  */
+     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 
+     test_context dc;
+     ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		     "_foo = \xcf\x80"
+ 			     "_bar.\xf0\x9f\x98\x82"
+ 				    "_field\xcf\x80"
+ 					   ";\n"
+ 		  "          ^~~~~~~~~~~~~~~~                     "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          \n"
+ 		  "          -------------------------------------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------"
+ 		  "----------\n",
+ 		dc.test_show_locus (richloc));
+   }
+ 
+   /* Replace.  */
+   {
+     rich_location richloc (line_table, loc);
+     source_range range = source_range::from_locations (loc, c162);
+     richloc.add_fixit_replace (range, "test");
+     /* It should not have been discarded by the validator.  */
+     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 
+     test_context dc;
+     ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		     "_foo = \xcf\x80"
+ 			     "_bar.\xf0\x9f\x98\x82"
+ 				    "_field\xcf\x80"
+ 					   ";\n"
+ 		  "          ^~~~~~~~~~~~~~~~                     "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          "
+ 		  "          \n"
+ 		  "          test\n",
+ 		dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Test of consolidating insertions at the same location.  */
+ 
+ static void
+ test_one_liner_many_fixits_1_utf8 ()
+ {
+   test_context dc;
+   location_t equals = linemap_position_for_column (line_table, 10);
+   rich_location richloc (line_table, equals);
+   for (int i = 0; i < 19; i++)
+     richloc.add_fixit_insert_before (i & 1 ? "@" : "\xcf\x80");
+   ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		"        ^\n"
+ 		"        \xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80@"
+ 		"\xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Ensure that we can add an arbitrary number of fix-it hints to a
+    rich_location, even if they are not consolidated.  */
+ 
+ static void
+ test_one_liner_many_fixits_2_utf8 ()
+ {
+   test_context dc;
+   location_t equals = linemap_position_for_column (line_table, 10);
+   rich_location richloc (line_table, equals);
+   const int nlocs = 19;
+   int locs[nlocs] = {1, 5, 7, 9, 11, 14, 16, 18, 23, 25, 27, 29, 32,
+ 		     34, 36, 38, 40, 42, 44};
+   for (int i = 0; i != nlocs; ++i)
+     {
+       location_t loc = linemap_position_for_column (line_table, locs[i]);
+       richloc.add_fixit_insert_before (loc, i & 1 ? "@" : "\xcf\x80");
+     }
+ 
+   ASSERT_EQ (nlocs, richloc.get_num_fixit_hints ());
+   ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		   "_foo = \xcf\x80"
+ 			   "_bar.\xf0\x9f\x98\x82"
+ 				  "_field\xcf\x80"
+ 					 ";\n"
+ 		"        ^\n"
+ 		" \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80 @  \xcf\x80 @"
+ 		" \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Test of labeling the ranges within a rich_location.  */
+ 
+ static void
+ test_one_liner_labels_utf8 ()
+ {
+   location_t foo
+     = make_location (linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 1),
+ 		     linemap_position_for_column (line_table, 8));
+   location_t bar
+     = make_location (linemap_position_for_column (line_table, 12),
+ 		     linemap_position_for_column (line_table, 12),
+ 		     linemap_position_for_column (line_table, 17));
+   location_t field
+     = make_location (linemap_position_for_column (line_table, 19),
+ 		     linemap_position_for_column (line_table, 19),
+ 		     linemap_position_for_column (line_table, 30));
+ 
+   /* Example where all the labels fit on one line.  */
+   {
+     /* These three labels contain multibyte characters such that their byte
+        lengths are respectively (12, 10, 18), but their display widths are only
+        (6, 5, 9).  All three fit on the line when considering the display
+        widths, but not when considering the byte widths, so verify that we do
+        indeed put them all on one line.  */
+     text_range_label label0
+       ("\xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80");
+     text_range_label label1
+       ("\xf0\x9f\x98\x82\xf0\x9f\x98\x82\xcf\x80");
+     text_range_label label2
+       ("\xf0\x9f\x98\x82\xcf\x80\xf0\x9f\x98\x82\xf0\x9f\x98\x82\xcf\x80"
+        "\xcf\x80");
+     gcc_rich_location richloc (foo, &label0, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+ 
+     {
+       test_context dc;
+       ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		       "_foo = \xcf\x80"
+ 			       "_bar.\xf0\x9f\x98\x82"
+ 				      "_field\xcf\x80"
+ 					     ";\n"
+ 		    " ^~~~~~   ~~~~~ ~~~~~~~~~\n"
+ 		    " |        |     |\n"
+ 		    " \xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80"
+ 			   "   \xf0\x9f\x98\x82\xf0\x9f\x98\x82\xcf\x80"
+ 				   " \xf0\x9f\x98\x82\xcf\x80\xf0\x9f\x98\x82"
+ 					 "\xf0\x9f\x98\x82\xcf\x80\xcf\x80\n",
+ 		    dc.test_show_locus (richloc));
+     }
+ 
+   }
+ 
+   /* Example where the labels need extra lines.  */
+   {
+     text_range_label label0 ("label 0\xf0\x9f\x98\x82");
+     text_range_label label1 ("label 1\xcf\x80");
+     text_range_label label2 ("label 2\xcf\x80");
+     gcc_rich_location richloc (foo, &label0, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+ 
+     test_context dc;
+     ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		     "_foo = \xcf\x80"
+ 			     "_bar.\xf0\x9f\x98\x82"
+ 				    "_field\xcf\x80"
+ 					   ";\n"
+ 		  " ^~~~~~   ~~~~~ ~~~~~~~~~\n"
+ 		  " |        |     |\n"
+ 		  " |        |     label 2\xcf\x80\n"
+ 		  " |        label 1\xcf\x80\n"
+ 		  " label 0\xf0\x9f\x98\x82\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of boundary conditions: label 0 and 1 have just enough clearance,
+      but label 1 just touches label 2.  */
+   {
+     text_range_label label0 ("aaaaa\xf0\x9f\x98\x82\xcf\x80");
+     text_range_label label1 ("bb\xf0\x9f\x98\x82\xf0\x9f\x98\x82");
+     text_range_label label2 ("c");
+     gcc_rich_location richloc (foo, &label0, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+ 
+     test_context dc;
+     ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ 		     "_foo = \xcf\x80"
+ 			     "_bar.\xf0\x9f\x98\x82"
+ 				    "_field\xcf\x80"
+ 					   ";\n"
+ 		  " ^~~~~~   ~~~~~ ~~~~~~~~~\n"
+ 		  " |        |     |\n"
+ 		  " |        |     c\n"
+ 		  " aaaaa\xf0\x9f\x98\x82\xcf\x80"
+ 			   " bb\xf0\x9f\x98\x82\xf0\x9f\x98\x82\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of escaping the source lines.  */
+   {
+     text_range_label label0 ("label 0\xf0\x9f\x98\x82");
+     text_range_label label1 ("label 1\xcf\x80");
+     text_range_label label2 ("label 2\xcf\x80");
+     gcc_rich_location richloc (foo, &label0, nullptr);
+     richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+     richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+     richloc.set_escape_on_output (true);
+ 
+     {
+       test_context dc;
+       dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
+       ASSERT_STREQ (" <U+1F602>_foo = <U+03C0>_bar.<U+1F602>_field<U+03C0>;\n"
+ 		    " ^~~~~~~~~~~~~   ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~\n"
+ 		    " |               |            |\n"
+ 		    " label 0\xf0\x9f\x98\x82"
+ 		    /* ... */ "       label 1\xcf\x80"
+ 		    /* ...................*/ "     label 2\xcf\x80\n",
+ 		    dc.test_show_locus (richloc));
+     }
+     {
+       test_context dc;
+       dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
+       ASSERT_STREQ
+ 	(" <f0><9f><98><82>_foo = <cf><80>_bar.<f0><9f><98><82>_field<cf><80>;\n"
+ 	 " ^~~~~~~~~~~~~~~~~~~~   ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
+ 	 " |                      |            |\n"
+ 	 " label 0\xf0\x9f\x98\x82"
+ 	 /* ... */ "              label 1\xcf\x80"
+ 	 /* ..........................*/ "     label 2\xcf\x80\n",
+ 	 dc.test_show_locus (richloc));
+     }
+   }
+ }
+ 
+ /* Make sure that colorization codes don't interrupt a multibyte
+    sequence, which would corrupt it.  */
+ static void
+ test_one_liner_colorized_utf8 ()
+ {
+   test_context dc;
+   dc.colorize_source (true);
+   diagnostic_color_init (&dc, DIAGNOSTICS_COLOR_YES);
+   const location_t pi = linemap_position_for_column (line_table, 12);
+   rich_location richloc (line_table, pi);
+ 
+   /* In order to avoid having the test depend on exactly how the colorization
+      was effected, just confirm there are two pi characters in the output.  */
+   const char *result = dc.test_show_locus (richloc);
+   const char *null_term = result + strlen (result);
+   const char *first_pi = strstr (result, "\xcf\x80");
+   ASSERT_TRUE (first_pi && first_pi <= null_term - 2);
+   ASSERT_STR_CONTAINS (first_pi + 2, "\xcf\x80");
+ }
+ 
+ static const char * const one_liner_utf8_content
+   /* Display columns.
+      0000000000000000000000011111111111111111111111111111112222222222222
+      1111111122222222345678900000000123456666666677777777890123444444445  */
+   = "\xf0\x9f\x98\x82_foo = \xcf\x80_bar.\xf0\x9f\x98\x82_field\xcf\x80;\n";
+   /* 0000000000000000000001111111111111111111222222222222222222222233333
+      1111222233334444567890122223333456789999000011112222345678999900001
+      Byte columns.  */
+ 
+ source_printing_fixture_one_liner_utf8::
+ source_printing_fixture_one_liner_utf8 (const line_table_case &case_)
+ : source_printing_fixture (case_, one_liner_utf8_content)
+ {
+ }
+ 
+ /* Run the various one-liner tests.  */
+ 
+ static void
+ test_diagnostic_show_locus_one_liner_utf8 (const line_table_case &case_)
+ {
+   source_printing_fixture_one_liner_utf8 f (case_);
+ 
+   location_t line_end = linemap_position_for_column (line_table, 31);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   ASSERT_STREQ (f.get_filename (), LOCATION_FILE (line_end));
+   ASSERT_EQ (1, LOCATION_LINE (line_end));
+   ASSERT_EQ (31, LOCATION_COLUMN (line_end));
+ 
+   diagnostics::char_span lspan = f.m_fc.get_source_line (f.get_filename (), 1);
+   ASSERT_EQ (25, cpp_display_width (lspan.get_buffer (), lspan.length (),
+ 				    def_policy ()));
+   ASSERT_EQ (25, location_compute_display_column (f.m_fc,
+ 						  expand_location (line_end),
+ 						  def_policy ()));
+ 
+   test_one_liner_simple_caret_utf8 ();
+   test_one_liner_caret_and_range_utf8 ();
+   test_one_liner_multiple_carets_and_ranges_utf8 ();
+   test_one_liner_fixit_insert_before_utf8 ();
+   test_one_liner_fixit_insert_after_utf8 ();
+   test_one_liner_fixit_remove_utf8 ();
+   test_one_liner_fixit_replace_utf8 ();
+   test_one_liner_fixit_replace_non_equal_range_utf8 ();
+   test_one_liner_fixit_replace_equal_secondary_range_utf8 ();
+   test_one_liner_fixit_validation_adhoc_locations_utf8 ();
+   test_one_liner_many_fixits_1_utf8 ();
+   test_one_liner_many_fixits_2_utf8 ();
+   test_one_liner_labels_utf8 ();
+   test_one_liner_colorized_utf8 ();
+ }
+ 
+ /* Verify that gcc_rich_location::add_location_if_nearby works.  */
+ 
+ static void
+ test_add_location_if_nearby (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      ...000000000111111111122222222223333333333.
+      ...123456789012345678901234567890123456789.  */
+   const char *content
+     = ("struct same_line { double x; double y; ;\n" /* line 1.  */
+        "struct different_line\n"                    /* line 2.  */
+        "{\n"                                        /* line 3.  */
+        "  double x;\n"                              /* line 4.  */
+        "  double y;\n"                              /* line 5.  */
+        ";\n");                                      /* line 6.  */
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", content, nullptr);
+   line_table_test ltt (case_);
+ 
+   const line_map_ordinary *ord_map
+     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ 					   tmp.get_filename (), 0));
+ 
+   linemap_line_start (line_table, 1, 100);
+ 
+   const location_t final_line_end
+     = linemap_position_for_line_and_column (line_table, ord_map, 6, 7);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Test of add_location_if_nearby on the same line as the
+      primary location.  */
+   {
+     test_context dc;
+     const location_t missing_close_brace_1_39
+       = linemap_position_for_line_and_column (line_table, ord_map, 1, 39);
+     const location_t matching_open_brace_1_18
+       = linemap_position_for_line_and_column (line_table, ord_map, 1, 18);
+     gcc_rich_location richloc (missing_close_brace_1_39);
+     bool added = richloc.add_location_if_nearby (dc,
+ 						 matching_open_brace_1_18);
+     ASSERT_TRUE (added);
+     ASSERT_EQ (2, richloc.get_num_locations ());
+     ASSERT_STREQ (" struct same_line { double x; double y; ;\n"
+ 		  "                  ~                    ^\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Test of add_location_if_nearby on a different line to the
+      primary location.  */
+   {
+     test_context dc;
+     const location_t missing_close_brace_6_1
+       = linemap_position_for_line_and_column (line_table, ord_map, 6, 1);
+     const location_t matching_open_brace_3_1
+       = linemap_position_for_line_and_column (line_table, ord_map, 3, 1);
+     gcc_rich_location richloc (missing_close_brace_6_1);
+     bool added = richloc.add_location_if_nearby (dc,
+ 						 matching_open_brace_3_1);
+     ASSERT_FALSE (added);
+     ASSERT_EQ (1, richloc.get_num_locations ());
+   }
+ }
+ 
+ /* Verify that we print fixits even if they only affect lines
+    outside those covered by the ranges in the rich_location.  */
+ 
+ static void
+ test_diagnostic_show_locus_fixit_lines (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      ...000000000111111111122222222223333333333.
+      ...123456789012345678901234567890123456789.  */
+   const char *content
+     = ("struct point { double x; double y; };\n" /* line 1.  */
+        "struct point origin = {x: 0.0,\n"        /* line 2.  */
+        "                       y\n"              /* line 3.  */
+        "\n"                                      /* line 4.  */
+        "\n"                                      /* line 5.  */
+        "                        : 0.0};\n");     /* line 6.  */
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+   line_table_test ltt (case_);
+ 
+   const line_map_ordinary *ord_map
+     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ 					   tmp.get_filename (), 0));
+ 
+   linemap_line_start (line_table, 1, 100);
+ 
+   const location_t final_line_end
+     = linemap_position_for_line_and_column (line_table, ord_map, 6, 36);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* A pair of tests for modernizing the initializers to C99-style.  */
+ 
+   /* The one-liner case (line 2).  */
+   {
+     test_context dc;
+     const location_t x
+       = linemap_position_for_line_and_column (line_table, ord_map, 2, 24);
+     const location_t colon
+       = linemap_position_for_line_and_column (line_table, ord_map, 2, 25);
+     rich_location richloc (line_table, colon);
+     richloc.add_fixit_insert_before (x, ".");
+     richloc.add_fixit_replace (colon, "=");
+     ASSERT_STREQ (" struct point origin = {x: 0.0,\n"
+ 		  "                         ^\n"
+ 		  "                        .=\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* The multiline case.  The caret for the rich_location is on line 6;
+      verify that insertion fixit on line 3 is still printed (and that
+      span starts are printed due to the gap between the span at line 3
+      and that at line 6).  */
+   {
+     test_context dc;
+     const location_t y
+       = linemap_position_for_line_and_column (line_table, ord_map, 3, 24);
+     const location_t colon
+       = linemap_position_for_line_and_column (line_table, ord_map, 6, 25);
+     rich_location richloc (line_table, colon);
+     richloc.add_fixit_insert_before (y, ".");
+     richloc.add_fixit_replace (colon, "=");
+     ASSERT_STREQ ("FILENAME:3:24:\n"
+ 		  "                        y\n"
+ 		  "                        .\n"
+ 		  "FILENAME:6:25:\n"
+ 		  "                         : 0.0};\n"
+ 		  "                         ^\n"
+ 		  "                         =\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* As above, but verify the behavior of multiple line spans
+      with line-numbering enabled.  */
+   {
+     const location_t y
+       = linemap_position_for_line_and_column (line_table, ord_map, 3, 24);
+     const location_t colon
+       = linemap_position_for_line_and_column (line_table, ord_map, 6, 25);
+     rich_location richloc (line_table, colon);
+     richloc.add_fixit_insert_before (y, ".");
+     richloc.add_fixit_replace (colon, "=");
+     test_context dc;
+     dc.show_line_numbers (true);
+     ASSERT_STREQ ("    3 |                        y\n"
+ 		  "      |                        .\n"
+ 		  "......\n"
+ 		  "    6 |                         : 0.0};\n"
+ 		  "      |                         ^\n"
+ 		  "      |                         =\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ 
+ /* Verify that fix-it hints are appropriately consolidated.
+ 
+    If any fix-it hints in a rich_location involve locations beyond
+    LINE_MAP_MAX_LOCATION_WITH_COLS, then we can't reliably apply
+    the fix-it as a whole, so there should be none.
+ 
+    Otherwise, verify that consecutive "replace" and "remove" fix-its
+    are merged, and that other fix-its remain separate.   */
+ 
+ static void
+ test_fixit_consolidation (const line_table_case &case_)
+ {
+   line_table_test ltt (case_);
+ 
+   linemap_add (line_table, LC_ENTER, false, "test.c", 1);
+ 
+   const location_t c10 = linemap_position_for_column (line_table, 10);
+   const location_t c15 = linemap_position_for_column (line_table, 15);
+   const location_t c16 = linemap_position_for_column (line_table, 16);
+   const location_t c17 = linemap_position_for_column (line_table, 17);
+   const location_t c20 = linemap_position_for_column (line_table, 20);
+   const location_t c21 = linemap_position_for_column (line_table, 21);
+   const location_t caret = c10;
+ 
+   /* Insert + insert. */
+   {
+     rich_location richloc (line_table, caret);
+     richloc.add_fixit_insert_before (c10, "foo");
+     richloc.add_fixit_insert_before (c15, "bar");
+ 
+     if (c15 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+       /* Bogus column info for 2nd fixit, so no fixits.  */
+       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+     else
+       /* They should not have been merged.  */
+       ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+   }
+ 
+   /* Insert + replace. */
+   {
+     rich_location richloc (line_table, caret);
+     richloc.add_fixit_insert_before (c10, "foo");
+     richloc.add_fixit_replace (source_range::from_locations (c15, c17),
+ 			       "bar");
+ 
+     if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+       /* Bogus column info for 2nd fixit, so no fixits.  */
+       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+     else
+       /* They should not have been merged.  */
+       ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+   }
+ 
+   /* Replace + non-consecutive insert. */
+   {
+     rich_location richloc (line_table, caret);
+     richloc.add_fixit_replace (source_range::from_locations (c10, c15),
+ 			       "bar");
+     richloc.add_fixit_insert_before (c17, "foo");
+ 
+     if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+       /* Bogus column info for 2nd fixit, so no fixits.  */
+       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+     else
+       /* They should not have been merged.  */
+       ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+   }
+ 
+   /* Replace + non-consecutive replace. */
+   {
+     rich_location richloc (line_table, caret);
+     richloc.add_fixit_replace (source_range::from_locations (c10, c15),
+ 			       "foo");
+     richloc.add_fixit_replace (source_range::from_locations (c17, c20),
+ 			       "bar");
+ 
+     if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+       /* Bogus column info for 2nd fixit, so no fixits.  */
+       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+     else
+       /* They should not have been merged.  */
+       ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+   }
+ 
+   /* Replace + consecutive replace. */
+   {
+     rich_location richloc (line_table, caret);
+     richloc.add_fixit_replace (source_range::from_locations (c10, c15),
+ 			       "foo");
+     richloc.add_fixit_replace (source_range::from_locations (c16, c20),
+ 			       "bar");
+ 
+     if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+       /* Bogus column info for 2nd fixit, so no fixits.  */
+       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+     else
+       {
+ 	/* They should have been merged into a single "replace".  */
+ 	ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 	const fixit_hint *hint = richloc.get_fixit_hint (0);
+ 	ASSERT_STREQ ("foobar", hint->get_string ());
+ 	ASSERT_EQ (c10, hint->get_start_loc ());
+ 	ASSERT_EQ (c21, hint->get_next_loc ());
+       }
+   }
+ 
+   /* Replace + consecutive removal. */
+   {
+     rich_location richloc (line_table, caret);
+     richloc.add_fixit_replace (source_range::from_locations (c10, c15),
+ 			       "foo");
+     richloc.add_fixit_remove (source_range::from_locations (c16, c20));
+ 
+     if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+       /* Bogus column info for 2nd fixit, so no fixits.  */
+       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+     else
+       {
+ 	/* They should have been merged into a single replace, with the
+ 	   range extended to cover that of the removal.  */
+ 	ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 	const fixit_hint *hint = richloc.get_fixit_hint (0);
+ 	ASSERT_STREQ ("foo", hint->get_string ());
+ 	ASSERT_EQ (c10, hint->get_start_loc ());
+ 	ASSERT_EQ (c21, hint->get_next_loc ());
+       }
+   }
+ 
+   /* Consecutive removals. */
+   {
+     rich_location richloc (line_table, caret);
+     richloc.add_fixit_remove (source_range::from_locations (c10, c15));
+     richloc.add_fixit_remove (source_range::from_locations (c16, c20));
+ 
+     if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+       /* Bogus column info for 2nd fixit, so no fixits.  */
+       ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+     else
+       {
+ 	/* They should have been merged into a single "replace-with-empty".  */
+ 	ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 	const fixit_hint *hint = richloc.get_fixit_hint (0);
+ 	ASSERT_STREQ ("", hint->get_string ());
+ 	ASSERT_EQ (c10, hint->get_start_loc ());
+ 	ASSERT_EQ (c21, hint->get_next_loc ());
+       }
+   }
+ }
+ 
+ /* Verify that the line_corrections machinery correctly prints
+    overlapping fixit-hints.  */
+ 
+ static void
+ test_overlapped_fixit_printing (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      ...000000000111111111122222222223333333333.
+      ...123456789012345678901234567890123456789.  */
+   const char *content
+     = ("  foo *f = (foo *)ptr->field;\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
+   diagnostics::file_cache fc;
+   line_table_test ltt (case_);
+ 
+   const line_map_ordinary *ord_map
+     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ 					   tmp.get_filename (), 0));
+ 
+   linemap_line_start (line_table, 1, 100);
+ 
+   const location_t final_line_end
+     = linemap_position_for_line_and_column (line_table, ord_map, 6, 36);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* A test for converting a C-style cast to a C++-style cast.  */
+   const location_t open_paren
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 12);
+   const location_t close_paren
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 18);
+   const location_t expr_start
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 19);
+   const location_t expr_finish
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 28);
+   const location_t expr = make_location (expr_start, expr_start, expr_finish);
+ 
+   /* Various examples of fix-it hints that aren't themselves consolidated,
+      but for which the *printing* may need consolidation.  */
+ 
+   /* Example where 3 fix-it hints are printed as one.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_replace (open_paren, "const_cast<");
+     richloc.add_fixit_replace (close_paren, "> (");
+     richloc.add_fixit_insert_after (")");
+ 
+     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
+ 		  "                   ^~~~~~~~~~\n"
+ 		  "            -----------------\n"
+ 		  "            const_cast<foo *> (ptr->field)\n",
+ 		  dc.test_show_locus (richloc));
+ 
+     /* Unit-test the line_corrections machinery.  */
+     char_display_policy policy (make_char_policy (dc, richloc));
+     ASSERT_EQ (3, richloc.get_num_fixit_hints ());
+     const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
+     ASSERT_EQ (column_range (12, 12),
+ 	       get_affected_range (fc, policy, hint_0, CU_BYTES));
+     ASSERT_EQ (column_range (12, 12),
+ 	       get_affected_range (fc, policy, hint_0, CU_DISPLAY_COLS));
+     ASSERT_EQ (column_range (12, 22), get_printed_columns (fc, policy, hint_0));
+     const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
+     ASSERT_EQ (column_range (18, 18),
+ 	       get_affected_range (fc, policy, hint_1, CU_BYTES));
+     ASSERT_EQ (column_range (18, 18),
+ 	       get_affected_range (fc, policy, hint_1, CU_DISPLAY_COLS));
+     ASSERT_EQ (column_range (18, 20), get_printed_columns (fc, policy, hint_1));
+     const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
+     ASSERT_EQ (column_range (29, 28),
+ 	       get_affected_range (fc, policy, hint_2, CU_BYTES));
+     ASSERT_EQ (column_range (29, 28),
+ 	       get_affected_range (fc, policy, hint_2, CU_DISPLAY_COLS));
+     ASSERT_EQ (column_range (29, 29), get_printed_columns (fc, policy, hint_2));
+ 
+     /* Add each hint in turn to a line_corrections instance,
+        and verify that they are consolidated into one correction instance
+        as expected.  */
+     line_corrections lc (fc, policy, tmp.get_filename (), 1);
+ 
+     /* The first replace hint by itself.  */
+     lc.add_hint (hint_0);
+     ASSERT_EQ (1, lc.m_corrections.length ());
+     ASSERT_EQ (column_range (12, 12), lc.m_corrections[0]->m_affected_bytes);
+     ASSERT_EQ (column_range (12, 12), lc.m_corrections[0]->m_affected_columns);
+     ASSERT_EQ (column_range (12, 22), lc.m_corrections[0]->m_printed_columns);
+     ASSERT_STREQ ("const_cast<", lc.m_corrections[0]->m_text);
+ 
+     /* After the second replacement hint, they are printed together
+        as a replacement (along with the text between them).  */
+     lc.add_hint (hint_1);
+     ASSERT_EQ (1, lc.m_corrections.length ());
+     ASSERT_STREQ ("const_cast<foo *> (", lc.m_corrections[0]->m_text);
+     ASSERT_EQ (column_range (12, 18), lc.m_corrections[0]->m_affected_bytes);
+     ASSERT_EQ (column_range (12, 18), lc.m_corrections[0]->m_affected_columns);
+     ASSERT_EQ (column_range (12, 30), lc.m_corrections[0]->m_printed_columns);
+ 
+     /* After the final insertion hint, they are all printed together
+        as a replacement (along with the text between them).  */
+     lc.add_hint (hint_2);
+     ASSERT_STREQ ("const_cast<foo *> (ptr->field)",
+ 		  lc.m_corrections[0]->m_text);
+     ASSERT_EQ (1, lc.m_corrections.length ());
+     ASSERT_EQ (column_range (12, 28), lc.m_corrections[0]->m_affected_bytes);
+     ASSERT_EQ (column_range (12, 28), lc.m_corrections[0]->m_affected_columns);
+     ASSERT_EQ (column_range (12, 41), lc.m_corrections[0]->m_printed_columns);
+   }
+ 
+   /* Example where two are consolidated during printing.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_replace (open_paren, "CAST (");
+     richloc.add_fixit_replace (close_paren, ") (");
+     richloc.add_fixit_insert_after (")");
+ 
+     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
+ 		  "                   ^~~~~~~~~~\n"
+ 		  "            -\n"
+ 		  "            CAST (-\n"
+ 		  "                  ) (        )\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example where none are consolidated during printing.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_replace (open_paren, "CST (");
+     richloc.add_fixit_replace (close_paren, ") (");
+     richloc.add_fixit_insert_after (")");
+ 
+     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
+ 		  "                   ^~~~~~~~~~\n"
+ 		  "            -\n"
+ 		  "            CST ( -\n"
+ 		  "                  ) (        )\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of deletion fix-it hints.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_insert_before (open_paren, "(bar *)");
+     source_range victim = {open_paren, close_paren};
+     richloc.add_fixit_remove (victim);
+ 
+     /* This case is actually handled by fixit-consolidation,
+        rather than by line_corrections.  */
+     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 
+     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
+ 		  "                   ^~~~~~~~~~\n"
+ 		  "            -------\n"
+ 		  "            (bar *)\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of deletion fix-it hints that would overlap.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_insert_before (open_paren, "(longer *)");
+     source_range victim = {expr_start, expr_finish};
+     richloc.add_fixit_remove (victim);
+ 
+     /* These fixits are not consolidated.  */
+     ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+ 
+     /* But the corrections are.  */
+     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
+ 		  "                   ^~~~~~~~~~\n"
+ 		  "            -----------------\n"
+ 		  "            (longer *)(foo *)\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of insertion fix-it hints that would overlap.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_insert_before (open_paren, "LONGER THAN THE CAST");
+     richloc.add_fixit_insert_after (close_paren, "TEST");
+ 
+     /* The first insertion is long enough that if printed naively,
+        it would overlap with the second.
+        Verify that they are printed as a single replacement.  */
+     ASSERT_STREQ ("   foo *f = (foo *)ptr->field;\n"
+ 		  "                   ^~~~~~~~~~\n"
+ 		  "            -------\n"
+ 		  "            LONGER THAN THE CAST(foo *)TEST\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Multibyte-aware version of preceding tests.  See comments above
+    test_one_liner_simple_caret_utf8() too, we use the same two multibyte
+    characters here.  */
+ 
+ static void
+ test_overlapped_fixit_printing_utf8 (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.  */
+ 
+   const char *content
+     /* Display columns.
+        00000000000000000000000111111111111111111111111222222222222222223
+        12344444444555555556789012344444444555555556789012345678999999990  */
+     = "  f\xf0\x9f\x98\x82 *f = (f\xf0\x9f\x98\x82 *)ptr->field\xcf\x80;\n";
+     /* 00000000000000000000011111111111111111111112222222222333333333333
+        12344445555666677778901234566667777888899990123456789012333344445
+        Byte columns.  */
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
+   line_table_test ltt (case_);
+ 
+   const line_map_ordinary *ord_map
+     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ 					   tmp.get_filename (), 0));
+ 
+   linemap_line_start (line_table, 1, 100);
+ 
+   const location_t final_line_end
+     = linemap_position_for_line_and_column (line_table, ord_map, 6, 50);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* A test for converting a C-style cast to a C++-style cast.  */
+   const location_t open_paren
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 14);
+   const location_t close_paren
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 22);
+   const location_t expr_start
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 23);
+   const location_t expr_finish
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 34);
+   const location_t expr = make_location (expr_start, expr_start, expr_finish);
+ 
+   /* Various examples of fix-it hints that aren't themselves consolidated,
+      but for which the *printing* may need consolidation.  */
+ 
+   /* Example where 3 fix-it hints are printed as one.  */
+   {
+     test_context dc;
+     diagnostics::file_cache &fc = dc.get_file_cache ();
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_replace (open_paren, "const_cast<");
+     richloc.add_fixit_replace (close_paren, "> (");
+     richloc.add_fixit_insert_after (")");
+ 
+     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
+ 			" *f = (f\xf0\x9f\x98\x82"
+ 				  " *)ptr->field\xcf\x80"
+ 						";\n"
+ 		  "                   ^~~~~~~~~~~\n"
+ 		  "            ------------------\n"
+ 		  "            const_cast<f\xf0\x9f\x98\x82"
+ 					    " *> (ptr->field\xcf\x80"
+ 							    ")\n",
+ 		  dc.test_show_locus (richloc));
+ 
+     /* Unit-test the line_corrections machinery.  */
+     char_display_policy policy (make_char_policy (dc, richloc));
+     ASSERT_EQ (3, richloc.get_num_fixit_hints ());
+     const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
+     ASSERT_EQ (column_range (14, 14),
+ 	       get_affected_range (fc, policy, hint_0, CU_BYTES));
+     ASSERT_EQ (column_range (12, 12),
+ 	       get_affected_range (fc, policy, hint_0, CU_DISPLAY_COLS));
+     ASSERT_EQ (column_range (12, 22), get_printed_columns (fc, policy, hint_0));
+     const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
+     ASSERT_EQ (column_range (22, 22),
+ 	       get_affected_range (fc, policy, hint_1, CU_BYTES));
+     ASSERT_EQ (column_range (18, 18),
+ 	       get_affected_range (fc, policy, hint_1, CU_DISPLAY_COLS));
+     ASSERT_EQ (column_range (18, 20), get_printed_columns (fc, policy, hint_1));
+     const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
+     ASSERT_EQ (column_range (35, 34),
+ 	       get_affected_range (fc, policy, hint_2, CU_BYTES));
+     ASSERT_EQ (column_range (30, 29),
+ 	       get_affected_range (fc, policy, hint_2, CU_DISPLAY_COLS));
+     ASSERT_EQ (column_range (30, 30), get_printed_columns (fc, policy, hint_2));
+ 
+     /* Add each hint in turn to a line_corrections instance,
+        and verify that they are consolidated into one correction instance
+        as expected.  */
+     line_corrections lc (fc, policy, tmp.get_filename (), 1);
+ 
+     /* The first replace hint by itself.  */
+     lc.add_hint (hint_0);
+     ASSERT_EQ (1, lc.m_corrections.length ());
+     ASSERT_EQ (column_range (14, 14), lc.m_corrections[0]->m_affected_bytes);
+     ASSERT_EQ (column_range (12, 12), lc.m_corrections[0]->m_affected_columns);
+     ASSERT_EQ (column_range (12, 22), lc.m_corrections[0]->m_printed_columns);
+     ASSERT_STREQ ("const_cast<", lc.m_corrections[0]->m_text);
+ 
+     /* After the second replacement hint, they are printed together
+        as a replacement (along with the text between them).  */
+     lc.add_hint (hint_1);
+     ASSERT_EQ (1, lc.m_corrections.length ());
+     ASSERT_STREQ ("const_cast<f\xf0\x9f\x98\x82 *> (",
+ 		  lc.m_corrections[0]->m_text);
+     ASSERT_EQ (column_range (14, 22), lc.m_corrections[0]->m_affected_bytes);
+     ASSERT_EQ (column_range (12, 18), lc.m_corrections[0]->m_affected_columns);
+     ASSERT_EQ (column_range (12, 30), lc.m_corrections[0]->m_printed_columns);
+ 
+     /* After the final insertion hint, they are all printed together
+        as a replacement (along with the text between them).  */
+     lc.add_hint (hint_2);
+     ASSERT_STREQ ("const_cast<f\xf0\x9f\x98\x82 *> (ptr->field\xcf\x80)",
+ 		  lc.m_corrections[0]->m_text);
+     ASSERT_EQ (1, lc.m_corrections.length ());
+     ASSERT_EQ (column_range (14, 34), lc.m_corrections[0]->m_affected_bytes);
+     ASSERT_EQ (column_range (12, 29), lc.m_corrections[0]->m_affected_columns);
+     ASSERT_EQ (column_range (12, 42), lc.m_corrections[0]->m_printed_columns);
+   }
+ 
+   /* Example where two are consolidated during printing.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_replace (open_paren, "CAST (");
+     richloc.add_fixit_replace (close_paren, ") (");
+     richloc.add_fixit_insert_after (")");
+ 
+     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
+ 			" *f = (f\xf0\x9f\x98\x82"
+ 				  " *)ptr->field\xcf\x80"
+ 						";\n"
+ 		  "                   ^~~~~~~~~~~\n"
+ 		  "            -\n"
+ 		  "            CAST (-\n"
+ 		  "                  ) (         )\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example where none are consolidated during printing.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_replace (open_paren, "CST (");
+     richloc.add_fixit_replace (close_paren, ") (");
+     richloc.add_fixit_insert_after (")");
+ 
+     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
+ 			" *f = (f\xf0\x9f\x98\x82"
+ 				  " *)ptr->field\xcf\x80"
+ 						";\n"
+ 		  "                   ^~~~~~~~~~~\n"
+ 		  "            -\n"
+ 		  "            CST ( -\n"
+ 		  "                  ) (         )\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of deletion fix-it hints.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_insert_before (open_paren, "(bar\xf0\x9f\x98\x82 *)");
+     source_range victim = {open_paren, close_paren};
+     richloc.add_fixit_remove (victim);
+ 
+     /* This case is actually handled by fixit-consolidation,
+        rather than by line_corrections.  */
+     ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ 
+     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
+ 			" *f = (f\xf0\x9f\x98\x82"
+ 				  " *)ptr->field\xcf\x80"
+ 						";\n"
+ 		  "                   ^~~~~~~~~~~\n"
+ 		  "            -------\n"
+ 		  "            (bar\xf0\x9f\x98\x82"
+ 				    " *)\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of deletion fix-it hints that would overlap.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_insert_before (open_paren, "(long\xf0\x9f\x98\x82 *)");
+     source_range victim = {expr_start, expr_finish};
+     richloc.add_fixit_remove (victim);
+ 
+     /* These fixits are not consolidated.  */
+     ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+ 
+     /* But the corrections are.  */
+     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
+ 			" *f = (f\xf0\x9f\x98\x82"
+ 				  " *)ptr->field\xcf\x80"
+ 						";\n"
+ 		  "                   ^~~~~~~~~~~\n"
+ 		  "            ------------------\n"
+ 		  "            (long\xf0\x9f\x98\x82"
+ 				     " *)(f\xf0\x9f\x98\x82"
+ 					    " *)\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Example of insertion fix-it hints that would overlap.  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, expr);
+     richloc.add_fixit_insert_before
+       (open_paren, "L\xf0\x9f\x98\x82NGER THAN THE CAST");
+     richloc.add_fixit_insert_after (close_paren, "TEST");
+ 
+     /* The first insertion is long enough that if printed naively,
+        it would overlap with the second.
+        Verify that they are printed as a single replacement.  */
+     ASSERT_STREQ ("   f\xf0\x9f\x98\x82"
+ 			" *f = (f\xf0\x9f\x98\x82"
+ 				  " *)ptr->field\xcf\x80"
+ 						";\n"
+ 		  "                   ^~~~~~~~~~~\n"
+ 		  "            -------\n"
+ 		  "            L\xf0\x9f\x98\x82"
+ 				 "NGER THAN THE CAST(f\xf0\x9f\x98\x82"
+ 						       " *)TEST\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Verify that the line_corrections machinery correctly prints
+    overlapping fixit-hints that have been added in the wrong
+    order.
+    Adapted from PR c/81405 seen on gcc.dg/init-excess-1.c*/
+ 
+ static void
+ test_overlapped_fixit_printing_2 (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      ...000000000111111111122222222223333333333.
+      ...123456789012345678901234567890123456789.  */
+   const char *content
+     = ("int a5[][0][0] = { 1, 2 };\n");
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+   line_table_test ltt (case_);
+ 
+   const line_map_ordinary *ord_map
+     = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ 					   tmp.get_filename (), 0));
+ 
+   linemap_line_start (line_table, 1, 100);
+ 
+   const location_t final_line_end
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 100);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   const location_t col_1
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 1);
+   const location_t col_20
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 20);
+   const location_t col_21
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 21);
+   const location_t col_23
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 23);
+   const location_t col_25
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 25);
+ 
+   /* Two insertions, in the wrong order.  */
+   {
+     test_context dc;
+     diagnostics::file_cache &fc = dc.get_file_cache ();
+ 
+     rich_location richloc (line_table, col_20);
+     richloc.add_fixit_insert_before (col_23, "{");
+     richloc.add_fixit_insert_before (col_21, "}");
+ 
+     /* These fixits should be accepted; they can't be consolidated.  */
+     char_display_policy policy (make_char_policy (dc, richloc));
+     ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+     const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
+     ASSERT_EQ (column_range (23, 22),
+ 	       get_affected_range (fc, policy, hint_0, CU_BYTES));
+     ASSERT_EQ (column_range (23, 23), get_printed_columns (fc, policy, hint_0));
+     const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
+     ASSERT_EQ (column_range (21, 20),
+ 	       get_affected_range (fc, policy, hint_1, CU_BYTES));
+     ASSERT_EQ (column_range (21, 21), get_printed_columns (fc, policy, hint_1));
+ 
+     /* Verify that they're printed correctly.  */
+     ASSERT_STREQ (" int a5[][0][0] = { 1, 2 };\n"
+ 		  "                    ^\n"
+ 		  "                     } {\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Various overlapping insertions, some occurring "out of order"
+      (reproducing the fix-it hints from PR c/81405).  */
+   {
+     test_context dc;
+     rich_location richloc (line_table, col_20);
+ 
+     richloc.add_fixit_insert_before (col_20, "{{");
+     richloc.add_fixit_insert_before (col_21, "}}");
+     richloc.add_fixit_insert_before (col_23, "{");
+     richloc.add_fixit_insert_before (col_21, "}");
+     richloc.add_fixit_insert_before (col_23, "{{");
+     richloc.add_fixit_insert_before (col_25, "}");
+     richloc.add_fixit_insert_before (col_21, "}");
+     richloc.add_fixit_insert_before (col_1, "{");
+     richloc.add_fixit_insert_before (col_25, "}");
+ 
+     ASSERT_STREQ (" int a5[][0][0] = { 1, 2 };\n"
+ 		  "                    ^\n"
+ 		  " {                  -----\n"
+ 		  "                    {{1}}}}, {{{2 }}\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Insertion fix-it hint: adding a "break;" on a line by itself.  */
+ 
+ static void
+ test_fixit_insert_containing_newline (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................0000000001111111.
+      .........................1234567890123456.  */
+   const char *old_content = ("    case 'a':\n" /* line 1. */
+ 			     "      x = a;\n"  /* line 2. */
+ 			     "    case 'b':\n" /* line 3. */
+ 			     "      x = b;\n");/* line 4. */
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
+ 
+   location_t case_start = linemap_position_for_column (line_table, 5);
+   location_t case_finish = linemap_position_for_column (line_table, 13);
+   location_t case_loc = make_location (case_start, case_start, case_finish);
+   location_t line_start = linemap_position_for_column (line_table, 1);
+ 
+   if (case_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Add a "break;" on a line by itself before line 3 i.e. before
+      column 1 of line 3. */
+   {
+     rich_location richloc (line_table, case_loc);
+     richloc.add_fixit_insert_before (line_start, "      break;\n");
+ 
+     /* Without line numbers.  */
+     {
+       test_context dc;
+       ASSERT_STREQ ("       x = a;\n"
+ 		    "+      break;\n"
+ 		    "     case 'b':\n"
+ 		    "     ^~~~~~~~~\n",
+ 		    dc.test_show_locus (richloc));
+     }
+ 
+     /* With line numbers.  */
+     {
+       test_context dc;
+       dc.show_line_numbers (true);
+       ASSERT_STREQ ("    2 |       x = a;\n"
+ 		    "  +++ |+      break;\n"
+ 		    "    3 |     case 'b':\n"
+ 		    "      |     ^~~~~~~~~\n",
+ 		    dc.test_show_locus (richloc));
+     }
+   }
+ 
+   /* Verify that attempts to add text with a newline fail when the
+      insertion point is *not* at the start of a line.  */
+   {
+     rich_location richloc (line_table, case_loc);
+     richloc.add_fixit_insert_before (case_start, "break;\n");
+     ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+     test_context dc;
+     ASSERT_STREQ ("     case 'b':\n"
+ 		  "     ^~~~~~~~~\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Insertion fix-it hint: adding a "#include <stdio.h>\n" to the top
+    of the file, where the fix-it is printed in a different line-span
+    to the primary range of the diagnostic.  */
+ 
+ static void
+ test_fixit_insert_containing_newline_2 (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+      .........................0000000001111111.
+      .........................1234567890123456.  */
+   const char *old_content = ("test (int ch)\n"  /* line 1. */
+ 			     "{\n"              /* line 2. */
+ 			     " putchar (ch);\n" /* line 3. */
+ 			     "}\n");            /* line 4. */
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   line_table_test ltt (case_);
+ 
+   const line_map_ordinary *ord_map = linemap_check_ordinary
+     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+   linemap_line_start (line_table, 1, 100);
+ 
+   /* The primary range is the "putchar" token.  */
+   location_t putchar_start
+     = linemap_position_for_line_and_column (line_table, ord_map, 3, 2);
+   location_t putchar_finish
+     = linemap_position_for_line_and_column (line_table, ord_map, 3, 8);
+   location_t putchar_loc
+     = make_location (putchar_start, putchar_start, putchar_finish);
+   rich_location richloc (line_table, putchar_loc);
+ 
+   /* Add a "#include <stdio.h>" on a line by itself at the top of the file.  */
+   location_t file_start
+      = linemap_position_for_line_and_column (line_table, ord_map,  1, 1);
+   richloc.add_fixit_insert_before (file_start, "#include <stdio.h>\n");
+ 
+   if (putchar_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   {
+     test_context dc;
+     ASSERT_STREQ ("FILENAME:1:1:\n"
+ 		  "+#include <stdio.h>\n"
+ 		  " test (int ch)\n"
+ 		  "FILENAME:3:2:\n"
+ 		  "  putchar (ch);\n"
+ 		  "  ^~~~~~~\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* With line-numbering, the line spans are close enough to be
+      consolidated, since it makes little sense to skip line 2.  */
+   {
+     test_context dc;
+     dc.show_line_numbers (true);
+     ASSERT_STREQ ("  +++ |+#include <stdio.h>\n"
+ 		  "    1 | test (int ch)\n"
+ 		  "    2 | {\n"
+ 		  "    3 |  putchar (ch);\n"
+ 		  "      |  ^~~~~~~\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Replacement fix-it hint containing a newline.
+    This will fail, as newlines are only supported when inserting at the
+    beginning of a line.  */
+ 
+ static void
+ test_fixit_replace_containing_newline (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+     .........................0000000001111.
+     .........................1234567890123.  */
+   const char *old_content = "foo = bar ();\n";
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+ 
+   /* Replace the " = " with "\n  = ", as if we were reformatting an
+      overly long line.  */
+   location_t start = linemap_position_for_column (line_table, 4);
+   location_t finish = linemap_position_for_column (line_table, 6);
+   location_t loc = linemap_position_for_column (line_table, 13);
+   rich_location richloc (line_table, loc);
+   source_range range = source_range::from_locations (start, finish);
+   richloc.add_fixit_replace (range, "\n =");
+ 
+   /* Arbitrary newlines are not yet supported within fix-it hints, so
+      the fix-it should not be displayed.  */
+   ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+ 
+   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   test_context dc;
+   ASSERT_STREQ (" foo = bar ();\n"
+ 		"             ^\n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Fix-it hint, attempting to delete a newline.
+    This will fail, as we currently only support fix-it hints that
+    affect one line at a time.  */
+ 
+ static void
+ test_fixit_deletion_affecting_newline (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.
+     ..........................0000000001111.
+     ..........................1234567890123.  */
+   const char *old_content = ("foo = bar (\n"
+ 			     "      );\n");
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+   line_table_test ltt (case_);
+   const line_map_ordinary *ord_map = linemap_check_ordinary
+     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+   linemap_line_start (line_table, 1, 100);
+ 
+   /* Attempt to delete the " (\n...)".  */
+   location_t start
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 10);
+   location_t caret
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 11);
+   location_t finish
+     = linemap_position_for_line_and_column (line_table, ord_map, 2, 7);
+   location_t loc = make_location (caret, start, finish);
+   rich_location richloc (line_table, loc);
+   richloc. add_fixit_remove ();
+ 
+   /* Fix-it hints that affect more than one line are not yet supported, so
+      the fix-it should not be displayed.  */
+   ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+ 
+   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   test_context dc;
+   ASSERT_STREQ (" foo = bar (\n"
+ 		"          ~^\n"
+ 		"       );\n"
+ 		"       ~    \n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ static void
+ test_tab_expansion (const line_table_case &case_)
+ {
+   /* Create a tempfile and write some text to it.  This example uses a tabstop
+      of 8, as the column numbers attempt to indicate:
+ 
+     .....................000.01111111111.22222333333  display
+     .....................123.90123456789.56789012345  columns  */
+   const char *content = "  \t   This: `\t' is a tab.\n";
+   /* ....................000 00000011111 11111222222  byte
+      ....................123 45678901234 56789012345  columns  */
+ 
+   const int tabstop = 8;
+   cpp_char_column_policy policy (tabstop, cpp_wcwidth);
+   const int first_non_ws_byte_col = 7;
+   const int right_quote_byte_col = 15;
+   const int last_byte_col = 25;
+   ASSERT_EQ (35, cpp_display_width (content, last_byte_col, policy));
+ 
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+   line_table_test ltt (case_);
+   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+ 
+   /* Don't attempt to run the tests if column data might be unavailable.  */
+   location_t line_end = linemap_position_for_column (line_table, last_byte_col);
+   if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Check that the leading whitespace with mixed tabs and spaces is expanded
+      into 11 spaces.  Recall that print_line() also puts one space before
+      everything too.  */
+   {
+     test_context dc;
+     dc.m_tabstop = tabstop;
+     rich_location richloc (line_table,
+ 			   linemap_position_for_column (line_table,
+ 							first_non_ws_byte_col));
+     ASSERT_STREQ ("            This: `      ' is a tab.\n"
+ 		  "            ^\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ 
+   /* Confirm the display width was tracked correctly across the internal tab
+      as well.  */
+   {
+     test_context dc;
+     dc.m_tabstop = tabstop;
+     rich_location richloc (line_table,
+ 			   linemap_position_for_column (line_table,
+ 							right_quote_byte_col));
+     ASSERT_STREQ ("            This: `      ' is a tab.\n"
+ 		  "                         ^\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Verify that the escaping machinery can cope with a variety of different
+    invalid bytes.  */
+ 
+ static void
+ test_escaping_bytes_1 (const line_table_case &case_)
+ {
+   const char content[] = "before\0\1\2\3\v\x80\xff""after\n";
+   const size_t sz = sizeof (content);
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz);
+   line_table_test ltt (case_);
+   const line_map_ordinary *ord_map = linemap_check_ordinary
+     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+   linemap_line_start (line_table, 1, 100);
+ 
+   location_t finish
+     = linemap_position_for_line_and_column (line_table, ord_map, 1,
+ 					    strlen (content));
+ 
+   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Locations of the NUL and \v bytes.  */
+   location_t nul_loc
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 7);
+   location_t v_loc
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 11);
+   gcc_rich_location richloc (nul_loc);
+   richloc.add_range (v_loc);
+ 
+   {
+     test_context dc;
+     ASSERT_STREQ (" before \1\2\3\v\x80\xff""after\n"
+ 		  "       ^   ~\n",
+ 		  dc.test_show_locus (richloc));
+   }
+   richloc.set_escape_on_output (true);
+   {
+     test_context dc;
+     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
+     ASSERT_STREQ
+       (" before<U+0000><U+0001><U+0002><U+0003><U+000B><80><ff>after\n"
+        "       ^~~~~~~~                        ~~~~~~~~\n",
+        dc.test_show_locus (richloc));
+   }
+   {
+     test_context dc;
+     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
+     ASSERT_STREQ (" before<00><01><02><03><0b><80><ff>after\n"
+ 		  "       ^~~~            ~~~~\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* As above, but verify that we handle the initial byte of a line
+    correctly.  */
+ 
+ static void
+ test_escaping_bytes_2 (const line_table_case &case_)
+ {
+   const char content[]  = "\0after\n";
+   const size_t sz = sizeof (content);
+   temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz);
+   line_table_test ltt (case_);
+   const line_map_ordinary *ord_map = linemap_check_ordinary
+     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+   linemap_line_start (line_table, 1, 100);
+ 
+   location_t finish
+     = linemap_position_for_line_and_column (line_table, ord_map, 1,
+ 					    strlen (content));
+ 
+   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+     return;
+ 
+   /* Location of the NUL byte.  */
+   location_t nul_loc
+     = linemap_position_for_line_and_column (line_table, ord_map, 1, 1);
+   gcc_rich_location richloc (nul_loc);
+ 
+   {
+     test_context dc;
+     ASSERT_STREQ ("  after\n"
+ 		  " ^\n",
+ 		  dc.test_show_locus (richloc));
+   }
+   richloc.set_escape_on_output (true);
+   {
+     test_context dc;
+     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE);
+     ASSERT_STREQ (" <U+0000>after\n"
+ 		  " ^~~~~~~~\n",
+ 		  dc.test_show_locus (richloc));
+   }
+   {
+     test_context dc;
+     dc.set_escape_format (DIAGNOSTICS_ESCAPE_FORMAT_BYTES);
+     ASSERT_STREQ (" <00>after\n"
+ 		  " ^~~~\n",
+ 		  dc.test_show_locus (richloc));
+   }
+ }
+ 
+ /* Verify that line numbers are correctly printed for the case of
+    a multiline range in which the width of the line numbers changes
+    (e.g. from "9" to "10").  */
+ 
+ static void
+ test_line_numbers_multiline_range ()
+ {
+   /* Create a tempfile and write some text to it.  */
+   pretty_printer pp;
+   for (int i = 0; i < 20; i++)
+     /* .........0000000001111111.
+    .............1234567890123456.  */
+     pp_printf (&pp, "this is line %i\n", i + 1);
+   temp_source_file tmp (SELFTEST_LOCATION, ".txt", pp_formatted_text (&pp));
+   line_table_test ltt;
+ 
+   const line_map_ordinary *ord_map = linemap_check_ordinary
+     (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+   linemap_line_start (line_table, 1, 100);
+ 
+   /* Create a multi-line location, starting at the "line" of line 9, with
+      a caret on the "is" of line 10, finishing on the "this" line 11.  */
+ 
+   location_t start
+     = linemap_position_for_line_and_column (line_table, ord_map, 9, 9);
+   location_t caret
+     = linemap_position_for_line_and_column (line_table, ord_map, 10, 6);
+   location_t finish
+     = linemap_position_for_line_and_column (line_table, ord_map, 11, 4);
+   location_t loc = make_location (caret, start, finish);
+ 
+   test_context dc;
+   dc.show_line_numbers (true);
+   auto &source_printing_opts = dc.get_source_printing_options ();
+   source_printing_opts.min_margin_width = 0;
+   gcc_rich_location richloc (loc);
+   ASSERT_STREQ (" 9 | this is line 9\n"
+ 		"   |         ~~~~~~\n"
+ 		"10 | this is line 10\n"
+ 		"   | ~~~~~^~~~~~~~~~\n"
+ 		"11 | this is line 11\n"
+ 		"   | ~~~~  \n",
+ 		dc.test_show_locus (richloc));
+ }
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ source_printing_cc_tests ()
+ {
+   test_line_span ();
+ 
+   test_layout_range_for_single_point ();
+   test_layout_range_for_single_line ();
+   test_layout_range_for_multiple_lines ();
+ 
+   test_display_widths ();
+ 
+   for_each_line_table_case (test_layout_x_offset_display_utf8);
+   for_each_line_table_case (test_layout_x_offset_display_tab);
+ 
+   test_get_line_bytes_without_trailing_whitespace ();
+ 
+   test_diagnostic_show_locus_unknown_location ();
+ 
+   for_each_line_table_case (test_diagnostic_show_locus_one_liner);
+   for_each_line_table_case (test_diagnostic_show_locus_one_liner_utf8);
+   for_each_line_table_case (test_add_location_if_nearby);
+   for_each_line_table_case (test_diagnostic_show_locus_fixit_lines);
+   for_each_line_table_case (test_fixit_consolidation);
+   for_each_line_table_case (test_overlapped_fixit_printing);
+   for_each_line_table_case (test_overlapped_fixit_printing_utf8);
+   for_each_line_table_case (test_overlapped_fixit_printing_2);
+   for_each_line_table_case (test_fixit_insert_containing_newline);
+   for_each_line_table_case (test_fixit_insert_containing_newline_2);
+   for_each_line_table_case (test_fixit_replace_containing_newline);
+   for_each_line_table_case (test_fixit_deletion_affecting_newline);
+   for_each_line_table_case (test_tab_expansion);
+   for_each_line_table_case (test_escaping_bytes_1);
+   for_each_line_table_case (test_escaping_bytes_2);
+ 
+   test_line_numbers_multiline_range ();
+ }
+ 
+ } // namespace diagnostics::selftest
+ } // namespace diagnostics
+ 
+ #endif /* #if CHECKING_P */
+ 
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic pop
+ #endif
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/state-graphs-to-dot.cc gcc-16-20250727/gcc/diagnostics/state-graphs-to-dot.cc
*** gcc-16-20250720/gcc/diagnostics/state-graphs-to-dot.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/state-graphs-to-dot.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,551 ----
+ /* Creating GraphViz .dot files from diagnostic state graphs.
+    Copyright (C) 2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ 
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #define INCLUDE_ALGORITHM
+ #define INCLUDE_MAP
+ #define INCLUDE_SET
+ #define INCLUDE_STRING
+ #define INCLUDE_VECTOR
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ 
+ #include "diagnostics/state-graphs.h"
+ #include "graphviz.h"
+ #include "xml.h"
+ #include "xml-printer.h"
+ #include "intl.h"
+ 
+ using namespace diagnostics;
+ using namespace diagnostics::state_graphs;
+ 
+ static int
+ get_depth (const digraphs::node &n)
+ {
+   int deepest_child = 0;
+   for (size_t i = 0; i < n.get_num_children (); ++i)
+       deepest_child = std::max (deepest_child,
+ 				get_depth (n.get_child (i)));
+   return deepest_child + 1;
+ }
+ 
+ static const char *
+ get_color_for_dynalloc_state (enum node_dynalloc_state dynalloc_st)
+ {
+   switch (dynalloc_st)
+     {
+     default:
+       gcc_unreachable ();
+       break;
+     case node_dynalloc_state::unknown:
+     case node_dynalloc_state::nonnull:
+       return nullptr;
+ 
+     case node_dynalloc_state::unchecked:
+       return "#ec7a08"; // pf-orange-400
+ 
+     case node_dynalloc_state::freed:
+       return "#cc0000"; // pf-red-100
+     }
+ }
+ 
+ static void
+ set_color_for_dynalloc_state (dot::attr_list &attrs,
+ 			      enum node_dynalloc_state state)
+ {
+   if (const char *color = get_color_for_dynalloc_state (state))
+     attrs.add (dot::id ("color"), dot::id (color));
+ }
+ 
+ class state_diagram : public dot::graph
+ {
+ public:
+   state_diagram (const diagnostics::digraphs::digraph &input_state_graph,
+ 		 const logical_locations::manager &logical_loc_mgr)
+   : m_logical_loc_mgr (logical_loc_mgr)
+   {
+     // "node [shape=plaintext]\n"
+     {
+       auto attr_stmt
+ 	= std::make_unique<dot::attr_stmt> (dot::attr_stmt::kind::node);
+       attr_stmt->m_attrs.add (dot::id ("shape"), dot::id ("plaintext"));
+       add_stmt (std::move (attr_stmt));
+     }
+ 
+     /* Determine which nodes are involved in edges.  */
+     for (size_t i = 0; i < input_state_graph.get_num_edges (); ++i)
+       {
+ 	auto &edge = input_state_graph.get_edge (i);
+ 	m_src_nodes.insert (&edge.get_src_node ());
+ 	m_dst_nodes.insert (&edge.get_dst_node ());
+       }
+ 
+     /* Recurse down the nodes in the state graph, creating subgraphs
+        and then eventually creating nodes, and recursively
+        creating XML tables, and adding ports for the endpoints of edges
+        where needed.  */
+ 
+     auto root_cluster
+       = std::make_unique<dot::subgraph> (dot::id ("cluster_memory_regions"));
+     for (size_t i = 0; i < input_state_graph.get_num_nodes (); ++i)
+       on_input_state_node (*root_cluster,
+ 			   state_node_ref (input_state_graph.get_node (i)));
+     add_stmt (std::move (root_cluster));
+ 
+     /* Now create dot edges for edges in input_stage_graph.  */
+     for (size_t i = 0; i < input_state_graph.get_num_edges (); ++i)
+       {
+ 	auto &edge = input_state_graph.get_edge (i);
+ 	auto &src_node = edge.get_src_node ();
+ 	auto &dst_node = edge.get_dst_node ();
+ 
+ 	auto src_port_id = m_src_node_to_port_id.find (&src_node);
+ 	if (src_port_id == m_src_node_to_port_id.end ())
+ 	  continue;
+ 	auto dst_port_id = m_dst_node_to_port_id.find (&dst_node);
+ 	if (dst_port_id == m_dst_node_to_port_id.end ())
+ 	  continue;
+ 
+ 	auto e = std::make_unique<dot::edge_stmt> (src_port_id->second,
+ 						   dst_port_id->second);
+ 	set_color_for_dynalloc_state
+ 	  (e->m_attrs, state_node_ref (dst_node).get_dynalloc_state ());
+ 
+ 	add_stmt (std::move (e));
+       }
+   }
+ 
+ private:
+   struct pending_edge
+   {
+     dot::node_id m_src_node_id;
+     std::string m_dst_region_id;
+   };
+ 
+   dot::id
+   get_id_for_region (const char *region_id)
+   {
+     gcc_assert (region_id);
+     return std::string ("cluster_region_") + region_id;
+   }
+ 
+   dot::id
+   make_id (state_node_ref state_node, bool cluster)
+   {
+     std::string input_node_id = state_node.m_node.get_id ();
+     if (cluster)
+       return std::string ("cluster_") + input_node_id;
+     else
+       return input_node_id;
+   }
+ 
+   bool
+   starts_node_p (state_node_ref state_node)
+   {
+     switch (state_node.get_node_kind ())
+       {
+       default:
+ 	return false;
+ 
+       case node_kind::stack:
+ 	/* We want all frames in the stack in the same table,
+ 	   so they are grouped.  */
+       case node_kind::dynalloc_buffer:
+       case node_kind::variable:
+ 	return true;
+       }
+   }
+ 
+   const char *
+   get_label_for_node (state_node_ref state_node)
+   {
+     switch (state_node.get_node_kind ())
+       {
+       default:
+ 	return nullptr;
+ 
+       case node_kind::globals:
+ 	return _("Globals");
+       case node_kind::code:
+ 	return _("Code");
+       case node_kind::stack:
+ 	return _("Stack");
+       case node_kind::heap_:
+ 	return _("Heap");
+       }
+   }
+ 
+   void
+   on_input_state_node (dot::subgraph &parent_subgraph,
+ 		       state_node_ref state_node)
+   {
+     dot::id sg_id = make_id (state_node, true);
+ 
+     if (starts_node_p (state_node))
+       {
+ 	// Create node with table
+ 	xml::element table ("table", false);
+ 	xml::printer xp (table);
+ 	xp.set_attr ("border", "0");
+ 	xp.set_attr ("cellborder", "1");
+ 	xp.set_attr ("cellspacing", "0");
+ 
+ 	const int max_depth = get_depth (state_node.m_node);
+ 	const int num_columns = max_depth + 2;
+ 
+ 	dot::id id_of_dot_node = make_id (state_node, false);
+ 	on_node_in_table (id_of_dot_node, xp, state_node,
+ 			  max_depth, 0, num_columns);
+ 
+ 	auto node = std::make_unique<dot::node_stmt> (std::move (id_of_dot_node));
+ 	node->m_attrs.add (dot::id ("shape"),
+ 			   dot::id ("plaintext"));
+ 
+ 	// xml must be done by now
+ 
+ 	node->m_attrs.add (dot::id ("label"),
+ 			   dot::id (table));
+ 
+ 	parent_subgraph.m_stmt_list.add_stmt (std::move (node));
+       }
+     else
+       {
+ 	auto child_subgraph = std::make_unique<dot::subgraph> (std::move (sg_id));
+ 
+ 	if (const char *label = get_label_for_node (state_node))
+ 	  child_subgraph->add_attr (dot::id ("label"), dot::id (label));
+ 
+ 	// recurse:
+ 	for (size_t i = 0; i < state_node.m_node.get_num_children (); ++i)
+ 	  on_input_state_node (*child_subgraph,
+ 			       state_node.m_node.get_child (i));
+ 	parent_subgraph.m_stmt_list.add_stmt (std::move (child_subgraph));
+       }
+   }
+ 
+   enum class style { h1, h2 };
+ 
+   void
+   add_title_tr (const dot::id &id_of_dot_node,
+ 		xml::printer &xp,
+ 		int num_columns,
+ 		state_node_ref state_node,
+ 		std::string heading,
+ 		enum style styl,
+ 		enum node_dynalloc_state dynalloc_state)
+   {
+     xp.push_tag ("tr", true);
+     xp.push_tag ("td", false);
+     xp.set_attr ("colspan", std::to_string (num_columns));
+     xp.set_attr ("cellpadding", "5");
+ 
+     const char *bgcolor;
+     const char *color;
+     if (const char *c = get_color_for_dynalloc_state (dynalloc_state))
+       {
+ 	bgcolor = c;
+ 	color = "white";
+       }
+     else
+       switch (styl)
+ 	{
+ 	default:
+ 	  gcc_unreachable ();
+ 	case style::h1:
+ 	  // from diagnostics/html-sink.cc: HTML_STYLE .linenum
+ 	  bgcolor = "#0088ce";
+ 	  color = "white";
+ 	  break;
+ 	case style::h2:
+ 	  // from diagnostics/html-sink.cc: HTML_STYLE .events-hdr
+ 	  bgcolor = "#393f44"; // pf-black-800
+ 	  color = "white";
+ 	  break;
+ 	}
+ 
+     xp.set_attr ("bgcolor", bgcolor);
+     xp.push_tag ("font", false);
+     xp.set_attr ("color", color);
+     if (heading == "")
+       heading = " ";
+     xp.add_text (std::move (heading));
+     xp.pop_tag ("font");
+ 
+     maybe_add_dst_port (id_of_dot_node, xp, state_node);
+ 
+     xp.pop_tag ("td");
+     xp.pop_tag ("tr");
+   }
+ 
+   /* Recursively add <TR> to XP for STATE_NODE and its descendents.  */
+   void
+   on_node_in_table (const dot::id &id_of_dot_node,
+ 		    xml::printer &xp,
+ 		    state_node_ref state_node,
+ 		    int max_depth,
+ 		    int depth,
+ 		    int num_columns)
+   {
+     bool recurse = true;
+     auto input_node_kind = state_node.get_node_kind ();
+ 
+     switch (input_node_kind)
+       {
+       case node_kind::padding:
+       case node_kind::other:
+ 	return;
+ 
+       case node_kind::stack:
+ 	add_title_tr (id_of_dot_node, xp, num_columns, state_node, "Stack",
+ 		      style::h1,
+ 		      node_dynalloc_state::unknown);
+ 	break;
+       case node_kind::stack_frame:
+ 	if (auto logical_loc = state_node.get_logical_loc ())
+ 	  if (const char *function
+ 		= m_logical_loc_mgr.get_short_name (logical_loc))
+ 	    add_title_tr (id_of_dot_node, xp, num_columns, state_node,
+ 			  std::string ("Frame: ") + function,
+ 			  style::h2,
+ 			  node_dynalloc_state::unknown);
+ 	break;
+       case node_kind::dynalloc_buffer:
+ 	{
+ 	  enum node_dynalloc_state dynalloc_st
+ 	    = state_node.get_dynalloc_state ();
+ 	  const char *extents = state_node.get_dynamic_extents ();
+ 	  const char *type = state_node.get_type ();
+ 	  pretty_printer pp;
+ 	  switch (dynalloc_st)
+ 	    {
+ 	    default:
+ 	      gcc_unreachable ();
+ 
+ 	    case node_dynalloc_state::unknown:
+ 	    case node_dynalloc_state::nonnull:
+ 	      if (type)
+ 		{
+ 		if (extents)
+ 		  pp_printf (&pp, "%s (%s byte allocation)",
+ 			     type, extents);
+ 		else
+ 		  pp_printf (&pp, "%s", type);
+ 		}
+ 	      else
+ 		{
+ 		  if (extents)
+ 		    pp_printf (&pp, "%s byte allocation",
+ 			       extents);
+ 		}
+ 	      break;
+ 
+ 	    case node_dynalloc_state::unchecked:
+ 	      if (type)
+ 		{
+ 		  if (extents)
+ 		    pp_printf (&pp, "%s (unchecked %s byte allocation)",
+ 			       type, extents);
+ 		}
+ 	      else
+ 		{
+ 		  if (extents)
+ 		    pp_printf (&pp, "Unchecked %s byte allocation",
+ 			       extents);
+ 		}
+ 	      break;
+ 
+ 	    case node_dynalloc_state::freed:
+ 	      // TODO: show deallocator
+ 	      // TODO: show deallocation event
+ 	      pp_printf (&pp, "Freed buffer");
+ 	      break;
+ 	    }
+ 	  maybe_add_dst_port (id_of_dot_node, xp, state_node);
+ 	  add_title_tr (id_of_dot_node, xp, num_columns, state_node,
+ 			pp_formatted_text (&pp),
+ 			style::h2,
+ 			dynalloc_st);
+ 	}
+ 	break;
+ 
+       default:
+ 	{
+ 	  xp.push_tag ("tr", true);
+ 
+ 	  maybe_add_dst_port (id_of_dot_node, xp, state_node);
+ 
+ 	  if (depth > 0)
+ 	    {
+ 	      /* Indent, by create a <td> spanning "depth" columns.  */
+ 	      xp.push_tag ("td", false);
+ 	      xp.set_attr ("colspan", std::to_string (depth));
+ 	      xp.add_text (" "); // graphviz doesn't like <td/>
+ 	      xp.pop_tag ("td");
+ 	    }
+ 
+ 	  switch (input_node_kind)
+ 	    {
+ 	    default:
+ 	      break;
+ 	    case node_kind::variable:
+ 	      {
+ 		const char *name = state_node.get_name ();
+ 		gcc_assert (name);
+ 		xp.push_tag ("td", false);
+ 		maybe_add_dst_port (id_of_dot_node, xp, state_node);
+ 		push_src_text (xp);
+ 		xp.add_text (name);
+ 		pop_src_text (xp);
+ 		xp.pop_tag ("td");
+ 	      }
+ 	      break;
+ 	    case node_kind::element:
+ 	      {
+ 		const char *index = state_node.get_index ();
+ 		gcc_assert (index);
+ 		xp.push_tag ("td", false);
+ 		maybe_add_dst_port (id_of_dot_node, xp, state_node);
+ 		push_src_text (xp);
+ 		xp.add_text ("[");
+ 		xp.add_text (index);
+ 		xp.add_text ("]");
+ 		pop_src_text (xp);
+ 		xp.pop_tag ("td");
+ 	      }
+ 	      break;
+ 	    case node_kind::field:
+ 	      {
+ 		const char *name = state_node.get_name ();
+ 		gcc_assert (name);
+ 		xp.push_tag ("td", false);
+ 		maybe_add_dst_port (id_of_dot_node, xp, state_node);
+ 		push_src_text (xp);
+ 		xp.add_text (".");
+ 		xp.add_text (name);
+ 		pop_src_text (xp);
+ 		xp.pop_tag ("td");
+ 	      }
+ 	      break;
+ 	    }
+ 
+ 	  if (const char *type = state_node.get_type ())
+ 	    {
+ 	      xp.push_tag ("td", false);
+ 	      xp.set_attr ("align", "right");
+ 	      push_src_text (xp);
+ 	      xp.add_text (type);
+ 	      pop_src_text (xp);
+ 	      xp.pop_tag ("td");
+ 	    }
+ 
+ 	  if (const char *value = state_node.get_value ())
+ 	    {
+ 	      xp.push_tag ("td", false);
+ 	      xp.set_attr ("align", "left");
+ 	      maybe_add_src_port (id_of_dot_node, xp, state_node);
+ 	      push_src_text (xp);
+ 	      xp.add_text (value);
+ 	      pop_src_text (xp);
+ 	      xp.pop_tag ("td");
+ 	      recurse = false;
+ 	    }
+ 	  xp.pop_tag ("tr");
+ 	}
+ 	break;
+       }
+ 
+     if (recurse)
+       for (size_t i = 0; i < state_node.m_node.get_num_children (); ++i)
+ 	on_node_in_table (id_of_dot_node, xp,
+ 			  state_node.m_node.get_child (i),
+ 			  max_depth, depth + 1, num_columns);
+   }
+ 
+   void
+   push_src_text (xml::printer &xp)
+   {
+     xp.push_tag ("font");
+     xp.set_attr ("color", "blue");
+   }
+ 
+   void
+   pop_src_text (xml::printer &xp)
+   {
+     xp.pop_tag ("font");
+   }
+ 
+   /* If STATE_NODE is in m_src_nodes, add a port to XP for possible
+      incoming edges to use.  */
+ 
+   void
+   maybe_add_src_port (const dot::id &id_of_dot_node,
+ 		      xml::printer &xp,
+ 		      state_node_ref state_node)
+   {
+     auto iter = m_src_nodes.find (&state_node.m_node);
+     if (iter == m_src_nodes.end ())
+       return;
+ 
+     dot::id src_id = make_id (state_node, false);
+     dot::node_id node_id (id_of_dot_node,
+ 			  dot::port (src_id,
+ 				     dot::compass_pt::e));
+     m_src_node_to_port_id.insert ({&state_node.m_node, node_id});
+     xp.set_attr ("port", src_id.m_str);
+   }
+ 
+   /* If STATE_NODE is in m_dst_nodes, add a port to XP for possible
+      incoming edges to use.  */
+ 
+   void
+   maybe_add_dst_port (const dot::id &id_of_dot_node,
+ 		      xml::printer &xp,
+ 		      state_node_ref state_node)
+   {
+     auto iter = m_dst_nodes.find (&state_node.m_node);
+     if (iter == m_dst_nodes.end ())
+       return;
+ 
+     dot::id dst_id = make_id (state_node, false);
+     dot::node_id node_id (id_of_dot_node,
+ 			  dot::port (dst_id/*,
+ 					     dot::compass_pt::w*/));
+     m_dst_node_to_port_id.insert ({&state_node.m_node, node_id});
+     xp.set_attr ("port", dst_id.m_str);
+   }
+ 
+ private:
+   const logical_locations::manager &m_logical_loc_mgr;
+ 
+   /* All nodes involved in edges (and thus will need a port).  */
+   std::set<digraphs::node *> m_src_nodes;
+   std::set<digraphs::node *> m_dst_nodes;
+ 
+   std::map<digraphs::node *, dot::node_id> m_src_node_to_port_id;
+   std::map<digraphs::node *, dot::node_id> m_dst_node_to_port_id;
+ };
+ 
+ std::unique_ptr<dot::graph>
+ state_graphs::
+ make_dot_graph (const digraphs::digraph &state_graph,
+ 		const logical_locations::manager &logical_loc_mgr)
+ {
+   return std::make_unique<state_diagram> (state_graph, logical_loc_mgr);
+ }
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/state-graphs.cc gcc-16-20250727/gcc/diagnostics/state-graphs.cc
*** gcc-16-20250720/gcc/diagnostics/state-graphs.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/state-graphs.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,156 ----
+ /* Extensions to diagnostics::digraphs to support state graphs.
+    Copyright (C) 2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ 
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #define INCLUDE_ALGORITHM
+ #define INCLUDE_MAP
+ #define INCLUDE_SET
+ #define INCLUDE_STRING
+ #define INCLUDE_VECTOR
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ 
+ #include "diagnostics/state-graphs.h"
+ #include "selftest.h"
+ 
+ using namespace diagnostics::state_graphs;
+ 
+ const char * const node_kind_strs[] = {
+   "globals",
+   "code",
+   "function",
+   "stack",
+   "stack-frame",
+   "heap",
+   "thread-local",
+   "dynalloc-buffer",
+   "variable",
+   "field",
+   "padding",
+   "element",
+   "other",
+ };
+ 
+ const char *
+ diagnostics::state_graphs::node_kind_to_str (enum node_kind k)
+ {
+   return node_kind_strs[static_cast<int> (k)];
+ }
+ 
+ // struct state_node_ref
+ 
+ enum node_kind
+ state_node_ref::get_node_kind () const
+ {
+   const char *value = get_attr ("kind");
+   if (!value)
+     return node_kind::other;
+ 
+   for (size_t i = 0; i < ARRAY_SIZE (node_kind_strs); ++i)
+     if (!strcmp (node_kind_strs[i], value))
+       return static_cast<enum node_kind> (i);
+ 
+   return node_kind::other;
+ }
+ 
+ void
+ state_node_ref::set_node_kind (enum node_kind k)
+ {
+   set_attr ("kind", node_kind_to_str (k));
+ }
+ 
+ const char * const dynalloc_state_strs[] = {
+   "unknown",
+   "nonnull",
+   "unchecked",
+   "freed"
+ };
+ 
+ enum node_dynalloc_state
+ state_node_ref::get_dynalloc_state () const
+ {
+   const char *value = get_attr ("dynalloc-state");
+   if (!value)
+     return node_dynalloc_state::unknown;
+ 
+   for (size_t i = 0; i < ARRAY_SIZE (dynalloc_state_strs); ++i)
+     if (!strcmp (dynalloc_state_strs[i], value))
+       return static_cast<enum node_dynalloc_state> (i);
+   
+   return node_dynalloc_state::unknown;
+ }
+ 
+ void
+ state_node_ref::set_dynalloc_state (enum node_dynalloc_state s) const
+ {
+   set_attr ("dynalloc-state",
+ 	    dynalloc_state_strs[static_cast <size_t> (s)]);
+ }
+ 
+ const char *
+ state_node_ref::get_dynamic_extents () const
+ {
+   return m_node.get_attr (STATE_NODE_PREFIX, "dynamic-extents");
+ }
+ 
+ void
+ state_node_ref::set_json_attr (const char *key,
+ 			       std::unique_ptr<json::value> value) const
+ {
+   m_node.set_json_attr (STATE_NODE_PREFIX, key, std::move (value));
+ }
+ 
+ #if CHECKING_P
+ 
+ namespace diagnostics {
+ namespace selftest {
+ 
+ static void
+ test_node_attrs ()
+ {
+   digraphs::digraph g;
+   digraphs::node n (g, "a");
+   state_node_ref node_ref (n);
+ 
+   ASSERT_EQ (node_ref.get_node_kind (), node_kind::other);
+   node_ref.set_node_kind (node_kind::stack);
+   ASSERT_EQ (node_ref.get_node_kind (), node_kind::stack);
+ 
+   ASSERT_EQ (node_ref.get_dynalloc_state (), node_dynalloc_state::unknown);
+   node_ref.set_dynalloc_state (node_dynalloc_state::freed);
+   ASSERT_EQ (node_ref.get_dynalloc_state (), node_dynalloc_state::freed);
+ 
+   ASSERT_EQ (node_ref.get_type (), nullptr);
+   node_ref.set_type ("const char *");
+   ASSERT_STREQ (node_ref.get_type (), "const char *");
+ }
+ 
+ /* Run all of the selftests within this file.  */
+ 
+ void
+ state_graphs_cc_tests ()
+ {
+   test_node_attrs ();
+ }
+ 
+ } // namespace diagnostics::selftest
+ } // namespace diagnostics
+ 
+ #endif /* CHECKING_P */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/state-graphs.h gcc-16-20250727/gcc/diagnostics/state-graphs.h
*** gcc-16-20250720/gcc/diagnostics/state-graphs.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/state-graphs.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,156 ----
+ /* Extensions to diagnostics::digraphs to support state graphs.
+    Copyright (C) 2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_STATE_GRAPHS_H
+ #define GCC_DIAGNOSTICS_STATE_GRAPHS_H
+ 
+ #include "diagnostics/digraphs.h"
+ #include "diagnostics/logical-locations.h"
+ 
+ /* diagnostics::digraphs provides support for directed graphs.
+ 
+    diagnostics::state_graphs provides a way to extend these graphs
+    for representing "state graphs" i.e. a representation of the state
+    of memory inside a program, for use e.g. by -fanalyzer.
+ 
+    Specifically, nodes represent memory regions, and we use property bags
+    in these nodes to stash extra properties (e.g. what kind of memory region
+    a node is e.g. stack vs heap).  */
+ 
+ class sarif_graph;
+ namespace dot { class graph; }
+ 
+ namespace diagnostics {
+ namespace state_graphs {
+ 
+ enum class node_kind
+ {
+   // Memory regions
+   globals,
+   code,
+   function, // code within a particular function
+   stack,
+   stack_frame,
+   heap_,
+   thread_local_,
+ 
+   /* Dynamically-allocated buffer,
+      on heap or stack (depending on parent).  */
+   dynalloc_buffer,
+ 
+   variable,
+ 
+   field, // field within a struct or union
+   padding, // padding bits in a struct or union
+   element, // element within an array
+ 
+   other // anything else
+ };
+ 
+ extern const char *
+ node_kind_to_str (enum node_kind);
+ 
+ enum class node_dynalloc_state
+ {
+   unknown,
+   nonnull,
+   unchecked,
+   freed
+ };
+ 
+ /* Prefixes to use in SARIF property bags.  */
+ #define STATE_GRAPH_PREFIX "gcc/diagnostic_state_graph/"
+ #define STATE_NODE_PREFIX "gcc/diagnostic_state_node/"
+ #define STATE_EDGE_PREFIX "gcc/diagnostic_state_edge/"
+ 
+ /* A wrapper around a node that gets/sets attributes, using
+    the node's property bag for storage, so that the data roundtrips
+    through SARIF.  */
+ 
+ struct state_node_ref
+ {
+   state_node_ref (diagnostics::digraphs::node &node)
+   : m_node (node)
+   {}
+ 
+   enum node_kind
+   get_node_kind () const;
+   void
+   set_node_kind (enum node_kind);
+ 
+   // For node_kind::stack_frame, this will be the function
+   logical_locations::key
+   get_logical_loc () const
+   {
+     return m_node.get_logical_loc ();
+   }
+ 
+   // For node_kind::dynalloc_buffer
+   enum node_dynalloc_state
+   get_dynalloc_state () const;
+ 
+   void
+   set_dynalloc_state (enum node_dynalloc_state) const;
+ 
+   const char *
+   get_dynamic_extents () const;
+ 
+   const char *
+   get_name () const { return get_attr ("name"); }
+   void
+   set_name (const char *name) const { set_attr ("name", name); }
+ 
+   const char *
+   get_type () const { return get_attr ("type"); }
+   void
+   set_type (const char *type) const { set_attr ("type", type); }
+ 
+   const char *
+   get_value () const { return get_attr ("value"); }
+ 
+   const char *
+   get_index () const { return get_attr ("index"); }
+ 
+   const char *
+   get_attr (const char *key) const
+   {
+     return m_node.get_attr (STATE_NODE_PREFIX, key);
+   }
+ 
+   void
+   set_attr (const char *key, const char *value) const
+   {
+     return m_node.set_attr (STATE_NODE_PREFIX, key, value);
+   }
+ 
+   void
+   set_json_attr (const char *key, std::unique_ptr<json::value> value) const;
+ 
+   diagnostics::digraphs::node &m_node;
+ };
+ 
+ extern std::unique_ptr<dot::graph>
+ make_dot_graph (const diagnostics::digraphs::digraph &state_graph,
+ 		const logical_locations::manager &logical_loc_mgr);
+ 
+ } // namespace state_graphs
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_STATE_GRAPHS_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/text-sink.cc gcc-16-20250727/gcc/diagnostics/text-sink.cc
*** gcc-16-20250720/gcc/diagnostics/text-sink.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/text-sink.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,728 ----
+ /* Classic text-based output of diagnostics.
+    Copyright (C) 1999-2025 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ 
+ #include "config.h"
+ #define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "version.h"
+ #include "intl.h"
+ #include "diagnostic.h"
+ #include "diagnostics/color.h"
+ #include "diagnostics/url.h"
+ #include "diagnostics/metadata.h"
+ #include "diagnostics/paths.h"
+ #include "diagnostics/client-data-hooks.h"
+ #include "diagnostics/diagram.h"
+ #include "diagnostics/text-sink.h"
+ #include "diagnostics/buffering.h"
+ #include "text-art/theme.h"
+ 
+ /* Disable warnings about quoting issues in the pp_xxx calls below
+    that (intentionally) don't follow GCC diagnostic conventions.  */
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic push
+ #  pragma GCC diagnostic ignored "-Wformat-diag"
+ #endif
+ 
+ namespace diagnostics {
+ 
+ /* Concrete buffering implementation subclass for text output.  */
+ 
+ class text_sink_buffer : public per_sink_buffer
+ {
+ public:
+   friend class text_sink;
+ 
+   text_sink_buffer (sink &sink_);
+ 
+   void dump (FILE *out, int indent) const final override;
+ 
+   bool empty_p () const final override;
+   void move_to (per_sink_buffer &dest) final override;
+   void clear () final override;
+   void flush () final override;
+ 
+ private:
+   sink &m_sink;
+   output_buffer m_output_buffer;
+ };
+ 
+ /* class text_sink_buffer : public per_sink_buffer.  */
+ 
+ text_sink_buffer::text_sink_buffer (sink &sink_)
+ : m_sink (sink_)
+ {
+   m_output_buffer.m_flush_p = false;
+ }
+ 
+ void
+ text_sink_buffer::dump (FILE *out, int indent) const
+ {
+   fprintf (out, "%*stext_sink_buffer:\n", indent, "");
+   m_output_buffer.dump (out, indent + 2);
+ }
+ 
+ bool
+ text_sink_buffer::empty_p () const
+ {
+   return output_buffer_last_position_in_text (&m_output_buffer) == nullptr;
+ }
+ 
+ void
+ text_sink_buffer::move_to (per_sink_buffer &base_dest)
+ {
+   text_sink_buffer &dest
+     = static_cast<text_sink_buffer &> (base_dest);
+   const char *str = output_buffer_formatted_text (&m_output_buffer);
+   output_buffer_append_r (&dest.m_output_buffer, str, strlen (str));
+ 
+   obstack_free (m_output_buffer.m_obstack,
+ 		obstack_base (m_output_buffer.m_obstack));
+   m_output_buffer.m_line_length = 0;
+ }
+ 
+ void
+ text_sink_buffer::clear ()
+ {
+   pretty_printer *const pp = m_sink.get_printer ();
+   output_buffer *const old_output_buffer = pp_buffer (pp);
+ 
+   pp_buffer (pp) = &m_output_buffer;
+ 
+   pp_clear_output_area (pp);
+   gcc_assert (empty_p ());
+ 
+   pp_buffer (pp) = old_output_buffer;
+ }
+ 
+ void
+ text_sink_buffer::flush ()
+ {
+   pretty_printer *const pp = m_sink.get_printer ();
+   output_buffer *const old_output_buffer = pp_buffer (pp);
+ 
+   pp_buffer (pp) = &m_output_buffer;
+ 
+   pp_really_flush (pp);
+   gcc_assert (empty_p ());
+ 
+   pp_buffer (pp) = old_output_buffer;
+ }
+ 
+ /* class diagnostics::text_sink : public diagnostics::sink.  */
+ 
+ text_sink::~text_sink ()
+ {
+   /* Some of the errors may actually have been warnings.  */
+   if (m_context.diagnostic_count (kind::werror))
+     {
+       pretty_printer *pp = get_printer ();
+       /* -Werror was given.  */
+       if (m_context.warning_as_error_requested_p ())
+ 	pp_verbatim (pp,
+ 		     _("%s: all warnings being treated as errors"),
+ 		     progname);
+       /* At least one -Werror= was given.  */
+       else
+ 	pp_verbatim (pp,
+ 		     _("%s: some warnings being treated as errors"),
+ 		     progname);
+       pp_newline_and_flush (pp);
+     }
+ 
+   if (m_includes_seen)
+     {
+       delete m_includes_seen;
+       m_includes_seen = nullptr;
+     }
+ }
+ 
+ void
+ text_sink::dump (FILE *out, int indent) const
+ {
+   fprintf (out, "%*stext_sink\n", indent, "");
+   fprintf (out, "%*sm_follows_reference_printer: %s\n",
+ 	   indent, "",
+ 	   m_follows_reference_printer ? "true" : "false");
+   sink::dump (out, indent);
+   fprintf (out, "%*ssaved_output_buffer:\n", indent + 2, "");
+   if (m_saved_output_buffer)
+     m_saved_output_buffer->dump (out, indent + 4);
+   else
+     fprintf (out, "%*s(none):\n", indent + 4, "");
+ }
+ 
+ void
+ text_sink::set_buffer (per_sink_buffer *base)
+ {
+   text_sink_buffer * const buffer
+     = static_cast<text_sink_buffer *> (base);
+ 
+   pretty_printer *const pp = get_printer ();
+ 
+   if (!m_saved_output_buffer)
+     m_saved_output_buffer = pp_buffer (pp);
+ 
+   if (buffer)
+     pp_buffer (pp) = &buffer->m_output_buffer;
+   else
+     {
+       gcc_assert (m_saved_output_buffer);
+       pp_buffer (pp) = m_saved_output_buffer;
+     }
+ }
+ 
+ std::unique_ptr<per_sink_buffer>
+ text_sink::make_per_sink_buffer ()
+ {
+   return std::make_unique<text_sink_buffer> (*this);
+ }
+ 
+ /* Implementation of diagnostics::sink::on_report_diagnostic vfunc
+    for GCC's standard textual output.  */
+ 
+ void
+ text_sink::on_report_diagnostic (const diagnostic_info &diagnostic,
+ 				 enum kind orig_diag_kind)
+ {
+   pretty_printer *pp = get_printer ();
+ 
+   (*text_starter (&m_context)) (*this, &diagnostic);
+ 
+   pp_output_formatted_text (pp, m_context.get_urlifier ());
+ 
+   if (m_context.m_show_cwe)
+     print_any_cwe (diagnostic);
+ 
+   if (m_context.m_show_rules)
+     print_any_rules (diagnostic);
+ 
+   if (m_context.m_show_option_requested)
+     print_option_information (diagnostic, orig_diag_kind);
+ 
+   /* If we're showing nested diagnostics, then print the location
+      on a new line, indented.  */
+   if (m_show_nesting && m_show_locations_in_nesting)
+     {
+       const int nesting_level = get_context ().get_diagnostic_nesting_level ();
+       if (nesting_level > 0)
+ 	{
+ 	  location_t loc = diagnostic_location (&diagnostic);
+ 	  pp_set_prefix (pp, nullptr);
+ 	  char *indent_prefix = build_indent_prefix (false);
+ 	  /* Only print changes of location.  */
+ 	  if (loc != get_context ().m_last_location
+ 	      && loc > BUILTINS_LOCATION)
+ 	    {
+ 	      const expanded_location s
+ 		= diagnostic_expand_location (&diagnostic);
+ 	      label_text location_text = get_location_text (s);
+ 	      pp_newline (pp);
+ 	      pp_printf (pp, "%s%s", indent_prefix, location_text.get ());
+ 	    }
+ 	  pp_set_prefix (pp, indent_prefix);
+ 	}
+     }
+ 
+   (*text_finalizer (&m_context)) (*this,
+ 				  &diagnostic,
+ 				  orig_diag_kind);
+ 
+   if (m_show_nesting && m_show_locations_in_nesting)
+     get_context ().m_last_location = diagnostic_location (&diagnostic);
+ }
+ 
+ void
+ text_sink::on_report_verbatim (text_info &text)
+ {
+   pp_format_verbatim (get_printer (), &text);
+   pp_newline_and_flush (get_printer ());
+ }
+ 
+ void
+ text_sink::on_diagram (const diagnostics::diagram &d)
+ {
+   pretty_printer *const pp = get_printer ();
+ 
+   char *saved_prefix = pp_take_prefix (pp);
+   pp_set_prefix (pp, nullptr);
+   /* Use a newline before and after and a two-space indent
+      to make the diagram stand out a little from the wall of text.  */
+   pp_newline (pp);
+   d.get_canvas ().print_to_pp (pp, "  ");
+   pp_newline (pp);
+   pp_set_prefix (pp, saved_prefix);
+   pp_flush (pp);
+ }
+ 
+ void
+ text_sink::
+ after_diagnostic (const diagnostic_info &diagnostic)
+ {
+   if (const paths::path *path = diagnostic.m_richloc->get_path ())
+     print_path (*path);
+ }
+ 
+ /* Return a malloc'd string describing a location and the severity of the
+    diagnostic, e.g. "foo.c:42:10: error: ".
+ 
+    If m_show_nesting, then the above will be preceded by indentation to show
+    the level, and a bullet point.
+ 
+    The caller is responsible for freeing the memory.  */
+ char *
+ text_sink::build_prefix (const diagnostic_info &diagnostic) const
+ {
+   gcc_assert (diagnostic.m_kind < kind::last_diagnostic_kind);
+ 
+   const char *text = _(get_text_for_kind (diagnostic.m_kind));
+   const char *text_cs = "", *text_ce = "";
+   pretty_printer *pp = get_printer ();
+ 
+   if (const char *color_name = get_color_for_kind (diagnostic.m_kind))
+     {
+       text_cs = colorize_start (pp_show_color (pp), color_name);
+       text_ce = colorize_stop (pp_show_color (pp));
+     }
+ 
+   const int nesting_level = get_context ().get_diagnostic_nesting_level ();
+   if (m_show_nesting && nesting_level > 0)
+     {
+       char *indent_prefix = build_indent_prefix (true);
+ 
+       /* Reduce verbosity of nested diagnostics by not printing "note: "
+ 	 all the time.  */
+       if (diagnostic.m_kind == kind::note)
+ 	return indent_prefix;
+ 
+       char *result = build_message_string ("%s%s%s%s", indent_prefix,
+ 					   text_cs, text, text_ce);
+       free (indent_prefix);
+       return result;
+     }
+   else
+     {
+       const expanded_location s = diagnostic_expand_location (&diagnostic);
+       label_text location_text = get_location_text (s);
+       return build_message_string ("%s %s%s%s", location_text.get (),
+ 				   text_cs, text, text_ce);
+     }
+ }
+ 
+ /* Same as build_prefix, but only the source FILE is given.  */
+ char *
+ text_sink::file_name_as_prefix (const char *f) const
+ {
+   pretty_printer *const pp = get_printer ();
+   const char *locus_cs
+     = colorize_start (pp_show_color (pp), "locus");
+   const char *locus_ce = colorize_stop (pp_show_color (pp));
+   return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
+ }
+ 
+ /* Get the unicode code point for bullet points when showing
+    nested diagnostics.  */
+ 
+ static unsigned
+ get_bullet_point_unichar (bool unicode)
+ {
+   if (unicode)
+     return 0x2022; /* U+2022: Bullet */
+   else
+     return '*';
+ }
+ 
+ /* Return true if DC's theme supports unicode characters.  */
+ 
+ static bool
+ use_unicode_p (const context &dc)
+ {
+   if (text_art::theme *theme = dc.get_diagram_theme ())
+     return theme->unicode_p ();
+   else
+     return false;
+ }
+ 
+ /* Get the unicode code point for bullet points when showing
+    nested diagnostics.  */
+ 
+ static unsigned
+ get_bullet_point_unichar (context &dc)
+ {
+   return get_bullet_point_unichar (use_unicode_p (dc));
+ }
+ 
+ /* Return a malloc'd string for use as a prefix to show indentation.
+    If m_show_nesting is false, or we're at the top-level, then the
+    result will be the empty string.
+ 
+    If m_show_nesting, then the result will contain indentation to show
+    the nesting level, then either a bullet point (if WITH_BULLET is true),
+    or a space.
+ 
+    The caller is responsible for freeing the memory.  */
+ 
+ char *
+ text_sink::build_indent_prefix (bool with_bullet) const
+ {
+   if (!m_show_nesting)
+     return xstrdup ("");
+ 
+   const int nesting_level = get_context ().get_diagnostic_nesting_level ();
+   if (nesting_level == 0)
+     return xstrdup ("");
+ 
+   pretty_printer pp;
+   for (int i = 0; i < nesting_level; i++)
+     pp_string (&pp, "  ");
+   if (with_bullet)
+     pp_unicode_character (&pp, get_bullet_point_unichar (get_context ()));
+   else
+     pp_space (&pp);
+   pp_space (&pp);
+   if (m_show_nesting_levels)
+     pp_printf (&pp, "(level %i):", nesting_level);
+   return xstrdup (pp_formatted_text (&pp));
+ }
+ 
+ /* Add a purely textual note with text GMSGID and with LOCATION.  */
+ 
+ void
+ text_sink::append_note (location_t location,
+ 			const char * gmsgid, ...)
+ {
+   context *dc = &get_context ();
+ 
+   diagnostic_info diagnostic;
+   va_list ap;
+   rich_location richloc (line_table, location);
+ 
+   va_start (ap, gmsgid);
+   diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, kind::note);
+   if (dc->m_inhibit_notes_p)
+     {
+       va_end (ap);
+       return;
+     }
+   pretty_printer *pp = get_printer ();
+   char *saved_prefix = pp_take_prefix (pp);
+   pp_set_prefix (pp, build_prefix (diagnostic));
+   pp_format (pp, &diagnostic.m_message);
+   pp_output_formatted_text (pp);
+   pp_destroy_prefix (pp);
+   pp_set_prefix (pp, saved_prefix);
+   pp_newline (pp);
+   diagnostic_show_locus (dc, get_source_printing_options (),
+ 			 &richloc, kind::note, pp);
+   va_end (ap);
+ }
+ 
+ bool
+ text_sink::follows_reference_printer_p () const
+ {
+   return m_follows_reference_printer;
+ }
+ 
+ void
+ text_sink::update_printer ()
+ {
+   pretty_printer *copy_from_pp
+     = (m_follows_reference_printer
+        ? get_context ().get_reference_printer ()
+        : m_printer.get ());
+   const bool show_color = pp_show_color (copy_from_pp);
+   const diagnostic_url_format url_format = copy_from_pp->get_url_format ();
+ 
+   m_printer = get_context ().clone_printer ();
+ 
+   pp_show_color (m_printer.get ()) = show_color;
+   m_printer->set_url_format (url_format);
+   // ...etc
+ 
+   m_source_printing = get_context ().m_source_printing;
+ }
+ 
+ /* If DIAGNOSTIC has a CWE identifier, print it.
+ 
+    For example, if the diagnostic metadata associates it with CWE-119,
+    " [CWE-119]" will be printed, suitably colorized, and with a URL of a
+    description of the security issue.  */
+ 
+ void
+ text_sink::print_any_cwe (const diagnostic_info &diagnostic)
+ {
+   if (!diagnostic.m_metadata)
+     return;
+ 
+   int cwe = diagnostic.m_metadata->get_cwe ();
+   if (cwe)
+     {
+       pretty_printer * const pp = get_printer ();
+       char *saved_prefix = pp_take_prefix (pp);
+       pp_string (pp, " [");
+       const char *kind_color = get_color_for_kind (diagnostic.m_kind);
+       pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
+       if (pp->supports_urls_p ())
+ 	{
+ 	  char *cwe_url = get_cwe_url (cwe);
+ 	  pp_begin_url (pp, cwe_url);
+ 	  free (cwe_url);
+ 	}
+       pp_printf (pp, "CWE-%i", cwe);
+       pp_set_prefix (pp, saved_prefix);
+       if (pp->supports_urls_p ())
+ 	pp_end_url (pp);
+       pp_string (pp, colorize_stop (pp_show_color (pp)));
+       pp_character (pp, ']');
+     }
+ }
+ 
+ /* If DIAGNOSTIC has any rules associated with it, print them.
+ 
+    For example, if the diagnostic metadata associates it with a rule
+    named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
+    with any URL provided by the rule.  */
+ 
+ void
+ text_sink::print_any_rules (const diagnostic_info &diagnostic)
+ {
+   if (!diagnostic.m_metadata)
+     return;
+ 
+   for (unsigned idx = 0; idx < diagnostic.m_metadata->get_num_rules (); idx++)
+     {
+       const diagnostics::metadata::rule &rule
+ 	= diagnostic.m_metadata->get_rule (idx);
+       if (char *desc = rule.make_description ())
+ 	{
+ 	  pretty_printer * const pp = get_printer ();
+ 	  char *saved_prefix = pp_take_prefix (pp);
+ 	  pp_string (pp, " [");
+ 	  const char *kind_color = get_color_for_kind (diagnostic.m_kind);
+ 	  pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
+ 	  char *url = nullptr;
+ 	  if (pp->supports_urls_p ())
+ 	    {
+ 	      url = rule.make_url ();
+ 	      if (url)
+ 		pp_begin_url (pp, url);
+ 	    }
+ 	  pp_string (pp, desc);
+ 	  pp_set_prefix (pp, saved_prefix);
+ 	  if (pp->supports_urls_p ())
+ 	    if (url)
+ 	      pp_end_url (pp);
+ 	  free (url);
+ 	  pp_string (pp, colorize_stop (pp_show_color (pp)));
+ 	  pp_character (pp, ']');
+ 	  free (desc);
+ 	}
+     }
+ }
+ 
+ /* Print any metadata about the option used to control DIAGNOSTIC to
+    the context's printer, e.g. " [-Werror=uninitialized]".  */
+ 
+ void
+ text_sink::print_option_information (const diagnostic_info &diagnostic,
+ 				     enum kind orig_diag_kind)
+ {
+   if (char *option_text
+       = m_context.make_option_name (diagnostic.m_option_id,
+ 				    orig_diag_kind, diagnostic.m_kind))
+     {
+       char *option_url = nullptr;
+       pretty_printer * const pp = get_printer ();
+       if (pp->supports_urls_p ())
+ 	option_url = m_context.make_option_url (diagnostic.m_option_id);
+       pp_string (pp, " [");
+       const char *kind_color = get_color_for_kind (diagnostic.m_kind);
+       pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
+       if (option_url)
+ 	pp_begin_url (pp, option_url);
+       pp_string (pp, option_text);
+       if (option_url)
+ 	{
+ 	  pp_end_url (pp);
+ 	  free (option_url);
+ 	}
+       pp_string (pp, colorize_stop (pp_show_color (pp)));
+       pp_character (pp, ']');
+       free (option_text);
+     }
+ }
+ 
+ /* Only dump the "In file included from..." stack once for each file.  */
+ 
+ bool
+ text_sink::includes_seen_p (const line_map_ordinary *map)
+ {
+   /* No include path for main.  */
+   if (MAIN_FILE_P (map))
+     return true;
+ 
+   /* Always identify C++ modules, at least for now.  */
+   auto probe = map;
+   if (linemap_check_ordinary (map)->reason == LC_RENAME)
+     /* The module source file shows up as LC_RENAME inside LC_MODULE.  */
+     probe = linemap_included_from_linemap (line_table, map);
+   if (MAP_MODULE_P (probe))
+     return false;
+ 
+   if (!m_includes_seen)
+     m_includes_seen = new hash_set<location_t, false, location_hash>;
+ 
+   /* Hash the location of the #include directive to better handle files
+      that are included multiple times with different macros defined.  */
+   return m_includes_seen->add (linemap_included_from (map));
+ }
+ 
+ label_text
+ text_sink::get_location_text (const expanded_location &s) const
+ {
+   column_policy column_policy_ (get_context ());
+   return column_policy_.get_location_text (s,
+ 					   show_column_p (),
+ 					   pp_show_color (get_printer ()));
+ }
+ 
+ /* Helpers for writing lang-specific starters/finalizers for text output.  */
+ 
+ /* Return a formatted line and column ':%line:%column'.  Elided if
+    line == 0 or col < 0.  (A column of 0 may be valid due to the
+    -fdiagnostics-column-origin option.)
+    The result is a statically allocated buffer.  */
+ 
+ const char *
+ maybe_line_and_column (int line, int col)
+ {
+   static char result[32];
+ 
+   if (line)
+     {
+       size_t l
+ 	= snprintf (result, sizeof (result),
+ 		    col >= 0 ? ":%d:%d" : ":%d", line, col);
+       gcc_checking_assert (l < sizeof (result));
+     }
+   else
+     result[0] = 0;
+   return result;
+ }
+ 
+ void
+ text_sink::report_current_module (location_t where)
+ {
+   pretty_printer *pp = get_printer ();
+   const line_map_ordinary *map = nullptr;
+ 
+   if (pp_needs_newline (pp))
+     {
+       pp_newline (pp);
+       pp_needs_newline (pp) = false;
+     }
+ 
+   if (where <= BUILTINS_LOCATION)
+     return;
+ 
+   linemap_resolve_location (line_table, where,
+ 			    LRK_MACRO_DEFINITION_LOCATION,
+ 			    &map);
+ 
+   if (map && m_last_module != map)
+     {
+       m_last_module = map;
+       if (!includes_seen_p (map))
+ 	{
+ 	  bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
+ 	  expanded_location s = {};
+ 	  do
+ 	    {
+ 	      where = linemap_included_from (map);
+ 	      map = linemap_included_from_linemap (line_table, map);
+ 	      bool is_module = MAP_MODULE_P (map);
+ 	      s.file = LINEMAP_FILE (map);
+ 	      s.line = SOURCE_LINE (map, where);
+ 	      int col = -1;
+ 	      if (first && show_column_p ())
+ 		{
+ 		  s.column = SOURCE_COLUMN (map, where);
+ 		  col = get_column_policy ().converted_column (s);
+ 		}
+ 	      const char *line_col = maybe_line_and_column (s.line, col);
+ 	      static const char *const msgs[] =
+ 		{
+ 		 nullptr,
+ 		 N_("                 from"),
+ 		 N_("In file included from"),	/* 2 */
+ 		 N_("        included from"),
+ 		 N_("In module"),		/* 4 */
+ 		 N_("of module"),
+ 		 N_("In module imported at"),	/* 6 */
+ 		 N_("imported at"),
+ 		};
+ 
+ 	      unsigned index = (was_module ? 6 : is_module ? 4
+ 				: need_inc ? 2 : 0) + !first;
+ 
+ 	      pp_verbatim (pp, "%s%s %r%s%s%R",
+ 			   first ? "" : was_module ? ", " : ",\n",
+ 			   _(msgs[index]),
+ 			   "locus", s.file, line_col);
+ 	      first = false, need_inc = was_module, was_module = is_module;
+ 	    }
+ 	  while (!includes_seen_p (map));
+ 	  pp_verbatim (pp, ":");
+ 	  pp_newline (pp);
+ 	}
+     }
+ }
+ 
+ void
+ default_text_starter (text_sink &text_output,
+ 		      const diagnostic_info *diagnostic)
+ {
+   text_output.report_current_module (diagnostic_location (diagnostic));
+   pretty_printer *const pp = text_output.get_printer ();
+   pp_set_prefix (pp, text_output.build_prefix (*diagnostic));
+ }
+ 
+ void
+ default_text_finalizer (text_sink &text_output,
+ 			const diagnostic_info *diagnostic,
+ 			enum kind)
+ {
+   pretty_printer *const pp = text_output.get_printer ();
+   char *saved_prefix = pp_take_prefix (pp);
+   pp_set_prefix (pp, nullptr);
+   pp_newline (pp);
+   diagnostic_show_locus (&text_output.get_context (),
+ 			 text_output.get_source_printing_options (),
+ 			 diagnostic->m_richloc, diagnostic->m_kind, pp);
+   pp_set_prefix (pp, saved_prefix);
+   pp_flush (pp);
+ }
+ 
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic pop
+ #endif
+ 
+ } // namespace diagnostics
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/text-sink.h gcc-16-20250727/gcc/diagnostics/text-sink.h
*** gcc-16-20250720/gcc/diagnostics/text-sink.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/text-sink.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,176 ----
+ /* Classic text-based output of diagnostics.
+    Copyright (C) 2023-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_TEXT_SINK_H
+ #define GCC_DIAGNOSTICS_TEXT_SINK_H
+ 
+ #include "diagnostics/sink.h"
+ 
+ namespace diagnostics {
+ 
+ /* Subclass of diagnostics::sink for classic text-based output
+    to stderr.
+ 
+    Uses diagnostics::context.m_text_callbacks to provide client-specific
+    textual output (e.g. include paths, macro expansions, etc).  */
+ 
+ class text_sink : public sink
+ {
+ public:
+   text_sink (context &dc,
+ 	     source_printing_options *source_printing = nullptr,
+ 	     bool follows_reference_printer = false)
+   : sink (dc),
+     m_saved_output_buffer (nullptr),
+     m_column_policy (dc),
+     m_last_module (nullptr),
+     m_includes_seen (nullptr),
+     m_source_printing (source_printing
+ 		       ? *source_printing
+ 		       : dc.get_source_printing_options ()),
+     m_follows_reference_printer (follows_reference_printer),
+     m_show_nesting (false),
+     m_show_nesting_levels (false)
+   {}
+   ~text_sink ();
+ 
+   void dump (FILE *out, int indent) const override;
+ 
+   std::unique_ptr<per_sink_buffer>
+   make_per_sink_buffer () final override;
+   void set_buffer (per_sink_buffer *) final override;
+ 
+   void on_begin_group () override {}
+   void on_end_group () override {}
+   void on_report_diagnostic (const diagnostic_info &,
+ 			     enum kind orig_diag_kind) override;
+   void on_report_verbatim (text_info &) final override;
+   void on_diagram (const diagram &d) override;
+   void after_diagnostic (const diagnostic_info &) override;
+   bool machine_readable_stderr_p () const final override
+   {
+     return false;
+   }
+   bool follows_reference_printer_p () const final override;
+ 
+   void update_printer () override;
+ 
+   void
+   report_global_digraph (const lazily_created<digraphs::digraph> &)
+     final override
+   {
+     // no-op for text
+   }
+ 
+   /* Helpers for writing lang-specific starters/finalizers for text output.  */
+   char *build_prefix (const diagnostic_info &) const;
+   void report_current_module (location_t where);
+   void append_note (location_t location,
+ 		    const char * gmsgid, ...) ATTRIBUTE_GCC_DIAG(3,4);
+ 
+ 
+   char *file_name_as_prefix (const char *) const;
+ 
+   char *build_indent_prefix (bool with_bullet) const;
+ 
+   void print_path (const paths::path &path);
+ 
+   bool show_column_p () const { return get_context ().m_show_column; }
+ 
+   const column_policy &get_column_policy () const
+   {
+     return m_column_policy;
+   }
+   location_print_policy get_location_print_policy () const;
+ 
+   bool show_nesting_p () const { return m_show_nesting; }
+   bool show_locations_in_nesting_p () const
+   {
+     return m_show_locations_in_nesting;
+   }
+ 
+   void set_show_nesting (bool show_nesting) { m_show_nesting = show_nesting; }
+   void set_show_locations_in_nesting (bool val)
+   {
+     m_show_locations_in_nesting = val;
+   }
+   void set_show_nesting_levels (bool show_nesting_levels)
+   {
+     m_show_nesting_levels = show_nesting_levels;
+   }
+ 
+   label_text get_location_text (const expanded_location &s) const;
+ 
+   source_printing_options &get_source_printing_options ()
+   {
+     return m_source_printing;
+   }
+   const source_printing_options &get_source_printing_options () const
+   {
+     return m_source_printing;
+   }
+ 
+ protected:
+   void print_any_cwe (const diagnostic_info &diagnostic);
+   void print_any_rules (const diagnostic_info &diagnostic);
+   void print_option_information (const diagnostic_info &diagnostic,
+ 				 enum kind orig_diag_kind);
+ 
+   bool includes_seen_p (const line_map_ordinary *map);
+ 
+   /* For handling diagnostics::buffer.  */
+   output_buffer *m_saved_output_buffer;
+ 
+   column_policy m_column_policy;
+ 
+   /* Used to detect when the input file stack has changed since last
+      described.  */
+   const line_map_ordinary *m_last_module;
+ 
+   /* Include files that report_current_module has already listed the
+      include path for.  */
+   hash_set<location_t, false, location_hash> *m_includes_seen;
+ 
+   source_printing_options &m_source_printing;
+ 
+   /* If true, this is the initial default text output format created
+      when the diagnostics::context was created, and, in particular, before
+      initializations of color and m_url_format.  Hence this should follow
+      the dc's reference printer for these.
+      If false, this text output was created after the dc was created, and
+      thus tracks its own values for color and m_url_format.  */
+   bool m_follows_reference_printer;
+ 
+   /* If true, then use indentation to show the nesting structure of
+      nested diagnostics, and print locations on separate lines after the
+      diagnostic message, rather than as a prefix to the message.  */
+   bool m_show_nesting;
+ 
+   /* Set to false to suppress location-printing when showing nested
+      diagnostics, for use in DejaGnu tests.  */
+   bool m_show_locations_in_nesting;
+ 
+   /* If true, then add "(level N):" when printing nested diagnostics.  */
+   bool m_show_nesting_levels;
+ };
+ 
+ } // namespace diagnostics
+ 
+ #endif /* ! GCC_DIAGNOSTICS_TEXT_SINK_H */
diff -Nrcpad gcc-16-20250720/gcc/diagnostics/url.h gcc-16-20250727/gcc/diagnostics/url.h
*** gcc-16-20250720/gcc/diagnostics/url.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/diagnostics/url.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,52 ----
+ /* Copyright (C) 2019-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTICS_URL_H
+ #define GCC_DIAGNOSTICS_URL_H
+ 
+ /* Whether to add URLs to diagnostics:
+    - DIAGNOSTICS_URL_NO: never
+    - DIAGNOSTICS_URL_YES: always
+    - DIAGNOSTICS_URL_AUTO: depending on the output stream.  */
+ typedef enum
+ {
+   DIAGNOSTICS_URL_NO       = 0,
+   DIAGNOSTICS_URL_YES      = 1,
+   DIAGNOSTICS_URL_AUTO     = 2
+ } diagnostic_url_rule_t;
+ 
+ /* Tells whether URLs should be emitted, and, if so, how to
+    terminate strings within the escape sequence.   */
+ enum diagnostic_url_format
+ {
+   /* No URLs shall be emitted.  */
+   URL_FORMAT_NONE,
+ 
+   /* Use ST string termination.  */
+   URL_FORMAT_ST,
+ 
+   /* Use BEL string termination.  */
+   URL_FORMAT_BEL
+ };
+ 
+ const diagnostic_url_format URL_FORMAT_DEFAULT = URL_FORMAT_BEL;
+ 
+ extern diagnostic_url_format determine_url_format (diagnostic_url_rule_t);
+ 
+ #endif /* ! GCC_DIAGNOSTICS_URL_H */
diff -Nrcpad gcc-16-20250720/gcc/doc/analyzer.texi gcc-16-20250727/gcc/doc/analyzer.texi
*** gcc-16-20250720/gcc/doc/analyzer.texi	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/doc/analyzer.texi	Sun Jul 27 22:32:08 2025
*************** binop_svalue (mult_expr, initial_svalue(
*** 432,438 ****
  @subsection Analyzer Paths
  
  We need to explain to the user what the problem is, and to persuade them
! that there really is a problem.  Hence having a @code{diagnostic_path}
  isn't just an incidental detail of the analyzer; it's required.
  
  Paths ought to be:
--- 432,438 ----
  @subsection Analyzer Paths
  
  We need to explain to the user what the problem is, and to persuade them
! that there really is a problem.  Hence having a @code{diagnostics::paths::path}
  isn't just an incidental detail of the analyzer; it's required.
  
  Paths ought to be:
*************** and notes if it is infeasible.
*** 491,497 ****
  
  The above gives us a shortest feasible @code{exploded_path} through the
  @code{exploded_graph} (a list of @code{exploded_edge *}).  We use this
! @code{exploded_path} to build a @code{diagnostic_path} (a list of
  @strong{events} for the diagnostic subsystem) - specifically a
  @code{checker_path}.
  
--- 491,497 ----
  
  The above gives us a shortest feasible @code{exploded_path} through the
  @code{exploded_graph} (a list of @code{exploded_edge *}).  We use this
! @code{exploded_path} to build a @code{diagnostics::paths::path} (a list of
  @strong{events} for the diagnostic subsystem) - specifically a
  @code{checker_path}.
  
diff -Nrcpad gcc-16-20250720/gcc/doc/cpp.texi gcc-16-20250727/gcc/doc/cpp.texi
*** gcc-16-20250720/gcc/doc/cpp.texi	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/doc/cpp.texi	Sun Jul 27 22:32:08 2025
*************** helps people match the @samp{#endif} to
*** 3252,3258 ****
  Older programs sometimes put @var{MACRO} directly after the
  @samp{#endif} without enclosing it in a comment.  This is invalid code
  according to the C standard.  CPP accepts it with a warning.  It
! never affects which @samp{#ifndef} the @samp{#endif} matches.
  
  @findex #ifndef
  Sometimes you wish to use some code if a macro is @emph{not} defined.
--- 3252,3258 ----
  Older programs sometimes put @var{MACRO} directly after the
  @samp{#endif} without enclosing it in a comment.  This is invalid code
  according to the C standard.  CPP accepts it with a warning.  It
! never affects which @samp{#ifdef} the @samp{#endif} matches.
  
  @findex #ifndef
  Sometimes you wish to use some code if a macro is @emph{not} defined.
diff -Nrcpad gcc-16-20250720/gcc/doc/extend.texi gcc-16-20250727/gcc/doc/extend.texi
*** gcc-16-20250720/gcc/doc/extend.texi	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/doc/extend.texi	Sun Jul 27 22:32:08 2025
*************** You can specify the kind of interrupt to
*** 5654,5665 ****
  parameter to the interrupt attribute like this:
  
  @smallexample
! void f (void) __attribute__ ((interrupt ("user")));
  @end smallexample
  
! Permissible values for this parameter are @code{user}, @code{supervisor},
! and @code{machine}.  If there is no parameter, then it defaults to
! @code{machine}.
  
  @cindex @code{riscv_vector_cc} function attribute, RISC-V
  @item riscv_vector_cc
--- 5654,5665 ----
  parameter to the interrupt attribute like this:
  
  @smallexample
! void f (void) __attribute__ ((interrupt ("supervisor")));
  @end smallexample
  
! Permissible values for this parameter are @code{supervisor},
! @code{machine}, and @code{rnmi}.  If there is no parameter, then it
! defaults to @code{machine}.
  
  @cindex @code{riscv_vector_cc} function attribute, RISC-V
  @item riscv_vector_cc
*************** the two, as explained in the sections be
*** 12775,12780 ****
--- 12775,12781 ----
  @menu
  * Global Register Variables::   Variables declared at global scope.
  * Local Register Variables::    Variables declared within a function.
+ * Hard Register Constraints::   Operands forced into specific machine registers.
  @end menu
  
  @node Global Register Variables
*************** with slightly different characteristics
*** 12980,12985 ****
--- 12981,13147 ----
  Defining coprocessor specifics for MIPS targets, gccint, 
  GNU Compiler Collection (GCC) Internals}).
  
+ @node Hard Register Constraints
+ @subsubsection Hard Register Constraints
+ 
+ Similar to register @code{asm} but still distinct, hard register constraints
+ are another way to force operands of inline @code{asm} into specific machine
+ registers.  In contrast to register @code{asm} where a variable is bound to a
+ machine register, a hard register constraint binds an @code{asm} operand to a
+ machine register.  Assume in the following that @code{r4} is a general-purpose
+ register, @code{f5} a floating-point register, and @code{v6} a vector register
+ for some target.
+ 
+ @smallexample
+ int x;
+ int y __attribute__ ((vector_size (16)));
+ @dots{}
+ asm ("some instructions"
+      : "=@{r4@}" (x)
+      : "@{f5@}" (42.0), "@{v6@}" (y));
+ @end smallexample
+ 
+ For the inline @code{asm}, variable @code{x} is bound to register @code{r4},
+ and @code{y} is loaded to @code{v6}.  Furthermore, constant @code{42.0} is
+ loaded into floating-point register @code{f5}.
+ 
+ A key difference between register @code{asm} and hard register constraints is
+ that the latter are specified at the point where they are supposed to
+ materialize, namely at inline @code{asm}, which may lead to more readable code.
+ 
+ @subsubheading Usage
+ 
+ Each input operand is loaded into the register specified by its corresponding
+ hard register constraint.  Furthermore, each hard register must be used at most
+ once among an alternative for inputs.  This renders hard register constraints
+ more strict compared to register @code{asm} where multiple inputs may share a
+ register as for example in
+ 
+ @smallexample
+ int x;
+ register int y asm ("0") = @dots{};
+ asm ("" : "=r" (x) : "r" (y), "r" (y));
+ @end smallexample
+ 
+ or even
+ 
+ @smallexample
+ register int x asm ("0") = 42;
+ register int y asm ("0") = 24;
+ asm ("" : "=r" (x) : "r" (x), "r" (y));
+ @end smallexample
+ 
+ The analogue for hard register constraints is invalid in order to prevent
+ subtle bugs.
+ 
+ Likewise, two outputs must not share a register among an alternative.  That
+ means, the following example is invalid
+ 
+ @smallexample
+ int x, y;
+ asm ("" : "=@{r4@}" (x), "=@{r4@}" (y));  // invalid
+ @end smallexample
+ 
+ which also aligns with register @code{asm}.  Despite that, each output must
+ refer to a distinct object if a hard register constraint is involved.  For
+ example, in the following, object @code{x} is assigned two registers.
+ 
+ @smallexample
+ int x;
+ asm ("" : "=r" (x), "=r" (x));
+ @end smallexample
+ 
+ This is not allowed for hard register constraints in order to prevent subtle
+ bugs.  Even if only one output operand has a hard register constraint, the code
+ is rejected since the allocation for the object is still ambiguous.
+ 
+ @smallexample
+ int x;
+ asm ("" : "=r" (x), "=@{1@}" (x));  // invalid
+ @end smallexample
+ 
+ The type of an operand must be supported by the corresponding machine register.
+ 
+ A hard register constraint may refer to any general, floating-point, or vector
+ register except a fixed register as e.g.@: the stack-pointer register.  The set
+ of allowed registers is target dependent analogue to register @code{asm}.
+ Furthermore, the referenced register must be a valid register name of the
+ target.  Note, on some targets, a single register may be referred to by
+ different names where each name specifies the length of the register.  For
+ example, on x86_64 the register names @code{rcx}, @code{ecx}, and @code{cx} all
+ refer to the same register but in different sizes.  If any of those names is
+ used for a hard register constraint, the actual size of a register is
+ determined by its corresponding operand.  For example
+ 
+ @smallexample
+ long x;
+ asm ("mov\t$42, %0" : "=@{ecx@}" (x));
+ @end smallexample
+ 
+ Although the hard register constraint refers to register @code{ecx}, the actual
+ register will be @code{rcx} since on x86_64 a @code{long} is 8 byte in total.
+ This aligns with register @code{asm} where you could have
+ 
+ @smallexample
+ register long x asm ("ecx");
+ @end smallexample
+ 
+ @subsubheading Interaction with Register @code{asm}
+ 
+ A mixture of both constructs as for example
+ 
+ @smallexample
+ register int x asm ("r4") = 42;
+ int y;
+ asm ("" : "=@{r5@}" (y) : "r" (x));
+ @end smallexample
+ 
+ is valid.
+ 
+ If an operand is a register @code{asm} and the corresponding constraint a hard
+ register, then both must refer to the same register.  That means
+ 
+ @smallexample
+ register int x asm ("r4");
+ asm ("" : "=@{r4@}" (x));
+ @end smallexample
+ 
+ is valid and
+ 
+ @smallexample
+ register int x asm ("r4");
+ asm ("" : "=@{r5@}" (x));  // invalid
+ @end smallexample
+ 
+ is invalid.
+ 
+ Note, register @code{asm} may not only be clobbered by function calls but also
+ by inline @code{asm} in conjunction with hard register constraints.  For
+ example, in the following
+ 
+ @smallexample
+ register int x asm ("r5") = 42;
+ int y;
+ asm ("" : "=@{r5@}" (y));
+ asm ("" : "+r" (x));
+ @end smallexample
+ 
+ variable @code{x} materializes before the very first inline @code{asm} which
+ writes to register @code{r5} and therefore clobbers @code{x} which in turn is
+ read by the subsequent inline @code{asm}.
+ 
+ @subsubheading Limitations
+ 
+ At the moment fixed registers are not supported for hard register constraints.
+ Thus, idioms like
+ 
+ @smallexample
+ register void *x asm ("rsp");
+ asm ("" : "=r" (x));
+ @end smallexample
+ 
+ are not supported for hard register constraints.  This might be lifted.
+ 
  @node Size of an asm
  @subsection Size of an @code{asm}
  
diff -Nrcpad gcc-16-20250720/gcc/doc/md.texi gcc-16-20250727/gcc/doc/md.texi
*** gcc-16-20250720/gcc/doc/md.texi	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/doc/md.texi	Sun Jul 27 22:32:08 2025
*************** as for @samp{<} apply.
*** 1366,1371 ****
--- 1366,1377 ----
  A register operand is allowed provided that it is in a general
  register.
  
+ @cindex hard registers in constraint
+ @item @samp{@{r@}}
+ An operand is bound to hard register @samp{r} which may be any general,
+ floating-point, or vector register except a fixed register like a stack pointer
+ register.  The set of fixed registers is target dependent.
+ 
  @cindex constants in constraints
  @cindex @samp{i} in constraint
  @item @samp{i}
diff -Nrcpad gcc-16-20250720/gcc/doc/tm.texi gcc-16-20250727/gcc/doc/tm.texi
*** gcc-16-20250720/gcc/doc/tm.texi	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/doc/tm.texi	Sun Jul 27 22:32:08 2025
*************** return type of the vectorized function s
*** 6382,6393 ****
  @var{vec_type_out} and the argument types should be @var{vec_type_in}.
  @end deftypefn
  
! @deftypefn {Target Hook} bool TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT (machine_mode @var{mode}, const_tree @var{type}, int @var{misalignment}, bool @var{is_packed})
  This hook should return true if the target supports misaligned vector
  store/load of a specific factor denoted in the @var{misalignment}
  parameter.  The vector store/load should be of machine mode @var{mode} and
! the elements in the vectors should be of type @var{type}.  @var{is_packed}
! parameter is true if the memory access is defined in a packed struct.
  @end deftypefn
  
  @deftypefn {Target Hook} machine_mode TARGET_VECTORIZE_PREFERRED_SIMD_MODE (scalar_mode @var{mode})
--- 6382,6395 ----
  @var{vec_type_out} and the argument types should be @var{vec_type_in}.
  @end deftypefn
  
! @deftypefn {Target Hook} bool TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT (machine_mode @var{mode}, const_tree @var{type}, int @var{misalignment}, bool @var{is_packed}, bool @var{is_gather_scatter})
  This hook should return true if the target supports misaligned vector
  store/load of a specific factor denoted in the @var{misalignment}
  parameter.  The vector store/load should be of machine mode @var{mode} and
! the elements in the vectors should be of type @var{type}.  The
! @var{is_packed} parameter is true if the misalignment is unknown and the
! memory access is defined in a packed struct.  @var{is_gather_scatter} is true
! if the load/store is a gather or scatter.
  @end deftypefn
  
  @deftypefn {Target Hook} machine_mode TARGET_VECTORIZE_PREFERRED_SIMD_MODE (scalar_mode @var{mode})
diff -Nrcpad gcc-16-20250720/gcc/edit-context.cc gcc-16-20250727/gcc/edit-context.cc
*** gcc-16-20250720/gcc/edit-context.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/edit-context.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,1847 ****
- /* Determining the results of applying fix-it hints.
-    Copyright (C) 2016-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "line-map.h"
- #include "edit-context.h"
- #include "pretty-print.h"
- #include "diagnostic-color.h"
- #include "selftest.h"
- 
- /* This file implements a way to track the effect of fix-its,
-    via a class edit_context; the other classes are support classes for
-    edit_context.
- 
-    A complication here is that fix-its are expressed relative to coordinates
-    in the file when it was parsed, before any changes have been made, and
-    so if there's more that one fix-it to be applied, we have to adjust
-    later fix-its to allow for the changes made by earlier ones.  This
-    is done by the various "get_effective_column" methods.
- 
-    The "filename" params are required to outlive the edit_context (no
-    copy of the underlying str is taken, just the ptr).  */
- 
- /* Forward decls.  class edit_context is declared within edit-context.h.
-    The other types are declared here.  */
- class edit_context;
- class edited_file;
- class edited_line;
- class line_event;
- 
- /* A struct to hold the params of a print_diff call.  */
- 
- class diff
- {
- public:
-   diff (pretty_printer *pp, bool show_filenames)
-   : m_pp (pp), m_show_filenames (show_filenames) {}
- 
-   pretty_printer *m_pp;
-   bool m_show_filenames;
- };
- 
- /* The state of one named file within an edit_context: the filename,
-    and the lines that have been edited so far.  */
- 
- class edited_file
- {
-  public:
-   edited_file (edit_context &ec, const char *filename);
-   static void delete_cb (edited_file *file);
- 
-   const char *get_filename () const { return m_filename; }
-   char *get_content ();
- 
-   bool apply_fixit (int line, int start_column,
- 		    int next_column,
- 		    const char *replacement_str,
- 		    int replacement_len);
-   int get_effective_column (int line, int column);
- 
-   static int call_print_diff (const char *, edited_file *file,
- 			      void *user_data)
-   {
-     diff *d = (diff *)user_data;
-     file->print_diff (d->m_pp, d->m_show_filenames);
-     return 0;
-   }
- 
-   file_cache &get_file_cache () const
-   {
-     return m_edit_context.get_file_cache ();
-   }
- 
-  private:
-   bool print_content (pretty_printer *pp);
-   void print_diff (pretty_printer *pp, bool show_filenames);
-   int print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
- 		       int old_end_of_hunk, int new_start_of_hunk);
-   edited_line *get_line (int line);
-   edited_line *get_or_insert_line (int line);
-   int get_num_lines (bool *missing_trailing_newline);
- 
-   int get_effective_line_count (int old_start_of_hunk,
- 				int old_end_of_hunk);
- 
-   void print_run_of_changed_lines (pretty_printer *pp,
- 				   int start_of_run,
- 				   int end_of_run);
- 
-   edit_context &m_edit_context;
-   const char *m_filename;
-   typed_splay_tree<int, edited_line *> m_edited_lines;
-   int m_num_lines;
- };
- 
- /* A line added before an edited_line.  */
- 
- class added_line
- {
-  public:
-   added_line (const char *content, int len)
-   : m_content (xstrndup (content, len)), m_len (len) {}
-   ~added_line () { free (m_content); }
- 
-   const char *get_content () const { return m_content; }
-   int get_len () const { return m_len; }
- 
-  private:
-   char *m_content;
-   int m_len;
- };
- 
- /* Class for representing edit events that have occurred on one line of
-    one file: the replacement of some text between some columns
-    on the line.
- 
-    Subsequent events will need their columns adjusting if they're
-    are on this line and their column is >= the start point.  */
- 
- class line_event
- {
-  public:
-   line_event (int start, int next, int len) : m_start (start),
-     m_delta (len - (next - start)) {}
- 
-   int get_effective_column (int orig_column) const
-   {
-     if (orig_column >= m_start)
-       return orig_column += m_delta;
-     else
-       return orig_column;
-   }
- 
-  private:
-   int m_start;
-   int m_delta;
- };
- 
- /* The state of one edited line within an edited_file.
-    As well as the current content of the line, it contains a record of
-    the changes, so that further changes can be applied in the correct
-    place.
- 
-    When handling fix-it hints containing newlines, new lines are added
-    as added_line predecessors to an edited_line.  Hence it's possible
-    for an "edited_line" to not actually have been changed, but to merely
-    be a placeholder for the lines added before it.  This can be tested
-    for with actuall_edited_p, and has a slight effect on how diff hunks
-    are generated.  */
- 
- class edited_line
- {
-  public:
-   edited_line (file_cache &fc, const char *filename, int line_num);
-   ~edited_line ();
-   static void delete_cb (edited_line *el);
- 
-   int get_line_num () const { return m_line_num; }
-   const char *get_content () const { return m_content; }
-   int get_len () const { return m_len; }
- 
-   int get_effective_column (int orig_column) const;
-   bool apply_fixit (int start_column,
- 		    int next_column,
- 		    const char *replacement_str,
- 		    int replacement_len);
- 
-   int get_effective_line_count () const;
- 
-   /* Has the content of this line actually changed, or are we merely
-      recording predecessor added_lines?  */
-   bool actually_edited_p () const { return m_line_events.length () > 0; }
- 
-   void print_content (pretty_printer *pp) const;
-   void print_diff_lines (pretty_printer *pp) const;
- 
-  private:
-   void ensure_capacity (int len);
-   void ensure_terminated ();
- 
-   int m_line_num;
-   char *m_content;
-   int m_len;
-   int m_alloc_sz;
-   auto_vec <line_event> m_line_events;
-   auto_vec <added_line *> m_predecessors;
- };
- 
- /* Forward decls.  */
- 
- static void
- print_diff_line (pretty_printer *pp, char prefix_char,
- 		 const char *line, int line_size);
- 
- /* Implementation of class edit_context.  */
- 
- /* edit_context's ctor.  */
- 
- edit_context::edit_context (file_cache &fc)
- : m_file_cache (fc),
-   m_valid (true),
-   m_files (strcmp, NULL, edited_file::delete_cb)
- {}
- 
- /* Add any fixits within RICHLOC to this context, recording the
-    changes that they make.  */
- 
- void
- edit_context::add_fixits (rich_location *richloc)
- {
-   if (!m_valid)
-     return;
-   if (richloc->seen_impossible_fixit_p ())
-     {
-       m_valid = false;
-       return;
-     }
-   for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
-     {
-       const fixit_hint *hint = richloc->get_fixit_hint (i);
-       if (!apply_fixit (hint))
- 	m_valid = false;
-     }
- }
- 
- /* Get the content of the given file, with fix-its applied.
-    If any errors occurred in this edit_context, return NULL.
-    The ptr should be freed by the caller.  */
- 
- char *
- edit_context::get_content (const char *filename)
- {
-   if (!m_valid)
-     return NULL;
-   edited_file &file = get_or_insert_file (filename);
-   return file.get_content ();
- }
- 
- /* Map a location before the edits to a column number after the edits.
-    This method is for the selftests.  */
- 
- int
- edit_context::get_effective_column (const char *filename, int line,
- 				    int column)
- {
-   edited_file *file = get_file (filename);
-   if (!file)
-     return column;
-   return file->get_effective_column (line, column);
- }
- 
- /* Generate a unified diff.  The resulting string should be freed by the
-    caller.  Primarily for selftests.
-    If any errors occurred in this edit_context, return NULL.  */
- 
- char *
- edit_context::generate_diff (bool show_filenames)
- {
-   if (!m_valid)
-     return NULL;
- 
-   pretty_printer pp;
-   print_diff (&pp, show_filenames);
-   return xstrdup (pp_formatted_text (&pp));
- }
- 
- /* Print a unified diff to PP, showing the changes made within the
-    context.  */
- 
- void
- edit_context::print_diff (pretty_printer *pp, bool show_filenames)
- {
-   if (!m_valid)
-     return;
-   diff d (pp, show_filenames);
-   m_files.foreach (edited_file::call_print_diff, &d);
- }
- 
- /* Attempt to apply the given fixit.  Return true if it can be
-    applied, or false otherwise.  */
- 
- bool
- edit_context::apply_fixit (const fixit_hint *hint)
- {
-   expanded_location start = expand_location (hint->get_start_loc ());
-   expanded_location next_loc = expand_location (hint->get_next_loc ());
-   if (start.file != next_loc.file)
-     return false;
-   if (start.line != next_loc.line)
-     return false;
-   if (start.column == 0)
-     return false;
-   if (next_loc.column == 0)
-     return false;
- 
-   edited_file &file = get_or_insert_file (start.file);
-   if (!m_valid)
-     return false;
-   return file.apply_fixit (start.line, start.column, next_loc.column,
- 			   hint->get_string (),
- 			   hint->get_length ());
- }
- 
- /* Locate the edited_file * for FILENAME, if any
-    Return NULL if there isn't one.  */
- 
- edited_file *
- edit_context::get_file (const char *filename)
- {
-   gcc_assert (filename);
-   return m_files.lookup (filename);
- }
- 
- /* Locate the edited_file for FILENAME, adding one if there isn't one.  */
- 
- edited_file &
- edit_context::get_or_insert_file (const char *filename)
- {
-   gcc_assert (filename);
- 
-   edited_file *file = get_file (filename);
-   if (file)
-     return *file;
- 
-   /* Not found.  */
-   file = new edited_file (*this, filename);
-   m_files.insert (filename, file);
-   return *file;
- }
- 
- /* Implementation of class edited_file.  */
- 
- /* Callback for m_edited_lines, for comparing line numbers.  */
- 
- static int line_comparator (int a, int b)
- {
-   return a - b;
- }
- 
- /* edited_file's constructor.  */
- 
- edited_file::edited_file (edit_context &ec, const char *filename)
- : m_edit_context (ec),
-   m_filename (filename),
-   m_edited_lines (line_comparator, NULL, edited_line::delete_cb),
-   m_num_lines (-1)
- {
- }
- 
- /* A callback for deleting edited_file *, for use as a
-    delete_value_fn for edit_context::m_files.  */
- 
- void
- edited_file::delete_cb (edited_file *file)
- {
-   delete file;
- }
- 
- /* Get the content of the file, with fix-its applied.
-    The ptr should be freed by the caller.  */
- 
- char *
- edited_file::get_content ()
- {
-   pretty_printer pp;
-   if (!print_content (&pp))
-     return NULL;
-   return xstrdup (pp_formatted_text (&pp));
- }
- 
- /* Attempt to replace columns START_COLUMN up to but not including NEXT_COLUMN
-    of LINE with the string REPLACEMENT_STR of length REPLACEMENT_LEN,
-    updating the in-memory copy of the line, and the record of edits to
-    the line.  */
- 
- bool
- edited_file::apply_fixit (int line, int start_column, int next_column,
- 			  const char *replacement_str,
- 			  int replacement_len)
- {
-   edited_line *el = get_or_insert_line (line);
-   if (!el)
-     return false;
-   return el->apply_fixit (start_column, next_column, replacement_str,
- 			  replacement_len);
- }
- 
- /* Given line LINE, map from COLUMN in the input file to its current
-    column after edits have been applied.  */
- 
- int
- edited_file::get_effective_column (int line, int column)
- {
-   const edited_line *el = get_line (line);
-   if (!el)
-     return column;
-   return el->get_effective_column (column);
- }
- 
- /* Attempt to print the content of the file to PP, with edits applied.
-    Return true if successful, false otherwise.  */
- 
- bool
- edited_file::print_content (pretty_printer *pp)
- {
-   bool missing_trailing_newline;
-   int line_count = get_num_lines (&missing_trailing_newline);
-   for (int line_num = 1; line_num <= line_count; line_num++)
-     {
-       edited_line *el = get_line (line_num);
-       if (el)
- 	el->print_content (pp);
-       else
- 	{
- 	  char_span line
- 	    = get_file_cache ().get_source_line (m_filename, line_num);
- 	  if (!line)
- 	    return false;
- 	  for (size_t i = 0; i < line.length (); i++)
- 	    pp_character (pp, line[i]);
- 	}
-       if (line_num < line_count)
- 	pp_character (pp, '\n');
-     }
- 
-   if (!missing_trailing_newline)
-     pp_character (pp, '\n');
- 
-   return true;
- }
- 
- /* Print a unified diff to PP, showing any changes that have occurred
-    to this file.  */
- 
- void
- edited_file::print_diff (pretty_printer *pp, bool show_filenames)
- {
-   if (show_filenames)
-     {
-       pp_string (pp, colorize_start (pp_show_color (pp), "diff-filename"));
-       /* Avoid -Wformat-diag in non-diagnostic output.  */
-       pp_string (pp, "--- ");
-       pp_string (pp, m_filename);
-       pp_newline (pp);
-       pp_string (pp, "+++ ");
-       pp_string (pp, m_filename);
-       pp_newline (pp);
-       pp_string (pp, colorize_stop (pp_show_color (pp)));
-     }
- 
-   edited_line *el = m_edited_lines.min ();
- 
-   bool missing_trailing_newline;
-   int line_count = get_num_lines (&missing_trailing_newline);
- 
-   const int context_lines = 3;
- 
-   /* Track new line numbers minus old line numbers.  */
- 
-   int line_delta = 0;
- 
-   while (el)
-     {
-       int start_of_hunk = el->get_line_num ();
-       start_of_hunk -= context_lines;
-       if (start_of_hunk < 1)
- 	start_of_hunk = 1;
- 
-       /* Locate end of hunk, merging in changed lines
- 	 that are sufficiently close.  */
-       while (true)
- 	{
- 	  edited_line *next_el
- 	    = m_edited_lines.successor (el->get_line_num ());
- 	  if (!next_el)
- 	    break;
- 
- 	  int end_of_printed_hunk = el->get_line_num () + context_lines;
- 	  if (!el->actually_edited_p ())
- 	    end_of_printed_hunk--;
- 
- 	  if (end_of_printed_hunk
- 	      >= next_el->get_line_num () - context_lines)
- 	    el = next_el;
- 	  else
- 	    break;
- 	}
- 
-       int end_of_hunk = el->get_line_num ();
-       end_of_hunk += context_lines;
-       if (!el->actually_edited_p ())
- 	end_of_hunk--;
-       if (end_of_hunk > line_count)
- 	end_of_hunk = line_count;
- 
-       int new_start_of_hunk = start_of_hunk + line_delta;
-       line_delta += print_diff_hunk (pp, start_of_hunk, end_of_hunk,
- 				     new_start_of_hunk);
-       el = m_edited_lines.successor (el->get_line_num ());
-     }
- }
- 
- /* Print one hunk within a unified diff to PP, covering the
-    given range of lines.  OLD_START_OF_HUNK and OLD_END_OF_HUNK are
-    line numbers in the unedited version of the file.
-    NEW_START_OF_HUNK is a line number in the edited version of the file.
-    Return the change in the line count within the hunk.  */
- 
- int
- edited_file::print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
- 			      int old_end_of_hunk, int new_start_of_hunk)
- {
-   int old_num_lines = old_end_of_hunk - old_start_of_hunk + 1;
-   int new_num_lines
-     = get_effective_line_count (old_start_of_hunk, old_end_of_hunk);
- 
-   pp_string (pp, colorize_start (pp_show_color (pp), "diff-hunk"));
-   pp_printf (pp, "%s -%i,%i +%i,%i %s",
- 	     "@@", old_start_of_hunk, old_num_lines,
- 	     new_start_of_hunk, new_num_lines, "@@\n");
-   pp_string (pp, colorize_stop (pp_show_color (pp)));
- 
-   int line_num = old_start_of_hunk;
-   while (line_num <= old_end_of_hunk)
-     {
-       edited_line *el = get_line (line_num);
-       if (el)
- 	{
- 	  /* We have an edited line.
- 	     Consolidate into runs of changed lines.  */
- 	  const int first_changed_line_in_run = line_num;
- 	  while (get_line (line_num))
- 	    line_num++;
- 	  const int last_changed_line_in_run = line_num - 1;
- 	  print_run_of_changed_lines (pp, first_changed_line_in_run,
- 				      last_changed_line_in_run);
- 	}
-       else
- 	{
- 	  /* Unchanged line.  */
- 	  char_span old_line
- 	    = get_file_cache ().get_source_line (m_filename, line_num);
- 	  print_diff_line (pp, ' ', old_line.get_buffer (), old_line.length ());
- 	  line_num++;
- 	}
-     }
- 
-   return new_num_lines - old_num_lines;
- }
- 
- /* Subroutine of edited_file::print_diff_hunk: given a run of lines
-    from START_OF_RUN to END_OF_RUN that all have edited_line instances,
-    print the diff to PP.  */
- 
- void
- edited_file::print_run_of_changed_lines (pretty_printer *pp,
- 					 int start_of_run,
- 					 int end_of_run)
- {
-   /* Show old version of lines.  */
-   pp_string (pp, colorize_start (pp_show_color (pp),
- 				 "diff-delete"));
-   for (int line_num = start_of_run;
-        line_num <= end_of_run;
-        line_num++)
-     {
-       edited_line *el_in_run = get_line (line_num);
-       gcc_assert (el_in_run);
-       if (el_in_run->actually_edited_p ())
- 	{
- 	  char_span old_line
- 	    = get_file_cache ().get_source_line (m_filename, line_num);
- 	  print_diff_line (pp, '-', old_line.get_buffer (),
- 			   old_line.length ());
- 	}
-     }
-   pp_string (pp, colorize_stop (pp_show_color (pp)));
- 
-   /* Show new version of lines.  */
-   pp_string (pp, colorize_start (pp_show_color (pp),
- 				 "diff-insert"));
-   for (int line_num = start_of_run;
-        line_num <= end_of_run;
-        line_num++)
-     {
-       edited_line *el_in_run = get_line (line_num);
-       gcc_assert (el_in_run);
-       el_in_run->print_diff_lines (pp);
-     }
-   pp_string (pp, colorize_stop (pp_show_color (pp)));
- }
- 
- /* Print one line within a diff, starting with PREFIX_CHAR,
-    followed by the LINE of content, of length LEN.  LINE is
-    not necessarily 0-terminated.  Print a trailing newline.  */
- 
- static void
- print_diff_line (pretty_printer *pp, char prefix_char,
- 		 const char *line, int len)
- {
-   pp_character (pp, prefix_char);
-   for (int i = 0; i < len; i++)
-     pp_character (pp, line[i]);
-   pp_character (pp, '\n');
- }
- 
- /* Determine the number of lines that will be present after
-    editing for the range of lines from OLD_START_OF_HUNK to
-    OLD_END_OF_HUNK inclusive.  */
- 
- int
- edited_file::get_effective_line_count (int old_start_of_hunk,
- 				       int old_end_of_hunk)
- {
-   int line_count = 0;
-   for (int old_line_num = old_start_of_hunk; old_line_num <= old_end_of_hunk;
-        old_line_num++)
-     {
-       edited_line *el = get_line (old_line_num);
-       if (el)
- 	line_count += el->get_effective_line_count ();
-       else
- 	line_count++;
-     }
-   return line_count;
- }
- 
- /* Get the state of LINE within the file, or NULL if it is untouched.  */
- 
- edited_line *
- edited_file::get_line (int line)
- {
-   return m_edited_lines.lookup (line);
- }
- 
- /* Get the state of LINE within the file, creating a state for it
-    if necessary.  Return NULL if an error occurs.  */
- 
- edited_line *
- edited_file::get_or_insert_line (int line)
- {
-   edited_line *el = get_line (line);
-   if (el)
-     return el;
-   el = new edited_line (get_file_cache (), m_filename, line);
-   if (el->get_content () == NULL)
-     {
-       delete el;
-       return NULL;
-     }
-   m_edited_lines.insert (line, el);
-   return el;
- }
- 
- /* Get the total number of lines in m_content, writing
-    true to *MISSING_TRAILING_NEWLINE if the final line
-    if missing a newline, false otherwise.  */
- 
- int
- edited_file::get_num_lines (bool *missing_trailing_newline)
- {
-   gcc_assert (missing_trailing_newline);
-   if (m_num_lines == -1)
-     {
-       m_num_lines = 0;
-       while (true)
- 	{
- 	  char_span line
- 	    = get_file_cache ().get_source_line (m_filename, m_num_lines + 1);
- 	  if (line)
- 	    m_num_lines++;
- 	  else
- 	    break;
- 	}
-     }
-   *missing_trailing_newline
-     = get_file_cache ().missing_trailing_newline_p (m_filename);
-   return m_num_lines;
- }
- 
- /* Implementation of class edited_line.  */
- 
- /* edited_line's ctor.  */
- 
- edited_line::edited_line (file_cache &fc, const char *filename, int line_num)
- : m_line_num (line_num),
-   m_content (NULL), m_len (0), m_alloc_sz (0),
-   m_line_events (),
-   m_predecessors ()
- {
-   char_span line = fc.get_source_line (filename, line_num);
-   if (!line)
-     return;
-   m_len = line.length ();
-   ensure_capacity (m_len);
-   memcpy (m_content, line.get_buffer (), m_len);
-   ensure_terminated ();
- }
- 
- /* edited_line's dtor.  */
- 
- edited_line::~edited_line ()
- {
-   unsigned i;
-   added_line *pred;
- 
-   free (m_content);
-   FOR_EACH_VEC_ELT (m_predecessors, i, pred)
-     delete pred;
- }
- 
- /* A callback for deleting edited_line *, for use as a
-    delete_value_fn for edited_file::m_edited_lines.  */
- 
- void
- edited_line::delete_cb (edited_line *el)
- {
-   delete el;
- }
- 
- /* Map a location before the edits to a column number after the edits,
-    within a specific line.  */
- 
- int
- edited_line::get_effective_column (int orig_column) const
- {
-   int i;
-   line_event *event;
-   FOR_EACH_VEC_ELT (m_line_events, i, event)
-     orig_column = event->get_effective_column (orig_column);
-   return orig_column;
- }
- 
- /* Attempt to replace columns START_COLUMN up to but not including
-    NEXT_COLUMN of the line with the string REPLACEMENT_STR of
-    length REPLACEMENT_LEN, updating the in-memory copy of the line,
-    and the record of edits to the line.
-    Return true if successful; false if an error occurred.  */
- 
- bool
- edited_line::apply_fixit (int start_column,
- 			  int next_column,
- 			  const char *replacement_str,
- 			  int replacement_len)
- {
-   /* Handle newlines.  They will only ever be at the end of the
-      replacement text, thanks to the filtering in rich_location.  */
-   if (replacement_len > 1)
-     if (replacement_str[replacement_len - 1] == '\n')
-       {
- 	/* Stash in m_predecessors, stripping off newline.  */
- 	m_predecessors.safe_push (new added_line (replacement_str,
- 						  replacement_len - 1));
- 	return true;
-       }
- 
-   start_column = get_effective_column (start_column);
-   next_column = get_effective_column (next_column);
- 
-   int start_offset = start_column - 1;
-   int next_offset = next_column - 1;
- 
-   gcc_assert (start_offset >= 0);
-   gcc_assert (next_offset >= 0);
- 
-   if (start_column > next_column)
-     return false;
-   if (start_offset >= (m_len + 1))
-     return false;
-   if (next_offset >= (m_len + 1))
-     return false;
- 
-   size_t victim_len = next_offset - start_offset;
- 
-   /* Ensure buffer is big enough.  */
-   size_t new_len = m_len + replacement_len - victim_len;
-   ensure_capacity (new_len);
- 
-   char *suffix = m_content + next_offset;
-   gcc_assert (suffix <= m_content + m_len);
-   size_t len_suffix = (m_content + m_len) - suffix;
- 
-   /* Move successor content into position.  They overlap, so use memmove.  */
-   memmove (m_content + start_offset + replacement_len,
- 	   suffix, len_suffix);
- 
-   /* Replace target content.  They don't overlap, so use memcpy.  */
-   memcpy (m_content + start_offset,
- 	  replacement_str,
- 	  replacement_len);
- 
-   m_len = new_len;
- 
-   ensure_terminated ();
- 
-   /* Record the replacement, so that future changes to the line can have
-      their column information adjusted accordingly.  */
-   m_line_events.safe_push (line_event (start_column, next_column,
- 				       replacement_len));
-   return true;
- }
- 
- /* Determine the number of lines that will be present after
-    editing for this line.  Typically this is just 1, but
-    if newlines have been added before this line, they will
-    also be counted.  */
- 
- int
- edited_line::get_effective_line_count () const
- {
-   return m_predecessors.length () + 1;
- }
- 
- /* Subroutine of edited_file::print_content.
-    Print this line and any new lines added before it, to PP.  */
- 
- void
- edited_line::print_content (pretty_printer *pp) const
- {
-   unsigned i;
-   added_line *pred;
-   FOR_EACH_VEC_ELT (m_predecessors, i, pred)
-     {
-       pp_string (pp, pred->get_content ());
-       pp_newline (pp);
-     }
-   pp_string (pp, m_content);
- }
- 
- /* Subroutine of edited_file::print_run_of_changed_lines for
-    printing diff hunks to PP.
-    Print the '+' line for this line, and any newlines added
-    before it.
-    Note that if this edited_line was actually edited, the '-'
-    line has already been printed.  If it wasn't, then we merely
-    have a placeholder edited_line for adding newlines to, and
-    we need to print a ' ' line for the edited_line as we haven't
-    printed it yet.  */
- 
- void
- edited_line::print_diff_lines (pretty_printer *pp) const
- {
-   unsigned i;
-   added_line *pred;
-   FOR_EACH_VEC_ELT (m_predecessors, i, pred)
-     print_diff_line (pp, '+', pred->get_content (),
- 		     pred->get_len ());
-   if (actually_edited_p ())
-     print_diff_line (pp, '+', m_content, m_len);
-   else
-     print_diff_line (pp, ' ', m_content, m_len);
- }
- 
- /* Ensure that the buffer for m_content is at least large enough to hold
-    a string of length LEN and its 0-terminator, doubling on repeated
-    allocations.  */
- 
- void
- edited_line::ensure_capacity (int len)
- {
-   /* Allow 1 extra byte for 0-termination.  */
-   if (m_alloc_sz < (len + 1))
-     {
-       size_t new_alloc_sz = (len + 1) * 2;
-       m_content = (char *)xrealloc (m_content, new_alloc_sz);
-       m_alloc_sz = new_alloc_sz;
-     }
- }
- 
- /* Ensure that m_content is 0-terminated.  */
- 
- void
- edited_line::ensure_terminated ()
- {
-   /* 0-terminate the buffer.  */
-   gcc_assert (m_len < m_alloc_sz);
-   m_content[m_len] = '\0';
- }
- 
- #if CHECKING_P
- 
- /* Selftests of code-editing.  */
- 
- namespace selftest {
- 
- /* A wrapper class for ensuring that the underlying pointer is freed.  */
- 
- template <typename POINTER_T>
- class auto_free
- {
-  public:
-   auto_free (POINTER_T p) : m_ptr (p) {}
-   ~auto_free () { free (m_ptr); }
- 
-   operator POINTER_T () { return m_ptr; }
- 
-  private:
-   POINTER_T m_ptr;
- };
- 
- /* Verify that edit_context::get_content works for unedited files.  */
- 
- static void
- test_get_content ()
- {
-   /* Test of empty file.  */
-   {
-     const char *content = ("");
-     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-     file_cache fc;
-     edit_context edit (fc);
-     auto_free <char *> result = edit.get_content (tmp.get_filename ());
-     ASSERT_STREQ ("", result);
-   }
- 
-   /* Test of simple content.  */
-   {
-     const char *content = ("/* before */\n"
- 			   "foo = bar.field;\n"
- 			   "/* after */\n");
-     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-     file_cache fc;
-     edit_context edit (fc);
-     auto_free <char *> result = edit.get_content (tmp.get_filename ());
-     ASSERT_STREQ ("/* before */\n"
- 		  "foo = bar.field;\n"
- 		  "/* after */\n", result);
-   }
- 
-   /* Test of omitting the trailing newline on the final line.  */
-   {
-     const char *content = ("/* before */\n"
- 			   "foo = bar.field;\n"
- 			   "/* after */");
-     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
-     file_cache fc;
-     edit_context edit (fc);
-     auto_free <char *> result = edit.get_content (tmp.get_filename ());
-     /* We should respect the omitted trailing newline.  */
-     ASSERT_STREQ ("/* before */\n"
- 		  "foo = bar.field;\n"
- 		  "/* after */", result);
-   }
- }
- 
- /* Test applying an "insert" fixit, using insert_before.  */
- 
- static void
- test_applying_fixits_insert_before (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................0000000001111111.
-      .........................1234567890123456.  */
-   const char *old_content = ("/* before */\n"
- 			     "foo = bar.field;\n"
- 			     "/* after */\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
- 
-   /* Add a comment in front of "bar.field".  */
-   location_t start = linemap_position_for_column (line_table, 7);
-   rich_location richloc (line_table, start);
-   richloc.add_fixit_insert_before ("/* inserted */");
- 
-   if (start > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&richloc);
-   auto_free <char *> new_content = edit.get_content (filename);
-   if (start <= LINE_MAP_MAX_LOCATION_WITH_COLS)
-     ASSERT_STREQ ("/* before */\n"
- 		  "foo = /* inserted */bar.field;\n"
- 		  "/* after */\n", new_content);
- 
-   /* Verify that locations on other lines aren't affected by the change.  */
-   ASSERT_EQ (100, edit.get_effective_column (filename, 1, 100));
-   ASSERT_EQ (100, edit.get_effective_column (filename, 3, 100));
- 
-   /* Verify locations on the line before the change.  */
-   ASSERT_EQ (1, edit.get_effective_column (filename, 2, 1));
-   ASSERT_EQ (6, edit.get_effective_column (filename, 2, 6));
- 
-   /* Verify locations on the line at and after the change.  */
-   ASSERT_EQ (21, edit.get_effective_column (filename, 2, 7));
-   ASSERT_EQ (22, edit.get_effective_column (filename, 2, 8));
- 
-   /* Verify diff.  */
-   auto_free <char *> diff = edit.generate_diff (false);
-   ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
- 		" /* before */\n"
- 		"-foo = bar.field;\n"
- 		"+foo = /* inserted */bar.field;\n"
- 		" /* after */\n", diff);
- }
- 
- /* Test applying an "insert" fixit, using insert_after, with
-    a range of length > 1 (to ensure that the end-point of
-    the input range is used).  */
- 
- static void
- test_applying_fixits_insert_after (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................0000000001111111.
-      .........................1234567890123456.  */
-   const char *old_content = ("/* before */\n"
- 			     "foo = bar.field;\n"
- 			     "/* after */\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
- 
-   /* Add a comment after "field".  */
-   location_t start = linemap_position_for_column (line_table, 11);
-   location_t finish = linemap_position_for_column (line_table, 15);
-   location_t field = make_location (start, start, finish);
-   rich_location richloc (line_table, field);
-   richloc.add_fixit_insert_after ("/* inserted */");
- 
-   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Verify that the text was inserted after the end of "field". */
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&richloc);
-   auto_free <char *> new_content = edit.get_content (filename);
-   ASSERT_STREQ ("/* before */\n"
- 		"foo = bar.field/* inserted */;\n"
- 		"/* after */\n", new_content);
- 
-   /* Verify diff.  */
-   auto_free <char *> diff = edit.generate_diff (false);
-   ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
- 		" /* before */\n"
- 		"-foo = bar.field;\n"
- 		"+foo = bar.field/* inserted */;\n"
- 		" /* after */\n", diff);
- }
- 
- /* Test applying an "insert" fixit, using insert_after at the end of
-    a line (contrast with test_applying_fixits_insert_after_failure
-    below).  */
- 
- static void
- test_applying_fixits_insert_after_at_line_end (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................0000000001111111.
-      .........................1234567890123456.  */
-   const char *old_content = ("/* before */\n"
- 			     "foo = bar.field;\n"
- 			     "/* after */\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
- 
-   /* Add a comment after the semicolon.  */
-   location_t loc = linemap_position_for_column (line_table, 16);
-   rich_location richloc (line_table, loc);
-   richloc.add_fixit_insert_after ("/* inserted */");
- 
-   if (loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&richloc);
-   auto_free <char *> new_content = edit.get_content (filename);
-   ASSERT_STREQ ("/* before */\n"
- 		"foo = bar.field;/* inserted */\n"
- 		"/* after */\n", new_content);
- 
-   /* Verify diff.  */
-   auto_free <char *> diff = edit.generate_diff (false);
-   ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
- 		" /* before */\n"
- 		"-foo = bar.field;\n"
- 		"+foo = bar.field;/* inserted */\n"
- 		" /* after */\n", diff);
- }
- 
- /* Test of a failed attempt to apply an "insert" fixit, using insert_after,
-    due to the relevant linemap ending.  Contrast with
-    test_applying_fixits_insert_after_at_line_end above.  */
- 
- static void
- test_applying_fixits_insert_after_failure (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................0000000001111111.
-      .........................1234567890123456.  */
-   const char *old_content = ("/* before */\n"
- 			     "foo = bar.field;\n"
- 			     "/* after */\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
- 
-   /* Add a comment after the semicolon.  */
-   location_t loc = linemap_position_for_column (line_table, 16);
-   rich_location richloc (line_table, loc);
- 
-   /* We want a failure of linemap_position_for_loc_and_offset.
-      We can do this by starting a new linemap at line 3, so that
-      there is no appropriate location value for the insertion point
-      within the linemap for line 2.  */
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
- 
-   /* The failure fails to happen at the transition point from
-      packed ranges to unpacked ranges (where there are some "spare"
-      location_t values).  Skip the test there.  */
-   if (loc >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
-     return;
- 
-   /* Offsetting "loc" should now fail (by returning the input loc. */
-   ASSERT_EQ (loc, linemap_position_for_loc_and_offset (line_table, loc, 1));
- 
-   /* Hence attempting to use add_fixit_insert_after at the end of the line
-      should now fail.  */
-   richloc.add_fixit_insert_after ("/* inserted */");
-   ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
- 
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&richloc);
-   ASSERT_FALSE (edit.valid_p ());
-   ASSERT_EQ (NULL, edit.get_content (filename));
-   ASSERT_EQ (NULL, edit.generate_diff (false));
- }
- 
- /* Test applying an "insert" fixit that adds a newline.  */
- 
- static void
- test_applying_fixits_insert_containing_newline (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................0000000001111111.
-      .........................1234567890123456.  */
-   const char *old_content = ("    case 'a':\n" /* line 1. */
- 			     "      x = a;\n"  /* line 2. */
- 			     "    case 'b':\n" /* line 3. */
- 			     "      x = b;\n");/* line 4. */
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
- 
-   /* Add a "break;" on a line by itself before line 3 i.e. before
-      column 1 of line 3. */
-   location_t case_start = linemap_position_for_column (line_table, 5);
-   location_t case_finish = linemap_position_for_column (line_table, 13);
-   location_t case_loc = make_location (case_start, case_start, case_finish);
-   rich_location richloc (line_table, case_loc);
-   location_t line_start = linemap_position_for_column (line_table, 1);
-   richloc.add_fixit_insert_before (line_start, "      break;\n");
- 
-   if (case_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&richloc);
-   auto_free <char *> new_content = edit.get_content (filename);
-   ASSERT_STREQ (("    case 'a':\n"
- 		 "      x = a;\n"
- 		 "      break;\n"
- 		 "    case 'b':\n"
- 		 "      x = b;\n"),
- 		new_content);
- 
-   /* Verify diff.  */
-   auto_free <char *> diff = edit.generate_diff (false);
-   ASSERT_STREQ (("@@ -1,4 +1,5 @@\n"
- 		 "     case 'a':\n"
- 		 "       x = a;\n"
- 		 "+      break;\n"
- 		 "     case 'b':\n"
- 		 "       x = b;\n"),
- 		diff);
- }
- 
- /* Test applying a "replace" fixit that grows the affected line.  */
- 
- static void
- test_applying_fixits_growing_replace (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................0000000001111111.
-      .........................1234567890123456.  */
-   const char *old_content = ("/* before */\n"
- 			     "foo = bar.field;\n"
- 			     "/* after */\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, filename, 2);
- 
-   /* Replace "field" with "m_field".  */
-   location_t start = linemap_position_for_column (line_table, 11);
-   location_t finish = linemap_position_for_column (line_table, 15);
-   location_t field = make_location (start, start, finish);
-   rich_location richloc (line_table, field);
-   richloc.add_fixit_replace ("m_field");
- 
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&richloc);
-   auto_free <char *> new_content = edit.get_content (filename);
-   if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
-     {
-       ASSERT_STREQ ("/* before */\n"
- 		    "foo = bar.m_field;\n"
- 		    "/* after */\n", new_content);
- 
-       /* Verify location of ";" after the change.  */
-       ASSERT_EQ (18, edit.get_effective_column (filename, 2, 16));
- 
-       /* Verify diff.  */
-       auto_free <char *> diff = edit.generate_diff (false);
-       ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
- 		    " /* before */\n"
- 		    "-foo = bar.field;\n"
- 		    "+foo = bar.m_field;\n"
- 		    " /* after */\n", diff);
-     }
- }
- 
- /* Test applying a "replace" fixit that shrinks the affected line.  */
- 
- static void
- test_applying_fixits_shrinking_replace (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................000000000111111111.
-      .........................123456789012345678.  */
-   const char *old_content = ("/* before */\n"
- 			     "foo = bar.m_field;\n"
- 			     "/* after */\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, filename, 2);
- 
-   /* Replace "field" with "m_field".  */
-   location_t start = linemap_position_for_column (line_table, 11);
-   location_t finish = linemap_position_for_column (line_table, 17);
-   location_t m_field = make_location (start, start, finish);
-   rich_location richloc (line_table, m_field);
-   richloc.add_fixit_replace ("field");
- 
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&richloc);
-   auto_free <char *> new_content = edit.get_content (filename);
-   if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
-     {
-       ASSERT_STREQ ("/* before */\n"
- 		    "foo = bar.field;\n"
- 		    "/* after */\n", new_content);
- 
-       /* Verify location of ";" after the change.  */
-       ASSERT_EQ (16, edit.get_effective_column (filename, 2, 18));
- 
-       /* Verify diff.  */
-       auto_free <char *> diff = edit.generate_diff (false);
-       ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
- 		    " /* before */\n"
- 		    "-foo = bar.m_field;\n"
- 		    "+foo = bar.field;\n"
- 		    " /* after */\n", diff);
-     }
- }
- 
- /* Replacement fix-it hint containing a newline.  */
- 
- static void
- test_applying_fixits_replace_containing_newline (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-     .........................0000000001111.
-     .........................1234567890123.  */
-   const char *old_content = "foo = bar ();\n";
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, filename, 1);
- 
-   /* Replace the " = " with "\n  = ", as if we were reformatting an
-      overly long line.  */
-   location_t start = linemap_position_for_column (line_table, 4);
-   location_t finish = linemap_position_for_column (line_table, 6);
-   location_t loc = linemap_position_for_column (line_table, 13);
-   rich_location richloc (line_table, loc);
-   source_range range = source_range::from_locations (start, finish);
-   richloc.add_fixit_replace (range, "\n  = ");
- 
-   /* Newlines are only supported within fix-it hints that
-      are at the start of lines (for entirely new lines), hence
-      this fix-it should not be displayed.  */
-   ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
- 
-   if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&richloc);
-   auto_free <char *> new_content = edit.get_content (filename);
-   //ASSERT_STREQ ("foo\n  = bar ();\n", new_content);
- }
- 
- /* Test applying a "remove" fixit.  */
- 
- static void
- test_applying_fixits_remove (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................000000000111111111.
-      .........................123456789012345678.  */
-   const char *old_content = ("/* before */\n"
- 			     "foo = bar.m_field;\n"
- 			     "/* after */\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, filename, 2);
- 
-   /* Remove ".m_field".  */
-   location_t start = linemap_position_for_column (line_table, 10);
-   location_t finish = linemap_position_for_column (line_table, 17);
-   rich_location richloc (line_table, start);
-   source_range range;
-   range.m_start = start;
-   range.m_finish = finish;
-   richloc.add_fixit_remove (range);
- 
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&richloc);
-   auto_free <char *> new_content = edit.get_content (filename);
-   if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
-     {
-       ASSERT_STREQ ("/* before */\n"
- 		    "foo = bar;\n"
- 		    "/* after */\n", new_content);
- 
-       /* Verify location of ";" after the change.  */
-       ASSERT_EQ (10, edit.get_effective_column (filename, 2, 18));
- 
-       /* Verify diff.  */
-       auto_free <char *> diff = edit.generate_diff (false);
-       ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
- 		    " /* before */\n"
- 		    "-foo = bar.m_field;\n"
- 		    "+foo = bar;\n"
- 		    " /* after */\n", diff);
-     }
- }
- 
- /* Test applying multiple fixits to one line.  */
- 
- static void
- test_applying_fixits_multiple (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................00000000011111111.
-      .........................12345678901234567.  */
-   const char *old_content = ("/* before */\n"
- 			     "foo = bar.field;\n"
- 			     "/* after */\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, filename, 2);
- 
-   location_t c7 = linemap_position_for_column (line_table, 7);
-   location_t c9 = linemap_position_for_column (line_table, 9);
-   location_t c11 = linemap_position_for_column (line_table, 11);
-   location_t c15 = linemap_position_for_column (line_table, 15);
-   location_t c17 = linemap_position_for_column (line_table, 17);
- 
-   if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Add a comment in front of "bar.field".  */
-   rich_location insert_a (line_table, c7);
-   insert_a.add_fixit_insert_before (c7, "/* alpha */");
- 
-   /* Add a comment after "bar.field;".  */
-   rich_location insert_b (line_table, c17);
-   insert_b.add_fixit_insert_before (c17, "/* beta */");
- 
-   /* Replace "bar" with "pub".   */
-   rich_location replace_a (line_table, c7);
-   replace_a.add_fixit_replace (source_range::from_locations (c7, c9),
- 			       "pub");
- 
-   /* Replace "field" with "meadow".   */
-   rich_location replace_b (line_table, c7);
-   replace_b.add_fixit_replace (source_range::from_locations (c11, c15),
- 			       "meadow");
- 
-   file_cache fc;
-   edit_context edit (fc);
-   edit.add_fixits (&insert_a);
-   ASSERT_EQ (100, edit.get_effective_column (filename, 1, 100));
-   ASSERT_EQ (1, edit.get_effective_column (filename, 2, 1));
-   ASSERT_EQ (6, edit.get_effective_column (filename, 2, 6));
-   ASSERT_EQ (18, edit.get_effective_column (filename, 2, 7));
-   ASSERT_EQ (27, edit.get_effective_column (filename, 2, 16));
-   ASSERT_EQ (100, edit.get_effective_column (filename, 3, 100));
- 
-   edit.add_fixits (&insert_b);
-   edit.add_fixits (&replace_a);
-   edit.add_fixits (&replace_b);
- 
-   if (c17 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
-     {
-       auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
-       ASSERT_STREQ ("/* before */\n"
- 		     "foo = /* alpha */pub.meadow;/* beta */\n"
- 		     "/* after */\n",
- 		    new_content);
- 
-       /* Verify diff.  */
-       auto_free <char *> diff = edit.generate_diff (false);
-       ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
- 		    " /* before */\n"
- 		    "-foo = bar.field;\n"
- 		    "+foo = /* alpha */pub.meadow;/* beta */\n"
- 		    " /* after */\n", diff);
-     }
- }
- 
- /* Subroutine of test_applying_fixits_multiple_lines.
-    Add the text "CHANGED: " to the front of the given line.  */
- 
- static location_t
- change_line (edit_context &edit, int line_num)
- {
-   const line_map_ordinary *ord_map
-     = LINEMAPS_LAST_ORDINARY_MAP (line_table);
-   const int column = 1;
-   location_t loc =
-     linemap_position_for_line_and_column (line_table, ord_map,
- 					  line_num, column);
- 
-   expanded_location exploc = expand_location (loc);
-   if (loc <= LINE_MAP_MAX_LOCATION_WITH_COLS)
-     {
-       ASSERT_EQ (line_num, exploc.line);
-       ASSERT_EQ (column, exploc.column);
-     }
- 
-   rich_location insert (line_table, loc);
-   insert.add_fixit_insert_before ("CHANGED: ");
-   edit.add_fixits (&insert);
-   return loc;
- }
- 
- /* Subroutine of test_applying_fixits_multiple_lines.
-    Add the text "INSERTED\n" in front of the given line.  */
- 
- static location_t
- insert_line (edit_context &edit, int line_num)
- {
-   const line_map_ordinary *ord_map
-     = LINEMAPS_LAST_ORDINARY_MAP (line_table);
-   const int column = 1;
-   location_t loc =
-     linemap_position_for_line_and_column (line_table, ord_map,
- 					  line_num, column);
- 
-   expanded_location exploc = expand_location (loc);
-   if (loc <= LINE_MAP_MAX_LOCATION_WITH_COLS)
-     {
-       ASSERT_EQ (line_num, exploc.line);
-       ASSERT_EQ (column, exploc.column);
-     }
- 
-   rich_location insert (line_table, loc);
-   insert.add_fixit_insert_before ("INSERTED\n");
-   edit.add_fixits (&insert);
-   return loc;
- }
- 
- /* Test of editing multiple lines within a long file,
-    to ensure that diffs are generated as expected.  */
- 
- static void
- test_applying_fixits_multiple_lines (const line_table_case &case_)
- {
-   /* Create a tempfile and write many lines of text to it.  */
-   named_temp_file tmp (".txt");
-   const char *filename = tmp.get_filename ();
-   FILE *f = fopen (filename, "w");
-   ASSERT_NE (f, NULL);
-   for (int i = 1; i <= 1000; i++)
-     fprintf (f, "line %i\n", i);
-   fclose (f);
- 
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, filename, 1);
-   linemap_position_for_column (line_table, 127);
- 
-   file_cache fc;
-   edit_context edit (fc);
- 
-   /* A run of consecutive lines.  */
-   change_line (edit, 2);
-   change_line (edit, 3);
-   change_line (edit, 4);
-   insert_line (edit, 5);
- 
-   /* A run of nearby lines, within the contextual limit.  */
-   change_line (edit, 150);
-   change_line (edit, 151);
-   location_t last_loc = change_line (edit, 153);
- 
-   if (last_loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Verify diff.  */
-   auto_free <char *> diff = edit.generate_diff (false);
-   ASSERT_STREQ ("@@ -1,7 +1,8 @@\n"
- 		" line 1\n"
- 		"-line 2\n"
- 		"-line 3\n"
- 		"-line 4\n"
- 		"+CHANGED: line 2\n"
- 		"+CHANGED: line 3\n"
- 		"+CHANGED: line 4\n"
- 		"+INSERTED\n"
- 		" line 5\n"
- 		" line 6\n"
- 		" line 7\n"
- 		"@@ -147,10 +148,10 @@\n"
- 		" line 147\n"
- 		" line 148\n"
- 		" line 149\n"
- 		"-line 150\n"
- 		"-line 151\n"
- 		"+CHANGED: line 150\n"
- 		"+CHANGED: line 151\n"
- 		" line 152\n"
- 		"-line 153\n"
- 		"+CHANGED: line 153\n"
- 		" line 154\n"
- 		" line 155\n"
- 		" line 156\n", diff);
- 
-   /* Ensure tmp stays alive until this point, so that the tempfile
-      persists until after the generate_diff call.  */
-   tmp.get_filename ();
- }
- 
- /* Test of converting an initializer for a named field from
-    the old GCC extension to C99 syntax.
-    Exercises a shrinking replacement followed by a growing
-    replacement on the same line.  */
- 
- static void
- test_applying_fixits_modernize_named_init (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      .........................00000000011111111.
-      .........................12345678901234567.  */
-   const char *old_content = ("/* before */\n"
- 			     "bar    : 1,\n"
- 			     "/* after */\n");
-   temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, filename, 2);
- 
-   location_t c1 = linemap_position_for_column (line_table, 1);
-   location_t c3 = linemap_position_for_column (line_table, 3);
-   location_t c8 = linemap_position_for_column (line_table, 8);
- 
-   if (c8 > LINE_MAP_MAX_LOCATION_WITH_COLS)
-     return;
- 
-   /* Replace "bar" with ".".  */
-   rich_location r1 (line_table, c8);
-   r1.add_fixit_replace (source_range::from_locations (c1, c3),
- 			".");
- 
-   /* Replace ":" with "bar =".   */
-   rich_location r2 (line_table, c8);
-   r2.add_fixit_replace (source_range::from_locations (c8, c8),
- 			"bar =");
- 
-   /* The order should not matter.  Do r1 then r2. */
-   {
-     file_cache fc;
-     edit_context edit (fc);
-     edit.add_fixits (&r1);
- 
-     /* Verify state after first replacement.  */
-     {
-       auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
-       /* We should now have:
- 	 ............00000000011.
- 	 ............12345678901.  */
-       ASSERT_STREQ ("/* before */\n"
- 		    ".    : 1,\n"
- 		    "/* after */\n",
- 		    new_content);
-       /* Location of the "1".  */
-       ASSERT_EQ (6, edit.get_effective_column (filename, 2, 8));
-       /* Location of the ",".  */
-       ASSERT_EQ (9, edit.get_effective_column (filename, 2, 11));
-     }
- 
-     edit.add_fixits (&r2);
- 
-     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
-     /* Verify state after second replacement.
-        ............00000000011111111.
-        ............12345678901234567.  */
-     ASSERT_STREQ ("/* before */\n"
- 		  ".    bar = 1,\n"
- 		  "/* after */\n",
- 		  new_content);
-   }
- 
-   /* Try again, doing r2 then r1; the new_content should be the same.  */
-   {
-     file_cache fc;
-     edit_context edit (fc);
-     edit.add_fixits (&r2);
-     edit.add_fixits (&r1);
-     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
-     /*.............00000000011111111.
-       .............12345678901234567.  */
-     ASSERT_STREQ ("/* before */\n"
- 		  ".    bar = 1,\n"
- 		  "/* after */\n",
- 		  new_content);
-   }
- }
- 
- /* Test of a fixit affecting a file that can't be read.  */
- 
- static void
- test_applying_fixits_unreadable_file ()
- {
-   const char *filename = "this-does-not-exist.txt";
-   line_table_test ltt;
-   linemap_add (line_table, LC_ENTER, false, filename, 1);
- 
-   location_t loc = linemap_position_for_column (line_table, 1);
- 
-   rich_location insert (line_table, loc);
-   insert.add_fixit_insert_before ("change 1");
-   insert.add_fixit_insert_before ("change 2");
- 
-   file_cache fc;
-   edit_context edit (fc);
-   /* Attempting to add the fixits affecting the unreadable file
-      should transition the edit from valid to invalid.  */
-   ASSERT_TRUE (edit.valid_p ());
-   edit.add_fixits (&insert);
-   ASSERT_FALSE (edit.valid_p ());
-   ASSERT_EQ (NULL, edit.get_content (filename));
-   ASSERT_EQ (NULL, edit.generate_diff (false));
- }
- 
- /* Verify that we gracefully handle an attempt to edit a line
-    that's beyond the end of the file.  */
- 
- static void
- test_applying_fixits_line_out_of_range ()
- {
-   /* Create a tempfile and write some text to it.
-      ........................00000000011111111.
-      ........................12345678901234567.  */
-   const char *old_content = "One-liner file\n";
-   temp_source_file tmp (SELFTEST_LOCATION, ".txt", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt;
-   linemap_add (line_table, LC_ENTER, false, filename, 2);
- 
-   /* Try to insert a string in line 2.  */
-   location_t loc = linemap_position_for_column (line_table, 1);
- 
-   rich_location insert (line_table, loc);
-   insert.add_fixit_insert_before ("change");
- 
-   /* Verify that attempting the insertion puts an edit_context
-      into an invalid state.  */
-   file_cache fc;
-   edit_context edit (fc);
-   ASSERT_TRUE (edit.valid_p ());
-   edit.add_fixits (&insert);
-   ASSERT_FALSE (edit.valid_p ());
-   ASSERT_EQ (NULL, edit.get_content (filename));
-   ASSERT_EQ (NULL, edit.generate_diff (false));
- }
- 
- /* Verify the boundary conditions of column values in fix-it
-    hints applied to edit_context instances.  */
- 
- static void
- test_applying_fixits_column_validation (const line_table_case &case_)
- {
-   /* Create a tempfile and write some text to it.
-      ........................00000000011111111.
-      ........................12345678901234567.  */
-   const char *old_content = "One-liner file\n";
-   temp_source_file tmp (SELFTEST_LOCATION, ".txt", old_content);
-   const char *filename = tmp.get_filename ();
-   line_table_test ltt (case_);
-   linemap_add (line_table, LC_ENTER, false, filename, 1);
- 
-   location_t c11 = linemap_position_for_column (line_table, 11);
-   location_t c14 = linemap_position_for_column (line_table, 14);
-   location_t c15 = linemap_position_for_column (line_table, 15);
-   location_t c16 = linemap_position_for_column (line_table, 16);
- 
-   /* Verify limits of valid columns in insertion fixits.  */
- 
-   /* Verify inserting at the end of the line.  */
-   {
-     rich_location richloc (line_table, c11);
-     richloc.add_fixit_insert_before (c15, " change");
- 
-     /* Col 15 is at the end of the line, so the insertion
-        should succeed.  */
-     file_cache fc;
-     edit_context edit (fc);
-     edit.add_fixits (&richloc);
-     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
-     if (c15 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
-       ASSERT_STREQ ("One-liner file change\n", new_content);
-     else
-       ASSERT_EQ (NULL, new_content);
-   }
- 
-   /* Verify inserting beyond the end of the line.  */
-   {
-     rich_location richloc (line_table, c11);
-     richloc.add_fixit_insert_before (c16, " change");
- 
-     /* Col 16 is beyond the end of the line, so the insertion
-        should fail gracefully.  */
-     file_cache fc;
-     edit_context edit (fc);
-     ASSERT_TRUE (edit.valid_p ());
-     edit.add_fixits (&richloc);
-     ASSERT_FALSE (edit.valid_p ());
-     ASSERT_EQ (NULL, edit.get_content (filename));
-     ASSERT_EQ (NULL, edit.generate_diff (false));
-   }
- 
-   /* Verify limits of valid columns in replacement fixits.  */
- 
-   /* Verify replacing the end of the line.  */
-   {
-     rich_location richloc (line_table, c11);
-     source_range range = source_range::from_locations (c11, c14);
-     richloc.add_fixit_replace (range, "change");
- 
-     /* Col 14 is at the end of the line, so the replacement
-        should succeed.  */
-     file_cache fc;
-     edit_context edit (fc);
-     edit.add_fixits (&richloc);
-     auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
-     if (c14 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
-       ASSERT_STREQ ("One-liner change\n", new_content);
-     else
-       ASSERT_EQ (NULL, new_content);
-   }
- 
-   /* Verify going beyond the end of the line.  */
-   {
-     rich_location richloc (line_table, c11);
-     source_range range = source_range::from_locations (c11, c15);
-     richloc.add_fixit_replace (range, "change");
- 
-     /* Col 15 is after the end of the line, so the replacement
-        should fail; verify that the attempt fails gracefully.  */
-     file_cache fc;
-     edit_context edit (fc);
-     ASSERT_TRUE (edit.valid_p ());
-     edit.add_fixits (&richloc);
-     ASSERT_FALSE (edit.valid_p ());
-     ASSERT_EQ (NULL, edit.get_content (filename));
-     ASSERT_EQ (NULL, edit.generate_diff (false));
-   }
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- edit_context_cc_tests ()
- {
-   test_get_content ();
-   for_each_line_table_case (test_applying_fixits_insert_before);
-   for_each_line_table_case (test_applying_fixits_insert_after);
-   for_each_line_table_case (test_applying_fixits_insert_after_at_line_end);
-   for_each_line_table_case (test_applying_fixits_insert_after_failure);
-   for_each_line_table_case (test_applying_fixits_insert_containing_newline);
-   for_each_line_table_case (test_applying_fixits_growing_replace);
-   for_each_line_table_case (test_applying_fixits_shrinking_replace);
-   for_each_line_table_case (test_applying_fixits_replace_containing_newline);
-   for_each_line_table_case (test_applying_fixits_remove);
-   for_each_line_table_case (test_applying_fixits_multiple);
-   for_each_line_table_case (test_applying_fixits_multiple_lines);
-   for_each_line_table_case (test_applying_fixits_modernize_named_init);
-   test_applying_fixits_unreadable_file ();
-   test_applying_fixits_line_out_of_range ();
-   for_each_line_table_case (test_applying_fixits_column_validation);
- }
- 
- } // namespace selftest
- 
- #endif /* CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/edit-context.h gcc-16-20250727/gcc/edit-context.h
*** gcc-16-20250720/gcc/edit-context.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/edit-context.h	Thu Jan  1 00:00:00 1970
***************
*** 1,71 ****
- /* Determining the results of applying fix-it hints.
-    Copyright (C) 2016-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_EDIT_CONTEXT_H
- #define GCC_EDIT_CONTEXT_H
- 
- #include "typed-splay-tree.h"
- 
- class fixit_hint;
- class edit_context;
- class edited_file;
- 
- /* A set of changes to the source code.
- 
-    The changes are "atomic" - if any changes can't be applied,
-    none of them can be (tracked by the m_valid flag).
-    Similarly, attempts to add the changes from a rich_location flagged
-    as containing invalid changes mean that the whole of the edit_context
-    is flagged as invalid.
- 
-    A complication here is that fix-its are expressed relative to coordinates
-    in the files when they were parsed, before any changes have been made, and
-    so if there's more that one fix-it to be applied, we have to adjust
-    later fix-its to allow for the changes made by earlier ones.  This
-    is done by the various "get_effective_column" methods.  */
- 
- class edit_context
- {
-  public:
-   edit_context (file_cache &);
- 
-   bool valid_p () const { return m_valid; }
- 
-   void add_fixits (rich_location *richloc);
- 
-   char *get_content (const char *filename);
- 
-   int get_effective_column (const char *filename, int line, int column);
- 
-   char *generate_diff (bool show_filenames);
-   void print_diff (pretty_printer *pp, bool show_filenames);
- 
-   file_cache &get_file_cache () const { return m_file_cache; }
- 
-  private:
-   bool apply_fixit (const fixit_hint *hint);
-   edited_file *get_file (const char *filename);
-   edited_file &get_or_insert_file (const char *filename);
- 
-   file_cache &m_file_cache;
-   bool m_valid;
-   typed_splay_tree<const char *, edited_file *> m_files;
- };
- 
- #endif /* GCC_EDIT_CONTEXT_H.  */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/errors.cc gcc-16-20250727/gcc/errors.cc
*** gcc-16-20250720/gcc/errors.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/errors.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 19,25 ****
  
  /* warning, error, and fatal.  These definitions are suitable for use
     in the generator programs; the compiler has a more elaborate suite
!    of diagnostic printers, found in diagnostic.cc.  */
  
  #ifdef HOST_GENERATOR_FILE
  #include "config.h"
--- 19,26 ----
  
  /* warning, error, and fatal.  These definitions are suitable for use
     in the generator programs; the compiler has a more elaborate suite
!    of diagnostic printers, found in diagnostic-global-context.cc using
!    the diagnostics/ subdirectory.  */
  
  #ifdef HOST_GENERATOR_FILE
  #include "config.h"
*************** trim_filename (const char *name)
*** 126,132 ****
  
  /* "Fancy" abort.  Reports where in the compiler someone gave up.
     This file is used only by build programs, so we're not as polite as
!    the version in diagnostic.cc.  */
  void
  fancy_abort (const char *file, int line, const char *func)
  {
--- 127,133 ----
  
  /* "Fancy" abort.  Reports where in the compiler someone gave up.
     This file is used only by build programs, so we're not as polite as
!    the version in diagnostics/context.cc.  */
  void
  fancy_abort (const char *file, int line, const char *func)
  {
diff -Nrcpad gcc-16-20250720/gcc/expr.cc gcc-16-20250727/gcc/expr.cc
*** gcc-16-20250720/gcc/expr.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/expr.cc	Sun Jul 27 22:32:08 2025
*************** constant_byte_string (tree arg, tree *pt
*** 13206,13211 ****
--- 13206,13213 ----
  	     of the expected type and size.  */
  	  if (!initsize)
  	    initsize = integer_zero_node;
+ 	  else if (!tree_fits_uhwi_p (initsize))
+ 	    return NULL_TREE;
  
  	  unsigned HOST_WIDE_INT size = tree_to_uhwi (initsize);
  	  if (size > (unsigned HOST_WIDE_INT) INT_MAX)
diff -Nrcpad gcc-16-20250720/gcc/final.cc gcc-16-20250727/gcc/final.cc
*** gcc-16-20250720/gcc/final.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/final.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 83,88 ****
--- 83,89 ----
  #include "function-abi.h"
  #include "common/common-target.h"
  #include "diagnostic.h"
+ #include "diagnostics/file-cache.h"
  
  #include "dwarf2out.h"
  
*************** asm_show_source (const char *filename, i
*** 2116,2122 ****
    if (!filename)
      return;
  
!   char_span line
      = global_dc->get_file_cache ().get_source_line (filename, linenum);
    if (!line)
      return;
--- 2117,2123 ----
    if (!filename)
      return;
  
!   diagnostics::char_span line
      = global_dc->get_file_cache ().get_source_line (filename, linenum);
    if (!line)
      return;
diff -Nrcpad gcc-16-20250720/gcc/fortran/ChangeLog gcc-16-20250727/gcc/fortran/ChangeLog
*** gcc-16-20250720/gcc/fortran/ChangeLog	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/fortran/ChangeLog	Sun Jul 27 22:32:08 2025
***************
*** 1,3 ****
--- 1,75 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* error.cc: Make diagnostics::context::m_source_printing private.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* cpp.cc: Update usage of "diagnostic_info" to explicitly refer to
+ 	"diagnostics::diagnostic_info".
+ 	* error.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* cpp.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* error.cc: Likewise.
+ 	* options.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* cpp.cc: Update for renaming of
+ 	diagnostic_option_id to diagnostics::option_id.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* error.cc: Update for move of diagnostic-color.h to
+ 	diagnostics/color.h.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* error.cc: Update for diagnostic_context becoming
+ 	diagnostics::context.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* error.cc: Update to add "m_" prefix to fields of
+ 	diagnostic_info throughout.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* error.cc: Update for move of diagnostics output formats into
+ 	namespace "diagnostics" as "sinks".
+ 	* gfortran.h: Likewise.
+ 
+ 2025-07-23  Harald Anlauf  <anlauf@gmx.de>
+ 
+ 	PR fortran/121203
+ 	* trans-expr.cc (gfc_conv_procedure_call): Obtain the character
+ 	length of an assumed character length procedure from the typespec
+ 	of the actual argument even if there is no explicit interface.
+ 
+ 2025-07-21  Mikael Morin  <mikael@gcc.gnu.org>
+ 
+ 	* trans-decl.cc (gfc_trans_deferred_vars): Fix indentation.
+ 
+ 2025-07-21  Andre Vehreschild  <vehre@gcc.gnu.org>
+ 
+ 	PR fortran/119106
+ 	* expr.cc (simplify_constructor): Do not simplify constants.
+ 	(gfc_simplify_expr): Continue to simplify expression when an
+ 	iterator is present.
+ 
+ 2025-07-21  Mikael Morin  <mikael@gcc.gnu.org>
+ 
+ 	* trans-array.cc (gfc_conv_ss_descriptor): Move the descriptor
+ 	expression initialisation...
+ 	(set_factored_descriptor_value): ... to this new function.
+ 	Before initialisation, walk the reference expression passed as
+ 	argument and save some of its subexpressions to a variable.
+ 	(substitute_t): New struct.
+ 	(maybe_substitute_expr): New function.
+ 	(substitute_subexpr_in_expr): New function.
+ 
  2025-07-18  Harald Anlauf  <anlauf@gmx.de>
  
  	PR fortran/121145
diff -Nrcpad gcc-16-20250720/gcc/fortran/cpp.cc gcc-16-20250727/gcc/fortran/cpp.cc
*** gcc-16-20250720/gcc/fortran/cpp.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/fortran/cpp.cc	Sun Jul 27 22:32:08 2025
*************** cb_used_define (cpp_reader *pfile, locat
*** 1063,1069 ****
  /* Return the gcc option code associated with the reason for a cpp
     message, or 0 if none.  */
  
! static diagnostic_option_id
  cb_cpp_diagnostic_cpp_option (enum cpp_warning_reason reason)
  {
    const struct cpp_reason_option_codes_t *entry;
--- 1063,1069 ----
  /* Return the gcc option code associated with the reason for a cpp
     message, or 0 if none.  */
  
! static diagnostics::option_id
  cb_cpp_diagnostic_cpp_option (enum cpp_warning_reason reason)
  {
    const struct cpp_reason_option_codes_t *entry;
*************** cb_cpp_diagnostic (cpp_reader *pfile ATT
*** 1088,1095 ****
  		   rich_location *richloc,
  		   const char *msg, va_list *ap)
  {
!   diagnostic_info diagnostic;
!   diagnostic_t dlevel;
    bool save_warn_system_headers = global_dc->m_warn_system_headers;
    bool ret;
  
--- 1088,1095 ----
  		   rich_location *richloc,
  		   const char *msg, va_list *ap)
  {
!   diagnostics::diagnostic_info diagnostic;
!   enum diagnostics::kind dlevel;
    bool save_warn_system_headers = global_dc->m_warn_system_headers;
    bool ret;
  
*************** cb_cpp_diagnostic (cpp_reader *pfile ATT
*** 1099,1120 ****
        global_dc->m_warn_system_headers = 1;
        /* Fall through.  */
      case CPP_DL_WARNING:
!       dlevel = DK_WARNING;
        break;
      case CPP_DL_PEDWARN:
!       dlevel = DK_PEDWARN;
        break;
      case CPP_DL_ERROR:
!       dlevel = DK_ERROR;
        break;
      case CPP_DL_ICE:
!       dlevel = DK_ICE;
        break;
      case CPP_DL_NOTE:
!       dlevel = DK_NOTE;
        break;
      case CPP_DL_FATAL:
!       dlevel = DK_FATAL;
        break;
      default:
        gcc_unreachable ();
--- 1099,1120 ----
        global_dc->m_warn_system_headers = 1;
        /* Fall through.  */
      case CPP_DL_WARNING:
!       dlevel = diagnostics::kind::warning;
        break;
      case CPP_DL_PEDWARN:
!       dlevel = diagnostics::kind::pedwarn;
        break;
      case CPP_DL_ERROR:
!       dlevel = diagnostics::kind::error;
        break;
      case CPP_DL_ICE:
!       dlevel = diagnostics::kind::ice;
        break;
      case CPP_DL_NOTE:
!       dlevel = diagnostics::kind::note;
        break;
      case CPP_DL_FATAL:
!       dlevel = diagnostics::kind::fatal;
        break;
      default:
        gcc_unreachable ();
diff -Nrcpad gcc-16-20250720/gcc/fortran/error.cc gcc-16-20250727/gcc/fortran/error.cc
*** gcc-16-20250720/gcc/fortran/error.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/fortran/error.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 31,39 ****
  #include "gfortran.h"
  
  #include "diagnostic.h"
! #include "diagnostic-color.h"
  #include "tree-diagnostic.h" /* tree_diagnostics_defaults */
! #include "diagnostic-format-text.h"
  
  static int suppress_errors = 0;
  
--- 31,39 ----
  #include "gfortran.h"
  
  #include "diagnostic.h"
! #include "diagnostics/color.h"
  #include "tree-diagnostic.h" /* tree_diagnostics_defaults */
! #include "diagnostics/text-sink.h"
  
  static int suppress_errors = 0;
  
*************** static bool warnings_not_errors = false;
*** 43,49 ****
  static bool buffered_p;
  
  static gfc_error_buffer *error_buffer;
! static diagnostic_buffer *pp_error_buffer, *pp_warning_buffer;
  
  gfc_error_buffer::gfc_error_buffer ()
  : flag (false), buffer (*global_dc)
--- 43,49 ----
  static bool buffered_p;
  
  static gfc_error_buffer *error_buffer;
! static diagnostics::buffer *pp_error_buffer, *pp_warning_buffer;
  
  gfc_error_buffer::gfc_error_buffer ()
  : flag (false), buffer (*global_dc)
*************** gfc_print_wide_char (gfc_char_t c)
*** 228,234 ****
     it to global_dc.  */
  
  static void
! gfc_clear_diagnostic_buffer (diagnostic_buffer *this_buffer)
  {
    gcc_assert (this_buffer);
    global_dc->clear_diagnostic_buffer (*this_buffer);
--- 228,234 ----
     it to global_dc.  */
  
  static void
! gfc_clear_diagnostic_buffer (diagnostics::buffer *this_buffer)
  {
    gcc_assert (this_buffer);
    global_dc->clear_diagnostic_buffer (*this_buffer);
*************** gfc_clear_diagnostic_buffer (diagnostic_
*** 237,249 ****
  /* The currently-printing diagnostic, for use by gfc_format_decoder,
     for colorizing %C and %L.  */
  
! static diagnostic_info *curr_diagnostic;
  
  /* A helper function to call diagnostic_report_diagnostic, while setting
     curr_diagnostic for the duration of the call.  */
  
  static bool
! gfc_report_diagnostic (diagnostic_info *diagnostic)
  {
    gcc_assert (diagnostic != NULL);
    curr_diagnostic = diagnostic;
--- 237,249 ----
  /* The currently-printing diagnostic, for use by gfc_format_decoder,
     for colorizing %C and %L.  */
  
! static diagnostics::diagnostic_info *curr_diagnostic;
  
  /* A helper function to call diagnostic_report_diagnostic, while setting
     curr_diagnostic for the duration of the call.  */
  
  static bool
! gfc_report_diagnostic (diagnostics::diagnostic_info *diagnostic)
  {
    gcc_assert (diagnostic != NULL);
    curr_diagnostic = diagnostic;
*************** gfc_warning (int opt, const char *gmsgid
*** 261,269 ****
    va_list argp;
    va_copy (argp, ap);
  
!   diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
!   diagnostic_buffer *old_buffer = global_dc->get_diagnostic_buffer ();
    gcc_assert (!old_buffer);
  
    gfc_clear_diagnostic_buffer (pp_warning_buffer);
--- 261,269 ----
    va_list argp;
    va_copy (argp, ap);
  
!   diagnostics::diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
!   diagnostics::buffer *old_buffer = global_dc->get_diagnostic_buffer ();
    gcc_assert (!old_buffer);
  
    gfc_clear_diagnostic_buffer (pp_warning_buffer);
*************** gfc_warning (int opt, const char *gmsgid
*** 272,279 ****
      global_dc->set_diagnostic_buffer (pp_warning_buffer);
  
    diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       DK_WARNING);
!   diagnostic.option_id = opt;
    bool ret = gfc_report_diagnostic (&diagnostic);
  
    if (buffered_p)
--- 272,279 ----
      global_dc->set_diagnostic_buffer (pp_warning_buffer);
  
    diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       diagnostics::kind::warning);
!   diagnostic.m_option_id = opt;
    bool ret = gfc_report_diagnostic (&diagnostic);
  
    if (buffered_p)
*************** gfc_format_decoder (pretty_printer *pp,
*** 441,447 ****
  	const char *color
  	  = (loc_num
  	     ? "range1"
! 	     : diagnostic_get_color_for_kind (curr_diagnostic->kind));
  	pp_string (pp, colorize_start (pp_show_color (pp), color));
  	pp_string (pp, result[loc_num]);
  	pp_string (pp, colorize_stop (pp_show_color (pp)));
--- 441,447 ----
  	const char *color
  	  = (loc_num
  	     ? "range1"
! 	     : diagnostics::get_color_for_kind (curr_diagnostic->m_kind));
  	pp_string (pp, colorize_start (pp_show_color (pp), color));
  	pp_string (pp, result[loc_num]);
  	pp_string (pp, colorize_stop (pp_show_color (pp)));
*************** gfc_format_decoder (pretty_printer *pp,
*** 460,467 ****
  /* Return a malloc'd string describing the kind of diagnostic.  The
     caller is responsible for freeing the memory.  */
  static char *
! gfc_diagnostic_build_kind_prefix (diagnostic_context *context,
! 				  const diagnostic_info *diagnostic)
  {
    static const char *const diagnostic_kind_text[] = {
  #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
--- 460,467 ----
  /* Return a malloc'd string describing the kind of diagnostic.  The
     caller is responsible for freeing the memory.  */
  static char *
! gfc_diagnostic_build_kind_prefix (diagnostics::context *context,
! 				  const diagnostics::diagnostic_info *diagnostic)
  {
    static const char *const diagnostic_kind_text[] = {
  #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
*************** gfc_diagnostic_build_kind_prefix (diagno
*** 475,489 ****
  #undef DEFINE_DIAGNOSTIC_KIND
      NULL
    };
!   gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
!   const char *text = _(diagnostic_kind_text[diagnostic->kind]);
    const char *text_cs = "", *text_ce = "";
    pretty_printer *const pp = context->get_reference_printer ();
  
!   if (diagnostic_kind_color[diagnostic->kind])
      {
        text_cs = colorize_start (pp_show_color (pp),
! 				diagnostic_kind_color[diagnostic->kind]);
        text_ce = colorize_stop (pp_show_color (pp));
      }
    return build_message_string ("%s%s:%s ", text_cs, text, text_ce);
--- 475,490 ----
  #undef DEFINE_DIAGNOSTIC_KIND
      NULL
    };
!   const int diag_kind_idx = static_cast<int> (diagnostic->m_kind);
!   gcc_assert (diagnostic->m_kind < diagnostics::kind::last_diagnostic_kind);
!   const char *text = _(diagnostic_kind_text[diag_kind_idx]);
    const char *text_cs = "", *text_ce = "";
    pretty_printer *const pp = context->get_reference_printer ();
  
! if (diagnostic_kind_color[diag_kind_idx])
      {
        text_cs = colorize_start (pp_show_color (pp),
! 				diagnostic_kind_color[diag_kind_idx]);
        text_ce = colorize_stop (pp_show_color (pp));
      }
    return build_message_string ("%s%s:%s ", text_cs, text, text_ce);
*************** gfc_diagnostic_build_kind_prefix (diagno
*** 492,498 ****
  /* Return a malloc'd string describing a location.  The caller is
     responsible for freeing the memory.  */
  static char *
! gfc_diagnostic_build_locus_prefix (const diagnostic_location_print_policy &loc_policy,
  				   expanded_location s,
  				   bool colorize)
  {
--- 493,499 ----
  /* Return a malloc'd string describing a location.  The caller is
     responsible for freeing the memory.  */
  static char *
! gfc_diagnostic_build_locus_prefix (const diagnostics::location_print_policy &loc_policy,
  				   expanded_location s,
  				   bool colorize)
  {
*************** gfc_diagnostic_build_locus_prefix (const
*** 511,517 ****
  /* Return a malloc'd string describing two locations.  The caller is
     responsible for freeing the memory.  */
  static char *
! gfc_diagnostic_build_locus_prefix (const diagnostic_location_print_policy &loc_policy,
  				   expanded_location s, expanded_location s2,
  				   bool colorize)
  {
--- 512,518 ----
  /* Return a malloc'd string describing two locations.  The caller is
     responsible for freeing the memory.  */
  static char *
! gfc_diagnostic_build_locus_prefix (const diagnostics::location_print_policy &loc_policy,
  				   expanded_location s, expanded_location s2,
  				   bool colorize)
  {
*************** gfc_diagnostic_build_locus_prefix (const
*** 548,563 ****
         [locus of primary range]: Error: Some error at (1) and (2)
  */
  static void
! gfc_diagnostic_text_starter (diagnostic_text_output_format &text_output,
! 			     const diagnostic_info *diagnostic)
  {
!   diagnostic_context *const context = &text_output.get_context ();
    pretty_printer *const pp = text_output.get_printer ();
    char * kind_prefix = gfc_diagnostic_build_kind_prefix (context, diagnostic);
  
    expanded_location s1 = diagnostic_expand_location (diagnostic);
    expanded_location s2;
!   bool one_locus = diagnostic->richloc->get_num_locations () < 2;
    bool same_locus = false;
  
    if (!one_locus)
--- 549,564 ----
         [locus of primary range]: Error: Some error at (1) and (2)
  */
  static void
! gfc_diagnostic_text_starter (diagnostics::text_sink &text_output,
! 			     const diagnostics::diagnostic_info *diagnostic)
  {
!   diagnostics::context *const context = &text_output.get_context ();
    pretty_printer *const pp = text_output.get_printer ();
    char * kind_prefix = gfc_diagnostic_build_kind_prefix (context, diagnostic);
  
    expanded_location s1 = diagnostic_expand_location (diagnostic);
    expanded_location s2;
!   bool one_locus = diagnostic->m_richloc->get_num_locations () < 2;
    bool same_locus = false;
  
    if (!one_locus)
*************** gfc_diagnostic_text_starter (diagnostic_
*** 566,578 ****
        same_locus = diagnostic_same_line (context, s1, s2);
      }
  
!   diagnostic_location_print_policy loc_policy (text_output);
    const bool colorize = pp_show_color (pp);
    char * locus_prefix = (one_locus || !same_locus)
      ? gfc_diagnostic_build_locus_prefix (loc_policy, s1, colorize)
      : gfc_diagnostic_build_locus_prefix (loc_policy, s1, s2, colorize);
  
!   if (!context->m_source_printing.enabled
        || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
        || diagnostic_location (diagnostic, 0) == context->m_last_location)
      {
--- 567,579 ----
        same_locus = diagnostic_same_line (context, s1, s2);
      }
  
!   diagnostics::location_print_policy loc_policy (text_output);
    const bool colorize = pp_show_color (pp);
    char * locus_prefix = (one_locus || !same_locus)
      ? gfc_diagnostic_build_locus_prefix (loc_policy, s1, colorize)
      : gfc_diagnostic_build_locus_prefix (loc_policy, s1, s2, colorize);
  
!   if (!context->get_source_printing_options ().enabled
        || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
        || diagnostic_location (diagnostic, 0) == context->m_last_location)
      {
*************** gfc_diagnostic_text_starter (diagnostic_
*** 608,614 ****
        pp_newline (pp);
        diagnostic_show_locus (context,
  			     text_output.get_source_printing_options (),
! 			     diagnostic->richloc, diagnostic->kind,
  			     pp);
        /* If the caret line was shown, the prefix does not contain the
  	 locus.  */
--- 609,615 ----
        pp_newline (pp);
        diagnostic_show_locus (context,
  			     text_output.get_source_printing_options (),
! 			     diagnostic->m_richloc, diagnostic->m_kind,
  			     pp);
        /* If the caret line was shown, the prefix does not contain the
  	 locus.  */
*************** gfc_diagnostic_text_starter (diagnostic_
*** 617,627 ****
  }
  
  static void
! gfc_diagnostic_start_span (const diagnostic_location_print_policy &loc_policy,
! 			   to_text &sink,
  			   expanded_location exploc)
  {
!   pretty_printer *pp = get_printer (sink);
    const bool colorize = pp_show_color (pp);
    char *locus_prefix
      = gfc_diagnostic_build_locus_prefix (loc_policy, exploc, colorize);
--- 618,628 ----
  }
  
  static void
! gfc_diagnostic_start_span (const diagnostics::location_print_policy &loc_policy,
! 			   diagnostics::to_text &sink,
  			   expanded_location exploc)
  {
!   pretty_printer *pp = diagnostics::get_printer (sink);
    const bool colorize = pp_show_color (pp);
    char *locus_prefix
      = gfc_diagnostic_build_locus_prefix (loc_policy, exploc, colorize);
*************** gfc_diagnostic_start_span (const diagnos
*** 634,642 ****
  
  
  static void
! gfc_diagnostic_text_finalizer (diagnostic_text_output_format &text_output,
! 			       const diagnostic_info *diagnostic ATTRIBUTE_UNUSED,
! 			       diagnostic_t orig_diag_kind ATTRIBUTE_UNUSED)
  {
    pretty_printer *const pp = text_output.get_printer ();
    pp_destroy_prefix (pp);
--- 635,643 ----
  
  
  static void
! gfc_diagnostic_text_finalizer (diagnostics::text_sink &text_output,
! 			       const diagnostics::diagnostic_info *,
! 			       enum diagnostics::kind orig_diag_kind ATTRIBUTE_UNUSED)
  {
    pretty_printer *const pp = text_output.get_printer ();
    pp_destroy_prefix (pp);
*************** bool
*** 650,662 ****
  gfc_warning_now_at (location_t loc, int opt, const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostic_info diagnostic;
    rich_location rich_loc (line_table, loc);
    bool ret;
  
    va_start (argp, gmsgid);
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_WARNING);
!   diagnostic.option_id = opt;
    ret = gfc_report_diagnostic (&diagnostic);
    va_end (argp);
    return ret;
--- 651,664 ----
  gfc_warning_now_at (location_t loc, int opt, const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostics::diagnostic_info diagnostic;
    rich_location rich_loc (line_table, loc);
    bool ret;
  
    va_start (argp, gmsgid);
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       diagnostics::kind::warning);
!   diagnostic.m_option_id = opt;
    ret = gfc_report_diagnostic (&diagnostic);
    va_end (argp);
    return ret;
*************** bool
*** 668,681 ****
  gfc_warning_now (int opt, const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
    bool ret;
  
    va_start (argp, gmsgid);
    diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       DK_WARNING);
!   diagnostic.option_id = opt;
    ret = gfc_report_diagnostic (&diagnostic);
    va_end (argp);
    return ret;
--- 670,683 ----
  gfc_warning_now (int opt, const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostics::diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
    bool ret;
  
    va_start (argp, gmsgid);
    diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       diagnostics::kind::warning);
!   diagnostic.m_option_id = opt;
    ret = gfc_report_diagnostic (&diagnostic);
    va_end (argp);
    return ret;
*************** bool
*** 687,700 ****
  gfc_warning_internal (int opt, const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
    bool ret;
  
    va_start (argp, gmsgid);
    diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       DK_WARNING);
!   diagnostic.option_id = opt;
    ret = gfc_report_diagnostic (&diagnostic);
    va_end (argp);
    return ret;
--- 689,702 ----
  gfc_warning_internal (int opt, const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostics::diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
    bool ret;
  
    va_start (argp, gmsgid);
    diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       diagnostics::kind::warning);
!   diagnostic.m_option_id = opt;
    ret = gfc_report_diagnostic (&diagnostic);
    va_end (argp);
    return ret;
*************** void
*** 706,718 ****
  gfc_error_now (const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
  
    error_buffer->flag = true;
  
    va_start (argp, gmsgid);
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ERROR);
    gfc_report_diagnostic (&diagnostic);
    va_end (argp);
  }
--- 708,721 ----
  gfc_error_now (const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostics::diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
  
    error_buffer->flag = true;
  
    va_start (argp, gmsgid);
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       diagnostics::kind::error);
    gfc_report_diagnostic (&diagnostic);
    va_end (argp);
  }
*************** void
*** 724,734 ****
  gfc_fatal_error (const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
  
    va_start (argp, gmsgid);
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_FATAL);
    gfc_report_diagnostic (&diagnostic);
    va_end (argp);
  
--- 727,738 ----
  gfc_fatal_error (const char *gmsgid, ...)
  {
    va_list argp;
!   diagnostics::diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
  
    va_start (argp, gmsgid);
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       diagnostics::kind::fatal);
    gfc_report_diagnostic (&diagnostic);
    va_end (argp);
  
*************** gfc_error_opt (int opt, const char *gmsg
*** 776,784 ****
        return;
      }
  
!   diagnostic_info diagnostic;
    rich_location richloc (line_table, UNKNOWN_LOCATION);
!   diagnostic_buffer *old_buffer = global_dc->get_diagnostic_buffer ();
    gcc_assert (!old_buffer);
  
    gfc_clear_diagnostic_buffer (pp_error_buffer);
--- 780,788 ----
        return;
      }
  
!   diagnostics::diagnostic_info diagnostic;
    rich_location richloc (line_table, UNKNOWN_LOCATION);
!   diagnostics::buffer *old_buffer = global_dc->get_diagnostic_buffer ();
    gcc_assert (!old_buffer);
  
    gfc_clear_diagnostic_buffer (pp_error_buffer);
*************** gfc_error_opt (int opt, const char *gmsg
*** 786,792 ****
    if (buffered_p)
      global_dc->set_diagnostic_buffer (pp_error_buffer);
  
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &richloc, DK_ERROR);
    gfc_report_diagnostic (&diagnostic);
  
    if (buffered_p)
--- 790,797 ----
    if (buffered_p)
      global_dc->set_diagnostic_buffer (pp_error_buffer);
  
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &richloc,
! 		       diagnostics::kind::error);
    gfc_report_diagnostic (&diagnostic);
  
    if (buffered_p)
*************** gfc_internal_error (const char *gmsgid,
*** 823,829 ****
  {
    int e, w;
    va_list argp;
!   diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
  
    gfc_get_errors (&w, &e);
--- 828,834 ----
  {
    int e, w;
    va_list argp;
!   diagnostics::diagnostic_info diagnostic;
    rich_location rich_loc (line_table, UNKNOWN_LOCATION);
  
    gfc_get_errors (&w, &e);
*************** gfc_internal_error (const char *gmsgid,
*** 831,837 ****
      exit(EXIT_FAILURE);
  
    va_start (argp, gmsgid);
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ICE);
    gfc_report_diagnostic (&diagnostic);
    va_end (argp);
  
--- 836,843 ----
      exit(EXIT_FAILURE);
  
    va_start (argp, gmsgid);
!   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
! 		       diagnostics::kind::ice);
    gfc_report_diagnostic (&diagnostic);
    va_end (argp);
  
*************** static void
*** 885,892 ****
  gfc_move_error_buffer_from_to (gfc_error_buffer * buffer_from,
  			       gfc_error_buffer * buffer_to)
  {
!   diagnostic_buffer * from = &(buffer_from->buffer);
!   diagnostic_buffer * to =  &(buffer_to->buffer);
  
    buffer_to->flag = buffer_from->flag;
    buffer_from->flag = false;
--- 891,898 ----
  gfc_move_error_buffer_from_to (gfc_error_buffer * buffer_from,
  			       gfc_error_buffer * buffer_to)
  {
!   diagnostics::buffer * from = &(buffer_from->buffer);
!   diagnostics::buffer * to =  &(buffer_to->buffer);
  
    buffer_to->flag = buffer_from->flag;
    buffer_from->flag = false;
*************** gfc_errors_to_warnings (bool f)
*** 950,962 ****
  void
  gfc_diagnostics_init (void)
  {
!   diagnostic_text_starter (global_dc) = gfc_diagnostic_text_starter;
!   diagnostic_start_span (global_dc) = gfc_diagnostic_start_span;
!   diagnostic_text_finalizer (global_dc) = gfc_diagnostic_text_finalizer;
    global_dc->set_format_decoder (gfc_format_decoder);
!   global_dc->m_source_printing.caret_chars[0] = '1';
!   global_dc->m_source_printing.caret_chars[1] = '2';
!   pp_warning_buffer = new diagnostic_buffer (*global_dc);
    error_buffer = new gfc_error_buffer ();
    pp_error_buffer = &(error_buffer->buffer);
  }
--- 956,969 ----
  void
  gfc_diagnostics_init (void)
  {
!   diagnostics::text_starter (global_dc) = gfc_diagnostic_text_starter;
!   diagnostics::start_span (global_dc) = gfc_diagnostic_start_span;
!   diagnostics::text_finalizer (global_dc) = gfc_diagnostic_text_finalizer;
    global_dc->set_format_decoder (gfc_format_decoder);
!   auto &source_printing_opts = global_dc->get_source_printing_options ();
!   source_printing_opts.caret_chars[0] = '1';
!   source_printing_opts.caret_chars[1] = '2';
!   pp_warning_buffer = new diagnostics::buffer (*global_dc);
    error_buffer = new gfc_error_buffer ();
    pp_error_buffer = &(error_buffer->buffer);
  }
*************** gfc_diagnostics_finish (void)
*** 967,976 ****
    tree_diagnostics_defaults (global_dc);
    /* We still want to use the gfc starter and finalizer, not the tree
       defaults.  */
!   diagnostic_text_starter (global_dc) = gfc_diagnostic_text_starter;
!   diagnostic_text_finalizer (global_dc) = gfc_diagnostic_text_finalizer;
!   global_dc->m_source_printing.caret_chars[0] = '^';
!   global_dc->m_source_printing.caret_chars[1] = '^';
    delete error_buffer;
    error_buffer = nullptr;
    pp_error_buffer = nullptr;
--- 974,984 ----
    tree_diagnostics_defaults (global_dc);
    /* We still want to use the gfc starter and finalizer, not the tree
       defaults.  */
!   diagnostics::text_starter (global_dc) = gfc_diagnostic_text_starter;
!   diagnostics::text_finalizer (global_dc) = gfc_diagnostic_text_finalizer;
!   auto &source_printing_opts = global_dc->get_source_printing_options ();
!   source_printing_opts.caret_chars[0] = '^';
!   source_printing_opts.caret_chars[1] = '^';
    delete error_buffer;
    error_buffer = nullptr;
    pp_error_buffer = nullptr;
diff -Nrcpad gcc-16-20250720/gcc/fortran/expr.cc gcc-16-20250727/gcc/fortran/expr.cc
*** gcc-16-20250720/gcc/fortran/expr.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/fortran/expr.cc	Sun Jul 27 22:32:08 2025
*************** simplify_constructor (gfc_constructor_ba
*** 1372,1378 ****
  	      || !gfc_simplify_expr (c->iterator->step, type)))
  	return false;
  
!       if (c->expr)
  	{
  	  /* Try and simplify a copy.  Replace the original if successful
  	     but keep going through the constructor at all costs.  Not
--- 1372,1378 ----
  	      || !gfc_simplify_expr (c->iterator->step, type)))
  	return false;
  
!       if (c->expr && c->expr->expr_type != EXPR_CONSTANT)
  	{
  	  /* Try and simplify a copy.  Replace the original if successful
  	     but keep going through the constructor at all costs.  Not
*************** gfc_simplify_expr (gfc_expr *p, int type
*** 2469,2475 ****
  	{
  	  if (!simplify_parameter_variable (p, type))
  	    return false;
! 	  break;
  	}
  
        if (type == 1)
--- 2469,2476 ----
  	{
  	  if (!simplify_parameter_variable (p, type))
  	    return false;
! 	  if (!iter_stack)
! 	    break;
  	}
  
        if (type == 1)
diff -Nrcpad gcc-16-20250720/gcc/fortran/gfortran.h gcc-16-20250727/gcc/fortran/gfortran.h
*** gcc-16-20250720/gcc/fortran/gfortran.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/fortran/gfortran.h	Sun Jul 27 22:32:08 2025
*************** bool gfc_notify_std (int, const char *,
*** 3594,3604 ****
  #define gfc_syntax_error(ST)	\
    gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST));
  
! #include "diagnostic-buffer.h"  /* For diagnostic_buffer.  */
  struct gfc_error_buffer
  {
    bool flag;
!   diagnostic_buffer buffer;
  
    gfc_error_buffer();
  };
--- 3594,3604 ----
  #define gfc_syntax_error(ST)	\
    gfc_error ("Syntax error in %s statement at %C", gfc_ascii_statement (ST));
  
! #include "diagnostics/buffering.h"  /* For diagnostics::buffer.  */
  struct gfc_error_buffer
  {
    bool flag;
!   diagnostics::buffer buffer;
  
    gfc_error_buffer();
  };
diff -Nrcpad gcc-16-20250720/gcc/fortran/options.cc gcc-16-20250727/gcc/fortran/options.cc
*** gcc-16-20250720/gcc/fortran/options.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/fortran/options.cc	Sun Jul 27 22:32:08 2025
*************** gfc_post_options (const char **pfilename
*** 406,412 ****
        if (warn_line_truncation && !OPTION_SET_P (warnings_are_errors)
  	  && option_unspecified_p (OPT_Wline_truncation))
  	diagnostic_classify_diagnostic (global_dc, OPT_Wline_truncation,
! 					DK_ERROR, UNKNOWN_LOCATION);
      }
    else
      {
--- 406,413 ----
        if (warn_line_truncation && !OPTION_SET_P (warnings_are_errors)
  	  && option_unspecified_p (OPT_Wline_truncation))
  	diagnostic_classify_diagnostic (global_dc, OPT_Wline_truncation,
! 					diagnostics::kind::error,
! 					UNKNOWN_LOCATION);
      }
    else
      {
diff -Nrcpad gcc-16-20250720/gcc/fortran/trans-array.cc gcc-16-20250727/gcc/fortran/trans-array.cc
*** gcc-16-20250720/gcc/fortran/trans-array.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/fortran/trans-array.cc	Sun Jul 27 22:32:08 2025
*************** save_descriptor_data (tree descr, tree d
*** 3437,3442 ****
--- 3437,3602 ----
  }
  
  
+ /* Type of the DATA argument passed to walk_tree by substitute_subexpr_in_expr
+    and used by maybe_substitute_expr.  */
+ 
+ typedef struct
+ {
+   tree target, repl;
+ }
+ substitute_t;
+ 
+ 
+ /* Check if the expression in *TP is equal to the substitution target provided
+    in DATA->TARGET and replace it with DATA->REPL in that case.   This is a
+    callback function for use with walk_tree.  */
+ 
+ static tree
+ maybe_substitute_expr (tree *tp, int *walk_subtree, void *data)
+ {
+   substitute_t *subst = (substitute_t *) data;
+   if (*tp == subst->target)
+     {
+       *tp = subst->repl;
+       *walk_subtree = 0;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
+ 
+ /* Substitute in EXPR any occurence of TARGET with REPLACEMENT.  */
+ 
+ static void
+ substitute_subexpr_in_expr (tree target, tree replacement, tree expr)
+ {
+   substitute_t subst;
+   subst.target = target;
+   subst.repl = replacement;
+ 
+   walk_tree (&expr, maybe_substitute_expr, &subst, nullptr);
+ }
+ 
+ 
+ /* Save REF to a fresh variable in all of REPLACEMENT_ROOTS, appending extra
+    code to CODE.  Before returning, add REF to REPLACEMENT_ROOTS and clear
+    REF.  */
+ 
+ static void
+ save_ref (tree &code, tree &ref, vec<tree> &replacement_roots)
+ {
+   stmtblock_t tmp_block;
+   gfc_init_block (&tmp_block);
+   tree var = gfc_evaluate_now (ref, &tmp_block);
+   gfc_add_expr_to_block (&tmp_block, code);
+   code = gfc_finish_block (&tmp_block);
+ 
+   unsigned i;
+   tree repl_root;
+   FOR_EACH_VEC_ELT (replacement_roots, i, repl_root)
+     substitute_subexpr_in_expr (ref, var, repl_root);
+ 
+   replacement_roots.safe_push (ref);
+   ref = NULL_TREE;
+ }
+ 
+ 
+ /* Save the descriptor reference VALUE to storage pointed by DESC_PTR.  Before
+    that, try to factor subexpressions of VALUE to variables, adding extra code
+    to BLOCK.
+ 
+    The candidate references to factoring are dereferenced pointers because they
+    are cheap to copy and array descriptors because they are often the base of
+    multiple subreferences.  */
+ 
+ static void
+ set_factored_descriptor_value (tree *desc_ptr, tree value, stmtblock_t *block)
+ {
+   /* As the reference is processed from outer to inner, variable definitions
+      will be generated in reversed order, so can't be put directly in BLOCK.
+      We use TMP_BLOCK instead.  */
+   tree accumulated_code = NULL_TREE;
+ 
+   /* The current candidate to factoring.  */
+   tree saveable_ref = NULL_TREE;
+ 
+   /* The root expressions in which we look for subexpressions to replace with
+      variables.  */
+   auto_vec<tree> replacement_roots;
+   replacement_roots.safe_push (value);
+ 
+   tree data_ref = value;
+   tree next_ref = NULL_TREE;
+ 
+   /* If the candidate reference is not followed by a subreference, it can't be
+      saved to a variable as it may be reallocatable, and we have to keep the
+      parent reference to be able to store the new pointer value in case of
+      reallocation.  */
+   bool maybe_reallocatable = true;
+ 
+   while (true)
+     {
+       if (!maybe_reallocatable
+ 	  && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (data_ref)))
+ 	saveable_ref = data_ref;
+ 
+       if (TREE_CODE (data_ref) == INDIRECT_REF)
+ 	{
+ 	  next_ref = TREE_OPERAND (data_ref, 0);
+ 
+ 	  if (!maybe_reallocatable)
+ 	    {
+ 	      if (saveable_ref != NULL_TREE && saveable_ref != data_ref)
+ 		{
+ 		  /* A reference worth saving has been seen, and now the pointer
+ 		     to the current reference is also worth saving.  If the
+ 		     previous reference to save wasn't the current one, do save
+ 		     it now.  Otherwise drop it as we prefer saving the
+ 		     pointer.  */
+ 		  save_ref (accumulated_code, saveable_ref, replacement_roots);
+ 		}
+ 
+ 	      /* Don't evaluate the pointer to a variable yet; do it only if the
+ 		 variable would be significantly more simple than the reference
+ 		 it replaces.  That is if the reference contains anything
+ 		 different from NOPs, COMPONENTs and DECLs.  */
+ 	      saveable_ref = next_ref;
+ 	    }
+ 	}
+       else if (TREE_CODE (data_ref) == COMPONENT_REF)
+ 	{
+ 	  maybe_reallocatable = false;
+ 	  next_ref = TREE_OPERAND (data_ref, 0);
+ 	}
+       else if (TREE_CODE (data_ref) == NOP_EXPR)
+ 	next_ref = TREE_OPERAND (data_ref, 0);
+       else
+ 	{
+ 	  if (DECL_P (data_ref))
+ 	    break;
+ 
+ 	  if (TREE_CODE (data_ref) == ARRAY_REF)
+ 	    {
+ 	      maybe_reallocatable = false;
+ 	      next_ref = TREE_OPERAND (data_ref, 0);
+ 	    }
+ 
+ 	  if (saveable_ref != NULL_TREE)
+ 	    /* We have seen a reference worth saving.  Do it now.  */
+ 	    save_ref (accumulated_code, saveable_ref, replacement_roots);
+ 
+ 	  if (TREE_CODE (data_ref) != ARRAY_REF)
+ 	    break;
+ 	}
+ 
+       data_ref = next_ref;
+     }
+ 
+   *desc_ptr = value;
+   gfc_add_expr_to_block (block, accumulated_code);
+ }
+ 
+ 
  /* Translate expressions for the descriptor and data pointer of a SS.  */
  /*GCC ARRAYS*/
  
*************** gfc_conv_ss_descriptor (stmtblock_t * bl
*** 3457,3463 ****
    se.descriptor_only = 1;
    gfc_conv_expr_lhs (&se, ss_info->expr);
    gfc_add_block_to_block (block, &se.pre);
!   info->descriptor = se.expr;
    ss_info->string_length = se.string_length;
    ss_info->class_container = se.class_container;
  
--- 3617,3623 ----
    se.descriptor_only = 1;
    gfc_conv_expr_lhs (&se, ss_info->expr);
    gfc_add_block_to_block (block, &se.pre);
!   set_factored_descriptor_value (&info->descriptor, se.expr, block);
    ss_info->string_length = se.string_length;
    ss_info->class_container = se.class_container;
  
diff -Nrcpad gcc-16-20250720/gcc/fortran/trans-decl.cc gcc-16-20250727/gcc/fortran/trans-decl.cc
*** gcc-16-20250720/gcc/fortran/trans-decl.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/fortran/trans-decl.cc	Sun Jul 27 22:32:08 2025
*************** gfc_trans_deferred_vars (gfc_symbol * pr
*** 4773,4786 ****
        /* Nullify explicit return class arrays on entry.  */
        tree type;
        tmp = get_proc_result (proc_sym);
! 	if (tmp && GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
! 	  {
! 	    gfc_start_block (&init);
! 	    tmp = gfc_class_data_get (tmp);
! 	    type = TREE_TYPE (gfc_conv_descriptor_data_get (tmp));
! 	    gfc_conv_descriptor_data_set (&init, tmp, build_int_cst (type, 0));
! 	    gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
! 	  }
      }
  
  
--- 4773,4786 ----
        /* Nullify explicit return class arrays on entry.  */
        tree type;
        tmp = get_proc_result (proc_sym);
!       if (tmp && GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
! 	{
! 	  gfc_start_block (&init);
! 	  tmp = gfc_class_data_get (tmp);
! 	  type = TREE_TYPE (gfc_conv_descriptor_data_get (tmp));
! 	  gfc_conv_descriptor_data_set (&init, tmp, build_int_cst (type, 0));
! 	  gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
! 	}
      }
  
  
diff -Nrcpad gcc-16-20250720/gcc/fortran/trans-expr.cc gcc-16-20250727/gcc/fortran/trans-expr.cc
*** gcc-16-20250720/gcc/fortran/trans-expr.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/fortran/trans-expr.cc	Sun Jul 27 22:32:08 2025
*************** gfc_get_class_from_expr (tree expr)
*** 714,719 ****
--- 714,721 ----
  {
    tree tmp;
    tree type;
+   bool array_descr_found = false;
+   bool comp_after_descr_found = false;
  
    for (tmp = expr; tmp; tmp = TREE_OPERAND (tmp, 0))
      {
*************** gfc_get_class_from_expr (tree expr)
*** 725,730 ****
--- 727,734 ----
  	{
  	  if (GFC_CLASS_TYPE_P (type))
  	    return tmp;
+ 	  if (GFC_DESCRIPTOR_TYPE_P (type))
+ 	    array_descr_found = true;
  	  if (type != TYPE_CANONICAL (type))
  	    type = TYPE_CANONICAL (type);
  	  else
*************** gfc_get_class_from_expr (tree expr)
*** 732,737 ****
--- 736,758 ----
  	}
        if (VAR_P (tmp) || TREE_CODE (tmp) == PARM_DECL)
  	break;
+ 
+       /* Avoid walking up the reference chain too far.  For class arrays, the
+ 	 array descriptor is a direct component (through a pointer) of the class
+ 	 container.  So there is exactly one COMPONENT_REF between a class
+ 	 container and its child array descriptor.  After seeing an array
+ 	 descriptor, we can give up on the second COMPONENT_REF we see, if no
+ 	 class container was found until that point.  */
+       if (array_descr_found)
+ 	{
+ 	  if (comp_after_descr_found)
+ 	    {
+ 	      if (TREE_CODE (tmp) == COMPONENT_REF)
+ 		return NULL_TREE;
+ 	    }
+ 	  else if (TREE_CODE (tmp) == COMPONENT_REF)
+ 	    comp_after_descr_found = true;
+ 	}
      }
  
    if (POINTER_TYPE_P (TREE_TYPE (tmp)))
*************** gfc_conv_procedure_call (gfc_se * se, gf
*** 7909,7929 ****
  	  se->ss->info->class_container = arg1_cntnr;
  	}
  
!       if (fsym && e)
  	{
! 	  /* Obtain the character length of an assumed character length
! 	     length procedure from the typespec.  */
! 	  if (fsym->ts.type == BT_CHARACTER
! 	      && parmse.string_length == NULL_TREE
! 	      && e->ts.type == BT_PROCEDURE
! 	      && e->symtree->n.sym->ts.type == BT_CHARACTER
! 	      && e->symtree->n.sym->ts.u.cl->length != NULL
! 	      && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
! 	    {
! 	      gfc_conv_const_charlen (e->symtree->n.sym->ts.u.cl);
! 	      parmse.string_length = e->symtree->n.sym->ts.u.cl->backend_decl;
! 	    }
  
  	  /* Obtain the character length for a NULL() actual with a character
  	     MOLD argument.  Otherwise substitute a suitable dummy length.
  	     Here we handle non-optional dummies of non-bind(c) procedures.  */
--- 7930,7950 ----
  	  se->ss->info->class_container = arg1_cntnr;
  	}
  
!       /* Obtain the character length of an assumed character length procedure
! 	 from the typespec of the actual argument.  */
!       if (e
! 	  && parmse.string_length == NULL_TREE
! 	  && e->ts.type == BT_PROCEDURE
! 	  && e->symtree->n.sym->ts.type == BT_CHARACTER
! 	  && e->symtree->n.sym->ts.u.cl->length != NULL
! 	  && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
  	{
! 	  gfc_conv_const_charlen (e->symtree->n.sym->ts.u.cl);
! 	  parmse.string_length = e->symtree->n.sym->ts.u.cl->backend_decl;
! 	}
  
+       if (fsym && e)
+ 	{
  	  /* Obtain the character length for a NULL() actual with a character
  	     MOLD argument.  Otherwise substitute a suitable dummy length.
  	     Here we handle non-optional dummies of non-bind(c) procedures.  */
*************** gfc_trans_assignment_1 (gfc_expr * expr1
*** 12871,12879 ****
    gfc_init_se (&lse, NULL);
    gfc_init_se (&rse, NULL);
  
    /* Walk the lhs.  */
    lss = gfc_walk_expr (expr1);
!   if (gfc_is_reallocatable_lhs (expr1))
      {
        lss->no_bounds_check = 1;
        lss->is_alloc_lhs = 1;
--- 12892,12907 ----
    gfc_init_se (&lse, NULL);
    gfc_init_se (&rse, NULL);
  
+   gfc_fix_class_refs (expr1);
+ 
+   realloc_flag = flag_realloc_lhs
+ 		 && gfc_is_reallocatable_lhs (expr1)
+ 		 && expr2->rank
+ 		 && !is_runtime_conformable (expr1, expr2);
+ 
    /* Walk the lhs.  */
    lss = gfc_walk_expr (expr1);
!   if (realloc_flag)
      {
        lss->no_bounds_check = 1;
        lss->is_alloc_lhs = 1;
*************** gfc_trans_assignment_1 (gfc_expr * expr1
*** 12924,12934 ****
  
    assoc_assign = is_assoc_assign (expr1, expr2);
  
-   realloc_flag = flag_realloc_lhs
- 		 && gfc_is_reallocatable_lhs (expr1)
- 		 && expr2->rank
- 		 && !is_runtime_conformable (expr1, expr2);
- 
    /* Only analyze the expressions for coarray properties, when in coarray-lib
       mode.  Avoid false-positive uninitialized diagnostics with initializing
       the codimension flag unconditionally.  */
--- 12952,12957 ----
diff -Nrcpad gcc-16-20250720/gcc/function.cc gcc-16-20250727/gcc/function.cc
*** gcc-16-20250720/gcc/function.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/function.cc	Sun Jul 27 22:32:08 2025
*************** match_asm_constraints_1 (rtx_insn *insn,
*** 7009,7014 ****
--- 7009,7123 ----
      df_insn_rescan (insn);
  }
  
+ /* It is expected and desired that optimizations coalesce multiple pseudos into
+    one whenever possible.  However, in case of hard register constraints we may
+    have to undo this and introduce copies since otherwise we could constraint a
+    single pseudo to different hard registers.  For example, during register
+    allocation the following insn would be unsatisfiable since pseudo 60 is
+    constrained to hard register r5 and r6 at the same time.
+ 
+    (insn 7 5 0 2 (asm_operands/v ("foo") ("") 0 [
+ 	       (reg:DI 60) repeated x2
+ 	   ]
+ 	    [
+ 	       (asm_input:DI ("{r5}") t.c:4)
+ 	       (asm_input:DI ("{r6}") t.c:4)
+ 	   ]
+ 	    [] t.c:4) "t.c":4:3 -1
+ 	(expr_list:REG_DEAD (reg:DI 60)
+ 	   (nil)))
+ 
+    Therefore, introduce a copy of pseudo 60 and transform it into
+ 
+    (insn 10 5 7 2 (set (reg:DI 62)
+ 	   (reg:DI 60)) "t.c":4:3 1503 {*movdi_64}
+ 	(nil))
+    (insn 7 10 11 2 (asm_operands/v ("foo") ("") 0 [
+ 	       (reg:DI 60)
+ 	       (reg:DI 62)
+ 	   ]
+ 	    [
+ 	       (asm_input:DI ("{r5}") t.c:4)
+ 	       (asm_input:DI ("{r6}") t.c:4)
+ 	   ]
+ 	    [] t.c:4) "t.c":4:3 -1
+ 	(expr_list:REG_DEAD (reg:DI 62)
+ 	   (expr_list:REG_DEAD (reg:DI 60)
+ 	       (nil))))
+ 
+    Now, LRA can assign pseudo 60 to r5, and pseudo 62 to r6.
+ 
+    TODO: The current implementation is conservative and we could do a bit
+    better in case of alternatives.  For example
+ 
+    (insn 7 5 0 2 (asm_operands/v ("foo") ("") 0 [
+ 	       (reg:DI 60) repeated x2
+ 	   ]
+ 	    [
+ 	       (asm_input:DI ("r,{r5}") t.c:4)
+ 	       (asm_input:DI ("{r6},r") t.c:4)
+ 	   ]
+ 	    [] t.c:4) "t.c":4:3 -1
+ 	(expr_list:REG_DEAD (reg:DI 60)
+ 	   (nil)))
+ 
+    For this insn we wouldn't need to come up with a copy of pseudo 60 since in
+    each alternative pseudo 60 is constrained exactly one time.  */
+ 
+ static void
+ match_asm_constraints_2 (rtx_insn *insn, rtx pat)
+ {
+   rtx op;
+   if (GET_CODE (pat) == SET && GET_CODE (SET_SRC (pat)) == ASM_OPERANDS)
+     op = SET_SRC (pat);
+   else if (GET_CODE (pat) == ASM_OPERANDS)
+     op = pat;
+   else
+     return;
+   int ninputs = ASM_OPERANDS_INPUT_LENGTH (op);
+   rtvec inputs = ASM_OPERANDS_INPUT_VEC (op);
+   bool changed = false;
+   auto_bitmap constrained_regs;
+ 
+   for (int i = 0; i < ninputs; ++i)
+     {
+       rtx input = RTVEC_ELT (inputs, i);
+       const char *constraint = ASM_OPERANDS_INPUT_CONSTRAINT (op, i);
+       if ((!REG_P (input) && !SUBREG_P (input))
+ 	  || (REG_P (input) && HARD_REGISTER_P (input))
+ 	  || strchr (constraint, '{') == nullptr)
+ 	continue;
+       int regno;
+       if (SUBREG_P (input))
+ 	{
+ 	  if (REG_P (SUBREG_REG (input)))
+ 	    regno = REGNO (SUBREG_REG (input));
+ 	  else
+ 	    continue;
+ 	}
+       else
+ 	regno = REGNO (input);
+       /* Keep the first usage of a constrained pseudo as is and only
+ 	 introduce copies for subsequent usages.  */
+       if (! bitmap_bit_p (constrained_regs, regno))
+ 	{
+ 	  bitmap_set_bit (constrained_regs, regno);
+ 	  continue;
+ 	}
+       rtx tmp = gen_reg_rtx (GET_MODE (input));
+       start_sequence ();
+       emit_move_insn (tmp, input);
+       rtx_insn *insns = get_insns ();
+       end_sequence ();
+       emit_insn_before (insns, insn);
+       RTVEC_ELT (inputs, i) = tmp;
+       changed = true;
+     }
+ 
+   if (changed)
+     df_insn_rescan (insn);
+ }
+ 
  /* Add the decl D to the local_decls list of FUN.  */
  
  void
*************** pass_match_asm_constraints::execute (fun
*** 7065,7070 ****
--- 7174,7186 ----
  	    continue;
  
  	  pat = PATTERN (insn);
+ 
+ 	  if (GET_CODE (pat) == PARALLEL)
+ 	    for (int i = XVECLEN (pat, 0) - 1; i >= 0; --i)
+ 	      match_asm_constraints_2 (insn, XVECEXP (pat, 0, i));
+ 	  else
+ 	    match_asm_constraints_2 (insn, pat);
+ 
  	  if (GET_CODE (pat) == PARALLEL)
  	    p_sets = &XVECEXP (pat, 0, 0), noutputs = XVECLEN (pat, 0);
  	  else if (GET_CODE (pat) == SET)
diff -Nrcpad gcc-16-20250720/gcc/gcc-diagnostic-spec.cc gcc-16-20250727/gcc/gcc-diagnostic-spec.cc
*** gcc-16-20250720/gcc/gcc-diagnostic-spec.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/gcc-diagnostic-spec.cc	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,230 ----
+ /* Functions to enable and disable individual warnings on an expression
+    and statement basis.
+    Copyright (C) 2021-2025 Free Software Foundation, Inc.
+    Contributed by Martin Sebor <msebor@redhat.com>
+ 
+    This file is part of GCC.
+ 
+    GCC is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License as published by the Free
+    Software Foundation; either version 3, or (at your option) any later
+    version.
+ 
+    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with GCC; see the file COPYING3.  If not see
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+ #include "bitmap.h"
+ #include "tree.h"
+ #include "cgraph.h"
+ #include "hash-map.h"
+ #include "gcc-diagnostic-spec.h"
+ #include "pretty-print.h"
+ #include "options.h"
+ 
+ /* Initialize *THIS from warning option OPT.  */
+ 
+ nowarn_spec_t::nowarn_spec_t (opt_code opt)
+ {
+   /* Create a very simple mapping based on testing and experience.
+      It should become more refined with time. */
+   switch (opt)
+     {
+     case no_warning:
+       m_bits = 0;
+       break;
+ 
+     case all_warnings:
+       m_bits = -1;
+       break;
+ 
+       /* Flow-sensitive warnings about pointer problems issued by both
+ 	 front ends and the middle end.  */
+     case OPT_Waddress:
+     case OPT_Wnonnull:
+       m_bits = NW_NONNULL;
+       break;
+ 
+       /* Flow-sensitive warnings about arithmetic overflow issued by both
+ 	 front ends and the middle end.  */
+     case OPT_Woverflow:
+     case OPT_Wshift_count_negative:
+     case OPT_Wshift_count_overflow:
+     case OPT_Wstrict_overflow:
+       m_bits = NW_VFLOW;
+       break;
+ 
+       /* Lexical warnings issued by front ends.  */
+     case OPT_Wabi:
+     case OPT_Wlogical_op:
+     case OPT_Wparentheses:
+     case OPT_Wreturn_type:
+     case OPT_Wsizeof_array_div:
+     case OPT_Wstrict_aliasing:
+     case OPT_Wunused:
+     case OPT_Wunused_function:
+     case OPT_Wunused_but_set_variable_:
+     case OPT_Wunused_variable:
+     case OPT_Wunused_but_set_parameter_:
+       m_bits = NW_LEXICAL;
+       break;
+ 
+       /* Access warning group.  */
+     case OPT_Warray_bounds_:
+     case OPT_Wformat_overflow_:
+     case OPT_Wformat_truncation_:
+     case OPT_Wrestrict:
+     case OPT_Wsizeof_pointer_memaccess:
+     case OPT_Wstrict_aliasing_:
+     case OPT_Wstringop_overflow_:
+     case OPT_Wstringop_overread:
+     case OPT_Wstringop_truncation:
+       m_bits = NW_ACCESS;
+       break;
+ 
+       /* Initialization warning group.  */
+     case OPT_Winit_self:
+     case OPT_Wuninitialized:
+     case OPT_Wmaybe_uninitialized:
+       m_bits = NW_UNINIT;
+       break;
+ 
+     case OPT_Wdangling_pointer_:
+     case OPT_Wreturn_local_addr:
+     case OPT_Wuse_after_free_:
+       m_bits = NW_DANGLING;
+       break;
+ 
+     case OPT_Wpessimizing_move:
+     case OPT_Wredundant_move:
+       m_bits = NW_REDUNDANT;
+       break;
+ 
+     default:
+       /* A catchall group for everything else.  */
+       m_bits = NW_OTHER;
+     }
+ }
+ 
+ /* A mapping from a 'location_t' to the warning spec set for it.  */
+ 
+ GTY(()) nowarn_map_t *nowarn_map;
+ 
+ /* Return the no-warning disposition for location LOC and option OPT
+    or for all/any otions by default.  */
+ 
+ bool
+ warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
+ {
+   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+ 
+   if (!nowarn_map)
+     return false;
+ 
+   if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
+     {
+       const nowarn_spec_t optspec (opt);
+       return *pspec & optspec;
+     }
+ 
+   return false;
+ }
+ 
+  /* Change the supression of warnings for location LOC.
+     OPT controls which warnings are affected.
+     The wildcard OPT of -1 controls all warnings.
+     If SUPP is true (the default), enable the suppression of the warnings.
+     If SUPP is false, disable the suppression of the warnings.  */
+ 
+ bool
+ suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
+ 		     bool supp /* = true */)
+ {
+   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+ 
+   const nowarn_spec_t optspec (supp ? opt : opt_code ());
+ 
+   if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : nullptr)
+     {
+       if (supp)
+ 	{
+ 	  *pspec |= optspec;
+ 	  return true;
+ 	}
+ 
+       *pspec &= optspec;
+       if (*pspec)
+ 	return true;
+ 
+       nowarn_map->remove (loc);
+       return false;
+     }
+ 
+   if (!supp || opt == no_warning)
+     return false;
+ 
+   if (!nowarn_map)
+     nowarn_map = nowarn_map_t::create_ggc (32);
+ 
+   nowarn_map->put (loc, optspec);
+   return true;
+ }
+ 
+ /* Change the warning disposition for LOC to match OPTSPEC.  */
+ 
+ void
+ put_warning_spec_at (location_t loc, unsigned bits)
+ {
+   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+ 
+   nowarn_spec_t optspec = nowarn_spec_t::from_bits (bits);
+   if (!optspec)
+     {
+       if (nowarn_map)
+ 	nowarn_map->remove (loc);
+     }
+   else
+     {
+       if (!nowarn_map)
+ 	nowarn_map = nowarn_map_t::create_ggc (32);
+       nowarn_map->put (loc, optspec);
+     }
+ }
+ 
+ /* Copy the no-warning disposition from one location to another.  */
+ 
+ void
+ copy_warning (location_t to, location_t from)
+ {
+   if (!nowarn_map)
+     return;
+ 
+   nowarn_spec_t *from_spec;
+   if (RESERVED_LOCATION_P (from))
+     from_spec = nullptr;
+   else
+     from_spec = nowarn_map->get (from);
+   if (RESERVED_LOCATION_P (to))
+     /* We cannot set no-warning dispositions for 'to', so we have no chance but
+        lose those potentially set for 'from'.  */
+     ;
+   else
+     {
+       if (from_spec)
+ 	{
+ 	  nowarn_spec_t tem = *from_spec;
+ 	  nowarn_map->put (to, tem);
+ 	}
+       else
+ 	nowarn_map->remove (to);
+     }
+ }
diff -Nrcpad gcc-16-20250720/gcc/gcc-diagnostic-spec.h gcc-16-20250727/gcc/gcc-diagnostic-spec.h
*** gcc-16-20250720/gcc/gcc-diagnostic-spec.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/gcc-diagnostic-spec.h	Sun Jul 27 22:32:08 2025
***************
*** 0 ****
--- 1,149 ----
+ /* Language-independent APIs to enable/disable per-location warnings.
+ 
+    Copyright (C) 2021-2025 Free Software Foundation, Inc.
+    Contributed by Martin Sebor <msebor@redhat.com>
+ 
+    This file is part of GCC.
+ 
+    GCC is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License as published by the Free
+    Software Foundation; either version 3, or (at your option) any later
+    version.
+ 
+    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with GCC; see the file COPYING3.  If not see
+    <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_DIAGNOSTIC_SPEC_H_INCLUDED
+ #define GCC_DIAGNOSTIC_SPEC_H_INCLUDED
+ 
+ #include "hash-map.h"
+ 
+ /* A "bitset" of warning groups.  */
+ 
+ class nowarn_spec_t
+ {
+ public:
+   enum
+     {
+      /* Middle end warnings about invalid accesses.  */
+      NW_ACCESS = 1 << 0,
+      /* Front end/lexical warnings.  */
+      NW_LEXICAL = 1 << 1,
+      /* Warnings about null pointers.  */
+      NW_NONNULL = 1 << 2,
+      /* Warnings about uninitialized reads.  */
+      NW_UNINIT = 1 << 3,
+      /* Warnings about arithmetic overflow.  */
+      NW_VFLOW = 1 << 4,
+      /* Warnings about dangling pointers.  */
+      NW_DANGLING = 1 << 5,
+      /* All other unclassified warnings.  */
+      NW_OTHER = 1 << 6,
+      /* Warnings about redundant calls.  */
+      NW_REDUNDANT = 1 << 7,
+      /* All groups of warnings.  */
+      NW_ALL = (NW_ACCESS | NW_LEXICAL | NW_NONNULL
+ 	       | NW_UNINIT | NW_VFLOW | NW_DANGLING | NW_REDUNDANT | NW_OTHER)
+    };
+ 
+   nowarn_spec_t (): m_bits () { }
+ 
+   nowarn_spec_t (opt_code);
+ 
+   static nowarn_spec_t from_bits (unsigned bits)
+   {
+     nowarn_spec_t spec;
+     spec.m_bits = bits;
+     return spec;
+   }
+ 
+   /* Return the raw bitset.  */
+   operator unsigned() const
+   {
+     return m_bits;
+   }
+ 
+   /* Return true if the bitset is clear.  */
+   bool operator!() const
+   {
+     return !m_bits;
+   }
+ 
+   /* Return the inverse of the bitset.  */
+   nowarn_spec_t operator~() const
+   {
+     nowarn_spec_t res (*this);
+     res.m_bits &= ~NW_ALL;
+     return res;
+   }
+ 
+   /* Set *THIS to the bitwise OR of *THIS and RHS.  */
+   nowarn_spec_t& operator|= (const nowarn_spec_t &rhs)
+   {
+     m_bits |= rhs.m_bits;
+     return *this;
+   }
+ 
+   /* Set *THIS to the bitwise AND of *THIS and RHS.  */
+   nowarn_spec_t& operator&= (const nowarn_spec_t &rhs)
+   {
+     m_bits &= rhs.m_bits;
+     return *this;
+   }
+ 
+   /* Set *THIS to the bitwise exclusive OR of *THIS and RHS.  */
+   nowarn_spec_t& operator^= (const nowarn_spec_t &rhs)
+   {
+     m_bits ^= rhs.m_bits;
+     return *this;
+   }
+ 
+ private:
+   /* Bitset of warning groups.  */
+   unsigned m_bits;
+ };
+ 
+ /* Return the bitwise OR of LHS and RHS.  */
+ 
+ inline nowarn_spec_t
+ operator| (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+ {
+   return nowarn_spec_t (lhs) |= rhs;
+ }
+ 
+ /* Return the bitwise AND of LHS and RHS.  */
+ 
+ inline nowarn_spec_t
+ operator& (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+ {
+   return nowarn_spec_t (lhs) &= rhs;
+ }
+ 
+ /* Return true if LHS is equal RHS.  */
+ 
+ inline bool
+ operator== (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+ {
+   return static_cast<unsigned>(lhs) == static_cast<unsigned>(rhs);
+ }
+ 
+ /* Return true if LHS is not equal RHS.  */
+ 
+ inline bool
+ operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+ {
+   return !(lhs == rhs);
+ }
+ 
+ typedef hash_map<location_hash, nowarn_spec_t> nowarn_map_t;
+ 
+ /* A mapping from a 'location_t' to the warning spec set for it.  */
+ extern GTY(()) nowarn_map_t *nowarn_map;
+ 
+ #endif // GCC_DIAGNOSTIC_SPEC_H_INCLUDED
diff -Nrcpad gcc-16-20250720/gcc/gcc-rich-location.cc gcc-16-20250727/gcc/gcc-rich-location.cc
*** gcc-16-20250720/gcc/gcc-rich-location.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/gcc-rich-location.cc	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 37,42 ****
--- 37,43 ----
  #include "intl.h"
  #include "cpplib.h"
  #include "diagnostic.h"
+ #include "diagnostics/file-cache.h"
  
  /* Add a range to the rich_location, covering expression EXPR,
     using LABEL if non-NULL. */
*************** gcc_rich_location::add_fixit_misspelled_
*** 79,89 ****
  /* Return true if there is nothing on LOC's line before LOC.  */
  
  static bool
! blank_line_before_p (file_cache &fc,
  		     location_t loc)
  {
    expanded_location exploc = expand_location (loc);
!   char_span line = fc.get_source_line (exploc.file, exploc.line);
    if (!line)
      return false;
    if (line.length () < (size_t)exploc.column)
--- 80,90 ----
  /* Return true if there is nothing on LOC's line before LOC.  */
  
  static bool
! blank_line_before_p (diagnostics::file_cache &fc,
  		     location_t loc)
  {
    expanded_location exploc = expand_location (loc);
!   diagnostics::char_span line = fc.get_source_line (exploc.file, exploc.line);
    if (!line)
      return false;
    if (line.length () < (size_t)exploc.column)
*************** blank_line_before_p (file_cache &fc,
*** 101,107 ****
     If true is returned then *OUT_START_OF_LINE is written to.  */
  
  static bool
! use_new_line (file_cache &fc,
  	      location_t insertion_point, location_t indent,
  	      location_t *out_start_of_line)
  {
--- 102,108 ----
     If true is returned then *OUT_START_OF_LINE is written to.  */
  
  static bool
! use_new_line (diagnostics::file_cache &fc,
  	      location_t insertion_point, location_t indent,
  	      location_t *out_start_of_line)
  {
diff -Nrcpad gcc-16-20250720/gcc/gcc-rich-location.h gcc-16-20250727/gcc/gcc-rich-location.h
*** gcc-16-20250720/gcc/gcc-rich-location.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/gcc-rich-location.h	Sun Jul 27 22:32:08 2025
*************** along with GCC; see the file COPYING3.
*** 22,28 ****
  
  #include "rich-location.h"
  
! class diagnostic_source_print_policy;
  
  /* A gcc_rich_location is libcpp's rich_location with additional
     helper methods for working with gcc's types.  The class is not
--- 22,28 ----
  
  #include "rich-location.h"
  
! namespace diagnostics { class source_print_policy; }
  
  /* A gcc_rich_location is libcpp's rich_location with additional
     helper methods for working with gcc's types.  The class is not
*************** class gcc_rich_location : public rich_lo
*** 79,92 ****
  	if (!added secondary)
  	  inform (secondary_loc, "message for secondary");
  
!      Implemented in diagnostic-show-locus.cc.  */
  
!   bool add_location_if_nearby (const diagnostic_source_print_policy &policy,
  			       location_t loc,
  			       bool restrict_to_current_line_spans = true,
  			       const range_label *label = NULL);
  
!   bool add_location_if_nearby (const diagnostic_context &dc,
  			       location_t loc,
  			       bool restrict_to_current_line_spans = true,
  			       const range_label *label = NULL);
--- 79,92 ----
  	if (!added secondary)
  	  inform (secondary_loc, "message for secondary");
  
!      Implemented in diagnostics/source-printing.cc.  */
  
!   bool add_location_if_nearby (const diagnostics::source_print_policy &policy,
  			       location_t loc,
  			       bool restrict_to_current_line_spans = true,
  			       const range_label *label = NULL);
  
!   bool add_location_if_nearby (const diagnostics::context &dc,
  			       location_t loc,
  			       bool restrict_to_current_line_spans = true,
  			       const range_label *label = NULL);
diff -Nrcpad gcc-16-20250720/gcc/gcc.cc gcc-16-20250727/gcc/gcc.cc
*** gcc-16-20250720/gcc/gcc.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/gcc.cc	Sun Jul 27 22:32:08 2025
*************** compilation is specified by a string cal
*** 43,49 ****
  #include "opt-suggestions.h"
  #include "gcc.h"
  #include "diagnostic.h"
! #include "diagnostic-format.h"
  #include "pretty-print-urlifier.h"
  #include "flags.h"
  #include "opts.h"
--- 43,49 ----
  #include "opt-suggestions.h"
  #include "gcc.h"
  #include "diagnostic.h"
! #include "diagnostics/sink.h"
  #include "pretty-print-urlifier.h"
  #include "flags.h"
  #include "opts.h"
*************** driver_handle_option (struct gcc_options
*** 4195,4201 ****
  		      unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
  		      location_t loc,
  		      const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
! 		      diagnostic_context *dc,
  		      void (*) (void))
  {
    size_t opt_index = decoded->opt_index;
--- 4195,4201 ----
  		      unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
  		      location_t loc,
  		      const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
! 		      diagnostics::context *dc,
  		      void (*) (void))
  {
    size_t opt_index = decoded->opt_index;
*************** driver_handle_option (struct gcc_options
*** 4207,4213 ****
  
    gcc_assert (opts == &global_options);
    gcc_assert (opts_set == &global_options_set);
!   gcc_assert (kind == DK_UNSPECIFIED);
    gcc_assert (loc == UNKNOWN_LOCATION);
    gcc_assert (dc == global_dc);
  
--- 4207,4214 ----
  
    gcc_assert (opts == &global_options);
    gcc_assert (opts_set == &global_options_set);
!   gcc_assert (static_cast<diagnostics::kind> (kind)
! 	      == diagnostics::kind::unspecified);
    gcc_assert (loc == UNKNOWN_LOCATION);
    gcc_assert (dc == global_dc);
  
*************** driver_handle_option (struct gcc_options
*** 4367,4376 ****
  	  const char *basename = (opts->x_dump_base_name ? opts->x_dump_base_name
  				  : opts->x_main_input_basename);
  	  gcc_assert (dc);
! 	  diagnostic_output_format_init (*dc,
! 					 opts->x_main_input_filename, basename,
! 					 (enum diagnostics_output_format)value,
! 					 opts->x_flag_diagnostics_json_formatting);
  	  break;
  	}
  
--- 4368,4377 ----
  	  const char *basename = (opts->x_dump_base_name ? opts->x_dump_base_name
  				  : opts->x_main_input_basename);
  	  gcc_assert (dc);
! 	  diagnostics::output_format_init (*dc,
! 					   opts->x_main_input_filename, basename,
! 					   (enum diagnostics_output_format)value,
! 					   opts->x_flag_diagnostics_json_formatting);
  	  break;
  	}
  
diff -Nrcpad gcc-16-20250720/gcc/gdbinit.in gcc-16-20250727/gcc/gdbinit.in
*** gcc-16-20250720/gcc/gdbinit.in	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/gdbinit.in	Sun Jul 27 22:32:08 2025
*************** See also 'help-gcc-hooks'.
*** 293,304 ****
  end
  
  define break-on-diagnostic
! break diagnostic_context::maybe_show_locus
  end
  
  document break-on-diagnostic
! Put a breakpoint on diagnostic_show_locus, called whenever a diagnostic
! is emitted (as opposed to those warnings that are suppressed by
  command-line options).
  end
  
--- 293,304 ----
  end
  
  define break-on-diagnostic
! break diagnostics::context::maybe_show_locus
  end
  
  document break-on-diagnostic
! Put a breakpoint on diagnostics::context::show_locus, called whenever
! a diagnostic is emitted (as opposed to those warnings that are suppressed by
  command-line options).
  end
  
diff -Nrcpad gcc-16-20250720/gcc/gengtype.cc gcc-16-20250727/gcc/gengtype.cc
*** gcc-16-20250720/gcc/gengtype.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/gengtype.cc	Sun Jul 27 22:32:08 2025
*************** open_base_files (void)
*** 1722,1728 ****
        "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
        "sreal.h", "ipa-cp.h", "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h",
        "omp-general.h", "omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h",
!       "symtab-thunks.h", "symtab-clones.h", "diagnostic-spec.h", "ctfc.h",
        NULL
      };
      const char *const *ifp;
--- 1722,1728 ----
        "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
        "sreal.h", "ipa-cp.h", "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h",
        "omp-general.h", "omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h",
!       "symtab-thunks.h", "symtab-clones.h", "gcc-diagnostic-spec.h", "ctfc.h",
        NULL
      };
      const char *const *ifp;
diff -Nrcpad gcc-16-20250720/gcc/genoutput.cc gcc-16-20250727/gcc/genoutput.cc
*** gcc-16-20250720/gcc/genoutput.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/genoutput.cc	Sun Jul 27 22:32:08 2025
*************** static const char indep_constraints[] =
*** 200,205 ****
--- 200,207 ----
  static class constraint_data *
  constraints_by_letter_table[1 << CHAR_BIT];
  
+ static hash_set<free_string_hash> used_reg_names;
+ 
  static int mdep_constraint_len (const char *, file_location, int);
  static void note_constraint (md_rtx_info *);
  
*************** main (int argc, const char **argv)
*** 1156,1161 ****
--- 1158,1202 ----
    output_insn_data ();
    output_get_insn_name ();
  
+   /* Since genoutput has no information about hard register names we cannot
+      statically verify hard register names in constraints of the machine
+      description.  Therefore, we have to do it at runtime.  Although
+      verification shouldn't be too expensive, restrict it to checking builds.
+    */
+   printf ("\n\n#if CHECKING_P\n");
+   if (used_reg_names.is_empty ())
+     printf ("void verify_reg_names_in_constraints () { }\n");
+   else
+     {
+       size_t max_len = 0;
+       for (auto it = used_reg_names.begin (); it != used_reg_names.end (); ++it)
+ 	{
+ 	  size_t len = strlen (*it);
+ 	  if (len > max_len)
+ 	    max_len = len;
+ 	}
+       printf ("void\nverify_reg_names_in_constraints ()\n{\n");
+       printf ("  static const char hregnames[%zu][%zu] = {\n",
+ 	      used_reg_names.elements (), max_len + 1);
+       auto it = used_reg_names.begin ();
+       while (it != used_reg_names.end ())
+ 	{
+ 	  printf ("    \"%s\"", *it);
+ 	  ++it;
+ 	  if (it != used_reg_names.end ())
+ 	    printf (",");
+ 	  printf ("\n");
+ 	}
+       printf ("  };\n");
+       printf ("  for (size_t i = 0; i < %zu; ++i)\n",
+ 	      used_reg_names.elements ());
+       printf ("    if (decode_reg_name (hregnames[i]) < 0)\n");
+       printf ("      internal_error (\"invalid register %%qs used in "
+ 	      "constraint of machine description\", hregnames[i]);\n");
+       printf ("}\n");
+     }
+   printf ("#endif\n");
+ 
    fflush (stdout);
    return (ferror (stdout) != 0 || have_error
  	? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
*************** mdep_constraint_len (const char *s, file
*** 1284,1289 ****
--- 1325,1349 ----
        if (!strncmp (s, p->name, p->namelen))
  	return p->namelen;
  
+   if (*s == '{')
+     {
+       const char *end = s + 1;
+       while (*end != '}' && *end != '"' && *end != '\0')
+ 	++end;
+       /* Similarly as in decode_hreg_constraint(), consider any hard register
+ 	 name longer than a few characters as an error.  */
+       ptrdiff_t len = end - s;
+       if (*end == '}' && len > 1 && len < 31)
+ 	{
+ 	  char *regname = new char[len];
+ 	  memcpy (regname, s + 1, len - 1);
+ 	  regname[len - 1] = '\0';
+ 	  if (used_reg_names.add (regname))
+ 	    delete[] regname;
+ 	  return len + 1;
+ 	}
+     }
+ 
    error_at (loc, "error: undefined machine-specific constraint "
  	    "at this point: \"%s\"", s);
    message_at (loc, "note:  in operand %d", opno);
diff -Nrcpad gcc-16-20250720/gcc/genpreds.cc gcc-16-20250727/gcc/genpreds.cc
*** gcc-16-20250720/gcc/genpreds.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/genpreds.cc	Sun Jul 27 22:32:08 2025
*************** static const char const_dbl_constraints[
*** 719,725 ****
  
  /* Summary data used to decide whether to output various functions and
     macro definitions.  */
- static unsigned int constraint_max_namelen;
  static bool have_register_constraints;
  static bool have_memory_constraints;
  static bool have_special_memory_constraints;
--- 719,724 ----
*************** add_constraint (const char *name, const
*** 942,948 ****
    *last_constraint_ptr = c;
    last_constraint_ptr = &c->next_textual;
  
-   constraint_max_namelen = MAX (constraint_max_namelen, strlen (name));
    have_register_constraints |= c->is_register;
    have_const_int_constraints |= c->is_const_int;
    have_extra_constraints |= c->is_extra;
--- 941,946 ----
*************** write_insn_constraint_len (void)
*** 1150,1156 ****
    unsigned int i;
  
    puts ("static inline size_t\n"
! 	"insn_constraint_len (char fc, const char *str ATTRIBUTE_UNUSED)\n"
  	"{\n"
  	"  switch (fc)\n"
  	"    {");
--- 1148,1154 ----
    unsigned int i;
  
    puts ("static inline size_t\n"
! 	"insn_constraint_len (char fc, const char *str)\n"
  	"{\n"
  	"  switch (fc)\n"
  	"    {");
*************** write_insn_constraint_len (void)
*** 1183,1188 ****
--- 1181,1193 ----
  
    puts ("    default: break;\n"
  	"    }\n"
+ 	"  if (str[0] == '{')\n"
+ 	"    {\n"
+ 	"      size_t len = 1;\n"
+ 	"      while (str[len] != '}' && str[len] != '\\0')\n"
+ 	"        ++len;\n"
+ 	"      return len + 1;\n"
+ 	"    }\n"
  	"  return 1;\n"
  	"}\n");
  }
*************** write_tm_preds_h (void)
*** 1556,1688 ****
  	  "#endif\n"
  	  "\n");
  
!   if (constraint_max_namelen > 0)
!     {
!       write_enum_constraint_num ();
!       puts ("extern enum constraint_num lookup_constraint_1 (const char *);\n"
! 	    "extern const unsigned char lookup_constraint_array[];\n"
  	    "\n"
! 	    "/* Return the constraint at the beginning of P, or"
! 	    " CONSTRAINT__UNKNOWN if it\n"
! 	    "   isn't recognized.  */\n"
  	    "\n"
! 	    "static inline enum constraint_num\n"
! 	    "lookup_constraint (const char *p)\n"
  	    "{\n"
! 	    "  unsigned int index = lookup_constraint_array"
! 	    "[(unsigned char) *p];\n"
! 	    "  return (index == UCHAR_MAX\n"
! 	    "          ? lookup_constraint_1 (p)\n"
! 	    "          : (enum constraint_num) index);\n"
! 	    "}\n");
!       if (satisfied_start == num_constraints)
! 	puts ("/* Return true if X satisfies constraint C.  */\n"
! 	      "\n"
! 	      "static inline bool\n"
! 	      "constraint_satisfied_p (rtx, enum constraint_num)\n"
! 	      "{\n"
! 	      "  return false;\n"
! 	      "}\n");
!       else
! 	printf ("extern bool (*constraint_satisfied_p_array[]) (rtx);\n"
! 		"\n"
! 		"/* Return true if X satisfies constraint C.  */\n"
! 		"\n"
! 		"static inline bool\n"
! 		"constraint_satisfied_p (rtx x, enum constraint_num c)\n"
! 		"{\n"
! 		"  int i = (int) c - (int) CONSTRAINT_%s;\n"
! 		"  return i >= 0 && constraint_satisfied_p_array[i] (x);\n"
! 		"}\n"
! 		"\n",
! 		enum_order[satisfied_start]->name);
  
!       write_range_function ("insn_extra_register_constraint",
! 			    register_start, register_end);
!       write_range_function ("insn_extra_memory_constraint",
! 			    memory_start, memory_end);
!       write_range_function ("insn_extra_special_memory_constraint",
! 			    special_memory_start, special_memory_end);
!       write_range_function ("insn_extra_relaxed_memory_constraint",
! 			    relaxed_memory_start, relaxed_memory_end);
!       write_range_function ("insn_extra_address_constraint",
! 			    address_start, address_end);
!       write_allows_reg_mem_function ();
  
!       if (constraint_max_namelen > 1)
!         {
! 	  write_insn_constraint_len ();
! 	  puts ("#define CONSTRAINT_LEN(c_,s_) "
! 		"insn_constraint_len (c_,s_)\n");
! 	}
!       else
! 	puts ("#define CONSTRAINT_LEN(c_,s_) 1\n");
!       if (have_register_constraints)
! 	puts ("extern enum reg_class reg_class_for_constraint_1 "
! 	      "(enum constraint_num);\n"
! 	      "\n"
! 	      "static inline enum reg_class\n"
! 	      "reg_class_for_constraint (enum constraint_num c)\n"
! 	      "{\n"
! 	      "  if (insn_extra_register_constraint (c))\n"
! 	      "    return reg_class_for_constraint_1 (c);\n"
! 	      "  return NO_REGS;\n"
! 	      "}\n");
!       else
! 	puts ("static inline enum reg_class\n"
! 	      "reg_class_for_constraint (enum constraint_num)\n"
! 	      "{\n"
! 	      "  return NO_REGS;\n"
! 	      "}\n");
!       if (have_const_int_constraints)
! 	puts ("extern bool insn_const_int_ok_for_constraint "
! 	      "(HOST_WIDE_INT, enum constraint_num);\n"
! 	      "#define CONST_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n"
! 	      "    insn_const_int_ok_for_constraint (v_, "
! 	      "lookup_constraint (s_))\n");
!       else
! 	puts ("static inline bool\n"
! 	      "insn_const_int_ok_for_constraint (HOST_WIDE_INT,"
! 	      " enum constraint_num)\n"
! 	      "{\n"
! 	      "  return false;\n"
! 	      "}\n");
  
!       puts ("enum constraint_type\n"
! 	    "{\n"
! 	    "  CT_REGISTER,\n"
! 	    "  CT_CONST_INT,\n"
! 	    "  CT_MEMORY,\n"
! 	    "  CT_SPECIAL_MEMORY,\n"
! 	    "  CT_RELAXED_MEMORY,\n"
! 	    "  CT_ADDRESS,\n"
! 	    "  CT_FIXED_FORM\n"
! 	    "};\n"
! 	    "\n"
! 	    "static inline enum constraint_type\n"
! 	    "get_constraint_type (enum constraint_num c)\n"
! 	    "{");
!       auto_vec <std::pair <unsigned int, const char *>, 4> values;
!       if (const_int_start != const_int_end)
! 	values.safe_push (std::make_pair (const_int_start, "CT_CONST_INT"));
!       if (memory_start != memory_end)
! 	values.safe_push (std::make_pair (memory_start, "CT_MEMORY"));
!       if (special_memory_start != special_memory_end)
! 	values.safe_push (std::make_pair (special_memory_start,
! 					  "CT_SPECIAL_MEMORY"));
!       if (relaxed_memory_start != relaxed_memory_end)
! 	values.safe_push (std::make_pair (relaxed_memory_start,
! 					  "CT_RELAXED_MEMORY"));
!       if (address_start != address_end)
! 	values.safe_push (std::make_pair (address_start, "CT_ADDRESS"));
!       if (address_end != num_constraints)
! 	values.safe_push (std::make_pair (address_end, "CT_FIXED_FORM"));
!       print_type_tree (values, 0, values.length (), "CT_REGISTER", 2);
!       puts ("}");
  
!       write_get_register_filter ();
!       write_get_register_filter_id ();
!     }
  
    puts ("#endif /* tm-preds.h */");
  }
--- 1561,1684 ----
  	  "#endif\n"
  	  "\n");
  
!   write_enum_constraint_num ();
!   puts ("extern enum constraint_num lookup_constraint_1 (const char *);\n"
! 	"extern const unsigned char lookup_constraint_array[];\n"
! 	"\n"
! 	"/* Return the constraint at the beginning of P, or"
! 	" CONSTRAINT__UNKNOWN if it\n"
! 	"   isn't recognized.  */\n"
! 	"\n"
! 	"static inline enum constraint_num\n"
! 	"lookup_constraint (const char *p)\n"
! 	"{\n"
! 	"  unsigned int index = lookup_constraint_array"
! 	"[(unsigned char) *p];\n"
! 	"  return (index == UCHAR_MAX\n"
! 	"          ? lookup_constraint_1 (p)\n"
! 	"          : (enum constraint_num) index);\n"
! 	"}\n");
!   if (satisfied_start == num_constraints)
!     puts ("/* Return true if X satisfies constraint C.  */\n"
! 	  "\n"
! 	  "static inline bool\n"
! 	  "constraint_satisfied_p (rtx, enum constraint_num)\n"
! 	  "{\n"
! 	  "  return false;\n"
! 	  "}\n");
!   else
!     printf ("extern bool (*constraint_satisfied_p_array[]) (rtx);\n"
  	    "\n"
! 	    "/* Return true if X satisfies constraint C.  */\n"
  	    "\n"
! 	    "static inline bool\n"
! 	    "constraint_satisfied_p (rtx x, enum constraint_num c)\n"
  	    "{\n"
! 	    "  int i = (int) c - (int) CONSTRAINT_%s;\n"
! 	    "  return i >= 0 && constraint_satisfied_p_array[i] (x);\n"
! 	    "}\n"
! 	    "\n",
! 	    enum_order[satisfied_start]->name);
  
!   write_range_function ("insn_extra_register_constraint",
! 			register_start, register_end);
!   write_range_function ("insn_extra_memory_constraint",
! 			memory_start, memory_end);
!   write_range_function ("insn_extra_special_memory_constraint",
! 			special_memory_start, special_memory_end);
!   write_range_function ("insn_extra_relaxed_memory_constraint",
! 			relaxed_memory_start, relaxed_memory_end);
!   write_range_function ("insn_extra_address_constraint",
! 			address_start, address_end);
!   write_allows_reg_mem_function ();
  
!   write_insn_constraint_len ();
!   puts ("#define CONSTRAINT_LEN(c_,s_) insn_constraint_len (c_,s_)\n");
!   if (have_register_constraints)
!     puts ("extern enum reg_class reg_class_for_constraint_1 "
! 	  "(enum constraint_num);\n"
! 	  "\n"
! 	  "static inline enum reg_class\n"
! 	  "reg_class_for_constraint (enum constraint_num c)\n"
! 	  "{\n"
! 	  "  if (insn_extra_register_constraint (c))\n"
! 	  "    return reg_class_for_constraint_1 (c);\n"
! 	  "  return NO_REGS;\n"
! 	  "}\n");
!   else
!     puts ("static inline enum reg_class\n"
! 	  "reg_class_for_constraint (enum constraint_num)\n"
! 	  "{\n"
! 	  "  return NO_REGS;\n"
! 	  "}\n");
!   if (have_const_int_constraints)
!     puts ("extern bool insn_const_int_ok_for_constraint "
! 	  "(HOST_WIDE_INT, enum constraint_num);\n"
! 	  "#define CONST_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n"
! 	  "    insn_const_int_ok_for_constraint (v_, "
! 	  "lookup_constraint (s_))\n");
!   else
!     puts ("static inline bool\n"
! 	  "insn_const_int_ok_for_constraint (HOST_WIDE_INT,"
! 	  " enum constraint_num)\n"
! 	  "{\n"
! 	  "  return false;\n"
! 	  "}\n");
  
!   puts ("enum constraint_type\n"
! 	"{\n"
! 	"  CT_REGISTER,\n"
! 	"  CT_CONST_INT,\n"
! 	"  CT_MEMORY,\n"
! 	"  CT_SPECIAL_MEMORY,\n"
! 	"  CT_RELAXED_MEMORY,\n"
! 	"  CT_ADDRESS,\n"
! 	"  CT_FIXED_FORM\n"
! 	"};\n"
! 	"\n"
! 	"static inline enum constraint_type\n"
! 	"get_constraint_type (enum constraint_num c)\n"
! 	"{");
!   auto_vec <std::pair <unsigned int, const char *>, 4> values;
!   if (const_int_start != const_int_end)
!     values.safe_push (std::make_pair (const_int_start, "CT_CONST_INT"));
!   if (memory_start != memory_end)
!     values.safe_push (std::make_pair (memory_start, "CT_MEMORY"));
!   if (special_memory_start != special_memory_end)
!     values.safe_push (std::make_pair (special_memory_start,
! 				      "CT_SPECIAL_MEMORY"));
!   if (relaxed_memory_start != relaxed_memory_end)
!     values.safe_push (std::make_pair (relaxed_memory_start,
! 				      "CT_RELAXED_MEMORY"));
!   if (address_start != address_end)
!     values.safe_push (std::make_pair (address_start, "CT_ADDRESS"));
!   if (address_end != num_constraints)
!     values.safe_push (std::make_pair (address_end, "CT_FIXED_FORM"));
!   print_type_tree (values, 0, values.length (), "CT_REGISTER", 2);
!   puts ("}");
  
!   write_get_register_filter ();
!   write_get_register_filter_id ();
  
    puts ("#endif /* tm-preds.h */");
  }
*************** write_insn_preds_c (void)
*** 1743,1759 ****
    FOR_ALL_PREDICATES (p)
      write_one_predicate_function (p);
  
!   if (constraint_max_namelen > 0)
!     {
!       write_lookup_constraint_1 ();
!       write_lookup_constraint_array ();
!       if (have_register_constraints)
! 	write_reg_class_for_constraint_1 ();
!       write_constraint_satisfied_p_array ();
  
!       if (have_const_int_constraints)
! 	write_insn_const_int_ok_for_constraint ();
!     }
  
    write_init_reg_class_start_regs ();
  }
--- 1739,1752 ----
    FOR_ALL_PREDICATES (p)
      write_one_predicate_function (p);
  
!   write_lookup_constraint_1 ();
!   write_lookup_constraint_array ();
!   if (have_register_constraints)
!     write_reg_class_for_constraint_1 ();
!   write_constraint_satisfied_p_array ();
  
!   if (have_const_int_constraints)
!     write_insn_const_int_ok_for_constraint ();
  
    write_init_reg_class_start_regs ();
  }
diff -Nrcpad gcc-16-20250720/gcc/gimple-walk.cc gcc-16-20250727/gcc/gimple-walk.cc
*** gcc-16-20250720/gcc/gimple-walk.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/gimple-walk.cc	Sun Jul 27 22:32:09 2025
*************** walk_gimple_asm (gasm *stmt, walk_tree_f
*** 118,124 ****
        if (wi)
  	{
  	  if (parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 				       &allows_reg, &is_inout))
  	    wi->val_only = (allows_reg || !allows_mem);
  	}
        if (wi)
--- 118,124 ----
        if (wi)
  	{
  	  if (parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 				       &allows_reg, &is_inout, nullptr))
  	    wi->val_only = (allows_reg || !allows_mem);
  	}
        if (wi)
*************** walk_gimple_asm (gasm *stmt, walk_tree_f
*** 137,143 ****
        if (wi)
  	{
  	  if (parse_input_constraint (&constraint, 0, 0, noutputs, 0,
! 				      oconstraints, &allows_mem, &allows_reg))
  	    {
  	      wi->val_only = (allows_reg || !allows_mem);
  	      /* Although input "m" is not really a LHS, we need a lvalue.  */
--- 137,144 ----
        if (wi)
  	{
  	  if (parse_input_constraint (&constraint, 0, 0, noutputs, 0,
! 				      oconstraints, &allows_mem, &allows_reg,
! 				      nullptr))
  	    {
  	      wi->val_only = (allows_reg || !allows_mem);
  	      /* Although input "m" is not really a LHS, we need a lvalue.  */
*************** walk_stmt_load_store_addr_ops (gimple *s
*** 897,903 ****
  		    (TREE_VALUE (TREE_PURPOSE (link)));
  		oconstraints[i] = constraint;
  		parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 					 &allows_reg, &is_inout);
  		if (op && !allows_reg && allows_mem)
  		  ret |= visit_addr (stmt, op, TREE_VALUE (link), data);
  	      }
--- 898,904 ----
  		    (TREE_VALUE (TREE_PURPOSE (link)));
  		oconstraints[i] = constraint;
  		parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 					 &allows_reg, &is_inout, nullptr);
  		if (op && !allows_reg && allows_mem)
  		  ret |= visit_addr (stmt, op, TREE_VALUE (link), data);
  	      }
*************** walk_stmt_load_store_addr_ops (gimple *s
*** 922,929 ****
  			constraint = TREE_STRING_POINTER
  			    (TREE_VALUE (TREE_PURPOSE (link)));
  			parse_input_constraint (&constraint, 0, 0, noutputs,
! 						0, oconstraints,
! 						&allows_mem, &allows_reg);
  			if (!allows_reg && allows_mem)
  			  ret |= visit_addr (stmt, op, TREE_VALUE (link),
  					     data);
--- 923,930 ----
  			constraint = TREE_STRING_POINTER
  			    (TREE_VALUE (TREE_PURPOSE (link)));
  			parse_input_constraint (&constraint, 0, 0, noutputs,
! 						0, oconstraints, &allows_mem,
! 						&allows_reg, nullptr);
  			if (!allows_reg && allows_mem)
  			  ret |= visit_addr (stmt, op, TREE_VALUE (link),
  					     data);
diff -Nrcpad gcc-16-20250720/gcc/gimplify-me.cc gcc-16-20250727/gcc/gimplify-me.cc
*** gcc-16-20250720/gcc/gimplify-me.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/gimplify-me.cc	Sun Jul 27 22:32:09 2025
*************** gimple_regimplify_operands (gimple *stmt
*** 194,200 ****
  	    constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
  	    oconstraints[i] = constraint;
  	    parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 				     &allows_reg, &is_inout);
  	    gimplify_expr (&TREE_VALUE (op), &pre, NULL,
  			   is_inout ? is_gimple_min_lval : is_gimple_lvalue,
  			   fb_lvalue | fb_mayfail);
--- 194,200 ----
  	    constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
  	    oconstraints[i] = constraint;
  	    parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 				     &allows_reg, &is_inout, nullptr);
  	    gimplify_expr (&TREE_VALUE (op), &pre, NULL,
  			   is_inout ? is_gimple_min_lval : is_gimple_lvalue,
  			   fb_lvalue | fb_mayfail);
*************** gimple_regimplify_operands (gimple *stmt
*** 204,210 ****
  	    tree op = gimple_asm_input_op (asm_stmt, i);
  	    constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
  	    parse_input_constraint (&constraint, 0, 0, noutputs, 0,
! 				    oconstraints, &allows_mem, &allows_reg);
  	    if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem)
  	      allows_reg = 0;
  	    if (!allows_reg && allows_mem)
--- 204,211 ----
  	    tree op = gimple_asm_input_op (asm_stmt, i);
  	    constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
  	    parse_input_constraint (&constraint, 0, 0, noutputs, 0,
! 				    oconstraints, &allows_mem, &allows_reg,
! 				    nullptr);
  	    if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem)
  	      allows_reg = 0;
  	    if (!allows_reg && allows_mem)
diff -Nrcpad gcc-16-20250720/gcc/gimplify.cc gcc-16-20250727/gcc/gimplify.cc
*** gcc-16-20250720/gcc/gimplify.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/gimplify.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 71,76 ****
--- 71,80 ----
  #include "context.h"
  #include "tree-nested.h"
  #include "gcc-urlifier.h"
+ #include "insn-config.h"
+ #include "recog.h"
+ #include "output.h"
+ #include "gimplify_reg_info.h"
  
  /* Identifier for a basic condition, mapping it to other basic conditions of
     its Boolean expression.  Basic conditions given the same uid (in the same
*************** gimplify_addr_expr (tree *expr_p, gimple
*** 7823,7828 ****
--- 7827,7868 ----
    return ret;
  }
  
+ /* Return the number of times character C occurs in string S.  */
+ 
+ static int
+ num_occurrences (int c, const char *s)
+ {
+   int n = 0;
+   while (*s)
+     n += (*s++ == c);
+   return n;
+ }
+ 
+ /* A subroutine of gimplify_asm_expr.  Check that all operands have
+    the same number of alternatives.  Return -1 if this is violated.  Otherwise
+    return the number of alternatives.  */
+ 
+ static int
+ num_alternatives (const_tree link)
+ {
+   if (link == nullptr)
+     return 0;
+ 
+   const char *constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+   int num = num_occurrences (',', constraint);
+ 
+   if (num + 1 > MAX_RECOG_ALTERNATIVES)
+     return -1;
+ 
+   for (link = TREE_CHAIN (link); link; link = TREE_CHAIN (link))
+     {
+       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+       if (num_occurrences (',', constraint) != num)
+ 	return -1;
+     }
+   return num + 1;
+ }
+ 
  /* Gimplify the operands of an ASM_EXPR.  Input operands should be a gimple
     value; output operands should be a gimple lvalue.  */
  
*************** gimplify_asm_expr (tree *expr_p, gimple_
*** 7853,7858 ****
--- 7893,7928 ----
    clobbers = NULL;
    labels = NULL;
  
+   int num_alternatives_out = num_alternatives (ASM_OUTPUTS (expr));
+   int num_alternatives_in = num_alternatives (ASM_INPUTS (expr));
+   if (num_alternatives_out == -1 || num_alternatives_in == -1
+       || (num_alternatives_out > 0 && num_alternatives_in > 0
+ 	  && num_alternatives_out != num_alternatives_in))
+     {
+       error ("operand constraints for %<asm%> differ "
+ 	     "in number of alternatives");
+       return GS_ERROR;
+     }
+   int num_alternatives = MAX (num_alternatives_out, num_alternatives_in);
+ 
+   gimplify_reg_info reg_info (num_alternatives, noutputs);
+ 
+   link_next = NULL_TREE;
+   for (link = ASM_CLOBBERS (expr); link; link = link_next)
+     {
+       /* The clobber entry could also be an error marker.  */
+       if (TREE_CODE (TREE_VALUE (link)) == STRING_CST)
+ 	{
+ 	  const char *regname= TREE_STRING_POINTER (TREE_VALUE (link));
+ 	  int regno = decode_reg_name (regname);
+ 	  if (regno >= 0)
+ 	    reg_info.set_clobbered (regno);
+ 	}
+       link_next = TREE_CHAIN (link);
+       TREE_CHAIN (link) = NULL_TREE;
+       vec_safe_push (clobbers, link);
+     }
+ 
    ret = GS_ALL_DONE;
    link_next = NULL_TREE;
    for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = link_next)
*************** gimplify_asm_expr (tree *expr_p, gimple_
*** 7869,7876 ****
        if (constraint_len == 0)
          continue;
  
!       ok = parse_output_constraint (&constraint, i, 0, 0,
! 				    &allows_mem, &allows_reg, &is_inout);
        if (!ok)
  	{
  	  ret = GS_ERROR;
--- 7939,7947 ----
        if (constraint_len == 0)
          continue;
  
!       reg_info.operand = TREE_VALUE (link);
!       ok = parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 				    &allows_reg, &is_inout, &reg_info);
        if (!ok)
  	{
  	  ret = GS_ERROR;
*************** gimplify_asm_expr (tree *expr_p, gimple_
*** 8001,8008 ****
  			*end = '\0';
  		      beg[-1] = '=';
  		      tem = beg - 1;
! 		      parse_output_constraint (&tem, i, 0, 0,
! 					       &mem_p, &reg_p, &inout_p);
  		      if (dst != str)
  			*dst++ = ',';
  		      if (reg_p)
--- 8072,8079 ----
  			*end = '\0';
  		      beg[-1] = '=';
  		      tem = beg - 1;
! 		      parse_output_constraint (&tem, i, 0, 0, &mem_p, &reg_p,
! 					       &inout_p, nullptr);
  		      if (dst != str)
  			*dst++ = ',';
  		      if (reg_p)
*************** gimplify_asm_expr (tree *expr_p, gimple_
*** 8041,8053 ****
  	}
      }
  
    link_next = NULL_TREE;
!   for (link = ASM_INPUTS (expr); link; ++i, link = link_next)
      {
        link_next = TREE_CHAIN (link);
        constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
!       parse_input_constraint (&constraint, 0, 0, noutputs, 0,
! 			      oconstraints, &allows_mem, &allows_reg);
  
        /* If we can't make copies, we can only accept memory.  */
        tree intype = TREE_TYPE (TREE_VALUE (link));
--- 8112,8171 ----
  	}
      }
  
+   /* After all output operands have been gimplified, verify that each output
+      operand is used at most once in case of hard register constraints.  Thus,
+      error out in cases like
+        asm ("" : "={0}" (x), "={1}" (x));
+      or even for
+        asm ("" : "=r" (x), "={1}" (x));
+ 
+      FIXME: Ideally we would also error out for cases like
+        int x;
+        asm ("" : "=r" (x), "=r" (x));
+      However, since code like that was previously accepted, erroring out now might
+      break existing code.  On the other hand, we already error out for register
+      asm like
+        register int x asm ("0");
+        asm ("" : "=r" (x), "=r" (x));
+      Thus, maybe it wouldn't be too bad to also error out in the former
+      non-register-asm case.
+   */
+   for (unsigned i = 0; i < vec_safe_length (outputs); ++i)
+     {
+       tree link = (*outputs)[i];
+       tree op1 = TREE_VALUE (link);
+       const char *constraint
+ 	= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+       if (strchr (constraint, '{') != nullptr)
+ 	for (unsigned j = 0; j < vec_safe_length (outputs); ++j)
+ 	  {
+ 	    if (i == j)
+ 	      continue;
+ 	    tree link2 = (*outputs)[j];
+ 	    tree op2 = TREE_VALUE (link2);
+ 	    if (op1 == op2)
+ 	      {
+ 		error ("multiple outputs to lvalue %qE", op2);
+ 		return GS_ERROR;
+ 	      }
+ 	  }
+     }
+ 
    link_next = NULL_TREE;
!   int input_num = 0;
!   for (link = ASM_INPUTS (expr); link; ++input_num, ++i, link = link_next)
      {
        link_next = TREE_CHAIN (link);
        constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
!       reg_info.operand = TREE_VALUE (link);
!       bool ok = parse_input_constraint (&constraint, input_num, 0, noutputs, 0,
! 					oconstraints, &allows_mem, &allows_reg,
! 					&reg_info);
!       if (!ok)
! 	{
! 	  ret = GS_ERROR;
! 	  is_inout = false;
! 	}
  
        /* If we can't make copies, we can only accept memory.  */
        tree intype = TREE_TYPE (TREE_VALUE (link));
*************** gimplify_asm_expr (tree *expr_p, gimple_
*** 8129,8143 ****
      }
  
    link_next = NULL_TREE;
!   for (link = ASM_CLOBBERS (expr); link; ++i, link = link_next)
!     {
!       link_next = TREE_CHAIN (link);
!       TREE_CHAIN (link) = NULL_TREE;
!       vec_safe_push (clobbers, link);
!     }
! 
!   link_next = NULL_TREE;
!   for (link = ASM_LABELS (expr); link; ++i, link = link_next)
      {
        link_next = TREE_CHAIN (link);
        TREE_CHAIN (link) = NULL_TREE;
--- 8247,8253 ----
      }
  
    link_next = NULL_TREE;
!   for (link = ASM_LABELS (expr); link; link = link_next)
      {
        link_next = TREE_CHAIN (link);
        TREE_CHAIN (link) = NULL_TREE;
diff -Nrcpad gcc-16-20250720/gcc/gimplify_reg_info.h gcc-16-20250727/gcc/gimplify_reg_info.h
*** gcc-16-20250720/gcc/gimplify_reg_info.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/gimplify_reg_info.h	Sun Jul 27 22:32:09 2025
***************
*** 0 ****
--- 1,182 ----
+ /* gimplify_reg_info is used during gimplification while walking over
+    operands and their corresponding constraints of asm statements in order to
+    detect errors.
+ 
+    m_alt_output is a mapping describing which registers are potentially used in
+    which alternative over all outputs.  Similarly for m_alt_input but over all
+    inputs.
+ 
+    m_early_clobbered_alt is a mapping describing which register is early
+    clobbered in which alternative over all outputs.
+ 
+    m_early_clobbered_output is the counter part to the prior one, i.e., it
+    is a mapping describing which register is early clobbered in which operand
+    over all alternatives.
+ 
+    m_reg_asm_output is the set of registers (including register pairs) used for
+    register asm output operands.
+ 
+    m_reg_asm_input similar as m_reg_asm_output but for inputs.  */
+ 
+ #include "regs.h"
+ 
+ class gimplify_reg_info
+ {
+   HARD_REG_SET *m_buf;
+   HARD_REG_SET *m_alt_output;
+   HARD_REG_SET *m_alt_input;
+   HARD_REG_SET *m_early_clobbered_alt;
+   HARD_REG_SET *m_early_clobbered_output;
+   HARD_REG_SET m_reg_asm_output;
+   HARD_REG_SET m_reg_asm_input;
+   const unsigned m_num_alternatives;
+   const unsigned m_num_outputs;
+   /* Member m_clobbered describes all the registers marked as clobbered in an
+      asm statement, i.e., this is the clobbers list of an extended asm
+ 
+      asm asm-qualifiers ( AssemblerTemplate
+ 		 : OutputOperands
+ 		 [ : InputOperands
+ 		 [ : Clobbers ] ])
+ 
+      and is not to be confused with the early clobbers sets.  */
+   HARD_REG_SET m_clobbered;
+ 
+   /* Return the first overlapping register of REGS and REGNO:MODE or -1.  */
+   int test (const HARD_REG_SET &regs, int regno) const
+   {
+     machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
+ 
+     if (TEST_HARD_REG_BIT (regs, regno))
+       return regno;
+ 
+     int end_regno = end_hard_regno (mode, regno);
+     while (++regno < end_regno)
+       if (TEST_HARD_REG_BIT (regs, regno))
+ 	return regno;
+ 
+     return -1;
+   }
+ 
+ public:
+   tree operand;
+ 
+   gimplify_reg_info (unsigned num_alternatives,
+ 		     unsigned num_outputs)
+     : m_num_alternatives{num_alternatives}
+     , m_num_outputs{num_outputs}
+   {
+     CLEAR_HARD_REG_SET (m_reg_asm_output);
+     CLEAR_HARD_REG_SET (m_reg_asm_input);
+     CLEAR_HARD_REG_SET (m_clobbered);
+ 
+     /* If there are no alternatives, then there are no outputs/inputs and there
+        is nothing to do on our end.  Thus, we are dealing most likely with a
+        basic asm.  */
+     if (num_alternatives == 0)
+       return;
+ 
+     unsigned buf_size = num_alternatives * 3 + num_outputs;
+     m_buf = new HARD_REG_SET[buf_size];
+     for (unsigned i = 0; i < buf_size; ++i)
+       CLEAR_HARD_REG_SET (m_buf[i]);
+     m_alt_output = &m_buf[0];
+     m_alt_input = &m_buf[num_alternatives];
+     m_early_clobbered_alt = &m_buf[num_alternatives * 2];
+     if (num_outputs > 0)
+       m_early_clobbered_output = &m_buf[num_alternatives * 3];
+     else
+       m_early_clobbered_output = nullptr;
+   }
+ 
+   ~gimplify_reg_info ()
+   {
+     if (m_num_alternatives > 0)
+       delete[] m_buf;
+   }
+ 
+   void set_output (unsigned alt, int regno)
+   {
+     gcc_checking_assert (alt < m_num_alternatives);
+     machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
+     add_to_hard_reg_set (&m_alt_output[alt], mode, regno);
+   }
+ 
+   void set_input (unsigned alt, int regno)
+   {
+     gcc_checking_assert (alt < m_num_alternatives);
+     machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
+     add_to_hard_reg_set (&m_alt_input[alt], mode, regno);
+   }
+ 
+   int test_alt_output (unsigned alt, int regno) const
+   {
+     gcc_checking_assert (alt < m_num_alternatives);
+     return test (m_alt_output[alt], regno);
+   }
+ 
+   int test_alt_input (unsigned alt, int regno) const
+   {
+     gcc_checking_assert (alt < m_num_alternatives);
+     return test (m_alt_input[alt], regno);
+   }
+ 
+   void set_reg_asm_output (int regno)
+   {
+     machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
+     add_to_hard_reg_set (&m_reg_asm_output, mode, regno);
+   }
+ 
+   int test_reg_asm_output (int regno) const
+   {
+     return test (m_reg_asm_output, regno);
+   }
+ 
+   void set_reg_asm_input (int regno)
+   {
+     machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
+     add_to_hard_reg_set (&m_reg_asm_input, mode, regno);
+   }
+ 
+   int test_reg_asm_input (int regno) const
+   {
+     return test (m_reg_asm_input, regno);
+   }
+ 
+   void set_early_clobbered (unsigned alt, unsigned output, int regno)
+   {
+     gcc_checking_assert (alt < m_num_alternatives);
+     gcc_checking_assert (output < m_num_outputs);
+     machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
+     add_to_hard_reg_set (&m_early_clobbered_alt[alt], mode, regno);
+     add_to_hard_reg_set (&m_early_clobbered_output[output], mode, regno);
+   }
+ 
+   bool test_early_clobbered_alt (unsigned alt, int regno) const
+   {
+     gcc_checking_assert (alt < m_num_alternatives);
+     return TEST_HARD_REG_BIT (m_early_clobbered_alt[alt], regno);
+   }
+ 
+   bool is_early_clobbered_in_any_output_unequal (unsigned operand,
+ 						 int regno) const
+   {
+     gcc_checking_assert (operand < m_num_outputs);
+     for (unsigned op = 0; op < m_num_outputs; ++op)
+       if (op != operand
+ 	  && TEST_HARD_REG_BIT (m_early_clobbered_output[op], regno))
+ 	return true;
+     return false;
+   }
+ 
+   void set_clobbered (int regno)
+   {
+     SET_HARD_REG_BIT (m_clobbered, regno);
+   }
+ 
+   bool is_clobbered (int regno) const
+   {
+     machine_mode mode = TYPE_MODE (TREE_TYPE (operand));
+     return overlaps_hard_reg_set_p (m_clobbered, mode, regno);
+   }
+ };
diff -Nrcpad gcc-16-20250720/gcc/input.cc gcc-16-20250727/gcc/input.cc
*** gcc-16-20250720/gcc/input.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/input.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 22,27 ****
--- 22,28 ----
  #include "coretypes.h"
  #include "intl.h"
  #include "diagnostic.h"
+ #include "diagnostics/file-cache.h"
  #include "selftest.h"
  #include "cpplib.h"
  
*************** special_fname_builtin ()
*** 35,222 ****
    return _("<built-in>");
  }
  
- /* Input charset configuration.  */
- static const char *default_charset_callback (const char *)
- {
-   return nullptr;
- }
- 
- void
- file_cache::initialize_input_context (diagnostic_input_charset_callback ccb,
- 				      bool should_skip_bom)
- {
-   m_input_context.ccb = (ccb ? ccb : default_charset_callback);
-   m_input_context.should_skip_bom = should_skip_bom;
- }
- 
- /* This is a cache used by get_next_line to store the content of a
-    file to be searched for file lines.  */
- class file_cache_slot
- {
- public:
-   file_cache_slot ();
-   ~file_cache_slot ();
- 
-   void dump (FILE *out, int indent) const;
-   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
- 
-   bool read_line_num (size_t line_num,
- 		      char ** line, ssize_t *line_len);
- 
-   /* Accessors.  */
-   const char *get_file_path () const { return m_file_path; }
-   unsigned get_use_count () const { return m_use_count; }
-   bool missing_trailing_newline_p () const
-   {
-     return m_missing_trailing_newline;
-   }
-   char_span get_full_file_content ();
- 
-   void inc_use_count () { m_use_count++; }
- 
-   bool create (const file_cache::input_context &in_context,
- 	       const char *file_path, FILE *fp, unsigned highest_use_count);
-   void evict ();
-   void set_content (const char *buf, size_t sz);
- 
-   static size_t tune (size_t line_record_size_)
-   {
-     size_t ret = line_record_size;
-     line_record_size = line_record_size_;
-     return ret;
-   }
- 
-  private:
-   /* These are information used to store a line boundary.  */
-   class line_info
-   {
-   public:
-     /* The line number.  It starts from 1.  */
-     size_t line_num;
- 
-     /* The position (byte count) of the beginning of the line,
-        relative to the file data pointer.  This starts at zero.  */
-     size_t start_pos;
- 
-     /* The position (byte count) of the last byte of the line.  This
-        normally points to the '\n' character, or to one byte after the
-        last byte of the file, if the file doesn't contain a '\n'
-        character.  */
-     size_t end_pos;
- 
-     line_info (size_t l, size_t s, size_t e)
-       : line_num (l), start_pos (s), end_pos (e)
-     {}
- 
-     line_info ()
-       :line_num (0), start_pos (0), end_pos (0)
-     {}
- 
-     static bool less_than(const line_info &a, const line_info &b)
-     {
-       return a.line_num < b.line_num;
-     }
-   };
- 
-   bool needs_read_p () const;
-   bool needs_grow_p () const;
-   void maybe_grow ();
-   bool read_data ();
-   bool maybe_read_data ();
-   bool get_next_line (char **line, ssize_t *line_len);
-   bool read_next_line (char ** line, ssize_t *line_len);
-   bool goto_next_line ();
- 
-   static const size_t buffer_size = 4 * 1024;
-   static size_t line_record_size;
-   static size_t recent_cached_lines_shift;
- 
-   /* The number of time this file has been accessed.  This is used
-      to designate which file cache to evict from the cache
-      array.  */
-   unsigned m_use_count;
- 
-   /* The file_path is the key for identifying a particular file in
-      the cache.  This copy is owned by the slot.  */
-   char *m_file_path;
- 
-   FILE *m_fp;
- 
-   /* True when an read error happened.  */
-   bool m_error;
- 
-   /* This points to the content of the file that we've read so
-      far.  */
-   char *m_data;
- 
-   /* The allocated buffer to be freed may start a little earlier than DATA,
-      e.g. if a UTF8 BOM was skipped at the beginning.  */
-   int m_alloc_offset;
- 
-   /*  The size of the DATA array above.*/
-   size_t m_size;
- 
-   /* The number of bytes read from the underlying file so far.  This
-      must be less (or equal) than SIZE above.  */
-   size_t m_nb_read;
- 
-   /* The index of the beginning of the current line.  */
-   size_t m_line_start_idx;
- 
-   /* The number of the previous line read.  This starts at 1.  Zero
-      means we've read no line so far.  */
-   size_t m_line_num;
- 
-   /* Could this file be missing a trailing newline on its final line?
-      Initially true (to cope with empty files), set to true/false
-      as each line is read.  */
-   bool m_missing_trailing_newline;
- 
-   /* This is a record of the beginning and end of the lines we've seen
-      while reading the file.  This is useful to avoid walking the data
-      from the beginning when we are asked to read a line that is
-      before LINE_START_IDX above.  When the lines exceed line_record_size
-      this is scaled down dynamically, with the line_info becoming anchors.  */
-   vec<line_info, va_heap> m_line_record;
- 
-   /* A cache of the recently seen lines. This is maintained as a ring
-      buffer. */
-   vec<line_info, va_heap> m_line_recent;
- 
-   /* First and last valid entry in m_line_recent.  */
-   size_t m_line_recent_last, m_line_recent_first;
- 
-   void offset_buffer (int offset)
-   {
-     gcc_assert (offset < 0 ? m_alloc_offset + offset >= 0
- 		: (size_t) offset <= m_size);
-     gcc_assert (m_data);
-     m_alloc_offset += offset;
-     m_data += offset;
-     m_size -= offset;
-   }
- 
- };
- 
- size_t file_cache_slot::line_record_size = 0;
- size_t file_cache_slot::recent_cached_lines_shift = 8;
- 
- /* Tune file_cache.  */
- void
- file_cache::tune (size_t num_file_slots, size_t lines)
- {
-   if (file_cache_slot::tune (lines) != lines
-       || m_num_file_slots != num_file_slots)
-     {
-       delete[] m_file_slots;
-       m_file_slots = new file_cache_slot[num_file_slots];
-     }
-   m_num_file_slots = num_file_slots;
- }
- 
- static const char *
- find_end_of_line (const char *s, size_t len);
- 
  /* Current position in real source file.  */
  
  location_t input_location = UNKNOWN_LOCATION;
--- 36,41 ----
*************** expand_location_1 (const line_maps *set,
*** 320,1057 ****
    return xloc;
  }
  
- /* Lookup the cache used for the content of a given file accessed by
-    caret diagnostic.  Return the found cached file, or NULL if no
-    cached file was found.  */
- 
- file_cache_slot *
- file_cache::lookup_file (const char *file_path)
- {
-   gcc_assert (file_path);
- 
-   /* This will contain the found cached file.  */
-   file_cache_slot *r = NULL;
-   for (unsigned i = 0; i < m_num_file_slots; ++i)
-     {
-       file_cache_slot *c = &m_file_slots[i];
-       if (c->get_file_path () && !strcmp (c->get_file_path (), file_path))
- 	{
- 	  c->inc_use_count ();
- 	  r = c;
- 	}
-     }
- 
-   if (r)
-     r->inc_use_count ();
- 
-   return r;
- }
- 
- /* Purge any mention of FILENAME from the cache of files used for
-    printing source code.  For use in selftests when working
-    with tempfiles.  */
- 
- void
- file_cache::forcibly_evict_file (const char *file_path)
- {
-   gcc_assert (file_path);
- 
-   file_cache_slot *r = lookup_file (file_path);
-   if (!r)
-     /* Not found.  */
-     return;
- 
-   r->evict ();
- }
- 
- /* Determine if FILE_PATH missing a trailing newline on its final line.
-    Only valid to call once all of the file has been loaded, by
-    requesting a line number beyond the end of the file.  */
- 
- bool
- file_cache::missing_trailing_newline_p (const char *file_path)
- {
-   gcc_assert (file_path);
- 
-   file_cache_slot *r = lookup_or_add_file (file_path);
-   return r->missing_trailing_newline_p ();
- }
- 
- void
- file_cache::add_buffered_content (const char *file_path,
- 				  const char *buffer,
- 				  size_t sz)
- {
-   gcc_assert (file_path);
- 
-   file_cache_slot *r = lookup_file (file_path);
-   if (!r)
-     {
-       unsigned highest_use_count = 0;
-       r = evicted_cache_tab_entry (&highest_use_count);
-       if (!r->create (m_input_context, file_path, nullptr, highest_use_count))
- 	return;
-     }
- 
-   r->set_content (buffer, sz);
- }
- 
- void
- file_cache_slot::evict ()
- {
-   free (m_file_path);
-   m_file_path = NULL;
-   if (m_fp)
-     fclose (m_fp);
-   m_error = false;
-   m_fp = NULL;
-   m_nb_read = 0;
-   m_line_start_idx = 0;
-   m_line_num = 0;
-   m_line_record.truncate (0);
-   m_line_recent_first = 0;
-   m_line_recent_last = 0;
-   m_use_count = 0;
-   m_missing_trailing_newline = true;
- }
- 
- /* Return the file cache that has been less used, recently, or the
-    first empty one.  If HIGHEST_USE_COUNT is non-null,
-    *HIGHEST_USE_COUNT is set to the highest use count of the entries
-    in the cache table.  */
- 
- file_cache_slot*
- file_cache::evicted_cache_tab_entry (unsigned *highest_use_count)
- {
-   file_cache_slot *to_evict = &m_file_slots[0];
-   unsigned huc = to_evict->get_use_count ();
-   for (unsigned i = 1; i < m_num_file_slots; ++i)
-     {
-       file_cache_slot *c = &m_file_slots[i];
-       bool c_is_empty = (c->get_file_path () == NULL);
- 
-       if (c->get_use_count () < to_evict->get_use_count ()
- 	  || (to_evict->get_file_path () && c_is_empty))
- 	/* We evict C because it's either an entry with a lower use
- 	   count or one that is empty.  */
- 	to_evict = c;
- 
-       if (huc < c->get_use_count ())
- 	huc = c->get_use_count ();
- 
-       if (c_is_empty)
- 	/* We've reached the end of the cache; subsequent elements are
- 	   all empty.  */
- 	break;
-     }
- 
-   if (highest_use_count)
-     *highest_use_count = huc;
- 
-   return to_evict;
- }
- 
- /* Create the cache used for the content of a given file to be
-    accessed by caret diagnostic.  This cache is added to an array of
-    cache and can be retrieved by lookup_file_in_cache_tab.  This
-    function returns the created cache.  Note that only the last
-    m_num_file_slots files are cached.
- 
-    This can return nullptr if the FILE_PATH can't be opened for
-    reading, or if the content can't be converted to the input_charset.  */
- 
- file_cache_slot*
- file_cache::add_file (const char *file_path)
- {
- 
-   FILE *fp = fopen (file_path, "r");
-   if (fp == NULL)
-     return NULL;
- 
-   unsigned highest_use_count = 0;
-   file_cache_slot *r = evicted_cache_tab_entry (&highest_use_count);
-   if (!r->create (m_input_context, file_path, fp, highest_use_count))
-     return NULL;
-   return r;
- }
- 
- /* Get a borrowed char_span to the full content of this file
-    as decoded according to the input charset, encoded as UTF-8.  */
- 
- char_span
- file_cache_slot::get_full_file_content ()
- {
-   char *line;
-   ssize_t line_len;
-   while (get_next_line (&line, &line_len))
-     {
-     }
-   return char_span (m_data, m_nb_read);
- }
- 
- /* Populate this slot for use on FILE_PATH and FP, dropping any
-    existing cached content within it.  */
- 
- bool
- file_cache_slot::create (const file_cache::input_context &in_context,
- 			 const char *file_path, FILE *fp,
- 			 unsigned highest_use_count)
- {
-   m_file_path = file_path ? xstrdup (file_path) : nullptr;
-   if (m_fp)
-     fclose (m_fp);
-   m_error = false;
-   m_fp = fp;
-   if (m_alloc_offset)
-     offset_buffer (-m_alloc_offset);
-   m_nb_read = 0;
-   m_line_start_idx = 0;
-   m_line_num = 0;
-   m_line_recent_first = 0;
-   m_line_recent_last = 0;
-   m_line_record.truncate (0);
-   /* Ensure that this cache entry doesn't get evicted next time
-      add_file_to_cache_tab is called.  */
-   m_use_count = ++highest_use_count;
-   m_missing_trailing_newline = true;
- 
- 
-   /* Check the input configuration to determine if we need to do any
-      transformations, such as charset conversion or BOM skipping.  */
-   if (const char *input_charset = in_context.ccb (file_path))
-     {
-       /* Need a full-blown conversion of the input charset.  */
-       fclose (m_fp);
-       m_fp = NULL;
-       const cpp_converted_source cs
- 	= cpp_get_converted_source (file_path, input_charset);
-       if (!cs.data)
- 	return false;
-       if (m_data)
- 	XDELETEVEC (m_data);
-       m_data = cs.data;
-       m_nb_read = m_size = cs.len;
-       m_alloc_offset = cs.data - cs.to_free;
-     }
-   else if (in_context.should_skip_bom)
-     {
-       if (read_data ())
- 	{
- 	  const int offset = cpp_check_utf8_bom (m_data, m_nb_read);
- 	  offset_buffer (offset);
- 	  m_nb_read -= offset;
- 	}
-     }
- 
-   return true;
- }
- 
- void
- file_cache_slot::set_content (const char *buf, size_t sz)
- {
-   m_data = (char *)xmalloc (sz);
-   memcpy (m_data, buf, sz);
-   m_nb_read = m_size = sz;
-   m_alloc_offset = 0;
- 
-   if (m_fp)
-     {
-       fclose (m_fp);
-       m_fp = nullptr;
-     }
- }
- 
- /* file_cache's ctor.  */
- 
- file_cache::file_cache ()
- : m_num_file_slots (16), m_file_slots (new file_cache_slot[m_num_file_slots])
- {
-   initialize_input_context (nullptr, false);
- }
- 
- /* file_cache's dtor.  */
- 
- file_cache::~file_cache ()
- {
-   delete[] m_file_slots;
- }
- 
- void
- file_cache::dump (FILE *out, int indent) const
- {
-   for (size_t i = 0; i < m_num_file_slots; ++i)
-     {
-       fprintf (out, "%*sslot[%i]:\n", indent, "", (int)i);
-       m_file_slots[i].dump (out, indent + 2);
-     }
- }
- 
- void
- file_cache::dump () const
- {
-   dump (stderr, 0);
- }
- 
- /* Lookup the cache used for the content of a given file accessed by
-    caret diagnostic.  If no cached file was found, create a new cache
-    for this file, add it to the array of cached file and return
-    it.
- 
-    This can return nullptr on a cache miss if FILE_PATH can't be opened for
-    reading, or if the content can't be converted to the input_charset.  */
- 
- file_cache_slot*
- file_cache::lookup_or_add_file (const char *file_path)
- {
-   file_cache_slot *r = lookup_file (file_path);
-   if (r == NULL)
-     r = add_file (file_path);
-   return r;
- }
- 
- /* Default constructor for a cache of file used by caret
-    diagnostic.  */
- 
- file_cache_slot::file_cache_slot ()
- : m_use_count (0), m_file_path (NULL), m_fp (NULL), m_error (false), m_data (0),
-   m_alloc_offset (0), m_size (0), m_nb_read (0), m_line_start_idx (0),
-   m_line_num (0), m_missing_trailing_newline (true),
-   m_line_recent_last (0), m_line_recent_first (0)
- {
-   m_line_record.create (0);
-   m_line_recent.create (1U << recent_cached_lines_shift);
-   for (int i = 0; i < 1 << recent_cached_lines_shift; i++)
-     m_line_recent.quick_push (file_cache_slot::line_info (0, 0, 0));
- }
- 
- /* Destructor for a cache of file used by caret diagnostic.  */
- 
- file_cache_slot::~file_cache_slot ()
- {
-   free (m_file_path);
-   if (m_fp)
-     {
-       fclose (m_fp);
-       m_fp = NULL;
-     }
-   if (m_data)
-     {
-       offset_buffer (-m_alloc_offset);
-       XDELETEVEC (m_data);
-       m_data = 0;
-     }
-   m_line_record.release ();
-   m_line_recent.release ();
- }
- 
- void
- file_cache_slot::dump (FILE *out, int indent) const
- {
-   if (!m_file_path)
-     {
-       fprintf (out, "%*s(unused)\n", indent, "");
-       return;
-     }
-   fprintf (out, "%*sfile_path: %s\n", indent, "", m_file_path);
-   fprintf (out, "%*sfp: %p\n", indent, "", (void *)m_fp);
-   fprintf (out, "%*sneeds_read_p: %i\n", indent, "", (int)needs_read_p ());
-   fprintf (out, "%*sneeds_grow_p: %i\n", indent, "", (int)needs_grow_p ());
-   fprintf (out, "%*suse_count: %i\n", indent, "", m_use_count);
-   fprintf (out, "%*ssize: %zi\n", indent, "", m_size);
-   fprintf (out, "%*snb_read: %zi\n", indent, "", m_nb_read);
-   fprintf (out, "%*sstart_line_idx: %zi\n", indent, "", m_line_start_idx);
-   fprintf (out, "%*sline_num: %zi\n", indent, "", m_line_num);
-   fprintf (out, "%*smissing_trailing_newline: %i\n",
- 	   indent, "", (int)m_missing_trailing_newline);
-   fprintf (out, "%*sline records (%i):\n",
- 	   indent, "", m_line_record.length ());
-   int idx = 0;
-   for (auto &line : m_line_record)
-     fprintf (out, "%*s[%i]: line %zi: byte offsets: %zi-%zi\n",
- 	     indent + 2, "",
- 	     idx++, line.line_num, line.start_pos, line.end_pos);
- }
- 
- /* Returns TRUE iff the cache would need to be filled with data coming
-    from the file.  That is, either the cache is empty or full or the
-    current line is empty.  Note that if the cache is full, it would
-    need to be extended and filled again.  */
- 
- bool
- file_cache_slot::needs_read_p () const
- {
-   return m_fp && (m_nb_read == 0
- 	  || m_nb_read == m_size
- 	  || (m_line_start_idx >= m_nb_read - 1));
- }
- 
- /*  Return TRUE iff the cache is full and thus needs to be
-     extended.  */
- 
- bool
- file_cache_slot::needs_grow_p () const
- {
-   return m_nb_read == m_size;
- }
- 
- /* Grow the cache if it needs to be extended.  */
- 
- void
- file_cache_slot::maybe_grow ()
- {
-   if (!needs_grow_p ())
-     return;
- 
-   if (!m_data)
-     {
-       gcc_assert (m_size == 0 && m_alloc_offset == 0);
-       m_size = buffer_size;
-       m_data = XNEWVEC (char, m_size);
-     }
-   else
-     {
-       const int offset = m_alloc_offset;
-       offset_buffer (-offset);
-       m_size *= 2;
-       m_data = XRESIZEVEC (char, m_data, m_size);
-       offset_buffer (offset);
-     }
- }
- 
- /*  Read more data into the cache.  Extends the cache if need be.
-     Returns TRUE iff new data could be read.  */
- 
- bool
- file_cache_slot::read_data ()
- {
-   if (feof (m_fp) || ferror (m_fp))
-     return false;
- 
-   maybe_grow ();
- 
-   char * from = m_data + m_nb_read;
-   size_t to_read = m_size - m_nb_read;
-   size_t nb_read = fread (from, 1, to_read, m_fp);
- 
-   if (ferror (m_fp))
-     {
-       m_error = true;
-       return false;
-     }
- 
-   m_nb_read += nb_read;
-   return !!nb_read;
- }
- 
- /* Read new data iff the cache needs to be filled with more data
-    coming from the file FP.  Return TRUE iff the cache was filled with
-    mode data.  */
- 
- bool
- file_cache_slot::maybe_read_data ()
- {
-   if (!needs_read_p ())
-     return false;
-   return read_data ();
- }
- 
- /* Helper function for file_cache_slot::get_next_line (), to find the end of
-    the next line.  Returns with the memchr convention, i.e. nullptr if a line
-    terminator was not found.  We need to determine line endings in the same
-    manner that libcpp does: any of \n, \r\n, or \r is a line ending.  */
- 
- static const char *
- find_end_of_line (const char *s, size_t len)
- {
-   for (const auto end = s + len; s != end; ++s)
-     {
-       if (*s == '\n')
- 	return s;
-       if (*s == '\r')
- 	{
- 	  const auto next = s + 1;
- 	  if (next == end)
- 	    {
- 	      /* Don't find the line ending if \r is the very last character
- 		 in the buffer; we do not know if it's the end of the file or
- 		 just the end of what has been read so far, and we wouldn't
- 		 want to break in the middle of what's actually a \r\n
- 		 sequence.  Instead, we will handle the case of a file ending
- 		 in a \r later.  */
- 	      break;
- 	    }
- 	  return (*next == '\n' ? next : s);
- 	}
-     }
-   return nullptr;
- }
- 
- /* Read a new line from file FP, using C as a cache for the data
-    coming from the file.  Upon successful completion, *LINE is set to
-    the beginning of the line found.  *LINE points directly in the
-    line cache and is only valid until the next call of get_next_line.
-    *LINE_LEN is set to the length of the line.  Note that the line
-    does not contain any terminal delimiter.  This function returns
-    true if some data was read or process from the cache, false
-    otherwise.  Note that subsequent calls to get_next_line might
-    make the content of *LINE invalid.  */
- 
- bool
- file_cache_slot::get_next_line (char **line, ssize_t *line_len)
- {
-   /* Fill the cache with data to process.  */
-   maybe_read_data ();
- 
-   size_t remaining_size = m_nb_read - m_line_start_idx;
-   if (remaining_size == 0)
-     /* There is no more data to process.  */
-     return false;
- 
-   const char *line_start = m_data + m_line_start_idx;
- 
-   const char *next_line_start = NULL;
-   size_t len = 0;
-   const char *line_end = find_end_of_line (line_start, remaining_size);
-   if (line_end == NULL)
-     {
-       /* We haven't found an end-of-line delimiter in the cache.
- 	 Fill the cache with more data from the file and look again.  */
-       while (maybe_read_data ())
- 	{
- 	  line_start = m_data + m_line_start_idx;
- 	  remaining_size = m_nb_read - m_line_start_idx;
- 	  line_end = find_end_of_line (line_start, remaining_size);
- 	  if (line_end != NULL)
- 	    {
- 	      next_line_start = line_end + 1;
- 	      break;
- 	    }
- 	}
-       if (line_end == NULL)
- 	{
- 	  /* We've loaded all the file into the cache and still no
- 	     terminator.  Let's say the line ends up at one byte past the
- 	     end of the file.  This is to stay consistent with the case
- 	     of when the line ends up with a terminator and line_end points to
- 	     that.  That consistency is useful below in the len calculation.
- 
- 	     If the file ends in a \r, we didn't identify it as a line
- 	     terminator above, so do that now instead.  */
- 	  line_end = m_data + m_nb_read;
- 	  if (m_nb_read && line_end[-1] == '\r')
- 	    {
- 	      --line_end;
- 	      m_missing_trailing_newline = false;
- 	    }
- 	  else
- 	    m_missing_trailing_newline = true;
- 	}
-       else
- 	m_missing_trailing_newline = false;
-     }
-   else
-     {
-       next_line_start = line_end + 1;
-       m_missing_trailing_newline = false;
-     }
- 
-   if (m_error)
-     return false;
- 
-   /* At this point, we've found the end of the of line.  It either points to
-      the line terminator or to one byte after the last byte of the file.  */
-   gcc_assert (line_end != NULL);
- 
-   len = line_end - line_start;
- 
-   if (m_line_start_idx < m_nb_read)
-     *line = const_cast<char *> (line_start);
- 
-   ++m_line_num;
- 
-   /* Now update our line record so that re-reading lines from the
-      before m_line_start_idx is faster.  */
-   size_t rlen = m_line_record.length ();
-   /* Only update when beyond the previously cached region.  */
-   if (rlen == 0 || m_line_record[rlen - 1].line_num < m_line_num)
-     {
-       size_t spacing
- 	= (rlen >= 2
- 	   ? (m_line_record[rlen - 1].line_num
- 	      - m_line_record[rlen - 2].line_num) : 1);
-       size_t delta
- 	= rlen >= 1 ? m_line_num - m_line_record[rlen - 1].line_num : 1;
- 
-       size_t max_size = line_record_size;
-       /* One anchor per hundred input lines.  */
-       if (max_size == 0)
- 	max_size = m_line_num / 100;
- 
-       /* If we're too far beyond drop half of the lines to rebalance.  */
-       if (rlen == max_size && delta >= spacing * 2)
- 	{
- 	  size_t j = 0;
- 	  for (size_t i = 1; i < rlen; i += 2)
- 	    m_line_record[j++] = m_line_record[i];
- 	  m_line_record.truncate (j);
- 	  rlen = j;
- 	  spacing *= 2;
- 	}
- 
-       if (rlen < max_size && delta >= spacing)
- 	{
- 	  file_cache_slot::line_info li (m_line_num, m_line_start_idx,
- 					 line_end - m_data);
- 	  m_line_record.safe_push (li);
- 	}
-     }
- 
-   /* Cache recent tail lines separately for fast access. This assumes
-      most accesses do not skip backwards.  */
-   if (m_line_recent_last == m_line_recent_first
-       || m_line_recent[m_line_recent_last].line_num == m_line_num - 1)
-     {
-       size_t mask = ((size_t) 1 << recent_cached_lines_shift) - 1;
-       m_line_recent_last = (m_line_recent_last + 1) & mask;
-       if (m_line_recent_last == m_line_recent_first)
- 	m_line_recent_first = (m_line_recent_first + 1) & mask;
-       m_line_recent[m_line_recent_last]
- 	= file_cache_slot::line_info (m_line_num, m_line_start_idx,
- 				      line_end - m_data);
-     }
- 
-   /* Update m_line_start_idx so that it points to the next line to be
-      read.  */
-   if (next_line_start)
-     m_line_start_idx = next_line_start - m_data;
-   else
-     /* We didn't find any terminal '\n'.  Let's consider that the end
-        of line is the end of the data in the cache.  The next
-        invocation of get_next_line will either read more data from the
-        underlying file or return false early because we've reached the
-        end of the file.  */
-     m_line_start_idx = m_nb_read;
- 
-   *line_len = len;
- 
-   return true;
- }
- 
- /* Consume the next bytes coming from the cache (or from its
-    underlying file if there are remaining unread bytes in the file)
-    until we reach the next end-of-line (or end-of-file).  There is no
-    copying from the cache involved.  Return TRUE upon successful
-    completion.  */
- 
- bool
- file_cache_slot::goto_next_line ()
- {
-   char *l;
-   ssize_t len;
- 
-   return get_next_line (&l, &len);
- }
- 
- /* Read an arbitrary line number LINE_NUM from the file cached in C.
-    If the line was read successfully, *LINE points to the beginning
-    of the line in the file cache and *LINE_LEN is the length of the
-    line.  *LINE is not nul-terminated, but may contain zero bytes.
-    *LINE is only valid until the next call of read_line_num.
-    This function returns bool if a line was read.  */
- 
- bool
- file_cache_slot::read_line_num (size_t line_num,
- 				char ** line, ssize_t *line_len)
- {
-   gcc_assert (line_num > 0);
- 
-   /* Is the line in the recent line cache?
-      This assumes the main file processing is only using
-      a single contiguous cursor with only temporary excursions.  */
-   if (m_line_recent_first != m_line_recent_last
- 	&& m_line_recent[m_line_recent_first].line_num <= line_num
- 	&& m_line_recent[m_line_recent_last].line_num >= line_num)
-     {
-       line_info &last = m_line_recent[m_line_recent_last];
-       size_t mask = (1U << recent_cached_lines_shift) - 1;
-       size_t idx = (m_line_recent_last - (last.line_num - line_num)) & mask;
-       line_info &recent = m_line_recent[idx];
-       gcc_assert (recent.line_num == line_num);
-       *line = m_data + recent.start_pos;
-       *line_len = recent.end_pos - recent.start_pos;
-       return true;
-     }
- 
-   if (line_num <= m_line_num)
-     {
-       line_info l (line_num, 0, 0);
-       int i = m_line_record.lower_bound (l, line_info::less_than);
-       if (i == 0)
- 	{
- 	  m_line_start_idx = 0;
- 	  m_line_num = 0;
- 	}
-       else if (m_line_record[i - 1].line_num == line_num)
- 	{
- 	  /* We have the start/end of the line.  */
- 	  *line = m_data + m_line_record[i - 1].start_pos;
- 	  *line_len = m_line_record[i - 1].end_pos - m_line_record[i - 1].start_pos;
- 	  return true;
- 	}
-       else
-        {
- 	 gcc_assert (m_line_record[i - 1].line_num < m_line_num);
- 	 m_line_start_idx = m_line_record[i - 1].start_pos;
- 	 m_line_num = m_line_record[i - 1].line_num - 1;
-        }
-     }
- 
-   /*  Let's walk from line m_line_num up to line_num - 1, without
-       copying any line.  */
-   while (m_line_num < line_num - 1)
-     if (!goto_next_line ())
-       return false;
- 
-   /* The line we want is the next one.  Let's read it.  */
-   return get_next_line (line, line_len);
- }
- 
- /* Return the physical source line that corresponds to FILE_PATH/LINE.
-    The line is not nul-terminated.  The returned pointer is only
-    valid until the next call of location_get_source_line.
-    Note that the line can contain several null characters,
-    so the returned value's length has the actual length of the line.
-    If the function fails, a NULL char_span is returned.  */
- 
- char_span
- file_cache::get_source_line (const char *file_path, int line)
- {
-   char *buffer = NULL;
-   ssize_t len;
- 
-   if (line == 0)
-     return char_span (NULL, 0);
- 
-   if (file_path == NULL)
-     return char_span (NULL, 0);
- 
-   file_cache_slot *c = lookup_or_add_file (file_path);
-   if (c == NULL)
-     return char_span (NULL, 0);
- 
-   bool read = c->read_line_num (line, &buffer, &len);
-   if (!read)
-     return char_span (NULL, 0);
- 
-   return char_span (buffer, len);
- }
- 
  /* Return a NUL-terminated copy of the source text between two locations, or
     NULL if the arguments are invalid.  The caller is responsible for freeing
     the return value.  */
  
  char *
! get_source_text_between (file_cache &fc, location_t start, location_t end)
  {
    expanded_location expstart
      = expand_location_to_spelling_point (start, LOCATION_ASPECT_START);
--- 139,151 ----
    return xloc;
  }
  
  /* Return a NUL-terminated copy of the source text between two locations, or
     NULL if the arguments are invalid.  The caller is responsible for freeing
     the return value.  */
  
  char *
! get_source_text_between (diagnostics::file_cache &fc,
! 			 location_t start, location_t end)
  {
    expanded_location expstart
      = expand_location_to_spelling_point (start, LOCATION_ASPECT_START);
*************** get_source_text_between (file_cache &fc,
*** 1076,1082 ****
    /* For a single line we need to trim both edges.  */
    if (expstart.line == expend.line)
      {
!       char_span line = fc.get_source_line (expstart.file, expstart.line);
        if (line.length () < 1)
  	return NULL;
        int s = expstart.column - 1;
--- 170,177 ----
    /* For a single line we need to trim both edges.  */
    if (expstart.line == expend.line)
      {
!       diagnostics::char_span line
! 	= fc.get_source_line (expstart.file, expstart.line);
        if (line.length () < 1)
  	return NULL;
        int s = expstart.column - 1;
*************** get_source_text_between (file_cache &fc,
*** 1093,1099 ****
       parts of the start and end lines off depending on column values.  */
    for (int lnum = expstart.line; lnum <= expend.line; ++lnum)
      {
!       char_span line = fc.get_source_line (expstart.file, lnum);
        if (line.length () < 1 && (lnum != expstart.line && lnum != expend.line))
  	continue;
  
--- 188,194 ----
       parts of the start and end lines off depending on column values.  */
    for (int lnum = expstart.line; lnum <= expend.line; ++lnum)
      {
!       diagnostics::char_span line = fc.get_source_line (expstart.file, lnum);
        if (line.length () < 1 && (lnum != expstart.line && lnum != expend.line))
  	continue;
  
*************** get_source_text_between (file_cache &fc,
*** 1138,1153 ****
    return xstrdup (buf);
  }
  
- 
- char_span
- file_cache::get_source_file_content (const char *file_path)
- {
-   file_cache_slot *c = lookup_or_add_file (file_path);
-   if (c == nullptr)
-     return char_span (nullptr, 0);
-   return c->get_full_file_content ();
- }
- 
  /* Test if the location originates from the spelling location of a
     builtin-tokens.  That is, return TRUE if LOC is a (possibly
     virtual) location of a built-in token that appears in the expansion
--- 233,238 ----
*************** make_location (location_t caret, source_
*** 1280,1292 ****
     source line in order to calculate the display width.  If that cannot be done
     for any reason, then returns the byte column as a fallback.  */
  int
! location_compute_display_column (file_cache &fc,
  				 expanded_location exploc,
  				 const cpp_char_column_policy &policy)
  {
    if (!(exploc.file && *exploc.file && exploc.line && exploc.column))
      return exploc.column;
!   char_span line = fc.get_source_line (exploc.file, exploc.line);
    /* If line is NULL, this function returns exploc.column which is the
       desired fallback.  */
    return cpp_byte_column_to_display_column (line.get_buffer (), line.length (),
--- 365,377 ----
     source line in order to calculate the display width.  If that cannot be done
     for any reason, then returns the byte column as a fallback.  */
  int
! location_compute_display_column (diagnostics::file_cache &fc,
  				 expanded_location exploc,
  				 const cpp_char_column_policy &policy)
  {
    if (!(exploc.file && *exploc.file && exploc.line && exploc.column))
      return exploc.column;
!   diagnostics::char_span line = fc.get_source_line (exploc.file, exploc.line);
    /* If line is NULL, this function returns exploc.column which is the
       desired fallback.  */
    return cpp_byte_column_to_display_column (line.get_buffer (), line.length (),
*************** dump_labelled_location_range (FILE *stre
*** 1431,1437 ****
  void
  dump_location_info (FILE *stream)
  {
!   file_cache fc;
  
    /* Visualize the reserved locations.  */
    dump_labelled_location_range (stream, "RESERVED LOCATIONS",
--- 516,522 ----
  void
  dump_location_info (FILE *stream)
  {
!   diagnostics::file_cache fc;
  
    /* Visualize the reserved locations.  */
    dump_labelled_location_range (stream, "RESERVED LOCATIONS",
*************** dump_location_info (FILE *stream)
*** 1506,1513 ****
  	    {
  	      /* Beginning of a new source line: draw the line.  */
  
! 	      char_span line_text = fc.get_source_line (exploc.file,
! 							exploc.line);
  	      if (!line_text)
  		break;
  	      fprintf (stream,
--- 591,598 ----
  	    {
  	      /* Beginning of a new source line: draw the line.  */
  
! 	      diagnostics::char_span line_text
! 		= fc.get_source_line (exploc.file, exploc.line);
  	      if (!line_text)
  		break;
  	      fprintf (stream,
*************** dump_location_info (FILE *stream)
*** 1524,1533 ****
  	      if (max_col > line_text.length ())
  		max_col = line_text.length () + 1;
  
! 	      int len_lnum = num_digits (exploc.line);
  	      if (len_lnum < 3)
  		len_lnum = 3;
! 	      int len_loc = num_digits (loc);
  	      if (len_loc < 5)
  		len_loc = 5;
  
--- 609,618 ----
  	      if (max_col > line_text.length ())
  		max_col = line_text.length () + 1;
  
! 	      int len_lnum = diagnostics::num_digits (exploc.line);
  	      if (len_lnum < 3)
  		len_lnum = 3;
! 	      int len_loc = diagnostics::num_digits (loc);
  	      if (len_loc < 5)
  		len_loc = 5;
  
*************** class auto_cpp_string_vec :  public auto
*** 1757,1763 ****
  
  static const char *
  get_substring_ranges_for_loc (cpp_reader *pfile,
! 			      file_cache &fc,
  			      string_concat_db *concats,
  			      location_t strloc,
  			      enum cpp_ttype type,
--- 842,848 ----
  
  static const char *
  get_substring_ranges_for_loc (cpp_reader *pfile,
! 			      diagnostics::file_cache &fc,
  			      string_concat_db *concats,
  			      location_t strloc,
  			      enum cpp_ttype type,
*************** get_substring_ranges_for_loc (cpp_reader
*** 1837,1843 ****
        if (start.column > finish.column)
  	return "range endpoints are reversed";
  
!       char_span line = fc.get_source_line (start.file, start.line);
        if (!line)
  	return "unable to read source line";
  
--- 922,928 ----
        if (start.column > finish.column)
  	return "range endpoints are reversed";
  
!       diagnostics::char_span line = fc.get_source_line (start.file, start.line);
        if (!line)
  	return "unable to read source line";
  
*************** get_substring_ranges_for_loc (cpp_reader
*** 1852,1858 ****
        if (line.length () < (start.column - 1 + literal_length))
  	return "line is not wide enough";
  
!       char_span literal = line.subspan (start.column - 1, literal_length);
  
        cpp_string from;
        from.len = literal_length;
--- 937,944 ----
        if (line.length () < (start.column - 1 + literal_length))
  	return "line is not wide enough";
  
!       diagnostics::char_span literal
! 	= line.subspan (start.column - 1, literal_length);
  
        cpp_string from;
        from.len = literal_length;
*************** get_substring_ranges_for_loc (cpp_reader
*** 1925,1931 ****
  
  const char *
  get_location_within_string (cpp_reader *pfile,
! 			    file_cache &fc,
  			    string_concat_db *concats,
  			    location_t strloc,
  			    enum cpp_ttype type,
--- 1011,1017 ----
  
  const char *
  get_location_within_string (cpp_reader *pfile,
! 			    diagnostics::file_cache &fc,
  			    string_concat_db *concats,
  			    location_t strloc,
  			    enum cpp_ttype type,
*************** namespace selftest {
*** 2008,2014 ****
  
  static const char *
  get_source_range_for_char (cpp_reader *pfile,
! 			   file_cache &fc,
  			   string_concat_db *concats,
  			   location_t strloc,
  			   enum cpp_ttype type,
--- 1094,1100 ----
  
  static const char *
  get_source_range_for_char (cpp_reader *pfile,
! 			   diagnostics::file_cache &fc,
  			   string_concat_db *concats,
  			   location_t strloc,
  			   enum cpp_ttype type,
*************** get_source_range_for_char (cpp_reader *p
*** 2036,2042 ****
  
  static const char *
  get_num_source_ranges_for_substring (cpp_reader *pfile,
! 				     file_cache &fc,
  				     string_concat_db *concats,
  				     location_t strloc,
  				     enum cpp_ttype type,
--- 1122,1128 ----
  
  static const char *
  get_num_source_ranges_for_substring (cpp_reader *pfile,
! 				     diagnostics::file_cache &fc,
  				     string_concat_db *concats,
  				     location_t strloc,
  				     enum cpp_ttype type,
*************** test_make_location_nonpure_range_endpoin
*** 2359,2477 ****
    ASSERT_FALSE (IS_ADHOC_LOC (get_finish (not_aaa_eq_bbb)));
  }
  
- /* Verify reading of a specific line LINENUM in TMP, FC.  */
- 
- static void
- check_line (temp_source_file &tmp, file_cache &fc, int linenum)
- {
-   char_span line = fc.get_source_line (tmp.get_filename (), linenum);
-   int n;
-   const char *b = line.get_buffer ();
-   size_t l = line.length ();
-   char buf[5];
-   ASSERT_LT (l, 5);
-   memcpy (buf, b, l);
-   buf[l] = '\0';
-   ASSERT_TRUE (sscanf (buf, "%d", &n) == 1);
-   ASSERT_EQ (n, linenum);
- }
- 
- /* Test file cache replacement.  */
- 
- static void
- test_replacement ()
- {
-   const int maxline = 1000;
- 
-   char *vec = XNEWVEC (char, maxline * 5);
-   char *p = vec;
-   int i;
-   for (i = 1; i <= maxline; i++)
-     p += sprintf (p, "%d\n", i);
- 
-   temp_source_file tmp (SELFTEST_LOCATION, ".txt", vec);
-   free (vec);
-   file_cache fc;
- 
-   for (i = 2; i <= maxline; i++)
-     {
-       check_line (tmp, fc, i);
-       check_line (tmp, fc, i - 1);
-       if (i >= 10)
- 	check_line (tmp, fc, i - 9);
-       if (i >= 350) /* Exceed the look behind cache.  */
- 	check_line (tmp, fc, i - 300);
-     }
-   for (i = 5; i <= maxline; i += 100)
-     check_line (tmp, fc, i);
-   for (i = 1; i <= maxline; i++)
-     check_line (tmp, fc, i);
- }
- 
- /* Verify reading of input files (e.g. for caret-based diagnostics).  */
- 
- static void
- test_reading_source_line ()
- {
-   /* Create a tempfile and write some text to it.  */
-   temp_source_file tmp (SELFTEST_LOCATION, ".txt",
- 			"01234567890123456789\n"
- 			"This is the test text\n"
- 			"This is the 3rd line");
-   file_cache fc;
- 
-   /* Read back a specific line from the tempfile.  */
-   char_span source_line = fc.get_source_line (tmp.get_filename (), 3);
-   ASSERT_TRUE (source_line);
-   ASSERT_TRUE (source_line.get_buffer () != NULL);
-   ASSERT_EQ (20, source_line.length ());
-   ASSERT_TRUE (!strncmp ("This is the 3rd line",
- 			 source_line.get_buffer (), source_line.length ()));
- 
-   source_line = fc.get_source_line (tmp.get_filename (), 2);
-   ASSERT_TRUE (source_line);
-   ASSERT_TRUE (source_line.get_buffer () != NULL);
-   ASSERT_EQ (21, source_line.length ());
-   ASSERT_TRUE (!strncmp ("This is the test text",
- 			 source_line.get_buffer (), source_line.length ()));
- 
-   source_line = fc.get_source_line (tmp.get_filename (), 4);
-   ASSERT_FALSE (source_line);
-   ASSERT_TRUE (source_line.get_buffer () == NULL);
- }
- 
- /* Verify reading from buffers (e.g. for sarif-replay).  */
- 
- static void
- test_reading_source_buffer ()
- {
-   const char *text = ("01234567890123456789\n"
- 		      "This is the test text\n"
- 		      "This is the 3rd line");
-   const char *filename = "foo.txt";
-   file_cache fc;
-   fc.add_buffered_content (filename, text, strlen (text));
- 
-   /* Read back a specific line from the tempfile.  */
-   char_span source_line = fc.get_source_line (filename, 3);
-   ASSERT_TRUE (source_line);
-   ASSERT_TRUE (source_line.get_buffer () != NULL);
-   ASSERT_EQ (20, source_line.length ());
-   ASSERT_TRUE (!strncmp ("This is the 3rd line",
- 			 source_line.get_buffer (), source_line.length ()));
- 
-   source_line = fc.get_source_line (filename, 2);
-   ASSERT_TRUE (source_line);
-   ASSERT_TRUE (source_line.get_buffer () != NULL);
-   ASSERT_EQ (21, source_line.length ());
-   ASSERT_TRUE (!strncmp ("This is the test text",
- 			 source_line.get_buffer (), source_line.length ()));
- 
-   source_line = fc.get_source_line (filename, 4);
-   ASSERT_FALSE (source_line);
-   ASSERT_TRUE (source_line.get_buffer () == NULL);
- }
- 
  /* Tests of lexing.  */
  
  /* Verify that token TOK from PARSER has cpp_token_as_text
--- 1445,1450 ----
*************** public:
*** 2628,2634 ****
    line_table_test m_ltt;
    cpp_reader_ptr m_parser;
    temp_source_file m_tempfile;
!   file_cache m_file_cache;
    string_concat_db m_concats;
    bool m_implicitly_expect_EOF;
  };
--- 1601,1607 ----
    line_table_test m_ltt;
    cpp_reader_ptr m_parser;
    temp_source_file m_tempfile;
!   diagnostics::file_cache m_file_cache;
    string_concat_db m_concats;
    bool m_implicitly_expect_EOF;
  };
*************** input_cc_tests ()
*** 4356,4365 ****
    for_each_line_table_case (test_lexer_string_locations_raw_string_unterminated);
    for_each_line_table_case (test_lexer_char_constants);
  
-   test_reading_source_line ();
-   test_reading_source_buffer ();
-   test_replacement ();
- 
    test_line_offset_overflow ();
  
    test_cpp_utf8 ();
--- 3329,3334 ----
diff -Nrcpad gcc-16-20250720/gcc/input.h gcc-16-20250727/gcc/input.h
*** gcc-16-20250720/gcc/input.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/input.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 23,29 ****
  
  #include "line-map.h"
  
! class file_cache;
  
  extern GTY(()) class line_maps *line_table;
  extern GTY(()) class line_maps *saved_line_table;
--- 23,29 ----
  
  #include "line-map.h"
  
! namespace diagnostics { class file_cache; }
  
  extern GTY(()) class line_maps *line_table;
  extern GTY(()) class line_maps *saved_line_table;
*************** extern expanded_location expand_location
*** 69,178 ****
  class cpp_char_column_policy;
  
  extern int
! location_compute_display_column (file_cache &fc,
  				 expanded_location exploc,
  				 const cpp_char_column_policy &policy);
  
- /* A class capturing the bounds of a buffer, to allow for run-time
-    bounds-checking in a checked build.  */
- 
- class char_span
- {
-  public:
-   char_span (const char *ptr, size_t n_elts) : m_ptr (ptr), m_n_elts (n_elts) {}
- 
-   /* Test for a non-NULL pointer.  */
-   operator bool() const { return m_ptr; }
- 
-   /* Get length, not including any 0-terminator (which may not be,
-      in fact, present).  */
-   size_t length () const { return m_n_elts; }
- 
-   const char *get_buffer () const { return m_ptr; }
- 
-   char operator[] (int idx) const
-   {
-     gcc_assert (idx >= 0);
-     gcc_assert ((size_t)idx < m_n_elts);
-     return m_ptr[idx];
-   }
- 
-   char_span subspan (int offset, int n_elts) const
-   {
-     gcc_assert (offset >= 0);
-     gcc_assert (offset < (int)m_n_elts);
-     gcc_assert (n_elts >= 0);
-     gcc_assert (offset + n_elts <= (int)m_n_elts);
-     return char_span (m_ptr + offset, n_elts);
-   }
- 
-   char *xstrdup () const
-   {
-     return ::xstrndup (m_ptr, m_n_elts);
-   }
- 
-  private:
-   const char *m_ptr;
-   size_t m_n_elts;
- };
- 
  extern char *
! get_source_text_between (file_cache &, location_t, location_t);
! 
! /* Forward decl of slot within file_cache, so that the definition doesn't
!    need to be in this header.  */
! class file_cache_slot;
! 
! /* A cache of source files for use when emitting diagnostics
!    (and in a few places in the C/C++ frontends).
! 
!    Results are only valid until the next call to the cache, as
!    slots can be evicted.
! 
!    Filenames are stored by pointer, and so must outlive the cache
!    instance.  */
! 
! class file_cache
! {
!  public:
!   file_cache ();
!   ~file_cache ();
! 
!   void dump (FILE *out, int indent) const;
!   void DEBUG_FUNCTION dump () const;
! 
!   file_cache_slot *lookup_or_add_file (const char *file_path);
!   void forcibly_evict_file (const char *file_path);
! 
!   /* See comments in diagnostic.h about the input conversion context.  */
!   struct input_context
!   {
!     diagnostic_input_charset_callback ccb;
!     bool should_skip_bom;
!   };
!   void initialize_input_context (diagnostic_input_charset_callback ccb,
! 				 bool should_skip_bom);
! 
!   char_span get_source_file_content (const char *file_path);
!   char_span get_source_line (const char *file_path, int line);
!   bool missing_trailing_newline_p (const char *file_path);
! 
!   void add_buffered_content (const char *file_path,
! 			     const char *buffer,
! 			     size_t sz);
! 
!   void tune (size_t num_file_slots, size_t lines);
! 
!  private:
!   file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count);
!   file_cache_slot *add_file (const char *file_path);
!   file_cache_slot *lookup_file (const char *file_path);
! 
!  private:
!   size_t m_num_file_slots;
!   file_cache_slot *m_file_slots;
!   input_context m_input_context;
! };
  
  extern expanded_location
  expand_location_to_spelling_point (location_t,
--- 69,80 ----
  class cpp_char_column_policy;
  
  extern int
! location_compute_display_column (diagnostics::file_cache &fc,
  				 expanded_location exploc,
  				 const cpp_char_column_policy &policy);
  
  extern char *
! get_source_text_between (diagnostics::file_cache &, location_t, location_t);
  
  extern expanded_location
  expand_location_to_spelling_point (location_t,
diff -Nrcpad gcc-16-20250720/gcc/internal-fn.cc gcc-16-20250727/gcc/internal-fn.cc
*** gcc-16-20250720/gcc/internal-fn.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/internal-fn.cc	Sun Jul 27 22:32:09 2025
*************** expand_scatter_store_optab_fn (internal_
*** 3652,3659 ****
    internal_fn ifn = gimple_call_internal_fn (stmt);
    int rhs_index = internal_fn_stored_value_index (ifn);
    tree base = gimple_call_arg (stmt, 0);
!   tree offset = gimple_call_arg (stmt, 1);
!   tree scale = gimple_call_arg (stmt, 2);
    tree rhs = gimple_call_arg (stmt, rhs_index);
  
    rtx base_rtx = expand_normal (base);
--- 3652,3659 ----
    internal_fn ifn = gimple_call_internal_fn (stmt);
    int rhs_index = internal_fn_stored_value_index (ifn);
    tree base = gimple_call_arg (stmt, 0);
!   tree offset = gimple_call_arg (stmt, internal_fn_offset_index (ifn));
!   tree scale = gimple_call_arg (stmt, internal_fn_scale_index (ifn));
    tree rhs = gimple_call_arg (stmt, rhs_index);
  
    rtx base_rtx = expand_normal (base);
*************** expand_scatter_store_optab_fn (internal_
*** 3678,3689 ****
  /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB.  */
  
  static void
! expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
  {
    tree lhs = gimple_call_lhs (stmt);
    tree base = gimple_call_arg (stmt, 0);
!   tree offset = gimple_call_arg (stmt, 1);
!   tree scale = gimple_call_arg (stmt, 2);
  
    rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    rtx base_rtx = expand_normal (base);
--- 3678,3689 ----
  /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB.  */
  
  static void
! expand_gather_load_optab_fn (internal_fn ifn, gcall *stmt, direct_optab optab)
  {
    tree lhs = gimple_call_lhs (stmt);
    tree base = gimple_call_arg (stmt, 0);
!   tree offset = gimple_call_arg (stmt, internal_fn_offset_index (ifn));
!   tree scale = gimple_call_arg (stmt, internal_fn_scale_index (ifn));
  
    rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
    rtx base_rtx = expand_normal (base);
*************** internal_fn_len_index (internal_fn fn)
*** 4967,4977 ****
        return 2;
  
      case IFN_MASK_LEN_SCATTER_STORE:
      case IFN_MASK_LEN_STRIDED_LOAD:
        return 5;
  
      case IFN_MASK_LEN_GATHER_LOAD:
!       return 6;
  
      case IFN_COND_LEN_FMA:
      case IFN_COND_LEN_FMS:
--- 4967,4979 ----
        return 2;
  
      case IFN_MASK_LEN_SCATTER_STORE:
+       return 6;
+ 
      case IFN_MASK_LEN_STRIDED_LOAD:
        return 5;
  
      case IFN_MASK_LEN_GATHER_LOAD:
!       return 7;
  
      case IFN_COND_LEN_FMA:
      case IFN_COND_LEN_FMS:
*************** internal_fn_else_index (internal_fn fn)
*** 5075,5081 ****
  
      case IFN_MASK_GATHER_LOAD:
      case IFN_MASK_LEN_GATHER_LOAD:
!       return 5;
  
      default:
        return -1;
--- 5077,5083 ----
  
      case IFN_MASK_GATHER_LOAD:
      case IFN_MASK_LEN_GATHER_LOAD:
!       return 6;
  
      default:
        return -1;
*************** internal_fn_mask_index (internal_fn fn)
*** 5110,5116 ****
      case IFN_MASK_SCATTER_STORE:
      case IFN_MASK_LEN_GATHER_LOAD:
      case IFN_MASK_LEN_SCATTER_STORE:
!       return 4;
  
      case IFN_VCOND_MASK:
      case IFN_VCOND_MASK_LEN:
--- 5112,5118 ----
      case IFN_MASK_SCATTER_STORE:
      case IFN_MASK_LEN_GATHER_LOAD:
      case IFN_MASK_LEN_SCATTER_STORE:
!       return 5;
  
      case IFN_VCOND_MASK:
      case IFN_VCOND_MASK_LEN:
*************** internal_fn_stored_value_index (internal
*** 5135,5144 ****
  
      case IFN_MASK_STORE:
      case IFN_MASK_STORE_LANES:
      case IFN_SCATTER_STORE:
      case IFN_MASK_SCATTER_STORE:
      case IFN_MASK_LEN_SCATTER_STORE:
!       return 3;
  
      case IFN_LEN_STORE:
        return 4;
--- 5137,5147 ----
  
      case IFN_MASK_STORE:
      case IFN_MASK_STORE_LANES:
+       return 3;
      case IFN_SCATTER_STORE:
      case IFN_MASK_SCATTER_STORE:
      case IFN_MASK_LEN_SCATTER_STORE:
!       return 4;
  
      case IFN_LEN_STORE:
        return 4;
*************** internal_fn_stored_value_index (internal
*** 5152,5157 ****
--- 5155,5229 ----
      }
  }
  
+ /* If FN has an alias pointer return its index, otherwise return -1.  */
+ 
+ int
+ internal_fn_alias_ptr_index (internal_fn fn)
+ {
+   switch (fn)
+     {
+     case IFN_MASK_LOAD:
+     case IFN_MASK_LEN_LOAD:
+     case IFN_GATHER_LOAD:
+     case IFN_MASK_GATHER_LOAD:
+     case IFN_MASK_LEN_GATHER_LOAD:
+     case IFN_SCATTER_STORE:
+     case IFN_MASK_SCATTER_STORE:
+     case IFN_MASK_LEN_SCATTER_STORE:
+       return 1;
+ 
+     default:
+       return -1;
+     }
+ }
+ 
+ /* If FN is a gather/scatter return the index of its offset argument,
+    otherwise return -1.  */
+ 
+ int
+ internal_fn_offset_index (internal_fn fn)
+ {
+   if (!internal_gather_scatter_fn_p (fn))
+     return -1;
+ 
+   switch (fn)
+     {
+     case IFN_GATHER_LOAD:
+     case IFN_MASK_GATHER_LOAD:
+     case IFN_MASK_LEN_GATHER_LOAD:
+     case IFN_SCATTER_STORE:
+     case IFN_MASK_SCATTER_STORE:
+     case IFN_MASK_LEN_SCATTER_STORE:
+       return 2;
+ 
+     default:
+       return -1;
+     }
+ }
+ 
+ /* If FN is a gather/scatter return the index of its scale argument,
+    otherwise return -1.  */
+ 
+ int
+ internal_fn_scale_index (internal_fn fn)
+ {
+   if (!internal_gather_scatter_fn_p (fn))
+     return -1;
+ 
+   switch (fn)
+     {
+     case IFN_GATHER_LOAD:
+     case IFN_MASK_GATHER_LOAD:
+     case IFN_MASK_LEN_GATHER_LOAD:
+     case IFN_SCATTER_STORE:
+     case IFN_MASK_SCATTER_STORE:
+     case IFN_MASK_LEN_SCATTER_STORE:
+       return 3;
+ 
+     default:
+       return -1;
+     }
+ }
  
  /* Store all supported else values for the optab referred to by ICODE
     in ELSE_VALS.  The index of the else operand must be specified in
*************** internal_gather_scatter_fn_supported_p (
*** 5230,5242 ****
      && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
      && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale));
  
-   /* For gather the optab's operand indices do not match the IFN's because
-      the latter does not have the extension operand (operand 3).  It is
-      implicitly added during expansion so we use the IFN's else index + 1.
-      */
    if (ok && elsvals)
      get_supported_else_vals
!       (icode, internal_fn_else_index (IFN_MASK_GATHER_LOAD) + 1, *elsvals);
  
    return ok;
  }
--- 5302,5310 ----
      && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
      && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale));
  
    if (ok && elsvals)
      get_supported_else_vals
!       (icode, internal_fn_else_index (IFN_MASK_GATHER_LOAD), *elsvals);
  
    return ok;
  }
diff -Nrcpad gcc-16-20250720/gcc/internal-fn.h gcc-16-20250727/gcc/internal-fn.h
*** gcc-16-20250720/gcc/internal-fn.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/internal-fn.h	Sun Jul 27 22:32:09 2025
*************** extern int internal_fn_mask_index (inter
*** 240,245 ****
--- 240,248 ----
  extern int internal_fn_len_index (internal_fn);
  extern int internal_fn_else_index (internal_fn);
  extern int internal_fn_stored_value_index (internal_fn);
+ extern int internal_fn_offset_index (internal_fn fn);
+ extern int internal_fn_scale_index (internal_fn fn);
+ extern int internal_fn_alias_ptr_index (internal_fn fn);
  extern bool internal_gather_scatter_fn_supported_p (internal_fn, tree,
  						    tree, tree, int,
  						    vec<int> * = nullptr);
diff -Nrcpad gcc-16-20250720/gcc/ipa-pure-const.cc gcc-16-20250727/gcc/ipa-pure-const.cc
*** gcc-16-20250720/gcc/ipa-pure-const.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/ipa-pure-const.cc	Sun Jul 27 22:32:09 2025
*************** function_always_visible_to_compiler_p (t
*** 200,206 ****
     by the function.  */
  
  static hash_set<tree> *
! suggest_attribute (diagnostic_option_id option, tree decl, bool known_finite,
  		   hash_set<tree> *warned_about,
  		   const char * attrib_name)
  {
--- 200,206 ----
     by the function.  */
  
  static hash_set<tree> *
! suggest_attribute (diagnostics::option_id option, tree decl, bool known_finite,
  		   hash_set<tree> *warned_about,
  		   const char * attrib_name)
  {
diff -Nrcpad gcc-16-20250720/gcc/ira.cc gcc-16-20250727/gcc/ira.cc
*** gcc-16-20250720/gcc/ira.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/ira.cc	Sun Jul 27 22:32:09 2025
*************** ira_get_dup_out_num (int op_num, alterna
*** 2113,2118 ****
--- 2113,2199 ----
  
  
  
+ /* Return true if a replacement of SRC by DEST does not lead to unsatisfiable
+    asm.  A replacement is valid if SRC or DEST are not constrained in asm
+    inputs of a single asm statement.  See match_asm_constraints_2() for more
+    details.  TODO: As in match_asm_constraints_2() consider alternatives more
+    precisely.  */
+ 
+ static bool
+ valid_replacement_for_asm_input_p_1 (const_rtx asmops, const_rtx src, const_rtx dest)
+ {
+   int ninputs = ASM_OPERANDS_INPUT_LENGTH (asmops);
+   rtvec inputs = ASM_OPERANDS_INPUT_VEC (asmops);
+   for (int i = 0; i < ninputs; ++i)
+     {
+       rtx input_src = RTVEC_ELT (inputs, i);
+       const char *constraint_src
+ 	= ASM_OPERANDS_INPUT_CONSTRAINT (asmops, i);
+       if (rtx_equal_p (input_src, src)
+ 	  && strchr (constraint_src, '{') != nullptr)
+ 	for (int j = 0; j < ninputs; ++j)
+ 	  {
+ 	    rtx input_dest = RTVEC_ELT (inputs, j);
+ 	    const char *constraint_dest
+ 	      = ASM_OPERANDS_INPUT_CONSTRAINT (asmops, j);
+ 	    if (rtx_equal_p (input_dest, dest)
+ 		&& strchr (constraint_dest, '{') != nullptr)
+ 	      return false;
+ 	  }
+     }
+   return true;
+ }
+ 
+ /* Return true if a replacement of SRC by DEST does not lead to unsatisfiable
+    asm.  A replacement is valid if SRC or DEST are not constrained in asm
+    inputs of a single asm statement.  The final check is done in function
+    valid_replacement_for_asm_input_p_1.  */
+ 
+ static bool
+ valid_replacement_for_asm_input_p (const_rtx src, const_rtx dest)
+ {
+   /* Bail out early if there is no asm statement.  */
+   if (!crtl->has_asm_statement)
+     return true;
+   for (df_ref use = DF_REG_USE_CHAIN (REGNO (src));
+        use;
+        use = DF_REF_NEXT_REG (use))
+     {
+       struct df_insn_info *use_info = DF_REF_INSN_INFO (use);
+       /* Only check real uses, not artificial ones.  */
+       if (use_info)
+ 	{
+ 	  rtx_insn *insn = DF_REF_INSN (use);
+ 	  rtx pat = PATTERN (insn);
+ 	  if (asm_noperands (pat) <= 0)
+ 	    continue;
+ 	  if (GET_CODE (pat) == SET)
+ 	    {
+ 	      if (!valid_replacement_for_asm_input_p_1 (SET_SRC (pat), src, dest))
+ 		return false;
+ 	    }
+ 	  else if (GET_CODE (pat) == PARALLEL)
+ 	    for (int i = 0, len = XVECLEN (pat, 0); i < len; ++i)
+ 	      {
+ 		rtx asmops = XVECEXP (pat, 0, i);
+ 		if (GET_CODE (asmops) == SET)
+ 		  asmops = SET_SRC (asmops);
+ 		if (GET_CODE (asmops) == ASM_OPERANDS
+ 		    && !valid_replacement_for_asm_input_p_1 (asmops, src, dest))
+ 		  return false;
+ 	      }
+ 	  else if (GET_CODE (pat) == ASM_OPERANDS)
+ 	    {
+ 	      if (!valid_replacement_for_asm_input_p_1 (pat, src, dest))
+ 		return false;
+ 	    }
+ 	  else
+ 	    gcc_unreachable ();
+ 	}
+     }
+   return true;
+ }
+ 
  /* Search forward to see if the source register of a copy insn dies
     before either it or the destination register is modified, but don't
     scan past the end of the basic block.  If so, we can replace the
*************** decrease_live_ranges_number (void)
*** 2162,2168 ****
  	       auto-inc memory reference, so we must disallow this
  	       optimization on them.  */
  	    || sregno == STACK_POINTER_REGNUM
! 	    || dregno == STACK_POINTER_REGNUM)
  	  continue;
  
  	dest_death = NULL_RTX;
--- 2243,2250 ----
  	       auto-inc memory reference, so we must disallow this
  	       optimization on them.  */
  	    || sregno == STACK_POINTER_REGNUM
! 	    || dregno == STACK_POINTER_REGNUM
! 	    || !valid_replacement_for_asm_input_p (src, dest))
  	  continue;
  
  	dest_death = NULL_RTX;
diff -Nrcpad gcc-16-20250720/gcc/jit/ChangeLog gcc-16-20250727/gcc/jit/ChangeLog
*** gcc-16-20250720/gcc/jit/ChangeLog	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/jit/ChangeLog	Sun Jul 27 22:32:09 2025
***************
*** 1,3 ****
--- 1,30 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* dummy-frontend.cc: Update usage of "diagnostic_info" to
+ 	explicitly refer to "diagnostics::diagnostic_info".
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* dummy-frontend.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* dummy-frontend.cc: Update for diagnostic_context becoming
+ 	diagnostics::context.
+ 	* jit-playback.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* jit-playback.cc: Update for diagnostic_info moving into
+ 	namespace diagnostics.
+ 	* jit-playback.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* dummy-frontend.cc: Update for move of diagnostics output formats
+ 	into namespace "diagnostics" as "sinks".
+ 
  2025-04-28  David Malcolm  <dmalcolm@redhat.com>
  
  	* dummy-frontend.cc: Drop include of "make-unique.h".
diff -Nrcpad gcc-16-20250720/gcc/jit/dummy-frontend.cc gcc-16-20250727/gcc/jit/dummy-frontend.cc
*** gcc-16-20250720/gcc/jit/dummy-frontend.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/jit/dummy-frontend.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 32,38 ****
  #include "attribs.h"
  #include "cgraph.h"
  #include "target.h"
! #include "diagnostic-format-text.h"
  #include "print-tree.h"
  
  #include <mpfr.h>
--- 32,38 ----
  #include "attribs.h"
  #include "cgraph.h"
  #include "target.h"
! #include "diagnostics/text-sink.h"
  #include "print-tree.h"
  
  #include <mpfr.h>
*************** struct ggc_root_tab jit_root_tab[] =
*** 993,1008 ****
      LAST_GGC_ROOT_TAB
    };
  
! /* Subclass of diagnostic_output_format for libgccjit: like text
     output, but capture the message and call add_diagnostic with it
     on the active playback context.  */
  
! class jit_diagnostic_listener : public diagnostic_text_output_format
  {
  public:
!   jit_diagnostic_listener (diagnostic_context &dc,
  			   gcc::jit::playback::context &playback_ctxt)
!   : diagnostic_text_output_format (dc),
      m_playback_ctxt (playback_ctxt)
    {
    }
--- 993,1008 ----
      LAST_GGC_ROOT_TAB
    };
  
! /* Subclass of diagnostics::text_sink for libgccjit: like text
     output, but capture the message and call add_diagnostic with it
     on the active playback context.  */
  
! class jit_diagnostic_listener : public diagnostics::text_sink
  {
  public:
!   jit_diagnostic_listener (diagnostics::context &dc,
  			   gcc::jit::playback::context &playback_ctxt)
!   : diagnostics::text_sink (dc),
      m_playback_ctxt (playback_ctxt)
    {
    }
*************** public:
*** 1015,1027 ****
  	     (void *)&m_playback_ctxt);
    }
  
!   void on_report_diagnostic (const diagnostic_info &info,
! 			     diagnostic_t orig_diag_kind) final override
    {
      JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
  
      /* Let the text output format do most of the work.  */
!     diagnostic_text_output_format::on_report_diagnostic (info, orig_diag_kind);
  
      const char *text = pp_formatted_text (get_printer ());
  
--- 1015,1027 ----
  	     (void *)&m_playback_ctxt);
    }
  
!   void on_report_diagnostic (const diagnostics::diagnostic_info &info,
! 			     enum diagnostics::kind orig_diag_kind) final override
    {
      JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
  
      /* Let the text output format do most of the work.  */
!     diagnostics::text_sink::on_report_diagnostic (info, orig_diag_kind);
  
      const char *text = pp_formatted_text (get_printer ());
  
*************** private:
*** 1041,1048 ****
  /* Implementation of "begin_diagnostic".  */
  
  static void
! jit_begin_diagnostic (diagnostic_text_output_format &,
! 		      const diagnostic_info */*diagnostic*/)
  {
    gcc_assert (gcc::jit::active_playback_ctxt);
    JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
--- 1041,1048 ----
  /* Implementation of "begin_diagnostic".  */
  
  static void
! jit_begin_diagnostic (diagnostics::text_sink &,
! 		      const diagnostics::diagnostic_info */*diagnostic*/)
  {
    gcc_assert (gcc::jit::active_playback_ctxt);
    JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
*************** jit_begin_diagnostic (diagnostic_text_ou
*** 1054,1062 ****
  /* Implementation of "end_diagnostic".  */
  
  static void
! jit_end_diagnostic (diagnostic_text_output_format &,
! 		    const diagnostic_info *,
! 		    diagnostic_t)
  {
    gcc_assert (gcc::jit::active_playback_ctxt);
    JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
--- 1054,1062 ----
  /* Implementation of "end_diagnostic".  */
  
  static void
! jit_end_diagnostic (diagnostics::text_sink &,
! 		    const diagnostics::diagnostic_info *,
! 		    enum diagnostics::kind)
  {
    gcc_assert (gcc::jit::active_playback_ctxt);
    JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
*************** jit_langhook_init (void)
*** 1081,1093 ****
      }
  
    gcc_assert (global_dc);
!   diagnostic_text_starter (global_dc) = jit_begin_diagnostic;
!   diagnostic_text_finalizer (global_dc) = jit_end_diagnostic;
    auto sink
      = std::make_unique<jit_diagnostic_listener>
  	(*global_dc,
  	 *gcc::jit::active_playback_ctxt);
!   global_dc->set_output_format (std::move (sink));
  
    build_common_tree_nodes (flag_signed_char);
  
--- 1081,1093 ----
      }
  
    gcc_assert (global_dc);
!   diagnostics::text_starter (global_dc) = jit_begin_diagnostic;
!   diagnostics::text_finalizer (global_dc) = jit_end_diagnostic;
    auto sink
      = std::make_unique<jit_diagnostic_listener>
  	(*global_dc,
  	 *gcc::jit::active_playback_ctxt);
!   global_dc->set_sink (std::move (sink));
  
    build_common_tree_nodes (flag_signed_char);
  
diff -Nrcpad gcc-16-20250720/gcc/jit/jit-playback.cc gcc-16-20250727/gcc/jit/jit-playback.cc
*** gcc-16-20250720/gcc/jit/jit-playback.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/jit/jit-playback.cc	Sun Jul 27 22:32:09 2025
*************** add_error_va (location *loc, const char
*** 3892,3898 ****
  void
  playback::context::
  add_diagnostic (const char *text,
! 		const diagnostic_info &diagnostic)
  {
    /* Get location information (if any) from the diagnostic.
       The recording::context::add_error[_va] methods require a
--- 3892,3898 ----
  void
  playback::context::
  add_diagnostic (const char *text,
! 		const diagnostics::diagnostic_info &diagnostic)
  {
    /* Get location information (if any) from the diagnostic.
       The recording::context::add_error[_va] methods require a
diff -Nrcpad gcc-16-20250720/gcc/jit/jit-playback.h gcc-16-20250727/gcc/jit/jit-playback.h
*** gcc-16-20250720/gcc/jit/jit-playback.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/jit/jit-playback.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 30,37 ****
  
  #include "jit-recording.h"
  
! class diagnostic_context;
! struct diagnostic_info;
  
  namespace gcc {
  
--- 30,40 ----
  
  #include "jit-recording.h"
  
! namespace diagnostics
! {
!   class context;
!   struct diagnostic_info;
! }
  
  namespace gcc {
  
*************** public:
*** 298,304 ****
  
    void
    add_diagnostic (const char *text,
! 		  const diagnostic_info &diagnostic);
  
    void
    set_tree_location (tree t, location *loc);
--- 301,307 ----
  
    void
    add_diagnostic (const char *text,
! 		  const diagnostics::diagnostic_info &diagnostic);
  
    void
    set_tree_location (tree t, location *loc);
diff -Nrcpad gcc-16-20250720/gcc/langhooks-def.h gcc-16-20250727/gcc/langhooks-def.h
*** gcc-16-20250720/gcc/langhooks-def.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/langhooks-def.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 23,29 ****
  
  #include "hooks.h"
  
! struct diagnostic_info;
  class substring_loc;
  
  /* Note to creators of new hooks:
--- 23,29 ----
  
  #include "hooks.h"
  
! namespace diagnostics { struct diagnostic_info; }
  class substring_loc;
  
  /* Note to creators of new hooks:
*************** extern void lhd_print_tree_nothing (FILE
*** 49,57 ****
  extern const char *lhd_decl_printable_name (tree, int);
  extern const char *lhd_dwarf_name (tree, int);
  extern int lhd_types_compatible_p (tree, tree);
! extern void lhd_print_error_function (diagnostic_text_output_format &,
  				      const char *,
! 				      const struct diagnostic_info *);
  extern void lhd_set_decl_assembler_name (tree decl);
  extern void lhd_overwrite_decl_assembler_name (tree decl, tree name);
  extern bool lhd_warn_unused_global_decl (const_tree);
--- 49,57 ----
  extern const char *lhd_decl_printable_name (tree, int);
  extern const char *lhd_dwarf_name (tree, int);
  extern int lhd_types_compatible_p (tree, tree);
! extern void lhd_print_error_function (diagnostics::text_sink &,
  				      const char *,
! 				      const diagnostics::diagnostic_info *);
  extern void lhd_set_decl_assembler_name (tree decl);
  extern void lhd_overwrite_decl_assembler_name (tree decl, tree name);
  extern bool lhd_warn_unused_global_decl (const_tree);
*************** extern tree lhd_builtin_function (tree);
*** 71,77 ****
  extern tree lhd_enum_underlying_base_type (const_tree);
  
  /* Declarations of default tree inlining hooks.  */
! extern void lhd_initialize_diagnostics (diagnostic_context *);
  extern void lhd_init_options (unsigned int,
  			      struct cl_decoded_option *);
  extern bool lhd_complain_wrong_lang_p (const struct cl_option *);
--- 71,77 ----
  extern tree lhd_enum_underlying_base_type (const_tree);
  
  /* Declarations of default tree inlining hooks.  */
! extern void lhd_initialize_diagnostics (diagnostics::context *);
  extern void lhd_init_options (unsigned int,
  			      struct cl_decoded_option *);
  extern bool lhd_complain_wrong_lang_p (const struct cl_option *);
diff -Nrcpad gcc-16-20250720/gcc/langhooks.cc gcc-16-20250727/gcc/langhooks.cc
*** gcc-16-20250720/gcc/langhooks.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/langhooks.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 38,44 ****
  #include "stor-layout.h"
  #include "cgraph.h"
  #include "debug.h"
! #include "diagnostic-format-text.h"
  
  /* Do nothing; in many cases the default hook.  */
  
--- 38,44 ----
  #include "stor-layout.h"
  #include "cgraph.h"
  #include "debug.h"
! #include "diagnostics/text-sink.h"
  
  /* Do nothing; in many cases the default hook.  */
  
*************** global_decl_processing (void)
*** 330,336 ****
  
  /* Called to perform language-specific initialization of CTX.  */
  void
! lhd_initialize_diagnostics (diagnostic_context *ctx ATTRIBUTE_UNUSED)
  {
  }
  
--- 330,336 ----
  
  /* Called to perform language-specific initialization of CTX.  */
  void
! lhd_initialize_diagnostics (diagnostics::context *ctx ATTRIBUTE_UNUSED)
  {
  }
  
*************** lhd_handle_option (size_t code ATTRIBUTE
*** 369,379 ****
  /* The default function to print out name of current function that caused
     an error.  */
  void
! lhd_print_error_function (diagnostic_text_output_format &text_output,
  			  const char *file,
! 			  const diagnostic_info *diagnostic)
  {
!   diagnostic_context *const context = &text_output.get_context ();
    if (diagnostic_last_function_changed (context, diagnostic))
      {
        pretty_printer *const pp = text_output.get_printer ();
--- 369,379 ----
  /* The default function to print out name of current function that caused
     an error.  */
  void
! lhd_print_error_function (diagnostics::text_sink &text_output,
  			  const char *file,
! 			  const diagnostics::diagnostic_info *diagnostic)
  {
!   diagnostics::context *const context = &text_output.get_context ();
    if (diagnostic_last_function_changed (context, diagnostic))
      {
        pretty_printer *const pp = text_output.get_printer ();
diff -Nrcpad gcc-16-20250720/gcc/langhooks.h gcc-16-20250727/gcc/langhooks.h
*** gcc-16-20250720/gcc/langhooks.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/langhooks.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 22,28 ****
  
  /* FIXME: This file should be #include-d after tree.h (for enum tree_code).  */
  
! struct diagnostic_info;
  
  struct gimplify_omp_ctx;
  
--- 22,28 ----
  
  /* FIXME: This file should be #include-d after tree.h (for enum tree_code).  */
  
! namespace diagnostics { struct diagnostic_info; }
  
  struct gimplify_omp_ctx;
  
*************** struct lang_hooks
*** 421,427 ****
  
    /* Callback used to perform language-specific initialization for the
       global diagnostic context structure.  */
!   void (*initialize_diagnostics) (diagnostic_context *);
  
    /* Beginning the main source file.  */
    void (*preprocess_main_file) (cpp_reader *, line_maps *,
--- 421,427 ----
  
    /* Callback used to perform language-specific initialization for the
       global diagnostic context structure.  */
!   void (*initialize_diagnostics) (diagnostics::context *);
  
    /* Beginning the main source file.  */
    void (*preprocess_main_file) (cpp_reader *, line_maps *,
*************** struct lang_hooks
*** 547,555 ****
  
    /* Called by diagnostic_report_current_function to print out function name
       for textual diagnostic output.  */
!   void (*print_error_function) (diagnostic_text_output_format &,
  				const char *,
! 				const struct diagnostic_info *);
  
    /* Convert a character from the host's to the target's character
       set.  The character should be in what C calls the "basic source
--- 547,555 ----
  
    /* Called by diagnostic_report_current_function to print out function name
       for textual diagnostic output.  */
!   void (*print_error_function) (diagnostics::text_sink &,
  				const char *,
! 				const diagnostics::diagnostic_info *);
  
    /* Convert a character from the host's to the target's character
       set.  The character should be in what C calls the "basic source
diff -Nrcpad gcc-16-20250720/gcc/lazily-created.h gcc-16-20250727/gcc/lazily-created.h
*** gcc-16-20250720/gcc/lazily-created.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/lazily-created.h	Sun Jul 27 22:32:09 2025
***************
*** 0 ****
--- 1,51 ----
+ /* Template for deferring object creation until the object is needed.
+    Copyright (C) 2024-2025 Free Software Foundation, Inc.
+    Contributed by David Malcolm <dmalcolm@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_LAZILY_CREATED_H
+ #define GCC_LAZILY_CREATED_H
+ 
+ /* A template for deferring object creation for a type T until the object
+    is needed, to avoid potentially expensive creation of T unless it's
+    actually needed (e.g. for directed graphs associated with a diagnostic,
+    which are ignored by the default "text" sink).  */
+ 
+ template <typename T>
+ class lazily_created
+ {
+  public:
+   virtual ~lazily_created () {}
+ 
+   const T &
+   get_or_create () const
+   {
+     if (!m_object)
+       m_object = create_object ();
+     gcc_assert (m_object);
+     return *m_object;
+   }
+ 
+ private:
+   virtual std::unique_ptr<T>
+   create_object () const = 0;
+ 
+   mutable std::unique_ptr<T> m_object;
+ };
+ 
+ #endif /* ! GCC_LAZILY_CREATED_H */
diff -Nrcpad gcc-16-20250720/gcc/lazy-diagnostic-path.cc gcc-16-20250727/gcc/lazy-diagnostic-path.cc
*** gcc-16-20250720/gcc/lazy-diagnostic-path.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/lazy-diagnostic-path.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,237 ****
- /* Helper class for deferring path creation until a diagnostic is emitted.
-    Copyright (C) 2019-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- 
- #include "config.h"
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "tree.h"
- #include "version.h"
- #include "intl.h"
- #include "diagnostic.h"
- #include "lazy-diagnostic-path.h"
- #include "selftest.h"
- #include "selftest-diagnostic.h"
- #include "simple-diagnostic-path.h"
- #include "gcc-rich-location.h"
- #include "diagnostic-format-text.h"
- 
- /* class lazy_diagnostic_path : public diagnostic_path.  */
- 
- /* Implementation of diagnostic_path vfuncs in terms of a lazily-generated
-    path.  */
- 
- unsigned
- lazy_diagnostic_path::num_events () const
- {
-   lazily_generate_path ();
-   return m_inner_path->num_events ();
- }
- 
- const diagnostic_event &
- lazy_diagnostic_path::get_event (int idx) const
- {
-   lazily_generate_path ();
-   return m_inner_path->get_event (idx);
- }
- 
- unsigned
- lazy_diagnostic_path::num_threads () const
- {
-   lazily_generate_path ();
-   return m_inner_path->num_threads ();
- }
- 
- const diagnostic_thread &
- lazy_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
- {
-   lazily_generate_path ();
-   return m_inner_path->get_thread (idx);
- }
- 
- bool
- lazy_diagnostic_path::same_function_p (int event_idx_a,
- 					   int event_idx_b) const
- {
-   lazily_generate_path ();
-   return m_inner_path->same_function_p (event_idx_a, event_idx_b);
- }
- 
- void
- lazy_diagnostic_path::lazily_generate_path () const
- {
-   if (!m_inner_path)
-     m_inner_path = make_inner_path ();
-   gcc_assert (m_inner_path != nullptr);
- }
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- class test_lazy_path : public lazy_diagnostic_path
- {
- public:
-   test_lazy_path (pretty_printer &pp)
-   : lazy_diagnostic_path (m_logical_loc_mgr),
-     m_pp (pp)
-   {
-   }
-   std::unique_ptr<diagnostic_path> make_inner_path () const final override
-   {
-     tree fntype_void_void
-       = build_function_type_array (void_type_node, 0, nullptr);
-     tree fndecl_foo = build_fn_decl ("foo", fntype_void_void);
-     auto path
-       = std::make_unique<simple_diagnostic_path> (m_logical_loc_mgr,
- 						  &m_pp);
-     path->add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "first %qs", "free");
-     path->add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "double %qs", "free");
-     return path;
-   }
- private:
-   const tree_logical_location_manager m_logical_loc_mgr;
-   pretty_printer &m_pp;
- };
- 
- static void
- test_intraprocedural_path (pretty_printer *event_pp)
- {
-   test_lazy_path path (*event_pp);
-   ASSERT_FALSE (path.generated_p ());
-   ASSERT_EQ (path.num_events (), 2);
-   ASSERT_TRUE (path.generated_p ());
-   ASSERT_EQ (path.num_threads (), 1);
-   ASSERT_FALSE (path.interprocedural_p ());
-   ASSERT_STREQ (path.get_event (0).get_desc (*event_pp).get (),
- 		"first `free'");
-   ASSERT_STREQ (path.get_event (1).get_desc (*event_pp).get (),
- 		"double `free'");
- }
- 
- /* Implementation of diagnostic_option_manager for which all
-    options are disabled, for use in selftests.
-    Note that this is *not* called for diagnostic_option_id (0), which
-    means "always warn"  */
- 
- class all_warnings_disabled : public diagnostic_option_manager
- {
- public:
-   int option_enabled_p (diagnostic_option_id) const final override
-   {
-     /* Treat all options as disabled.  */
-     return 0;
-   }
-   char *make_option_name (diagnostic_option_id,
- 			  diagnostic_t,
- 			  diagnostic_t) const final override
-   {
-     return nullptr;
-   }
-   char *make_option_url (diagnostic_option_id) const final override
-   {
-     return nullptr;
-   }
- };
- 
- static void
- test_emission (pretty_printer *event_pp)
- {
-   struct test_rich_location : public gcc_rich_location
-   {
-     test_rich_location (pretty_printer &event_pp)
-     : gcc_rich_location (UNKNOWN_LOCATION),
-       m_path (event_pp)
-     {
-       set_path (&m_path);
-     }
-     test_lazy_path m_path;
-   };
- 
-   /* Verify that we don't bother generating the inner path if the warning
-      is skipped.  */
-   {
-     test_diagnostic_context dc;
-     dc.set_option_manager (std::make_unique<all_warnings_disabled> (), 0);
- 
-     test_rich_location rich_loc (*event_pp);
-     ASSERT_FALSE (rich_loc.m_path.generated_p ());
- 
-     diagnostic_option_id option_id (42); // has to be non-zero
-     bool emitted
-       = dc.emit_diagnostic_with_group (DK_WARNING, rich_loc, nullptr,
- 				       option_id,
- 				       "this warning should be skipped");
-     ASSERT_FALSE (emitted);
-     ASSERT_FALSE (rich_loc.m_path.generated_p ());
-   }
- 
-   /* Verify that we *do* generate the inner path for a diagnostic that
-      is emitted, such as an error.  */
-   {
-     test_diagnostic_context dc;
- 
-     test_rich_location rich_loc (*event_pp);
-     ASSERT_FALSE (rich_loc.m_path.generated_p ());
- 
-     bool emitted
-       = dc.emit_diagnostic_with_group (DK_ERROR, rich_loc, nullptr, 0,
- 				       "this is a test");
-     ASSERT_TRUE (emitted);
-     ASSERT_TRUE (rich_loc.m_path.generated_p ());
- 
-     /* Verify that the path works as expected.  */
-     dc.set_path_format (DPF_INLINE_EVENTS);
-     diagnostic_text_output_format sink (dc);
-     pp_buffer (sink.get_printer ())->m_flush_p = false;
-     sink.print_path (rich_loc.m_path);
-     ASSERT_STREQ (pp_formatted_text (sink.get_printer ()),
- 		  "  `foo': event 1\n"
- 		  " (1): first `free'\n"
- 		  "  `foo': event 2\n"
- 		  " (2): double `free'\n");
-   }
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- lazy_diagnostic_path_cc_tests ()
- {
-   /* In a few places we use the global dc's printer to determine
-      colorization so ensure this off during the tests.  */
-   pretty_printer *global_pp = global_dc->get_reference_printer ();
-   const bool saved_show_color = pp_show_color (global_pp);
-   pp_show_color (global_pp) = false;
- 
-   auto_fix_quotes fix_quotes;
-   std::unique_ptr<pretty_printer> event_pp
-     = std::unique_ptr<pretty_printer> (global_pp->clone ());
- 
-   test_intraprocedural_path (event_pp.get ());
-   test_emission (event_pp.get ());
- 
-   pp_show_color (global_pp) = saved_show_color;
- }
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/lazy-diagnostic-path.h gcc-16-20250727/gcc/lazy-diagnostic-path.h
*** gcc-16-20250720/gcc/lazy-diagnostic-path.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/lazy-diagnostic-path.h	Thu Jan  1 00:00:00 1970
***************
*** 1,64 ****
- /* Helper class for deferring path creation until a diagnostic is emitted.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_LAZY_DIAGNOSTIC_PATH_H
- #define GCC_LAZY_DIAGNOSTIC_PATH_H
- 
- #include "diagnostic-path.h"
- 
- /* An implementation of diagnostic_path which has a trivial ctor
-    and lazily creates another diagnostic_path the first time the path
-    is queried, deferring to this inner path for all queries.
- 
-    Use this to avoid expensive path creation logic when creating
-    rich_location instances, so that expense can be deferred until the path
-    is actually used by a diagnostic, and thus avoided for warnings that
-    are disabled.  */
- 
- class lazy_diagnostic_path : public diagnostic_path
- {
-  public:
-   virtual ~lazy_diagnostic_path () {}
- 
-   unsigned num_events () const final override;
-   const diagnostic_event & get_event (int idx) const final override;
-   unsigned num_threads () const final override;
-   const diagnostic_thread &
-   get_thread (diagnostic_thread_id_t) const final override;
-   bool
-   same_function_p (int event_idx_a,
- 		   int event_idx_b) const final override;
- 
-   bool generated_p () const { return m_inner_path != nullptr; }
- 
- protected:
-   lazy_diagnostic_path (const logical_location_manager &logical_loc_mgr)
-   : diagnostic_path (logical_loc_mgr)
-   {
-   }
- 
-  private:
-   void lazily_generate_path () const;
-   virtual std::unique_ptr<diagnostic_path> make_inner_path () const = 0;
- 
-   mutable std::unique_ptr<diagnostic_path> m_inner_path;
- };
- 
- #endif /* ! GCC_LAZY_DIAGNOSTIC_PATH_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/libgdiagnostics.cc gcc-16-20250727/gcc/libgdiagnostics.cc
*** gcc-16-20250720/gcc/libgdiagnostics.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/libgdiagnostics.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 25,42 ****
  #include "coretypes.h"
  #include "intl.h"
  #include "diagnostic.h"
! #include "diagnostic-color.h"
! #include "diagnostic-url.h"
! #include "diagnostic-metadata.h"
! #include "diagnostic-path.h"
! #include "diagnostic-client-data-hooks.h"
! #include "diagnostic-format-sarif.h"
! #include "diagnostic-format-text.h"
! #include "diagnostic-output-spec.h"
! #include "diagnostic-digraphs.h"
! #include "diagnostic-state-graphs.h"
! #include "logical-location.h"
! #include "edit-context.h"
  #include "libgdiagnostics.h"
  #include "libgdiagnostics-private.h"
  #include "pretty-print-format-impl.h"
--- 25,43 ----
  #include "coretypes.h"
  #include "intl.h"
  #include "diagnostic.h"
! #include "diagnostics/color.h"
! #include "diagnostics/file-cache.h"
! #include "diagnostics/url.h"
! #include "diagnostics/metadata.h"
! #include "diagnostics/paths.h"
! #include "diagnostics/client-data-hooks.h"
! #include "diagnostics/sarif-sink.h"
! #include "diagnostics/text-sink.h"
! #include "diagnostics/output-spec.h"
! #include "diagnostics/digraphs.h"
! #include "diagnostics/state-graphs.h"
! #include "diagnostics/logical-locations.h"
! #include "diagnostics/changes.h"
  #include "libgdiagnostics.h"
  #include "libgdiagnostics-private.h"
  #include "pretty-print-format-impl.h"
*************** struct diagnostic_logical_location
*** 210,216 ****
  };
  
  static diagnostic_event_id
! as_diagnostic_event_id (diagnostic_event_id_t id)
  {
    return id.zero_based ();
  }
--- 211,217 ----
  };
  
  static diagnostic_event_id
! as_diagnostic_event_id (diagnostics::paths::event_id_t id)
  {
    return id.zero_based ();
  }
*************** public:
*** 232,238 ****
  			FILE *dst_stream,
  			enum diagnostic_colorize colorize);
  
!   diagnostic_source_printing_options &get_source_printing_options ()
    {
      return m_source_printing;
    }
--- 233,239 ----
  			FILE *dst_stream,
  			enum diagnostic_colorize colorize);
  
!   diagnostics::source_printing_options &get_source_printing_options ()
    {
      return m_source_printing;
    }
*************** public:
*** 241,252 ****
    set_colorize (enum diagnostic_colorize colorize);
  
    static void
!   text_starter (diagnostic_text_output_format &text_output,
! 		const diagnostic_info *diagnostic);
  
  private:
!   diagnostic_text_output_format *m_inner_sink; // borrowed from dc
!   diagnostic_source_printing_options m_source_printing;
  };
  
  /* A token_printer that makes a deep copy of the pp_token_list
--- 242,253 ----
    set_colorize (enum diagnostic_colorize colorize);
  
    static void
!   text_starter (diagnostics::text_sink &text_output,
! 		const diagnostics::diagnostic_info *diagnostic);
  
  private:
!   diagnostics::text_sink *m_inner_sink; // borrowed from dc
!   diagnostics::source_printing_options m_source_printing;
  };
  
  /* A token_printer that makes a deep copy of the pp_token_list
*************** public:
*** 346,352 ****
    sarif_sink (diagnostic_manager &mgr,
  	      FILE *dst_stream,
  	      const diagnostic_file *main_input_file,
! 	      const sarif_generation_options &sarif_gen_opts);
  };
  
  struct diagnostic_message_buffer
--- 347,353 ----
    sarif_sink (diagnostic_manager &mgr,
  	      FILE *dst_stream,
  	      const diagnostic_file *main_input_file,
! 	      const diagnostics::sarif_generation_options &sarif_gen_opts);
  };
  
  struct diagnostic_message_buffer
*************** round_alloc_size (size_t s)
*** 458,476 ****
    return s;
  }
  
! class impl_logical_location_manager : public logical_location_manager
  {
  public:
    static const diagnostic_logical_location *
!   ptr_from_key (logical_location k)
    {
      return k.cast_to<const diagnostic_logical_location *> ();
    }
  
!   static logical_location
    key_from_ptr (const diagnostic_logical_location *ptr)
    {
!     return logical_location::from_ptr (ptr);
    }
  
    const char *get_short_name (key k) const final override
--- 459,481 ----
    return s;
  }
  
! class impl_logical_location_manager
!   : public diagnostics::logical_locations::manager
  {
  public:
+   using key = diagnostics::logical_locations::key;
+   using kind = diagnostics::logical_locations::kind;
+ 
    static const diagnostic_logical_location *
!   ptr_from_key (key k)
    {
      return k.cast_to<const diagnostic_logical_location *> ();
    }
  
!   static key
    key_from_ptr (const diagnostic_logical_location *ptr)
    {
!     return key::from_ptr (ptr);
    }
  
    const char *get_short_name (key k) const final override
*************** public:
*** 497,503 ****
        return nullptr;
    }
  
!   enum logical_location_kind get_kind (key k) const final override
    {
      auto loc = ptr_from_key (k);
      gcc_assert (loc);
--- 502,508 ----
        return nullptr;
    }
  
!   kind get_kind (key k) const final override
    {
      auto loc = ptr_from_key (k);
      gcc_assert (loc);
*************** public:
*** 507,551 ****
  	gcc_unreachable ();
  
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION:
! 	return logical_location_kind::function;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER:
! 	return logical_location_kind::member;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE:
! 	return logical_location_kind::module_;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE:
! 	return logical_location_kind::namespace_;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE:
! 	return logical_location_kind::type;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE:
! 	return logical_location_kind::return_type;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER:
! 	return logical_location_kind::parameter;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE:
! 	return logical_location_kind::variable;
  
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT:
! 	return logical_location_kind::element;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE:
! 	return logical_location_kind::attribute;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT:
! 	return logical_location_kind::text;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT:
! 	return logical_location_kind::comment;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION:
! 	return logical_location_kind::processing_instruction;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD:
! 	return logical_location_kind::dtd;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION:
! 	return logical_location_kind::declaration;
  
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT:
! 	  return logical_location_kind::object;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY:
! 	return logical_location_kind::array;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY:
! 	return logical_location_kind::property;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE:
! 	return logical_location_kind::value;
        }
    }
  
--- 512,556 ----
  	gcc_unreachable ();
  
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION:
! 	return kind::function;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER:
! 	return kind::member;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE:
! 	return kind::module_;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE:
! 	return kind::namespace_;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE:
! 	return kind::type;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE:
! 	return kind::return_type;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER:
! 	return kind::parameter;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE:
! 	return kind::variable;
  
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT:
! 	return kind::element;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE:
! 	return kind::attribute;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT:
! 	return kind::text;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT:
! 	return kind::comment;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION:
! 	return kind::processing_instruction;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD:
! 	return kind::dtd;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION:
! 	return kind::declaration;
  
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT:
! 	  return kind::object;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY:
! 	return kind::array;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY:
! 	return kind::property;
        case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE:
! 	return kind::value;
        }
    }
  
*************** public:
*** 564,588 ****
    }
  };
  
! class impl_diagnostic_client_data_hooks : public diagnostic_client_data_hooks
  {
  public:
    impl_diagnostic_client_data_hooks (diagnostic_manager &mgr)
    : m_mgr (mgr)
    {}
  
!   const client_version_info *get_any_version_info () const final override;
  
!   const logical_location_manager *
    get_logical_location_manager () const final override
    {
      return &m_logical_location_manager;
    }
!   logical_location get_current_logical_location () const final override;
  
    const char * maybe_get_sarif_source_language (const char *filename)
      const final override;
!   void add_sarif_invocation_properties (sarif_object &invocation_obj)
      const final override;
  
  private:
--- 569,596 ----
    }
  };
  
! class impl_diagnostic_client_data_hooks : public diagnostics::client_data_hooks
  {
  public:
    impl_diagnostic_client_data_hooks (diagnostic_manager &mgr)
    : m_mgr (mgr)
    {}
  
!   const diagnostics::client_version_info *
!   get_any_version_info () const final override;
  
!   const diagnostics::logical_locations::manager *
    get_logical_location_manager () const final override
    {
      return &m_logical_location_manager;
    }
!   diagnostics::logical_locations::key
!   get_current_logical_location () const final override;
  
    const char * maybe_get_sarif_source_language (const char *filename)
      const final override;
!   void
!   add_sarif_invocation_properties (diagnostics::sarif_object &invocation_obj)
      const final override;
  
  private:
*************** private:
*** 590,596 ****
    impl_logical_location_manager m_logical_location_manager;
  };
  
! class impl_client_version_info : public client_version_info
  {
  public:
    const char *get_tool_name () const final override
--- 598,604 ----
    impl_logical_location_manager m_logical_location_manager;
  };
  
! class impl_client_version_info : public diagnostics::client_version_info
  {
  public:
    const char *get_tool_name () const final override
*************** public:
*** 649,671 ****
      m_dc.set_show_cwe (true);
      m_dc.set_show_rules (true);
      m_dc.m_show_column = true;
!     m_dc.m_source_printing.enabled = true;
!     m_dc.m_source_printing.colorize_source_p = true;
  
      /* We don't currently expose a way for clients to manipulate the
         following.  */
!     m_dc.m_source_printing.show_labels_p = true;
!     m_dc.m_source_printing.show_line_numbers_p = true;
!     m_dc.m_source_printing.min_margin_width = 6;
      m_dc.set_path_format (DPF_INLINE_EVENTS);
  
      m_dc.m_client_aux_data = this;
      m_dc.set_client_data_hooks
        (std::make_unique<impl_diagnostic_client_data_hooks> (*this));
  
!     diagnostic_text_starter (&m_dc) = diagnostic_text_sink::text_starter;
  
!     m_edit_context = std::make_unique <edit_context> (m_dc.get_file_cache ());
    }
  
    ~diagnostic_manager ()
--- 657,682 ----
      m_dc.set_show_cwe (true);
      m_dc.set_show_rules (true);
      m_dc.m_show_column = true;
!     auto &source_printing_opts = m_dc.get_source_printing_options ();
!     source_printing_opts.enabled = true;
!     source_printing_opts.colorize_source_p = true;
  
      /* We don't currently expose a way for clients to manipulate the
         following.  */
!     source_printing_opts.show_labels_p = true;
!     source_printing_opts.show_line_numbers_p = true;
!     source_printing_opts.min_margin_width = 6;
      m_dc.set_path_format (DPF_INLINE_EVENTS);
  
      m_dc.m_client_aux_data = this;
      m_dc.set_client_data_hooks
        (std::make_unique<impl_diagnostic_client_data_hooks> (*this));
  
!     diagnostics::text_starter (&m_dc) = diagnostic_text_sink::text_starter;
  
!     m_change_set
!       = std::make_unique <diagnostics::changes::change_set>
! 	  (m_dc.get_file_cache ());
    }
  
    ~diagnostic_manager ()
*************** public:
*** 686,694 ****
    }
  
    line_maps *get_line_table () { return &m_line_table; }
!   diagnostic_context &get_dc () { return m_dc; }
  
!   const logical_location_manager &
    get_logical_location_manager () const
    {
      auto mgr = m_dc.get_logical_location_manager ();
--- 697,705 ----
    }
  
    line_maps *get_line_table () { return &m_line_table; }
!   diagnostics::context &get_dc () { return m_dc; }
  
!   const diagnostics::logical_locations::manager &
    get_logical_location_manager () const
    {
      auto mgr = m_dc.get_logical_location_manager ();
*************** public:
*** 818,824 ****
  
    const diagnostic *get_current_diag () { return m_current_diag; }
  
!   const client_version_info *get_client_version_info () const
    {
      return &m_client_version_info;
    }
--- 829,836 ----
  
    const diagnostic *get_current_diag () { return m_current_diag; }
  
!   const diagnostics::client_version_info *
!   get_client_version_info () const
    {
      return &m_client_version_info;
    }
*************** private:
*** 884,890 ****
      return phys_loc;
    }
  
!   diagnostic_context m_dc;
    line_maps m_line_table;
    impl_client_version_info m_client_version_info;
    std::vector<std::unique_ptr<sink>> m_sinks;
--- 896,902 ----
      return phys_loc;
    }
  
!   diagnostics::context m_dc;
    line_maps m_line_table;
    impl_client_version_info m_client_version_info;
    std::vector<std::unique_ptr<sink>> m_sinks;
*************** private:
*** 896,902 ****
    logical_locs_map_t m_logical_locs;
    const diagnostic *m_current_diag;
    const diagnostic_logical_location *m_prev_diag_logical_loc;
!   std::unique_ptr<edit_context> m_edit_context;
  };
  
  class impl_rich_location : public rich_location
--- 908,914 ----
    logical_locs_map_t m_logical_locs;
    const diagnostic *m_current_diag;
    const diagnostic_logical_location *m_prev_diag_logical_loc;
!   std::unique_ptr<diagnostics::changes::change_set> m_change_set;
  };
  
  class impl_rich_location : public rich_location
*************** private:
*** 925,931 ****
    char *m_text;
  };
  
! class impl_rule : public diagnostic_metadata::rule
  {
  public:
    impl_rule (const char *title, const char *url)
--- 937,943 ----
    char *m_text;
  };
  
! class impl_rule : public diagnostics::metadata::rule
  {
  public:
    impl_rule (const char *title, const char *url)
*************** struct diagnostic_edge : public diagnost
*** 985,991 ****
    }
  };
  
! class libgdiagnostics_path_event : public diagnostic_event
  {
  public:
    libgdiagnostics_path_event (const diagnostic_physical_location *physical_loc,
--- 997,1003 ----
    }
  };
  
! class libgdiagnostics_path_event : public diagnostics::paths::event
  {
  public:
    libgdiagnostics_path_event (const diagnostic_physical_location *physical_loc,
*************** public:
*** 1002,1008 ****
      gcc_assert (m_msg_buf);
    }
  
!   /* diagnostic_event vfunc implementations.  */
  
    location_t get_location () const final override
    {
--- 1014,1020 ----
      gcc_assert (m_msg_buf);
    }
  
!   /* diagnostics::paths::event vfunc implementations.  */
  
    location_t get_location () const final override
    {
*************** public:
*** 1023,1029 ****
        }
    }
  
!   logical_location get_logical_location () const final override
    {
      return impl_logical_location_manager::key_from_ptr (m_logical_loc);
    }
--- 1035,1042 ----
        }
    }
  
!   diagnostics::logical_locations::key
!   get_logical_location () const final override
    {
      return impl_logical_location_manager::key_from_ptr (m_logical_loc);
    }
*************** public:
*** 1038,1044 ****
      return false; // TODO
    }
  
!   diagnostic_thread_id_t get_thread_id () const final override
    {
      return 0;
    }
--- 1051,1057 ----
      return false; // TODO
    }
  
!   diagnostics::paths::thread_id_t get_thread_id () const final override
    {
      return 0;
    }
*************** private:
*** 1081,1087 ****
    std::unique_ptr<diagnostic_message_buffer> m_msg_buf;
  };
  
! class libgdiagnostics_path_thread : public diagnostic_thread
  {
  public:
    libgdiagnostics_path_thread (const char *name) : m_name (name) {}
--- 1094,1100 ----
    std::unique_ptr<diagnostic_message_buffer> m_msg_buf;
  };
  
! class libgdiagnostics_path_thread : public diagnostics::paths::thread
  {
  public:
    libgdiagnostics_path_thread (const char *name) : m_name (name) {}
*************** private:
*** 1096,1110 ****
  
  /* This has to be a "struct" as it is exposed in the C API.  */
  
! struct diagnostic_execution_path : public diagnostic_path
  {
!   diagnostic_execution_path (const logical_location_manager &logical_loc_mgr)
!   : diagnostic_path (logical_loc_mgr),
      m_thread ("")
    {
    }
  
!   diagnostic_event_id_t
    add_event_va (const diagnostic_physical_location *physical_loc,
  		const diagnostic_logical_location *logical_loc,
  		unsigned stack_depth,
--- 1109,1123 ----
  
  /* This has to be a "struct" as it is exposed in the C API.  */
  
! struct diagnostic_execution_path : public diagnostics::paths::path
  {
!   diagnostic_execution_path (const diagnostics::logical_locations::manager &logical_loc_mgr)
!   : diagnostics::paths::path (logical_loc_mgr),
      m_thread ("")
    {
    }
  
!   diagnostics::paths::event_id_t
    add_event_va (const diagnostic_physical_location *physical_loc,
  		const diagnostic_logical_location *logical_loc,
  		unsigned stack_depth,
*************** struct diagnostic_execution_path : publi
*** 1139,1157 ****
      return m_events.size () - 1;
    }
  
!   /* diagnostic_path vfunc implementations.  */
  
    unsigned num_events () const final override
    {
      return m_events.size ();
    }
!   const diagnostic_event & get_event (int idx) const final override
    {
      return *m_events[idx];
    }
    unsigned num_threads () const final override { return 1; }
!   const diagnostic_thread &
!   get_thread (diagnostic_thread_id_t) const final override
    {
      return m_thread;
    }
--- 1152,1170 ----
      return m_events.size () - 1;
    }
  
!   /* diagnostics::paths::path vfunc implementations.  */
  
    unsigned num_events () const final override
    {
      return m_events.size ();
    }
!   const diagnostics::paths::event & get_event (int idx) const final override
    {
      return *m_events[idx];
    }
    unsigned num_threads () const final override { return 1; }
!   const diagnostics::paths::thread &
!   get_thread (diagnostics::paths::thread_id_t) const final override
    {
      return m_thread;
    }
*************** struct diagnostic_execution_path : publi
*** 1160,1168 ****
    same_function_p (int event_idx_a,
  		   int event_idx_b) const final override
    {
      logical_location logical_loc_a
        = m_events[event_idx_a]->get_logical_location ();
!     logical_location logical_loc_b
        = m_events[event_idx_b]->get_logical_location ();
  
      /* Pointer equality, as we uniqify logical location instances.  */
--- 1173,1182 ----
    same_function_p (int event_idx_a,
  		   int event_idx_b) const final override
    {
+     using logical_location = diagnostics::logical_locations::key;
      logical_location logical_loc_a
        = m_events[event_idx_a]->get_logical_location ();
!     logical_location  logical_loc_b
        = m_events[event_idx_b]->get_logical_location ();
  
      /* Pointer equality, as we uniqify logical location instances.  */
*************** private:
*** 1174,1186 ****
    std::vector<std::unique_ptr<libgdiagnostics_path_event>> m_events;
  };
  
! class prebuilt_digraphs : public diagnostics::digraphs::lazy_digraphs
  {
  public:
    using digraph = diagnostics::digraphs::digraph;
  
    std::unique_ptr<std::vector<std::unique_ptr<digraph>>>
!   create_digraphs () const final override
    {
      return std::make_unique<std::vector<std::unique_ptr<digraph>>> (std::move (m_digraphs));
    }
--- 1188,1201 ----
    std::vector<std::unique_ptr<libgdiagnostics_path_event>> m_events;
  };
  
! class prebuilt_digraphs
!   : public lazily_created<std::vector<std::unique_ptr<diagnostics::digraphs::digraph>>>
  {
  public:
    using digraph = diagnostics::digraphs::digraph;
  
    std::unique_ptr<std::vector<std::unique_ptr<digraph>>>
!   create_object () const final override
    {
      return std::make_unique<std::vector<std::unique_ptr<digraph>>> (std::move (m_digraphs));
    }
*************** public:
*** 1219,1225 ****
    enum diagnostic_level get_level () const { return m_level; }
  
    rich_location *get_rich_location () { return &m_rich_loc; }
!   const diagnostic_metadata *get_metadata () { return &m_metadata; }
  
    void set_cwe (unsigned cwe_id)
    {
--- 1234,1240 ----
    enum diagnostic_level get_level () const { return m_level; }
  
    rich_location *get_rich_location () { return &m_rich_loc; }
!   const diagnostics::metadata *get_metadata () { return &m_metadata; }
  
    void set_cwe (unsigned cwe_id)
    {
*************** private:
*** 1315,1342 ****
    enum diagnostic_level m_level;
    impl_rich_location m_rich_loc;
    const diagnostic_logical_location *m_logical_loc;
!   diagnostic_metadata m_metadata;
    prebuilt_digraphs m_graphs;
    std::vector<std::unique_ptr<range_label>> m_labels;
    std::vector<std::unique_ptr<impl_rule>> m_rules;
    std::unique_ptr<diagnostic_execution_path> m_path;
  };
  
! static diagnostic_t
! diagnostic_t_from_diagnostic_level (enum diagnostic_level level)
  {
    switch (level)
      {
      default:
        gcc_unreachable ();
      case DIAGNOSTIC_LEVEL_ERROR:
!       return DK_ERROR;
      case DIAGNOSTIC_LEVEL_WARNING:
!       return DK_WARNING;
      case DIAGNOSTIC_LEVEL_NOTE:
!       return DK_NOTE;
      case DIAGNOSTIC_LEVEL_SORRY:
!       return DK_SORRY;
      }
  }
  
--- 1330,1357 ----
    enum diagnostic_level m_level;
    impl_rich_location m_rich_loc;
    const diagnostic_logical_location *m_logical_loc;
!   diagnostics::metadata m_metadata;
    prebuilt_digraphs m_graphs;
    std::vector<std::unique_ptr<range_label>> m_labels;
    std::vector<std::unique_ptr<impl_rule>> m_rules;
    std::unique_ptr<diagnostic_execution_path> m_path;
  };
  
! static enum diagnostics::kind
! diagnostics_kind_from_diagnostic_level (enum diagnostic_level level)
  {
    switch (level)
      {
      default:
        gcc_unreachable ();
      case DIAGNOSTIC_LEVEL_ERROR:
!       return diagnostics::kind::error;
      case DIAGNOSTIC_LEVEL_WARNING:
!       return diagnostics::kind::warning;
      case DIAGNOSTIC_LEVEL_NOTE:
!       return diagnostics::kind::note;
      case DIAGNOSTIC_LEVEL_SORRY:
!       return diagnostics::kind::sorry;
      }
  }
  
*************** diagnostic_file::set_buffered_content (c
*** 1346,1352 ****
    m_content = std::make_unique<content_buffer> (buf, sz);
  
    // Populate file_cache:
!   file_cache &fc = m_mgr.get_dc ().get_file_cache ();
    fc.add_buffered_content (m_name.get_str (), buf, sz);
  }
  
--- 1361,1367 ----
    m_content = std::make_unique<content_buffer> (buf, sz);
  
    // Populate file_cache:
!   diagnostics::file_cache &fc = m_mgr.get_dc ().get_file_cache ();
    fc.add_buffered_content (m_name.get_str (), buf, sz);
  }
  
*************** diagnostic_physical_location::get_file (
*** 1364,1376 ****
  
  /* class impl_diagnostic_client_data_hooks.  */
  
! const client_version_info *
  impl_diagnostic_client_data_hooks::get_any_version_info () const
  {
    return m_mgr.get_client_version_info ();
  }
  
! logical_location
  impl_diagnostic_client_data_hooks::get_current_logical_location () const
  {
    gcc_assert (m_mgr.get_current_diag ());
--- 1379,1391 ----
  
  /* class impl_diagnostic_client_data_hooks.  */
  
! const diagnostics::client_version_info *
  impl_diagnostic_client_data_hooks::get_any_version_info () const
  {
    return m_mgr.get_client_version_info ();
  }
  
! diagnostics::logical_locations::key
  impl_diagnostic_client_data_hooks::get_current_logical_location () const
  {
    gcc_assert (m_mgr.get_current_diag ());
*************** maybe_get_sarif_source_language (const c
*** 1388,1394 ****
  
  void
  impl_diagnostic_client_data_hooks::
! add_sarif_invocation_properties (sarif_object &) const
  {
    // No-op.
  }
--- 1403,1409 ----
  
  void
  impl_diagnostic_client_data_hooks::
! add_sarif_invocation_properties (diagnostics::sarif_object &) const
  {
    // No-op.
  }
*************** diagnostic_text_sink::diagnostic_text_si
*** 1399,1408 ****
  					    FILE *dst_stream,
  					    enum diagnostic_colorize colorize)
  : sink (mgr),
!   m_source_printing (mgr.get_dc ().m_source_printing)
  {
    auto inner_sink
!     = std::make_unique<diagnostic_text_output_format> (mgr.get_dc (),
  						       &m_source_printing);
    inner_sink->get_printer ()->set_output_stream (dst_stream);
    m_inner_sink = inner_sink.get ();
--- 1414,1423 ----
  					    FILE *dst_stream,
  					    enum diagnostic_colorize colorize)
  : sink (mgr),
!   m_source_printing (mgr.get_dc ().get_source_printing_options ())
  {
    auto inner_sink
!     = std::make_unique<diagnostics::text_sink> (mgr.get_dc (),
  						       &m_source_printing);
    inner_sink->get_printer ()->set_output_stream (dst_stream);
    m_inner_sink = inner_sink.get ();
*************** diagnostic_text_sink::set_colorize (enum
*** 1432,1442 ****
  }
  
  void
! diagnostic_text_sink::text_starter (diagnostic_text_output_format &text_output,
! 				    const diagnostic_info *info)
  {
!   gcc_assert (info->x_data);
!   const diagnostic &diag = *static_cast<const diagnostic *> (info->x_data);
    pretty_printer *pp = text_output.get_printer ();
    const diagnostic_logical_location *diag_logical_loc
      = diag.get_logical_location ();
--- 1447,1457 ----
  }
  
  void
! diagnostic_text_sink::text_starter (diagnostics::text_sink &text_output,
! 				    const diagnostics::diagnostic_info *info)
  {
!   gcc_assert (info->m_x_data);
!   const diagnostic &diag = *static_cast<const diagnostic *> (info->m_x_data);
    pretty_printer *pp = text_output.get_printer ();
    const diagnostic_logical_location *diag_logical_loc
      = diag.get_logical_location ();
*************** diagnostic_text_sink::text_starter (diag
*** 1502,1516 ****
  
  /* class sarif_sink : public sink.  */
  
! sarif_sink::sarif_sink (diagnostic_manager &mgr,
! 			FILE *dst_stream,
! 			const diagnostic_file *main_input_file,
! 			const sarif_generation_options &sarif_gen_opts)
  : sink (mgr)
  {
!   diagnostic_output_file output_file (dst_stream, false,
! 				      label_text::borrow ("sarif_sink"));
!   auto serialization = std::make_unique<sarif_serialization_format_json> (true);
    auto inner_sink = make_sarif_sink (mgr.get_dc (),
  				     *mgr.get_line_table (),
  				     std::move (serialization),
--- 1517,1533 ----
  
  /* class sarif_sink : public sink.  */
  
! sarif_sink::
! sarif_sink (diagnostic_manager &mgr,
! 	    FILE *dst_stream,
! 	    const diagnostic_file *main_input_file,
! 	    const diagnostics::sarif_generation_options &sarif_gen_opts)
  : sink (mgr)
  {
!   diagnostics::output_file output_file (dst_stream, false,
! 					label_text::borrow ("sarif_sink"));
!   auto serialization
!     = std::make_unique<diagnostics::sarif_serialization_format_json> (true);
    auto inner_sink = make_sarif_sink (mgr.get_dc (),
  				     *mgr.get_line_table (),
  				     std::move (serialization),
*************** diagnostic_manager::write_patch (FILE *d
*** 1585,1591 ****
  {
    pretty_printer pp;
    pp.set_output_stream (dst_stream);
!   m_edit_context->print_diff (&pp, true);
    pp_flush (&pp);
  }
  
--- 1602,1608 ----
  {
    pretty_printer pp;
    pp.set_output_stream (dst_stream);
!   m_change_set->print_diff (&pp, true);
    pp_flush (&pp);
  }
  
*************** diagnostic_manager::emit_va (diagnostic
*** 1599,1611 ****
    {
      m_dc.begin_group ();
  
!     diagnostic_info info;
  GCC_DIAGNOSTIC_PUSH_IGNORED(-Wsuggest-attribute=format)
      diagnostic_set_info (&info, msgid, args, diag.get_rich_location (),
! 			 diagnostic_t_from_diagnostic_level (diag.get_level ()));
  GCC_DIAGNOSTIC_POP
!     info.metadata = diag.get_metadata ();
!     info.x_data = &diag;
      diagnostic_report_diagnostic (&m_dc, &info);
  
      m_dc.end_group ();
--- 1616,1629 ----
    {
      m_dc.begin_group ();
  
!     diagnostics::diagnostic_info info;
  GCC_DIAGNOSTIC_PUSH_IGNORED(-Wsuggest-attribute=format)
      diagnostic_set_info (&info, msgid, args, diag.get_rich_location (),
! 			 diagnostics_kind_from_diagnostic_level
! 			   (diag.get_level ()));
  GCC_DIAGNOSTIC_POP
!     info.m_metadata = diag.get_metadata ();
!     info.m_x_data = &diag;
      diagnostic_report_diagnostic (&m_dc, &info);
  
      m_dc.end_group ();
*************** GCC_DIAGNOSTIC_POP
*** 1613,1619 ****
  
    rich_location *rich_loc = diag.get_rich_location ();
    if (rich_loc->fixits_can_be_auto_applied_p ())
!     m_edit_context->add_fixits (rich_loc);
  
    m_prev_diag_logical_loc = diag.get_logical_location ();
    m_current_diag = nullptr;
--- 1631,1637 ----
  
    rich_location *rich_loc = diag.get_rich_location ();
    if (rich_loc->fixits_can_be_auto_applied_p ())
!     m_change_set->add_fixits (rich_loc);
  
    m_prev_diag_logical_loc = diag.get_logical_location ();
    m_current_diag = nullptr;
*************** diagnostic_manager::new_execution_path (
*** 1648,1654 ****
  void
  diagnostic_manager::take_global_graph (std::unique_ptr<diagnostic_graph> graph)
  {
!   class prebuilt_lazy_digraph : public diagnostics::digraphs::lazy_digraph
    {
    public:
      prebuilt_lazy_digraph (std::unique_ptr<diagnostic_graph> graph)
--- 1666,1672 ----
  void
  diagnostic_manager::take_global_graph (std::unique_ptr<diagnostic_graph> graph)
  {
!   class prebuilt_lazy_digraph : public lazily_created<diagnostics::digraphs::digraph>
    {
    public:
      prebuilt_lazy_digraph (std::unique_ptr<diagnostic_graph> graph)
*************** diagnostic_manager::take_global_graph (s
*** 1657,1663 ****
      }
  
      std::unique_ptr<diagnostics::digraphs::digraph>
!     create_digraph () const final override
      {
        return std::move (m_graph);
      }
--- 1675,1681 ----
      }
  
      std::unique_ptr<diagnostics::digraphs::digraph>
!     create_object () const final override
      {
        return std::move (m_graph);
      }
*************** diagnostic_manager_add_sarif_sink (diagn
*** 1808,1814 ****
    FAIL_IF_NULL (dst_stream);
    FAIL_IF_NULL (main_input_file);
  
!   sarif_generation_options sarif_gen_opts;
    switch (version)
      {
      default:
--- 1826,1832 ----
    FAIL_IF_NULL (dst_stream);
    FAIL_IF_NULL (main_input_file);
  
!   diagnostics::sarif_generation_options sarif_gen_opts;
    switch (version)
      {
      default:
*************** diagnostic_manager_add_sarif_sink (diagn
*** 1816,1825 ****
  	       __func__, (int)version);
        abort ();
      case DIAGNOSTIC_SARIF_VERSION_2_1_0:
!       sarif_gen_opts.m_version = sarif_version::v2_1_0;
        break;
      case DIAGNOSTIC_SARIF_VERSION_2_2_PRERELEASE:
!       sarif_gen_opts.m_version = sarif_version::v2_2_prerelease_2024_08_08;
        break;
      }
  
--- 1834,1844 ----
  	       __func__, (int)version);
        abort ();
      case DIAGNOSTIC_SARIF_VERSION_2_1_0:
!       sarif_gen_opts.m_version = diagnostics::sarif_version::v2_1_0;
        break;
      case DIAGNOSTIC_SARIF_VERSION_2_2_PRERELEASE:
!       sarif_gen_opts.m_version
! 	= diagnostics::sarif_version::v2_2_prerelease_2024_08_08;
        break;
      }
  
*************** diagnostic_manager_debug_dump_location (
*** 1949,1960 ****
        diag_mgr->set_line_table_global ();
        const expanded_location exp_loc (expand_location (cpplib_loc));
  
!       diagnostic_context dc;
        diagnostic_initialize (&dc, 0);
        dc.m_show_column = true;
  
!       diagnostic_text_output_format text_format (dc);
!       label_text loc_text = text_format.get_location_text (exp_loc);
        fprintf (out, "%s", loc_text.get ());
  
        diagnostic_finish (&dc);
--- 1968,1979 ----
        diag_mgr->set_line_table_global ();
        const expanded_location exp_loc (expand_location (cpplib_loc));
  
!       diagnostics::context dc;
        diagnostic_initialize (&dc, 0);
        dc.m_show_column = true;
  
!       diagnostics::text_sink text_output (dc);
!       label_text loc_text = text_output.get_location_text (exp_loc);
        fprintf (out, "%s", loc_text.get ());
  
        diagnostic_finish (&dc);
*************** diagnostic_execution_path_add_event (dia
*** 2293,2303 ****
  
    va_list args;
    va_start (args, gmsgid);
!   diagnostic_event_id_t result = path->add_event_va (physical_loc,
! 						     logical_loc,
! 						     stack_depth,
! 						     nullptr,
! 						     gmsgid, &args);
    va_end (args);
  
    return as_diagnostic_event_id (result);
--- 2312,2323 ----
  
    va_list args;
    va_start (args, gmsgid);
!   diagnostics::paths::event_id_t result
!     = path->add_event_va (physical_loc,
! 			  logical_loc,
! 			  stack_depth,
! 			  nullptr,
! 			  gmsgid, &args);
    va_end (args);
  
    return as_diagnostic_event_id (result);
*************** diagnostic_execution_path_add_event_va (
*** 2316,2326 ****
    FAIL_IF_NULL (path);
    FAIL_IF_NULL (gmsgid);
  
!   diagnostic_event_id_t result = path->add_event_va (physical_loc,
! 						     logical_loc,
! 						     stack_depth,
! 						     nullptr,
! 						     gmsgid, args);
    return as_diagnostic_event_id (result);
  }
  
--- 2336,2347 ----
    FAIL_IF_NULL (path);
    FAIL_IF_NULL (gmsgid);
  
!   diagnostics::paths::event_id_t result
!     = path->add_event_va (physical_loc,
! 			  logical_loc,
! 			  stack_depth,
! 			  nullptr,
! 			  gmsgid, args);
    return as_diagnostic_event_id (result);
  }
  
*************** diagnostic_logical_location_get_decorate
*** 2409,2415 ****
  
  namespace {
  
! struct spec_context : public diagnostics_output_spec::context
  {
  public:
    spec_context (const char *option_name,
--- 2430,2436 ----
  
  namespace {
  
! struct spec_context : public diagnostics::output_spec::context
  {
  public:
    spec_context (const char *option_name,
diff -Nrcpad gcc-16-20250720/gcc/libsarifreplay.cc gcc-16-20250727/gcc/libsarifreplay.cc
*** gcc-16-20250720/gcc/libsarifreplay.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/libsarifreplay.cc	Sun Jul 27 22:32:09 2025
*************** handle_thread_flow_location_object (cons
*** 1865,1871 ****
    libgdiagnostics::graph state_graph;
    if (auto sarif_state_graph
  	= maybe_get_property_bag_value<json::object> (tflow_loc_obj,
! 						      "gcc/diagnostic_event/state_graph"))
      {
        enum status s
  	= handle_graph_object (*sarif_state_graph, run_obj, state_graph);
--- 1865,1871 ----
    libgdiagnostics::graph state_graph;
    if (auto sarif_state_graph
  	= maybe_get_property_bag_value<json::object> (tflow_loc_obj,
! 						      "gcc/diagnostics/paths/event/state_graph"))
      {
        enum status s
  	= handle_graph_object (*sarif_state_graph, run_obj, state_graph);
diff -Nrcpad gcc-16-20250720/gcc/logical-location.h gcc-16-20250727/gcc/logical-location.h
*** gcc-16-20250720/gcc/logical-location.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/logical-location.h	Thu Jan  1 00:00:00 1970
***************
*** 1,175 ****
- /* Logical location support, without knowledge of "tree".
-    Copyright (C) 2022-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_LOGICAL_LOCATION_H
- #define GCC_LOGICAL_LOCATION_H
- 
- #include "label-text.h"
- 
- /* An enum for discriminating between different kinds of logical location
-    for a diagnostic.
- 
-    Roughly corresponds to logicalLocation's "kind" property in SARIF v2.1.0
-    (section 3.33.7).  */
- 
- enum class logical_location_kind
- {
-   unknown,
- 
-   /* Kinds within executable code.  */
-   function,
-   member,
-   module_,
-   namespace_,
-   type,
-   return_type,
-   parameter,
-   variable,
- 
-   /* Kinds within XML or HTML documents.  */
-   element,
-   attribute,
-   text,
-   comment,
-   processing_instruction,
-   dtd,
-   declaration,
- 
-   /* Kinds within JSON documents.  */
-   object,
-   array,
-   property,
-   value
- };
- 
- /* We want to efficiently support passing around logical locations in the
-    diagnostics subsystem, such as:
-    - "within function 'foo'", or
-    - "within method 'bar'"
- 
-    However we want to do this *without* requiring knowledge of trees (or of
-    libgdiagnostics internals), and without requiring heap allocation of an
-    interface class when emitting a diagnostic.
- 
-    To do this, we split the implementation into logical_location, which is
-    a wrapper around a (const void *), and logical_location_manager which
-    is provided by the client and has vfunc hooks for interpreting
-    logical_location instances.
- 
-    Every logical_location is associated with a logical_location_manager and
-    only has meaning in relation to that manager.
- 
-    A "nullptr" within a logical_location means "no logical location".
- 
-    See tree-logical-location.h for concrete subclasses relating to trees,
-    where the pointer is a const_tree.
- 
-    See selftest-logical-location.h for a concrete subclass for selftests.  */
- 
- /* Abstract base class for giving meaning to logical_location values.
-    Typically there will just be one client-provided instance, of a
-    client-specific subclass.  */
- 
- class logical_location_manager
- {
- public:
-   /* Extrinsic state for identifying a specific logical location.
-      This will be our logical_location type.
-      This only makes sense with respect to a specific manager.
-      e.g. for a tree-based one it's a wrapper around "tree".
-      "nullptr" means "no logical location".  */
-   class key
-   {
-   public:
-     key () : m_ptr (nullptr) {}
- 
-     static key from_ptr (const void *ptr)
-     {
-       return key (ptr);
-     }
- 
-     operator bool () const
-     {
-       return m_ptr != nullptr;
-     }
- 
-     template <typename T>
-     T cast_to () const { return static_cast<T> (m_ptr); }
- 
-     bool
-     operator== (const key &other) const
-     {
-       return m_ptr == other.m_ptr;
-     }
- 
-     bool
-     operator!= (const key &other) const
-     {
-       return m_ptr != other.m_ptr;
-     }
- 
-     bool
-     operator< (const key &other) const
-     {
-       return m_ptr < other.m_ptr;
-     }
- 
-   private:
-     explicit key (const void *ptr) : m_ptr (ptr) {}
- 
-     const void *m_ptr;
-   };
- 
-   virtual ~logical_location_manager () {}
- 
-   /* vfuncs for interpreting logical_location values.  */
- 
-   /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
-      "name" property (SARIF v2.1.0 section 3.33.4).  */
-   virtual const char *get_short_name (key k) const = 0;
- 
-   /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
-      "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
-   virtual const char *get_name_with_scope (key k) const = 0;
- 
-   /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
-      "decoratedName" property (SARIF v2.1.0 section 3.33.6).  */
-   virtual const char *get_internal_name (key k) const = 0;
- 
-   /* Get what kind of SARIF logicalLocation K is (if any).  */
-   virtual enum logical_location_kind get_kind (key k) const = 0;
- 
-   /* Get a string for location K in a form suitable for path output.  */
-   virtual label_text get_name_for_path_output (key k) const = 0;
- 
-   /* Get the parent logical_logical of K, if any, or nullptr.  */
-   virtual key get_parent (key k) const = 0;
- 
-   bool function_p (key k) const;
- };
- 
- /* A logical location is a key for a given logical_location_manager.
- 
-    Note that there is no integration with GCC's garbage collector and thus
-    logical_location instances can't be long-lived.  */
- 
- typedef logical_location_manager::key logical_location;
- 
- #endif /* GCC_LOGICAL_LOCATION_H.  */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/lra-constraints.cc gcc-16-20250727/gcc/lra-constraints.cc
*** gcc-16-20250720/gcc/lra-constraints.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/lra-constraints.cc	Sun Jul 27 22:32:09 2025
***************
*** 114,119 ****
--- 114,120 ----
  #include "target.h"
  #include "rtl.h"
  #include "tree.h"
+ #include "stmt.h"
  #include "predict.h"
  #include "df.h"
  #include "memmodel.h"
*************** process_alt_operands (int only_alternati
*** 2168,2173 ****
--- 2169,2175 ----
    bool costly_p;
    enum reg_class cl;
    const HARD_REG_SET *cl_filter;
+   HARD_REG_SET hard_reg_constraint;
  
    /* Calculate some data common for all alternatives to speed up the
       function.	*/
*************** process_alt_operands (int only_alternati
*** 2545,2550 ****
--- 2547,2563 ----
  		  cl_filter = nullptr;
  		  goto reg;
  
+ 		case '{':
+ 		    {
+ 		      int regno = decode_hard_reg_constraint (p);
+ 		      gcc_assert (regno >= 0);
+ 		      cl = REGNO_REG_CLASS (regno);
+ 		      CLEAR_HARD_REG_SET (hard_reg_constraint);
+ 		      SET_HARD_REG_BIT (hard_reg_constraint, regno);
+ 		      cl_filter = &hard_reg_constraint;
+ 		      goto reg;
+ 		    }
+ 
  		default:
  		  cn = lookup_constraint (p);
  		  switch (get_constraint_type (cn))
diff -Nrcpad gcc-16-20250720/gcc/lto-wrapper.cc gcc-16-20250727/gcc/lto-wrapper.cc
*** gcc-16-20250720/gcc/lto-wrapper.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/lto-wrapper.cc	Sun Jul 27 22:32:09 2025
*************** public:
*** 2274,2286 ****
    : gcc_diagnostic_option_manager (0 /* lang_mask */)
    {
    }
!   int option_enabled_p (diagnostic_option_id) const final override
    {
      return true;
    }
!   char *make_option_name (diagnostic_option_id,
! 			  diagnostic_t,
! 			  diagnostic_t) const final override
    {
      return nullptr;
    }
--- 2274,2286 ----
    : gcc_diagnostic_option_manager (0 /* lang_mask */)
    {
    }
!   int option_enabled_p (diagnostics::option_id) const final override
    {
      return true;
    }
!   char *make_option_name (diagnostics::option_id,
! 			  enum diagnostics::kind,
! 			  enum diagnostics::kind) const final override
    {
      return nullptr;
    }
diff -Nrcpad gcc-16-20250720/gcc/m2/ChangeLog gcc-16-20250727/gcc/m2/ChangeLog
*** gcc-16-20250720/gcc/m2/ChangeLog	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/ChangeLog	Sun Jul 27 22:32:09 2025
***************
*** 1,3 ****
--- 1,75 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gm2-gcc/m2linemap.cc: Update usage of "diagnostic_info" to
+ 	explicitly refer to "diagnostics::diagnostic_info".
+ 	* gm2-gcc/rtegraph.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gm2-gcc/m2linemap.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* gm2-gcc/rtegraph.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gm2-gcc/m2color.cc: Update for move of diagnostic-color.h to
+ 	diagnostics/color.h.
+ 
+ 2025-07-23  Gaius Mulley  <gaiusmod2@gmail.com>
+ 
+ 	* gm2-libs/M2EXCEPTION.mod (M2Exception): Add return
+ 	exException in case Raise completes.
+ 
+ 2025-07-23  Gaius Mulley  <gaiusmod2@gmail.com>
+ 
+ 	PR modula2/121164
+ 	* gm2-compiler/P1SymBuild.mod: Remove PutProcTypeParam.
+ 	Remove PutProcTypeParam.
+ 	(CheckFileName): Remove.
+ 	(P1EndBuildDefinitionModule): Correct spelling.
+ 	(P1EndBuildImplementationModule): Ditto.
+ 	(P1EndBuildProgramModule): Ditto.
+ 	(EndBuildInnerModule): Ditto.
+ 	* gm2-compiler/P2SymBuild.mod (P2EndBuildDefModule): Correct
+ 	spelling.
+ 	(P2EndBuildImplementationModule): Ditto.
+ 	(P2EndBuildProgramModule): Ditto.
+ 	(EndBuildInnerModule): Ditto.
+ 	(CheckFormalParameterSection): Ditto.
+ 	* gm2-compiler/P3SymBuild.mod (P3EndBuildDefModule): Ditto.
+ 	* gm2-compiler/PCSymBuild.mod (PCEndBuildDefModule): Ditto.
+ 	(fixupProcedureType): Pass tok to PutProcTypeVarParam.
+ 	Pass tok to PutProcTypeParam.
+ 	* gm2-compiler/SymbolTable.def (PutProcTypeParam): Add tok
+ 	parameter.
+ 	(PutProcTypeVarParam): Ditto.
+ 	* gm2-compiler/SymbolTable.mod (SymParam): At change type to
+ 	CARDINAL.
+ 	New field FullTok.
+ 	New field Scope.
+ 	(SymVarParam): At change type to CARDINAL.
+ 	New field FullTok.
+ 	New field Scope.
+ 	(GetVarDeclTok): Check ShadowVar for NulSym and return At.
+ 	(PutParam): Initialize FullTok.
+ 	Initialize At.
+ 	Initialize Scope.
+ 	(PutVarParam): Initialize FullTok.
+ 	Assign At.
+ 	Initialize Scope.
+ 	(AddProcedureProcTypeParam): Add tok parameter.
+ 	(GetScope): Add ParamSym and VarParamSym clause.
+ 	(PutProcTypeVarParam): Add tok parameter.
+ 	Initialize At.
+ 	Initialize FullTok.
+ 	(GetDeclaredDefinition): Clause ParamSym return At.
+ 	Clause VarParamSym return At.
+ 	(GetDeclaredModule): Ditto.
+ 	(PutDeclaredDefinition): Remove clause ParamSym.
+ 	Remove clause VarParamSym.
+ 	(PutDeclaredModule): Remove clause ParamSym.
+ 	Remove clause VarParamSym.
+ 
  2025-07-18  Gaius Mulley  <gaiusmod2@gmail.com>
  
  	PR modula2/121164
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-compiler/P1SymBuild.mod gcc-16-20250727/gcc/m2/gm2-compiler/P1SymBuild.mod
*** gcc-16-20250720/gcc/m2/gm2-compiler/P1SymBuild.mod	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-compiler/P1SymBuild.mod	Sun Jul 27 22:32:09 2025
*************** FROM SymbolTable IMPORT NulSym,
*** 79,85 ****
                          MakeSubscript, PutSubscript,
                          PutArray, GetType, IsArray,
                          IsProcType, MakeProcType,
-                         PutProcTypeVarParam, PutProcTypeParam,
                          PutProcedureBuiltin, PutProcedureInline,
                          GetSymName,
                          ResolveImports, PutDeclared,
--- 79,84 ----
*************** VAR
*** 109,150 ****
  
  
  (*
-    CheckFileName - checks to see that the module name matches the file name.
- *)
- 
- (*
- PROCEDURE CheckFileName (tok: CARDINAL; name: Name; ModuleType: ARRAY OF CHAR) ;
- VAR
-    ext,
-    basename: INTEGER ;
-    s,
-    FileName: String ;
- BEGIN
-    FileName := GetFileName() ;
-    basename := RIndex(FileName, '/', 0) ;
-    IF basename=-1
-    THEN
-       basename := 0
-    END ;
-    ext := RIndex(FileName, '.', 0) ;
-    IF ext=-1
-    THEN
-       ext := 0
-    END ;
-    FileName := Slice(FileName, basename, ext) ;
-    IF EqualCharStar(FileName, KeyToCharStar(name))
-    THEN
-       FileName := KillString(FileName)
-    ELSE
-       s := ConCat (InitString (ModuleType),
-                    Mark (InitString (" module name {%1Ea} is inconsistant with the filename {%F{%2a}}"))) ;
-       MetaErrorString2 (s, MakeError (tok, name), MakeErrorS (tok, FileName))
-    END
- END CheckFileName ;
- *)
- 
- 
- (*
     StartBuildDefinitionModule - Creates a definition module and starts
                                  a new scope.
  
--- 108,113 ----
*************** BEGIN
*** 227,233 ****
     END ;
     IF NameStart#NameEnd
     THEN
!       MetaError1 ('inconsistant definition module name {%1Wa}', MakeError (start, NameStart))
     END ;
     LeaveBlock
  END P1EndBuildDefinitionModule ;
--- 190,196 ----
     END ;
     IF NameStart#NameEnd
     THEN
!       MetaError1 ('inconsistent definition module name {%1Wa}', MakeError (start, NameStart))
     END ;
     LeaveBlock
  END P1EndBuildDefinitionModule ;
*************** BEGIN
*** 301,307 ****
     IF NameStart#NameEnd
     THEN
        MetaErrorT1 (end,
!                    'inconsistant implementation module name {%1Wa}', MakeError (start, NameStart))
     END ;
     LeaveBlock
  END P1EndBuildImplementationModule ;
--- 264,270 ----
     IF NameStart#NameEnd
     THEN
        MetaErrorT1 (end,
!                    'inconsistent implementation module name {%1Wa}', MakeError (start, NameStart))
     END ;
     LeaveBlock
  END P1EndBuildImplementationModule ;
*************** BEGIN
*** 381,387 ****
     IF NameStart#NameEnd
     THEN
        MetaErrorT1 (end,
!                    'inconsistant program module name {%1Wa}', MakeError (start, NameStart))
     END ;
     LeaveBlock
  END P1EndBuildProgramModule ;
--- 344,350 ----
     IF NameStart#NameEnd
     THEN
        MetaErrorT1 (end,
!                    'inconsistent program module name {%1Wa}', MakeError (start, NameStart))
     END ;
     LeaveBlock
  END P1EndBuildProgramModule ;
*************** BEGIN
*** 446,452 ****
     IF NameStart#NameEnd
     THEN
        MetaErrorT1 (end,
!                    'inconsistant inner module name {%1Wa}', MakeError (start, NameStart))
     END ;
     LeaveBlock
  END EndBuildInnerModule ;
--- 409,415 ----
     IF NameStart#NameEnd
     THEN
        MetaErrorT1 (end,
!                    'inconsistent inner module name {%1Wa}', MakeError (start, NameStart))
     END ;
     LeaveBlock
  END EndBuildInnerModule ;
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-compiler/P2SymBuild.mod gcc-16-20250727/gcc/m2/gm2-compiler/P2SymBuild.mod
*** gcc-16-20250720/gcc/m2/gm2-compiler/P2SymBuild.mod	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-compiler/P2SymBuild.mod	Sun Jul 27 22:32:09 2025
*************** BEGIN
*** 356,362 ****
     END ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistant definition module name, module began as (%a) and ended with (%a)', NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
  END P2EndBuildDefModule ;
--- 356,362 ----
     END ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistent definition module name, module began as (%a) and ended with (%a)', NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
  END P2EndBuildDefModule ;
*************** BEGIN
*** 425,431 ****
     PopT (NameEnd) ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat1('inconsistant implementation module name %a', NameStart)
     END ;
     M2Error.LeaveErrorScope
  END P2EndBuildImplementationModule ;
--- 425,431 ----
     PopT (NameEnd) ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat1('inconsistent implementation module name %a', NameStart)
     END ;
     M2Error.LeaveErrorScope
  END P2EndBuildImplementationModule ;
*************** BEGIN
*** 499,505 ****
     END ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistant program module name %a does not match %a', NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
  END P2EndBuildProgramModule ;
--- 499,505 ----
     END ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistent program module name %a does not match %a', NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
  END P2EndBuildProgramModule ;
*************** BEGIN
*** 564,570 ****
     PopT(NameEnd) ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistant inner module name %a does not match %a',
                     NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
--- 564,570 ----
     PopT(NameEnd) ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistent inner module name %a does not match %a',
                     NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
*************** BEGIN
*** 1835,1847 ****
           (* WarnStringAt (InitString ('parampos?'), OperandTok (pi)) ;  *)
           IF Unbounded AND (NOT IsUnboundedParam (ProcSym, prevkind, ParamTotal+i))
           THEN
!             ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistant, %s',
                              'the parameter {%3EHa} was not declared as an ARRAY OF type',
                              'the parameter {%3EVa} was declared as an ARRAY OF type',
                              ParamTotal+i, ProcSym, curkind, prevkind)
           ELSIF (NOT Unbounded) AND IsUnboundedParam (ProcSym, prevkind, ParamTotal+i)
           THEN
!             ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistant, %s',
                              'the parameter {%3EHa} was declared as an ARRAY OF type',
                              'the parameter {%3EVa} was not declared as an ARRAY OF type',
                              ParamTotal+i, ProcSym, curkind, prevkind)
--- 1835,1847 ----
           (* WarnStringAt (InitString ('parampos?'), OperandTok (pi)) ;  *)
           IF Unbounded AND (NOT IsUnboundedParam (ProcSym, prevkind, ParamTotal+i))
           THEN
!             ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistent, %s',
                              'the parameter {%3EHa} was not declared as an ARRAY OF type',
                              'the parameter {%3EVa} was declared as an ARRAY OF type',
                              ParamTotal+i, ProcSym, curkind, prevkind)
           ELSIF (NOT Unbounded) AND IsUnboundedParam (ProcSym, prevkind, ParamTotal+i)
           THEN
!             ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistent, %s',
                              'the parameter {%3EHa} was declared as an ARRAY OF type',
                              'the parameter {%3EVa} was not declared as an ARRAY OF type',
                              ParamTotal+i, ProcSym, curkind, prevkind)
*************** BEGIN
*** 1850,1856 ****
           THEN
              IF GetDimension (GetNthParam (ProcSym, prevkind, ParamTotal+1)) # ndim
              THEN
!                ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistant, %s',
                                 'the dynamic array parameter {%3EHa} was declared with a different of dimensions',
                                 'the dynamic array parameter {%3EVa} was declared with a different of dimensions',
                                 ParamTotal+i, ProcSym, curkind, prevkind)
--- 1850,1856 ----
           THEN
              IF GetDimension (GetNthParam (ProcSym, prevkind, ParamTotal+1)) # ndim
              THEN
!                ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistent, %s',
                                 'the dynamic array parameter {%3EHa} was declared with a different of dimensions',
                                 'the dynamic array parameter {%3EVa} was declared with a different of dimensions',
                                 ParamTotal+i, ProcSym, curkind, prevkind)
*************** BEGIN
*** 1859,1872 ****
           IF isVarParam AND (NOT IsVarParam (ProcSym, prevkind, ParamTotal+i))
           THEN
              (* Expecting non VAR parameter.  *)
!             ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistant, %s',
                              '{%3EHa} was not declared as a {%kVAR} parameter',
                              '{%3EVa} was declared as a {%kVAR} parameter',
                              ParamTotal+i, ProcSym, curkind, prevkind)
           ELSIF (NOT isVarParam) AND IsVarParam (ProcSym, prevkind, ParamTotal+i)
           THEN
              (* Expecting VAR pamarater.  *)
!             ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistant, %s',
                              '{%3EHa} was declared as a {%kVAR} parameter',
                              '{%3EVa} was not declared as a {%kVAR} parameter',
                              ParamTotal+i, ProcSym, curkind, prevkind)
--- 1859,1872 ----
           IF isVarParam AND (NOT IsVarParam (ProcSym, prevkind, ParamTotal+i))
           THEN
              (* Expecting non VAR parameter.  *)
!             ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistent, %s',
                              '{%3EHa} was not declared as a {%kVAR} parameter',
                              '{%3EVa} was declared as a {%kVAR} parameter',
                              ParamTotal+i, ProcSym, curkind, prevkind)
           ELSIF (NOT isVarParam) AND IsVarParam (ProcSym, prevkind, ParamTotal+i)
           THEN
              (* Expecting VAR pamarater.  *)
!             ParameterError ('declaration of procedure {%%1a} in the %s differs from the %s, {%%2N} parameter is inconsistent, %s',
                              '{%3EHa} was declared as a {%kVAR} parameter',
                              '{%3EVa} was not declared as a {%kVAR} parameter',
                              ParamTotal+i, ProcSym, curkind, prevkind)
*************** BEGIN
*** 1877,1883 ****
              IF GetSymName (ParamI) # OperandT (pi)
              THEN
                 (* Different parameter names.  *)
!                ParameterError ('procedure {%%1a} in the %s differs from the %s, {%%2N} parameter name is inconsistant, %s',
                              'named as {%3EVa}',
                              'named as {%3EVa}',
                              ParamTotal+i, ProcSym, curkind, prevkind)
--- 1877,1883 ----
              IF GetSymName (ParamI) # OperandT (pi)
              THEN
                 (* Different parameter names.  *)
!                ParameterError ('procedure {%%1a} in the %s differs from the %s, {%%2N} parameter name is inconsistent, %s',
                              'named as {%3EVa}',
                              'named as {%3EVa}',
                              ParamTotal+i, ProcSym, curkind, prevkind)
*************** BEGIN
*** 1897,1903 ****
              (NOT IsUnknown(SkipType(ParamIType)))
           THEN
              (* Different parameter types.  *)
!             ParameterError ('declaration in the %s differs from the %s, {%%2N} parameter is inconsistant, %s',
                              'the parameter {%3EHa} was declared with a different type',
                              'the parameter {%3EVa} was declared with a different type',
                              ParamTotal+i, ProcSym, curkind, prevkind)
--- 1897,1903 ----
              (NOT IsUnknown(SkipType(ParamIType)))
           THEN
              (* Different parameter types.  *)
!             ParameterError ('declaration in the %s differs from the %s, {%%2N} parameter is inconsistent, %s',
                              'the parameter {%3EHa} was declared with a different type',
                              'the parameter {%3EVa} was declared with a different type',
                              ParamTotal+i, ProcSym, curkind, prevkind)
*************** BEGIN
*** 3072,3081 ****
     IF Var=VarTok
     THEN
        (* VAR parameter *)
!       PutProcTypeVarParam(ProcTypeSym, TypeSym, IsUnbounded(TypeSym))
     ELSE
        (* Non VAR parameter *)
!       PutProcTypeParam(ProcTypeSym, TypeSym, IsUnbounded(TypeSym))
     END ;
     PushT(ProcTypeSym) ;
     Annotate("%1s(%1d)||proc type")
--- 3072,3081 ----
     IF Var=VarTok
     THEN
        (* VAR parameter *)
!       PutProcTypeVarParam (tok, ProcTypeSym, TypeSym, IsUnbounded (TypeSym))
     ELSE
        (* Non VAR parameter *)
!       PutProcTypeParam (tok, ProcTypeSym, TypeSym, IsUnbounded (TypeSym))
     END ;
     PushT(ProcTypeSym) ;
     Annotate("%1s(%1d)||proc type")
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-compiler/P3SymBuild.mod gcc-16-20250727/gcc/m2/gm2-compiler/P3SymBuild.mod
*** gcc-16-20250720/gcc/m2/gm2-compiler/P3SymBuild.mod	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-compiler/P3SymBuild.mod	Sun Jul 27 22:32:09 2025
*************** BEGIN
*** 126,132 ****
     PopT(NameStart) ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistant definition module was named (%a) and concluded as (%a)',
                     NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
--- 126,132 ----
     PopT(NameStart) ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistent definition module was named (%a) and concluded as (%a)',
                     NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-compiler/PCSymBuild.mod gcc-16-20250727/gcc/m2/gm2-compiler/PCSymBuild.mod
*** gcc-16-20250720/gcc/m2/gm2-compiler/PCSymBuild.mod	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-compiler/PCSymBuild.mod	Sun Jul 27 22:32:09 2025
*************** BEGIN
*** 269,275 ****
     PopT(NameStart) ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistant definition module was named (%a) and concluded as (%a)',
                     NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
--- 269,275 ----
     PopT(NameStart) ;
     IF NameStart#NameEnd
     THEN
!       WriteFormat2('inconsistent definition module was named (%a) and concluded as (%a)',
                     NameStart, NameEnd)
     END ;
     M2Error.LeaveErrorScope
*************** BEGIN
*** 1168,1176 ****
           par := GetParam (p, i) ;
           IF IsParameterVar (par)
           THEN
!             PutProcTypeVarParam (t, GetType (par), IsParameterUnbounded (par))
           ELSE
!             PutProcTypeParam (t, GetType (par), IsParameterUnbounded (par))
           END ;
           INC(i)
        END ;
--- 1168,1176 ----
           par := GetParam (p, i) ;
           IF IsParameterVar (par)
           THEN
!             PutProcTypeVarParam (tok, t, GetType (par), IsParameterUnbounded (par))
           ELSE
!             PutProcTypeParam (tok, t, GetType (par), IsParameterUnbounded (par))
           END ;
           INC(i)
        END ;
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-compiler/SymbolTable.def gcc-16-20250727/gcc/m2/gm2-compiler/SymbolTable.def
*** gcc-16-20250720/gcc/m2/gm2-compiler/SymbolTable.def	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-compiler/SymbolTable.def	Sun Jul 27 22:32:09 2025
*************** PROCEDURE MakeProcType (tok: CARDINAL; P
*** 2650,2656 ****
                        ParamType into ProcType Sym.
  *)
  
! PROCEDURE PutProcTypeParam (Sym: CARDINAL;
                              ParamType: CARDINAL; isUnbounded: BOOLEAN) ;
  
  
--- 2650,2657 ----
                        ParamType into ProcType Sym.
  *)
  
! PROCEDURE PutProcTypeParam (tok: CARDINAL;
!                             Sym: CARDINAL;
                              ParamType: CARDINAL; isUnbounded: BOOLEAN) ;
  
  
*************** PROCEDURE PutProcTypeParam (Sym: CARDINA
*** 2659,2665 ****
                           ParamType into ProcType Sym.
  *)
  
! PROCEDURE PutProcTypeVarParam (Sym: CARDINAL;
                                 ParamType: CARDINAL; isUnbounded: BOOLEAN) ;
  
  
--- 2660,2667 ----
                           ParamType into ProcType Sym.
  *)
  
! PROCEDURE PutProcTypeVarParam (tok: CARDINAL;
!                                Sym: CARDINAL;
                                 ParamType: CARDINAL; isUnbounded: BOOLEAN) ;
  
  
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-compiler/SymbolTable.mod gcc-16-20250727/gcc/m2/gm2-compiler/SymbolTable.mod
*** gcc-16-20250720/gcc/m2/gm2-compiler/SymbolTable.mod	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-compiler/SymbolTable.mod	Sun Jul 27 22:32:09 2025
*************** TYPE
*** 463,471 ****
                                                (* of param.                   *)
                   Type          : CARDINAL ;   (* Index to the type of param. *)
                   IsUnbounded   : BOOLEAN ;    (* Is it an ARRAY OF Type?     *)
                   ShadowVar     : CARDINAL ;   (* The local variable used to  *)
                                                (* shadow this parameter.      *)
!                  At            : Where ;      (* Where was sym declared/used *)
                END ;
  
     SymVarParam = RECORD
--- 463,473 ----
                                                (* of param.                   *)
                   Type          : CARDINAL ;   (* Index to the type of param. *)
                   IsUnbounded   : BOOLEAN ;    (* Is it an ARRAY OF Type?     *)
+                  Scope         : CARDINAL ;   (* Procedure declaration.      *)
                   ShadowVar     : CARDINAL ;   (* The local variable used to  *)
                                                (* shadow this parameter.      *)
!                  FullTok,                     (* name: type virtual token.   *)
!                  At            : CARDINAL ;   (* Where was sym declared.     *)
                END ;
  
     SymVarParam = RECORD
*************** TYPE
*** 476,484 ****
                      HeapVar       : CARDINAL ;(* The pointer value on heap.  *)
                                                (* Only used by static         *)
                                                (* analysis.                   *)
                      ShadowVar     : CARDINAL ;(* The local variable used to  *)
                                                (* shadow this parameter.      *)
!                     At            : Where ;   (* Where was sym declared/used *)
                   END ;
  
     ConstStringVariant = (m2str, cstr, m2nulstr, cnulstr) ;
--- 478,488 ----
                      HeapVar       : CARDINAL ;(* The pointer value on heap.  *)
                                                (* Only used by static         *)
                                                (* analysis.                   *)
+                     Scope         : CARDINAL ;(* Procedure declaration.      *)
                      ShadowVar     : CARDINAL ;(* The local variable used to  *)
                                                (* shadow this parameter.      *)
!                     FullTok,                  (* name: type virtual token.   *)
!                     At            : CARDINAL ;(* Where was sym declared.     *)
                   END ;
  
     ConstStringVariant = (m2str, cstr, m2nulstr, cnulstr) ;
*************** BEGIN
*** 4456,4464 ****
        pSym := GetPsym (sym) ;
        IF IsParameterVar (sym)
        THEN
!          RETURN GetVarDeclTok (pSym^.VarParam.ShadowVar)
        ELSE
!          RETURN GetVarDeclTok (pSym^.Param.ShadowVar)
        END
     ELSIF IsVar (sym)
     THEN
--- 4460,4478 ----
        pSym := GetPsym (sym) ;
        IF IsParameterVar (sym)
        THEN
!          IF pSym^.VarParam.ShadowVar = NulSym
!          THEN
!             RETURN pSym^.VarParam.At
!          ELSE
!             RETURN GetVarDeclTok (pSym^.VarParam.ShadowVar)
!          END
        ELSE
!          IF pSym^.Param.ShadowVar = NulSym
!          THEN
!             RETURN pSym^.Param.At
!          ELSE
!             RETURN GetVarDeclTok (pSym^.Param.ShadowVar)
!          END
        END
     ELSIF IsVar (sym)
     THEN
*************** BEGIN
*** 4549,4557 ****
     THEN
        IF IsParameterVar (sym)
        THEN
!          RETURN GetVarDeclFullTok (pSym^.VarParam.ShadowVar)
        ELSE
!          RETURN GetVarDeclFullTok (pSym^.Param.ShadowVar)
        END
     ELSIF IsVar (sym)
     THEN
--- 4563,4571 ----
     THEN
        IF IsParameterVar (sym)
        THEN
!          RETURN pSym^.VarParam.FullTok
        ELSE
!          RETURN pSym^.Param.FullTok
        END
     ELSIF IsVar (sym)
     THEN
*************** BEGIN
*** 10651,10658 ****
              name := ParamName ;
              Type := ParamType ;
              IsUnbounded := isUnbounded ;
              ShadowVar := NulSym ;
!             InitWhereDeclaredTok(tok, At)
           END
        END ;
        AddParameter (Sym, kind, ParSym) ;
--- 10665,10674 ----
              name := ParamName ;
              Type := ParamType ;
              IsUnbounded := isUnbounded ;
+             Scope := Sym ;
              ShadowVar := NulSym ;
!             FullTok := MakeVirtual2Tok (tok, typetok) ;
!             At := tok
           END
        END ;
        AddParameter (Sym, kind, ParSym) ;
*************** BEGIN
*** 10671,10677 ****
              pSym^.Param.ShadowVar := VariableSym
           END
        END ;
!       AddProcedureProcTypeParam (Sym, ParamType, isUnbounded, FALSE)
     END ;
     RETURN( TRUE )
  END PutParam ;
--- 10687,10693 ----
              pSym^.Param.ShadowVar := VariableSym
           END
        END ;
!       AddProcedureProcTypeParam (tok, Sym, ParamType, isUnbounded, FALSE)
     END ;
     RETURN( TRUE )
  END PutParam ;
*************** BEGIN
*** 10708,10716 ****
              name := ParamName ;
              Type := ParamType ;
              IsUnbounded := isUnbounded ;
              ShadowVar := NulSym ;
              HeapVar := NulSym ;  (* Will contain a pointer value.  *)
!             InitWhereDeclaredTok(tok, At)
           END
        END ;
        AddParameter (Sym, kind, ParSym) ;
--- 10724,10734 ----
              name := ParamName ;
              Type := ParamType ;
              IsUnbounded := isUnbounded ;
+             Scope := Sym ;
              ShadowVar := NulSym ;
              HeapVar := NulSym ;  (* Will contain a pointer value.  *)
!             FullTok := MakeVirtual2Tok (tok, typetok) ;
!             At := tok
           END
        END ;
        AddParameter (Sym, kind, ParSym) ;
*************** BEGIN
*** 10729,10735 ****
              pSym^.VarParam.ShadowVar := VariableSym
           END
        END ;
!       AddProcedureProcTypeParam (Sym, ParamType, isUnbounded, TRUE)
     END ;
     RETURN( TRUE )
  END PutVarParam ;
--- 10747,10753 ----
              pSym^.VarParam.ShadowVar := VariableSym
           END
        END ;
!       AddProcedureProcTypeParam (tok, Sym, ParamType, isUnbounded, TRUE)
     END ;
     RETURN( TRUE )
  END PutVarParam ;
*************** END AddParameter ;
*** 10816,10822 ****
                                 associated with procedure Sym.
  *)
  
! PROCEDURE AddProcedureProcTypeParam (Sym, ParamType: CARDINAL;
                                       isUnbounded, isVarParam: BOOLEAN) ;
  VAR
     pSym: PtrToSymbol ;
--- 10834,10841 ----
                                 associated with procedure Sym.
  *)
  
! PROCEDURE AddProcedureProcTypeParam (tok: CARDINAL;
!                                      Sym, ParamType: CARDINAL;
                                       isUnbounded, isVarParam: BOOLEAN) ;
  VAR
     pSym: PtrToSymbol ;
*************** BEGIN
*** 10829,10838 ****
                      THEN
                         IF isVarParam
                         THEN
!                           PutProcTypeVarParam (Procedure.ProcedureType,
                                                 ParamType, isUnbounded)
                         ELSE
!                           PutProcTypeParam (Procedure.ProcedureType,
                                              ParamType, isUnbounded)
                         END
                      END
--- 10848,10859 ----
                      THEN
                         IF isVarParam
                         THEN
!                           PutProcTypeVarParam (tok,
!                                                Procedure.ProcedureType,
                                                 ParamType, isUnbounded)
                         ELSE
!                           PutProcTypeParam (tok,
!                                             Procedure.ProcedureType,
                                              ParamType, isUnbounded)
                         END
                      END
*************** BEGIN
*** 13027,13044 ****
        ConstLitSym        : RETURN( ConstLit.Scope ) |
        ConstStringSym     : RETURN( ConstString.Scope ) |
        ConstVarSym        : RETURN( ConstVar.Scope ) |
!       ParamSym           : IF Param.ShadowVar = NulSym
!                            THEN
!                               RETURN NulSym
!                            ELSE
!                               RETURN( GetScope (Param.ShadowVar) )
!                            END |
!       VarParamSym        : IF VarParam.ShadowVar = NulSym
!                            THEN
!                               RETURN NulSym
!                            ELSE
!                               RETURN( GetScope (VarParam.ShadowVar) )
!                            END |
        UndefinedSym       : RETURN( NulSym ) |
        PartialUnboundedSym: InternalError ('should not be requesting the scope of a PartialUnbounded symbol')
  
--- 13048,13055 ----
        ConstLitSym        : RETURN( ConstLit.Scope ) |
        ConstStringSym     : RETURN( ConstString.Scope ) |
        ConstVarSym        : RETURN( ConstVar.Scope ) |
!       ParamSym           : RETURN( Param.Scope ) |
!       VarParamSym        : RETURN( VarParam.Scope ) |
        UndefinedSym       : RETURN( NulSym ) |
        PartialUnboundedSym: InternalError ('should not be requesting the scope of a PartialUnbounded symbol')
  
*************** END MakeProcType ;
*** 13186,13192 ****
                        ParamType into ProcType Sym.
  *)
  
! PROCEDURE PutProcTypeParam (Sym: CARDINAL;
                              ParamType: CARDINAL; isUnbounded: BOOLEAN) ;
  VAR
     pSym  : PtrToSymbol ;
--- 13197,13204 ----
                        ParamType into ProcType Sym.
  *)
  
! PROCEDURE PutProcTypeParam (tok: CARDINAL;
!                             Sym: CARDINAL;
                              ParamType: CARDINAL; isUnbounded: BOOLEAN) ;
  VAR
     pSym  : PtrToSymbol ;
*************** BEGIN
*** 13201,13207 ****
           Type := ParamType ;
           IsUnbounded := isUnbounded ;
           ShadowVar := NulSym ;
!          InitWhereDeclared(At)
        END
     END ;
     AddParameter (Sym, ProperProcedure, ParSym)
--- 13213,13220 ----
           Type := ParamType ;
           IsUnbounded := isUnbounded ;
           ShadowVar := NulSym ;
!          FullTok := tok ;
!          At := tok
        END
     END ;
     AddParameter (Sym, ProperProcedure, ParSym)
*************** END PutProcTypeParam ;
*** 13213,13219 ****
                           ParamType into ProcType Sym.
  *)
  
! PROCEDURE PutProcTypeVarParam (Sym: CARDINAL;
                                 ParamType: CARDINAL; isUnbounded: BOOLEAN) ;
  VAR
     pSym  : PtrToSymbol ;
--- 13226,13233 ----
                           ParamType into ProcType Sym.
  *)
  
! PROCEDURE PutProcTypeVarParam (tok: CARDINAL;
!                                Sym: CARDINAL;
                                 ParamType: CARDINAL; isUnbounded: BOOLEAN) ;
  VAR
     pSym  : PtrToSymbol ;
*************** BEGIN
*** 13228,13234 ****
           Type := ParamType ;
           IsUnbounded := isUnbounded ;
           ShadowVar := NulSym ;
!          InitWhereDeclared(At)
        END
     END ;
     AddParameter (Sym, ProperProcedure, ParSym)
--- 13242,13249 ----
           Type := ParamType ;
           IsUnbounded := isUnbounded ;
           ShadowVar := NulSym ;
!          FullTok := tok ;
!          At := tok
        END
     END ;
     AddParameter (Sym, ProperProcedure, ParSym)
*************** BEGIN
*** 13918,13925 ****
        UnboundedSym       : RETURN( Unbounded.At.DefDeclared ) |
        ProcedureSym       : RETURN( Procedure.At.DefDeclared ) |
        ProcTypeSym        : RETURN( ProcType.At.DefDeclared ) |
!       ParamSym           : RETURN( Param.At.DefDeclared ) |
!       VarParamSym        : RETURN( VarParam.At.DefDeclared ) |
        ConstStringSym     : RETURN( ConstString.At.DefDeclared ) |
        ConstLitSym        : RETURN( ConstLit.At.DefDeclared ) |
        ConstVarSym        : RETURN( ConstVar.At.DefDeclared ) |
--- 13933,13940 ----
        UnboundedSym       : RETURN( Unbounded.At.DefDeclared ) |
        ProcedureSym       : RETURN( Procedure.At.DefDeclared ) |
        ProcTypeSym        : RETURN( ProcType.At.DefDeclared ) |
!       ParamSym           : RETURN( Param.At ) |
!       VarParamSym        : RETURN( VarParam.At ) |
        ConstStringSym     : RETURN( ConstString.At.DefDeclared ) |
        ConstLitSym        : RETURN( ConstLit.At.DefDeclared ) |
        ConstVarSym        : RETURN( ConstVar.At.DefDeclared ) |
*************** BEGIN
*** 13968,13975 ****
        UnboundedSym       : RETURN( Unbounded.At.ModDeclared ) |
        ProcedureSym       : RETURN( Procedure.At.ModDeclared ) |
        ProcTypeSym        : RETURN( ProcType.At.ModDeclared ) |
!       ParamSym           : RETURN( Param.At.ModDeclared ) |
!       VarParamSym        : RETURN( VarParam.At.ModDeclared ) |
        ConstStringSym     : RETURN( ConstString.At.ModDeclared ) |
        ConstLitSym        : RETURN( ConstLit.At.ModDeclared ) |
        ConstVarSym        : RETURN( ConstVar.At.ModDeclared ) |
--- 13983,13990 ----
        UnboundedSym       : RETURN( Unbounded.At.ModDeclared ) |
        ProcedureSym       : RETURN( Procedure.At.ModDeclared ) |
        ProcTypeSym        : RETURN( ProcType.At.ModDeclared ) |
!       ParamSym           : RETURN( Param.At ) |
!       VarParamSym        : RETURN( VarParam.At ) |
        ConstStringSym     : RETURN( ConstString.At.ModDeclared ) |
        ConstLitSym        : RETURN( ConstLit.At.ModDeclared ) |
        ConstVarSym        : RETURN( ConstVar.At.ModDeclared ) |
*************** BEGIN
*** 14019,14026 ****
        UnboundedSym       : Unbounded.At.DefDeclared := tok |
        ProcedureSym       : Procedure.At.DefDeclared := tok |
        ProcTypeSym        : ProcType.At.DefDeclared := tok |
-       ParamSym           : Param.At.DefDeclared := tok |
-       VarParamSym        : VarParam.At.DefDeclared := tok |
        ConstStringSym     : ConstString.At.DefDeclared := tok |
        ConstLitSym        : ConstLit.At.DefDeclared := tok |
        ConstVarSym        : ConstVar.At.DefDeclared := tok |
--- 14034,14039 ----
*************** BEGIN
*** 14067,14074 ****
        UnboundedSym       : Unbounded.At.ModDeclared := tok |
        ProcedureSym       : Procedure.At.ModDeclared := tok |
        ProcTypeSym        : ProcType.At.ModDeclared := tok |
-       ParamSym           : Param.At.ModDeclared := tok |
-       VarParamSym        : VarParam.At.ModDeclared := tok |
        ConstStringSym     : ConstString.At.ModDeclared := tok |
        ConstLitSym        : ConstLit.At.ModDeclared := tok |
        ConstVarSym        : ConstVar.At.ModDeclared := tok |
--- 14080,14085 ----
*************** BEGIN
*** 14323,14330 ****
--- 14334,14343 ----
        UnboundedSym       : RETURN( Unbounded.At.FirstUsed ) |
        ProcedureSym       : RETURN( Procedure.At.FirstUsed ) |
        ProcTypeSym        : RETURN( ProcType.At.FirstUsed ) |
+       (*
        ParamSym           : RETURN( Param.At.FirstUsed ) |
        VarParamSym        : RETURN( VarParam.At.FirstUsed ) |
+       *)
        ConstStringSym     : RETURN( ConstString.At.FirstUsed ) |
        ConstLitSym        : RETURN( ConstLit.At.FirstUsed ) |
        ConstVarSym        : RETURN( ConstVar.At.FirstUsed ) |
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-gcc/m2color.cc gcc-16-20250727/gcc/m2/gm2-gcc/m2color.cc
*** gcc-16-20250720/gcc/m2/gm2-gcc/m2color.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-gcc/m2color.cc	Sun Jul 27 22:32:09 2025
*************** along with GNU Modula-2; see the file CO
*** 23,29 ****
  #include "m2color.h"
  
  #include "gcc-consolidation.h"
! #include "diagnostic-color.h"
  
  
  char *
--- 23,29 ----
  #include "m2color.h"
  
  #include "gcc-consolidation.h"
! #include "diagnostics/color.h"
  
  
  char *
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-gcc/m2linemap.cc gcc-16-20250727/gcc/m2/gm2-gcc/m2linemap.cc
*** gcc-16-20250720/gcc/m2/gm2-gcc/m2linemap.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-gcc/m2linemap.cc	Sun Jul 27 22:32:09 2025
*************** m2linemap_ErrorAt (location_t location,
*** 188,199 ****
  static void
  m2linemap_ErrorAtf_1 (location_t location, const char *message, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
  
    va_start (ap, message);
!   diagnostic_set_info (&diagnostic, message, &ap, &richloc, DK_ERROR);
    diagnostic_report_diagnostic (global_dc, &diagnostic);
    va_end (ap);
  }
--- 188,200 ----
  static void
  m2linemap_ErrorAtf_1 (location_t location, const char *message, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
  
    va_start (ap, message);
!   diagnostic_set_info (&diagnostic, message, &ap, &richloc,
! 		       diagnostics::kind::error);
    diagnostic_report_diagnostic (global_dc, &diagnostic);
    va_end (ap);
  }
*************** m2linemap_ErrorAtf (location_t location,
*** 209,220 ****
  static void
  m2linemap_WarningAtf_1 (location_t location, const char *message, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
  
    va_start (ap, message);
!   diagnostic_set_info (&diagnostic, message, &ap, &richloc, DK_WARNING);
    diagnostic_report_diagnostic (global_dc, &diagnostic);
    va_end (ap);
  }
--- 210,222 ----
  static void
  m2linemap_WarningAtf_1 (location_t location, const char *message, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
  
    va_start (ap, message);
!   diagnostic_set_info (&diagnostic, message, &ap, &richloc,
! 		       diagnostics::kind::warning);
    diagnostic_report_diagnostic (global_dc, &diagnostic);
    va_end (ap);
  }
*************** m2linemap_WarningAtf (location_t locatio
*** 230,241 ****
  static void
  m2linemap_NoteAtf_1 (location_t location, const char *message, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
  
    va_start (ap, message);
!   diagnostic_set_info (&diagnostic, message, &ap, &richloc, DK_NOTE);
    diagnostic_report_diagnostic (global_dc, &diagnostic);
    va_end (ap);
  }
--- 232,244 ----
  static void
  m2linemap_NoteAtf_1 (location_t location, const char *message, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
  
    va_start (ap, message);
!   diagnostic_set_info (&diagnostic, message, &ap, &richloc,
! 		       diagnostics::kind::note);
    diagnostic_report_diagnostic (global_dc, &diagnostic);
    va_end (ap);
  }
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-gcc/rtegraph.cc gcc-16-20250727/gcc/m2/gm2-gcc/rtegraph.cc
*** gcc-16-20250720/gcc/m2/gm2-gcc/rtegraph.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-gcc/rtegraph.cc	Sun Jul 27 22:32:09 2025
*************** rtegraph_lookup (gimple *g, tree fndecl,
*** 283,291 ****
  /* rte_error_at - wraps up an error message.  */
  
  static void
! rte_error_at (location_t location, diagnostic_t kind, const char *message, ...)
  {
!   diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
  
--- 283,292 ----
  /* rte_error_at - wraps up an error message.  */
  
  static void
! rte_error_at (location_t location, diagnostics::kind kind,
! 	      const char *message, ...)
  {
!   diagnostics::diagnostic_info diagnostic;
    va_list ap;
    rich_location richloc (line_table, location);
  
*************** access_string (tree t, const char **valu
*** 338,344 ****
     give the function context which might be misleading if this is inlined.  */
  
  static void
! generate_report (gimple *stmt, const char *report, diagnostic_t kind)
  {
    if (gimple_call_num_args (stmt) == 5)
      {
--- 339,345 ----
     give the function context which might be misleading if this is inlined.  */
  
  static void
! generate_report (gimple *stmt, const char *report, diagnostics::kind kind)
  {
    if (gimple_call_num_args (stmt) == 5)
      {
*************** const char *rtenode::create_message (con
*** 393,407 ****
    return message;
  }
  
! /* error_message issue an DK_ERROR from grtenode.  */
  
  void rtenode::error_message (void)
  {
    if (grtenode != NULL)
!     generate_report (grtenode, "runtime error will occur", DK_ERROR);
  }
  
! /* warning_message issue an DK_WARNING from grtenode.  */
  
  void rtenode::warning_message (void)
  {
--- 394,409 ----
    return message;
  }
  
! /* error_message issue an diagnostics::kind::error from grtenode.  */
  
  void rtenode::error_message (void)
  {
    if (grtenode != NULL)
!     generate_report (grtenode, "runtime error will occur",
! 		     diagnostics::kind::error);
  }
  
! /* warning_message issue an diagnostics::kind::warning from grtenode.  */
  
  void rtenode::warning_message (void)
  {
*************** void rtenode::warning_message (void)
*** 409,423 ****
      ("runtime error will occur if an exported procedure is called from %s",
       "runtime error will occur if an exported procedure is called");
    if (grtenode != NULL)
!     generate_report (grtenode, message, DK_WARNING);
  }
  
! /* note_message issue an DK_NOTE from grtenode.  */
  
  void rtenode::note_message (void)
  {
    if (grtenode != NULL)
!     generate_report (grtenode, "runtime will occur if this procedure is called", DK_NOTE);
  }
  
  /* dump_vec display contents of vector array list.  */
--- 411,426 ----
      ("runtime error will occur if an exported procedure is called from %s",
       "runtime error will occur if an exported procedure is called");
    if (grtenode != NULL)
!     generate_report (grtenode, message, diagnostics::kind::warning);
  }
  
! /* note_message issue an diagnostics::kind::note from grtenode.  */
  
  void rtenode::note_message (void)
  {
    if (grtenode != NULL)
!     generate_report (grtenode, "runtime will occur if this procedure is called",
! 		     diagnostics::kind::note);
  }
  
  /* dump_vec display contents of vector array list.  */
diff -Nrcpad gcc-16-20250720/gcc/m2/gm2-libs/M2EXCEPTION.mod gcc-16-20250727/gcc/m2/gm2-libs/M2EXCEPTION.mod
*** gcc-16-20250720/gcc/m2/gm2-libs/M2EXCEPTION.mod	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/m2/gm2-libs/M2EXCEPTION.mod	Sun Jul 27 22:32:09 2025
*************** FROM RTExceptions IMPORT EHBlock, GetExc
*** 33,39 ****
  
  (* If the program or coroutine is in the exception state then return the enumeration
     value representing the exception cause.  If it is not in the exception state then
!    raises and exception (exException).  *)
  
  PROCEDURE M2Exception () : M2Exceptions;
  VAR
--- 33,39 ----
  
  (* If the program or coroutine is in the exception state then return the enumeration
     value representing the exception cause.  If it is not in the exception state then
!    raises an exException exception.  *)
  
  PROCEDURE M2Exception () : M2Exceptions;
  VAR
*************** BEGIN
*** 45,51 ****
     IF n = MAX (CARDINAL)
     THEN
        Raise (ORD (exException), ADR (__FILE__), __LINE__, __COLUMN__, ADR (__FUNCTION__),
!              ADR ('current coroutine is not in the exceptional execution state'))
     ELSE
        RETURN VAL (M2Exceptions, n)
     END
--- 45,52 ----
     IF n = MAX (CARDINAL)
     THEN
        Raise (ORD (exException), ADR (__FILE__), __LINE__, __COLUMN__, ADR (__FUNCTION__),
!              ADR ('current coroutine is not in the exceptional execution state')) ;
!       RETURN exException
     ELSE
        RETURN VAL (M2Exceptions, n)
     END
diff -Nrcpad gcc-16-20250720/gcc/match.pd gcc-16-20250727/gcc/match.pd
*** gcc-16-20250720/gcc/match.pd	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/match.pd	Sun Jul 27 22:32:09 2025
*************** DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
*** 7035,7040 ****
--- 7035,7056 ----
      (icmp @0 @1)
      (if (ic == ncmp)
       (ncmp @0 @1)))))
+  /* ((cast)cmp) - 1 -> -(cast)icmp . */
+  (simplify
+   (plus (convert? (cmp@2 @0 @1)) integer_minus_onep)
+   (if (TYPE_PRECISION (type) > 1
+        && INTEGRAL_TYPE_P (TREE_TYPE (@2)) && TYPE_PRECISION (TREE_TYPE (@2)) == 1)
+    /* Comparison inversion may be impossible for trapping math,
+       invert_tree_comparison will tell us.  But we can't use
+       a computed operator in the replacement tree thus we have
+       to play the trick below.  */
+    (with { enum tree_code ic = invert_tree_comparison
+              (cmp, HONOR_NANS (@0));
+            tree cmptype = TREE_TYPE (@2); }
+     (if (ic == icmp)
+      (negate (convert (icmp:cmptype @0 @1)))
+      (if (ic == ncmp)
+       (negate (convert (ncmp:cmptype @0 @1))))))))
   /* The following bits are handled by fold_binary_op_with_conditional_arg.  */
   (simplify
    (ne (cmp@2 @0 @1) integer_zerop)
*************** and,
*** 11678,11681 ****
        && VECTOR_TYPE_P (type)
        && direct_internal_fn_supported_p (IFN_AVG_CEIL, type, OPTIMIZE_FOR_BOTH))
        (IFN_AVG_CEIL @0 @2)))
! #endif
\ No newline at end of file
--- 11694,11697 ----
        && VECTOR_TYPE_P (type)
        && direct_internal_fn_supported_p (IFN_AVG_CEIL, type, OPTIMIZE_FOR_BOTH))
        (IFN_AVG_CEIL @0 @2)))
! #endif
diff -Nrcpad gcc-16-20250720/gcc/optabs-query.cc gcc-16-20250727/gcc/optabs-query.cc
*** gcc-16-20250720/gcc/optabs-query.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/optabs-query.cc	Sun Jul 27 22:32:09 2025
*************** supports_vec_gather_load_p (machine_mode
*** 719,731 ****
  	= (icode != CODE_FOR_nothing) ? 1 : -1;
      }
  
-   /* For gather the optab's operand indices do not match the IFN's because
-      the latter does not have the extension operand (operand 3).  It is
-      implicitly added during expansion so we use the IFN's else index + 1.
-      */
    if (elsvals && icode != CODE_FOR_nothing)
      get_supported_else_vals
!       (icode, internal_fn_else_index (IFN_MASK_GATHER_LOAD) + 1, *elsvals);
  
    return this_fn_optabs->supports_vec_gather_load[mode] > 0;
  }
--- 719,727 ----
  	= (icode != CODE_FOR_nothing) ? 1 : -1;
      }
  
    if (elsvals && icode != CODE_FOR_nothing)
      get_supported_else_vals
!       (icode, internal_fn_else_index (IFN_MASK_GATHER_LOAD), *elsvals);
  
    return this_fn_optabs->supports_vec_gather_load[mode] > 0;
  }
diff -Nrcpad gcc-16-20250720/gcc/optc-gen.awk gcc-16-20250727/gcc/optc-gen.awk
*** gcc-16-20250720/gcc/optc-gen.awk	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/optc-gen.awk	Sun Jul 27 22:32:09 2025
*************** print "                           const
*** 497,503 ****
  print "                           unsigned int lang_mask, int kind,          "
  print "                           location_t loc,                            "
  print "                           const struct cl_option_handlers *handlers, "
! print "                           diagnostic_context *dc)                    "
  print "{                                                                     "
  print "  size_t scode = decoded->opt_index;                                  "
  print "  HOST_WIDE_INT value = decoded->value;                               "
--- 497,503 ----
  print "                           unsigned int lang_mask, int kind,          "
  print "                           location_t loc,                            "
  print "                           const struct cl_option_handlers *handlers, "
! print "                           diagnostics::context *dc)                  "
  print "{                                                                     "
  print "  size_t scode = decoded->opt_index;                                  "
  print "  HOST_WIDE_INT value = decoded->value;                               "
*************** for (i = 0; i < n_langs; i++) {
*** 554,560 ****
      print "                           unsigned int lang_mask" mark_unused ", int kind" mark_unused ",          "
      print "                           location_t loc" mark_unused ",                            "
      print "                           const struct cl_option_handlers *handlers" mark_unused ", "
!     print "                           diagnostic_context *dc" mark_unused ")                    "
      print "{                                                                     "
      print "  enum opt_code code = (enum opt_code) scode;                         "
      print "                                                                      "
--- 554,560 ----
      print "                           unsigned int lang_mask" mark_unused ", int kind" mark_unused ",          "
      print "                           location_t loc" mark_unused ",                            "
      print "                           const struct cl_option_handlers *handlers" mark_unused ", "
!     print "                           diagnostics::context *dc" mark_unused ")                  "
      print "{                                                                     "
      print "  enum opt_code code = (enum opt_code) scode;                         "
      print "                                                                      "
diff -Nrcpad gcc-16-20250720/gcc/opth-gen.awk gcc-16-20250727/gcc/opth-gen.awk
*** gcc-16-20250720/gcc/opth-gen.awk	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/opth-gen.awk	Sun Jul 27 22:32:09 2025
*************** print "                           const
*** 357,363 ****
  print "                           unsigned int lang_mask, int kind,          "
  print "                           location_t loc,                            "
  print "                           const struct cl_option_handlers *handlers, "
! print "                           diagnostic_context *dc);                   "
  for (i = 0; i < n_langs; i++) {
      lang_name = lang_sanitized_name(langs[i]);
      print "bool"
--- 357,363 ----
  print "                           unsigned int lang_mask, int kind,          "
  print "                           location_t loc,                            "
  print "                           const struct cl_option_handlers *handlers, "
! print "                           diagnostics::context *dc);                   "
  for (i = 0; i < n_langs; i++) {
      lang_name = lang_sanitized_name(langs[i]);
      print "bool"
*************** for (i = 0; i < n_langs; i++) {
*** 368,374 ****
      print "                           unsigned int lang_mask, int kind,"
      print "                           location_t loc,"
      print "                           const struct cl_option_handlers *handlers,"
!     print "                           diagnostic_context *dc);"
  }
  print "void cpp_handle_option_auto (const struct gcc_options * opts, size_t scode,"
  print "                             struct cpp_options * cpp_opts);"
--- 368,374 ----
      print "                           unsigned int lang_mask, int kind,"
      print "                           location_t loc,"
      print "                           const struct cl_option_handlers *handlers,"
!     print "                           diagnostics::context *dc);"
  }
  print "void cpp_handle_option_auto (const struct gcc_options * opts, size_t scode,"
  print "                             struct cpp_options * cpp_opts);"
diff -Nrcpad gcc-16-20250720/gcc/opts-common.cc gcc-16-20250727/gcc/opts-common.cc
*** gcc-16-20250720/gcc/opts-common.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/opts-common.cc	Sun Jul 27 22:32:09 2025
*************** keep:
*** 1282,1290 ****
  
  /* Handle option DECODED for the language indicated by LANG_MASK,
     using the handlers in HANDLERS and setting fields in OPTS and
!    OPTS_SET.  KIND is the diagnostic_t if this is a diagnostics
!    option, DK_UNSPECIFIED otherwise, and LOC is the location of the
!    option for options from the source file, UNKNOWN_LOCATION
     otherwise.  GENERATED_P is true for an option generated as part of
     processing another option or otherwise generated internally, false
     for one explicitly passed by the user.  control_warning_option
--- 1282,1290 ----
  
  /* Handle option DECODED for the language indicated by LANG_MASK,
     using the handlers in HANDLERS and setting fields in OPTS and
!    OPTS_SET.  KIND is the enum diagnostics::kind if this is a diagnostics
!    option, diagnostics::kind::unspecified otherwise, and LOC is the location
!    of the option for options from the source file, UNKNOWN_LOCATION
     otherwise.  GENERATED_P is true for an option generated as part of
     processing another option or otherwise generated internally, false
     for one explicitly passed by the user.  control_warning_option
*************** handle_option (struct gcc_options *opts,
*** 1298,1304 ****
  	       const struct cl_decoded_option *decoded,
  	       unsigned int lang_mask, int kind, location_t loc,
  	       const struct cl_option_handlers *handlers,
! 	       bool generated_p, diagnostic_context *dc)
  {
    size_t opt_index = decoded->opt_index;
    const char *arg = decoded->arg;
--- 1298,1304 ----
  	       const struct cl_decoded_option *decoded,
  	       unsigned int lang_mask, int kind, location_t loc,
  	       const struct cl_option_handlers *handlers,
! 	       bool generated_p, diagnostics::context *dc)
  {
    size_t opt_index = decoded->opt_index;
    const char *arg = decoded->arg;
*************** handle_generated_option (struct gcc_opti
*** 1336,1342 ****
  			 size_t opt_index, const char *arg, HOST_WIDE_INT value,
  			 unsigned int lang_mask, int kind, location_t loc,
  			 const struct cl_option_handlers *handlers,
! 			 bool generated_p, diagnostic_context *dc)
  {
    struct cl_decoded_option decoded;
  
--- 1336,1342 ----
  			 size_t opt_index, const char *arg, HOST_WIDE_INT value,
  			 unsigned int lang_mask, int kind, location_t loc,
  			 const struct cl_option_handlers *handlers,
! 			 bool generated_p, diagnostics::context *dc)
  {
    struct cl_decoded_option decoded;
  
*************** read_cmdline_option (struct gcc_options
*** 1604,1610 ****
  		     location_t loc,
  		     unsigned int lang_mask,
  		     const struct cl_option_handlers *handlers,
! 		     diagnostic_context *dc)
  {
    const struct cl_option *option;
    const char *opt = decoded->orig_option_with_args_text;
--- 1604,1610 ----
  		     location_t loc,
  		     unsigned int lang_mask,
  		     const struct cl_option_handlers *handlers,
! 		     diagnostics::context *dc)
  {
    const struct cl_option *option;
    const char *opt = decoded->orig_option_with_args_text;
*************** read_cmdline_option (struct gcc_options
*** 1645,1651 ****
  
    gcc_assert (!decoded->errors);
  
!   if (!handle_option (opts, opts_set, decoded, lang_mask, DK_UNSPECIFIED,
  		      loc, handlers, false, dc))
      error_at (loc, "unrecognized command-line option %qs", opt);
  }
--- 1645,1652 ----
  
    gcc_assert (!decoded->errors);
  
!   if (!handle_option (opts, opts_set, decoded, lang_mask,
! 		      static_cast<int> (diagnostics::kind::unspecified),
  		      loc, handlers, false, dc))
      error_at (loc, "unrecognized command-line option %qs", opt);
  }
*************** read_cmdline_option (struct gcc_options
*** 1658,1664 ****
  void
  set_option (struct gcc_options *opts, struct gcc_options *opts_set,
  	    size_t opt_index, HOST_WIDE_INT value, const char *arg,
! 	    int kind, location_t loc, diagnostic_context *dc,
  	    HOST_WIDE_INT mask /* = 0 */)
  {
    const struct cl_option *option = &cl_options[opt_index];
--- 1659,1665 ----
  void
  set_option (struct gcc_options *opts, struct gcc_options *opts_set,
  	    size_t opt_index, HOST_WIDE_INT value, const char *arg,
! 	    int kind, location_t loc, diagnostics::context *dc,
  	    HOST_WIDE_INT mask /* = 0 */)
  {
    const struct cl_option *option = &cl_options[opt_index];
*************** set_option (struct gcc_options *opts, st
*** 1668,1675 ****
    if (!flag_var)
      return;
  
!   if ((diagnostic_t) kind != DK_UNSPECIFIED && dc != NULL)
!     diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc);
  
    if (opts_set != NULL)
      set_flag_var = option_flag_var (opt_index, opts_set);
--- 1669,1678 ----
    if (!flag_var)
      return;
  
!   if ((enum diagnostics::kind) kind != diagnostics::kind::unspecified
!       && dc != nullptr)
!     diagnostic_classify_diagnostic (dc, opt_index,
! 				    (enum diagnostics::kind) kind, loc);
  
    if (opts_set != NULL)
      set_flag_var = option_flag_var (opt_index, opts_set);
*************** option_enabled (int opt_idx, unsigned la
*** 1874,1880 ****
  
  int
  compiler_diagnostic_option_manager::
! option_enabled_p (diagnostic_option_id opt_id) const
  {
    return option_enabled (opt_id.m_idx, m_lang_mask, m_opts);
  }
--- 1877,1883 ----
  
  int
  compiler_diagnostic_option_manager::
! option_enabled_p (diagnostics::option_id opt_id) const
  {
    return option_enabled (opt_id.m_idx, m_lang_mask, m_opts);
  }
*************** control_warning_option (unsigned int opt
*** 1941,1947 ****
  			const struct cl_option_handlers *handlers,
  			struct gcc_options *opts,
  			struct gcc_options *opts_set,
! 			diagnostic_context *dc)
  {
    if (cl_options[opt_index].alias_target != N_OPTS)
      {
--- 1944,1950 ----
  			const struct cl_option_handlers *handlers,
  			struct gcc_options *opts,
  			struct gcc_options *opts_set,
! 			diagnostics::context *dc)
  {
    if (cl_options[opt_index].alias_target != N_OPTS)
      {
*************** control_warning_option (unsigned int opt
*** 1954,1960 ****
    if (opt_index == OPT_SPECIAL_ignore || opt_index == OPT_SPECIAL_warn_removed)
      return;
    if (dc)
!     diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc);
    if (imply)
      {
        /* -Werror=foo implies -Wfoo.  */
--- 1957,1965 ----
    if (opt_index == OPT_SPECIAL_ignore || opt_index == OPT_SPECIAL_warn_removed)
      return;
    if (dc)
!     diagnostic_classify_diagnostic (dc, opt_index,
! 				    static_cast<enum diagnostics::kind> (kind),
! 				    loc);
    if (imply)
      {
        /* -Werror=foo implies -Wfoo.  */
diff -Nrcpad gcc-16-20250720/gcc/opts-diagnostic.cc gcc-16-20250727/gcc/opts-diagnostic.cc
*** gcc-16-20250720/gcc/opts-diagnostic.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/opts-diagnostic.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 20,26 ****
  
  /* This file implements the options -fdiagnostics-add-output=,
     -fdiagnostics-set-output=.  Most of the work is done
!    by diagnostic-output-spec.cc so it can be shared by libgdiagnostics.  */
  
  #include "config.h"
  #define INCLUDE_ARRAY
--- 20,26 ----
  
  /* This file implements the options -fdiagnostics-add-output=,
     -fdiagnostics-set-output=.  Most of the work is done
!    by diagnostics/output-spec.cc so it can be shared by libgdiagnostics.  */
  
  #include "config.h"
  #define INCLUDE_ARRAY
*************** along with GCC; see the file COPYING3.
*** 31,37 ****
  #include "version.h"
  #include "intl.h"
  #include "diagnostic.h"
! #include "diagnostic-output-spec.h"
  #include "opts.h"
  #include "options.h"
  
--- 31,37 ----
  #include "version.h"
  #include "intl.h"
  #include "diagnostic.h"
! #include "diagnostics/output-spec.h"
  #include "opts.h"
  #include "options.h"
  
*************** along with GCC; see the file COPYING3.
*** 39,57 ****
  
  namespace {
  
! struct opt_spec_context : public diagnostics_output_spec::gcc_spec_context
  {
  public:
    opt_spec_context (const gcc_options &opts,
! 		    diagnostic_context &dc,
  		    line_maps *location_mgr,
  		    location_t loc,
  		    const char *option_name)
!   : gcc_spec_context (dc,
! 		      location_mgr,
! 		      location_mgr,
! 		      loc,
! 		      option_name),
      m_opts (opts)
    {}
  
--- 39,57 ----
  
  namespace {
  
! struct opt_spec_context : public diagnostics::output_spec::dc_spec_context
  {
  public:
    opt_spec_context (const gcc_options &opts,
! 		    diagnostics::context &dc,
  		    line_maps *location_mgr,
  		    location_t loc,
  		    const char *option_name)
!   : dc_spec_context (dc,
! 		     location_mgr,
! 		     location_mgr,
! 		     loc,
! 		     option_name),
      m_opts (opts)
    {}
  
*************** public:
*** 70,76 ****
  
  void
  handle_OPT_fdiagnostics_add_output_ (const gcc_options &opts,
! 				     diagnostic_context &dc,
  				     const char *arg,
  				     location_t loc)
  {
--- 70,76 ----
  
  void
  handle_OPT_fdiagnostics_add_output_ (const gcc_options &opts,
! 				     diagnostics::context &dc,
  				     const char *arg,
  				     location_t loc)
  {
*************** handle_OPT_fdiagnostics_add_output_ (con
*** 89,95 ****
  
  void
  handle_OPT_fdiagnostics_set_output_ (const gcc_options &opts,
! 				     diagnostic_context &dc,
  				     const char *arg,
  				     location_t loc)
  {
--- 89,95 ----
  
  void
  handle_OPT_fdiagnostics_set_output_ (const gcc_options &opts,
! 				     diagnostics::context &dc,
  				     const char *arg,
  				     location_t loc)
  {
*************** handle_OPT_fdiagnostics_set_output_ (con
*** 103,107 ****
      return;
  
    sink->set_main_input_filename (opts.x_main_input_filename);
!   dc.set_output_format (std::move (sink));
  }
--- 103,107 ----
      return;
  
    sink->set_main_input_filename (opts.x_main_input_filename);
!   dc.set_sink (std::move (sink));
  }
diff -Nrcpad gcc-16-20250720/gcc/opts-diagnostic.h gcc-16-20250727/gcc/opts-diagnostic.h
*** gcc-16-20250720/gcc/opts-diagnostic.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/opts-diagnostic.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 20,31 ****
  #ifndef GCC_OPTS_DIAGNOSTIC_H
  #define GCC_OPTS_DIAGNOSTIC_H
  
! /* Abstract subclass of diagnostic_option_manager for gcc options.  */
  
! class gcc_diagnostic_option_manager : public diagnostic_option_manager
  {
  public:
!   char *make_option_url (diagnostic_option_id option_id) const final override;
  
  protected:
    gcc_diagnostic_option_manager (unsigned lang_mask)
--- 20,31 ----
  #ifndef GCC_OPTS_DIAGNOSTIC_H
  #define GCC_OPTS_DIAGNOSTIC_H
  
! /* Abstract subclass of diagnostics::option_manager for gcc options.  */
  
! class gcc_diagnostic_option_manager : public diagnostics::option_manager
  {
  public:
!   char *make_option_url (diagnostics::option_id option_id) const final override;
  
  protected:
    gcc_diagnostic_option_manager (unsigned lang_mask)
*************** protected:
*** 40,46 ****
  class compiler_diagnostic_option_manager : public gcc_diagnostic_option_manager
  {
  public:
!   compiler_diagnostic_option_manager (const diagnostic_context &context,
  				      unsigned lang_mask,
  				      void *opts)
    : gcc_diagnostic_option_manager (lang_mask),
--- 40,46 ----
  class compiler_diagnostic_option_manager : public gcc_diagnostic_option_manager
  {
  public:
!   compiler_diagnostic_option_manager (const diagnostics::context &context,
  				      unsigned lang_mask,
  				      void *opts)
    : gcc_diagnostic_option_manager (lang_mask),
*************** public:
*** 49,73 ****
    {
    }
  
!   int option_enabled_p (diagnostic_option_id option_id) const final override;
!   char *make_option_name (diagnostic_option_id option_id,
! 			  diagnostic_t orig_diag_kind,
! 			  diagnostic_t diag_kind) const final override;
  
  private:
!   const diagnostic_context &m_context;
    void *m_opts;
  };
  
  extern void
  handle_OPT_fdiagnostics_add_output_ (const gcc_options &opts,
! 				     diagnostic_context &dc,
  				     const char *arg,
  				     location_t loc);
  
  extern void
  handle_OPT_fdiagnostics_set_output_ (const gcc_options &opts,
! 				     diagnostic_context &dc,
  				     const char *arg,
  				     location_t loc);
  #endif
--- 49,74 ----
    {
    }
  
!   int option_enabled_p (diagnostics::option_id option_id) const final override;
!   char *
!   make_option_name (diagnostics::option_id option_id,
! 		    enum diagnostics::kind orig_diag_kind,
! 		    enum diagnostics::kind diag_kind) const final override;
  
  private:
!   const diagnostics::context &m_context;
    void *m_opts;
  };
  
  extern void
  handle_OPT_fdiagnostics_add_output_ (const gcc_options &opts,
! 				     diagnostics::context &dc,
  				     const char *arg,
  				     location_t loc);
  
  extern void
  handle_OPT_fdiagnostics_set_output_ (const gcc_options &opts,
! 				     diagnostics::context &dc,
  				     const char *arg,
  				     location_t loc);
  #endif
diff -Nrcpad gcc-16-20250720/gcc/opts-global.cc gcc-16-20250727/gcc/opts-global.cc
*** gcc-16-20250720/gcc/opts-global.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/opts-global.cc	Sun Jul 27 22:32:09 2025
*************** lang_handle_option (struct gcc_options *
*** 181,187 ****
  		    unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
  		    location_t loc,
  		    const struct cl_option_handlers *handlers,
! 		    diagnostic_context *dc,
  		    void (*) (void))
  {
    gcc_assert (opts == &global_options);
--- 181,187 ----
  		    unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
  		    location_t loc,
  		    const struct cl_option_handlers *handlers,
! 		    diagnostics::context *dc,
  		    void (*) (void))
  {
    gcc_assert (opts == &global_options);
*************** read_cmdline_options (struct gcc_options
*** 215,221 ****
  		      location_t loc,
  		      unsigned int lang_mask,
  		      const struct cl_option_handlers *handlers,
! 		      diagnostic_context *dc)
  {
    unsigned int i;
  
--- 215,221 ----
  		      location_t loc,
  		      unsigned int lang_mask,
  		      const struct cl_option_handlers *handlers,
! 		      diagnostics::context *dc)
  {
    unsigned int i;
  
*************** void
*** 312,318 ****
  decode_options (struct gcc_options *opts, struct gcc_options *opts_set,
  		struct cl_decoded_option *decoded_options,
  		unsigned int decoded_options_count,
! 		location_t loc, diagnostic_context *dc,
  		void (*target_option_override_hook) (void))
  {
    struct cl_option_handlers handlers;
--- 312,318 ----
  decode_options (struct gcc_options *opts, struct gcc_options *opts_set,
  		struct cl_decoded_option *decoded_options,
  		unsigned int decoded_options_count,
! 		location_t loc, diagnostics::context *dc,
  		void (*target_option_override_hook) (void))
  {
    struct cl_option_handlers handlers;
diff -Nrcpad gcc-16-20250720/gcc/opts.cc gcc-16-20250727/gcc/opts.cc
*** gcc-16-20250720/gcc/opts.cc	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/opts.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 31,38 ****
  #include "common/common-target.h"
  #include "spellcheck.h"
  #include "opt-suggestions.h"
! #include "diagnostic-color.h"
! #include "diagnostic-format.h"
  #include "version.h"
  #include "selftest.h"
  #include "file-prefix-map.h"
--- 31,38 ----
  #include "common/common-target.h"
  #include "spellcheck.h"
  #include "opt-suggestions.h"
! #include "diagnostics/color.h"
! #include "diagnostics/sink.h"
  #include "version.h"
  #include "selftest.h"
  #include "file-prefix-map.h"
*************** static void set_debug_level (uint32_t di
*** 347,353 ****
  			     location_t loc);
  static void set_fast_math_flags (struct gcc_options *opts, int set);
  static void decode_d_option (const char *arg, struct gcc_options *opts,
! 			     location_t loc, diagnostic_context *dc);
  static void set_unsafe_math_optimizations_flags (struct gcc_options *opts,
  						 int set);
  static void enable_warning_as_error (const char *arg, int value,
--- 347,353 ----
  			     location_t loc);
  static void set_fast_math_flags (struct gcc_options *opts, int set);
  static void decode_d_option (const char *arg, struct gcc_options *opts,
! 			     location_t loc, diagnostics::context *dc);
  static void set_unsafe_math_optimizations_flags (struct gcc_options *opts,
  						 int set);
  static void enable_warning_as_error (const char *arg, int value,
*************** static void enable_warning_as_error (con
*** 356,362 ****
  				     struct gcc_options *opts,
  				     struct gcc_options *opts_set,
  				     location_t loc,
! 				     diagnostic_context *dc);
  
  /* Handle a back-end option; arguments and return value as for
     handle_option.  */
--- 356,362 ----
  				     struct gcc_options *opts,
  				     struct gcc_options *opts_set,
  				     location_t loc,
! 				     diagnostics::context *dc);
  
  /* Handle a back-end option; arguments and return value as for
     handle_option.  */
*************** target_handle_option (struct gcc_options
*** 368,377 ****
  		      unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
  		      location_t loc,
  		      const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
! 		      diagnostic_context *dc, void (*) (void))
  {
    gcc_assert (dc == global_dc);
!   gcc_assert (kind == DK_UNSPECIFIED);
    return targetm_common.handle_option (opts, opts_set, decoded, loc);
  }
  
--- 368,378 ----
  		      unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
  		      location_t loc,
  		      const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
! 		      diagnostics::context *dc, void (*) (void))
  {
    gcc_assert (dc == global_dc);
!   gcc_assert (static_cast<diagnostics::kind> (kind)
! 	      == diagnostics::kind::unspecified);
    return targetm_common.handle_option (opts, opts_set, decoded, loc);
  }
  
*************** maybe_default_option (struct gcc_options
*** 469,475 ****
  		      unsigned int lang_mask,
  		      const struct cl_option_handlers *handlers,
  		      location_t loc,
! 		      diagnostic_context *dc)
  {
    const struct cl_option *option = &cl_options[default_opt->opt_index];
    bool enabled;
--- 470,476 ----
  		      unsigned int lang_mask,
  		      const struct cl_option_handlers *handlers,
  		      location_t loc,
! 		      diagnostics::context *dc)
  {
    const struct cl_option *option = &cl_options[default_opt->opt_index];
    bool enabled;
*************** maybe_default_option (struct gcc_options
*** 535,548 ****
    if (enabled)
      handle_generated_option (opts, opts_set, default_opt->opt_index,
  			     default_opt->arg, default_opt->value,
! 			     lang_mask, DK_UNSPECIFIED, loc,
  			     handlers, true, dc);
    else if (default_opt->arg == NULL
  	   && !option->cl_reject_negative
  	   && !(option->flags & CL_PARAMS))
      handle_generated_option (opts, opts_set, default_opt->opt_index,
  			     default_opt->arg, !default_opt->value,
! 			     lang_mask, DK_UNSPECIFIED, loc,
  			     handlers, true, dc);
  }
  
--- 536,553 ----
    if (enabled)
      handle_generated_option (opts, opts_set, default_opt->opt_index,
  			     default_opt->arg, default_opt->value,
! 			     lang_mask,
! 			     static_cast<int> (diagnostics::kind::unspecified),
! 			     loc,
  			     handlers, true, dc);
    else if (default_opt->arg == NULL
  	   && !option->cl_reject_negative
  	   && !(option->flags & CL_PARAMS))
      handle_generated_option (opts, opts_set, default_opt->opt_index,
  			     default_opt->arg, !default_opt->value,
! 			     lang_mask,
! 			     static_cast<int> (diagnostics::kind::unspecified),
! 			     loc,
  			     handlers, true, dc);
  }
  
*************** maybe_default_options (struct gcc_option
*** 559,565 ****
  		       unsigned int lang_mask,
  		       const struct cl_option_handlers *handlers,
  		       location_t loc,
! 		       diagnostic_context *dc)
  {
    size_t i;
  
--- 564,570 ----
  		       unsigned int lang_mask,
  		       const struct cl_option_handlers *handlers,
  		       location_t loc,
! 		       diagnostics::context *dc)
  {
    size_t i;
  
*************** default_options_optimization (struct gcc
*** 727,733 ****
  			      location_t loc,
  			      unsigned int lang_mask,
  			      const struct cl_option_handlers *handlers,
! 			      diagnostic_context *dc)
  {
    unsigned int i;
    int opt2;
--- 732,738 ----
  			      location_t loc,
  			      unsigned int lang_mask,
  			      const struct cl_option_handlers *handlers,
! 			      diagnostics::context *dc)
  {
    unsigned int i;
    int opt2;
*************** common_handle_option (struct gcc_options
*** 2703,2709 ****
  		      unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
  		      location_t loc,
  		      const struct cl_option_handlers *handlers,
! 		      diagnostic_context *dc,
  		      void (*target_option_override_hook) (void))
  {
    size_t scode = decoded->opt_index;
--- 2708,2714 ----
  		      unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
  		      location_t loc,
  		      const struct cl_option_handlers *handlers,
! 		      diagnostics::context *dc,
  		      void (*target_option_override_hook) (void))
  {
    size_t scode = decoded->opt_index;
*************** common_handle_option (struct gcc_options
*** 2957,2975 ****
        break;
  
      case OPT_fdiagnostics_show_caret:
!       dc->m_source_printing.enabled = value;
        break;
  
      case OPT_fdiagnostics_show_event_links:
!       dc->m_source_printing.show_event_links_p = value;
        break;
  
      case OPT_fdiagnostics_show_labels:
!       dc->m_source_printing.show_labels_p = value;
        break;
  
      case OPT_fdiagnostics_show_line_numbers:
!       dc->m_source_printing.show_line_numbers_p = value;
        break;
  
      case OPT_fdiagnostics_color_:
--- 2962,2980 ----
        break;
  
      case OPT_fdiagnostics_show_caret:
!       dc->get_source_printing_options ().enabled = value;
        break;
  
      case OPT_fdiagnostics_show_event_links:
!       dc->get_source_printing_options ().show_event_links_p = value;
        break;
  
      case OPT_fdiagnostics_show_labels:
!       dc->get_source_printing_options ().show_labels_p = value;
        break;
  
      case OPT_fdiagnostics_show_line_numbers:
!       dc->get_source_printing_options ().show_line_numbers_p = value;
        break;
  
      case OPT_fdiagnostics_color_:
*************** common_handle_option (struct gcc_options
*** 2985,2994 ****
  	  const char *basename = (opts->x_dump_base_name ? opts->x_dump_base_name
  				  : opts->x_main_input_basename);
  	  gcc_assert (dc);
! 	  diagnostic_output_format_init (*dc,
! 					 opts->x_main_input_filename, basename,
! 					 (enum diagnostics_output_format)value,
! 					 opts->x_flag_diagnostics_json_formatting);
  	  break;
  	}
  
--- 2990,2999 ----
  	  const char *basename = (opts->x_dump_base_name ? opts->x_dump_base_name
  				  : opts->x_main_input_basename);
  	  gcc_assert (dc);
! 	  diagnostics::output_format_init (*dc,
! 					   opts->x_main_input_filename, basename,
! 					   (enum diagnostics_output_format)value,
! 					   opts->x_flag_diagnostics_json_formatting);
  	  break;
  	}
  
*************** common_handle_option (struct gcc_options
*** 3047,3053 ****
        break;
  
      case OPT_fdiagnostics_minimum_margin_width_:
!       dc->m_source_printing.min_margin_width = value;
        break;
  
      case OPT_fdump_:
--- 3052,3058 ----
        break;
  
      case OPT_fdiagnostics_minimum_margin_width_:
!       dc->get_source_printing_options ().min_margin_width = value;
        break;
  
      case OPT_fdump_:
*************** common_handle_option (struct gcc_options
*** 3085,3091 ****
  
      case OPT_fmessage_length_:
        pp_set_line_maximum_length (dc->get_reference_printer (), value);
!       diagnostic_set_caret_max_width (dc, value);
        break;
  
      case OPT_fopt_info:
--- 3090,3096 ----
  
      case OPT_fmessage_length_:
        pp_set_line_maximum_length (dc->get_reference_printer (), value);
!       dc->set_caret_max_width (value);
        break;
  
      case OPT_fopt_info:
*************** common_handle_option (struct gcc_options
*** 3317,3323 ****
  
      case OPT_pedantic_errors:
        dc->m_pedantic_errors = 1;
!       control_warning_option (OPT_Wpedantic, DK_ERROR, NULL, value,
  			      loc, lang_mask,
  			      handlers, opts, opts_set,
                                dc);
--- 3322,3330 ----
  
      case OPT_pedantic_errors:
        dc->m_pedantic_errors = 1;
!       control_warning_option (OPT_Wpedantic,
! 			      static_cast<int> (diagnostics::kind::error),
! 			      NULL, value,
  			      loc, lang_mask,
  			      handlers, opts, opts_set,
                                dc);
*************** set_debug_level (uint32_t dinfo, int ext
*** 3618,3624 ****
     abort ().)  */
  
  static void
! setup_core_dumping (diagnostic_context *dc)
  {
  #ifdef SIGABRT
    signal (SIGABRT, SIG_DFL);
--- 3625,3631 ----
     abort ().)  */
  
  static void
! setup_core_dumping (diagnostics::context *dc)
  {
  #ifdef SIGABRT
    signal (SIGABRT, SIG_DFL);
*************** setup_core_dumping (diagnostic_context *
*** 3642,3648 ****
  
  static void
  decode_d_option (const char *arg, struct gcc_options *opts,
! 		 location_t loc, diagnostic_context *dc)
  {
    int c;
  
--- 3649,3655 ----
  
  static void
  decode_d_option (const char *arg, struct gcc_options *opts,
! 		 location_t loc, diagnostics::context *dc)
  {
    int c;
  
*************** enable_warning_as_error (const char *arg
*** 3691,3697 ****
  			 const struct cl_option_handlers *handlers,
  			 struct gcc_options *opts,
  			 struct gcc_options *opts_set,
! 			 location_t loc, diagnostic_context *dc)
  {
    char *new_option;
    int option_index;
--- 3698,3704 ----
  			 const struct cl_option_handlers *handlers,
  			 struct gcc_options *opts,
  			 struct gcc_options *opts_set,
! 			 location_t loc, diagnostics::context *dc)
  {
    char *new_option;
    int option_index;
*************** enable_warning_as_error (const char *arg
*** 3717,3723 ****
  	      "controls warnings", arg, new_option);
    else
      {
!       const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
        const char *arg = NULL;
  
        if (cl_options[option_index].flags & CL_JOINED)
--- 3724,3732 ----
  	      "controls warnings", arg, new_option);
    else
      {
!       const enum diagnostics::kind kind = (value
! 					   ? diagnostics::kind::error
! 					   : diagnostics::kind::warning);
        const char *arg = NULL;
  
        if (cl_options[option_index].flags & CL_JOINED)
*************** enable_warning_as_error (const char *arg
*** 3736,3750 ****
  
  char *
  compiler_diagnostic_option_manager::
! make_option_name (diagnostic_option_id option_id,
! 		  diagnostic_t orig_diag_kind,
! 		  diagnostic_t diag_kind) const
  {
    if (option_id.m_idx)
      {
        /* A warning classified as an error.  */
!       if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN)
! 	  && diag_kind == DK_ERROR)
  	return concat (cl_options[OPT_Werror_].opt_text,
  		       /* Skip over "-W".  */
  		       cl_options[option_id.m_idx].opt_text + 2,
--- 3745,3760 ----
  
  char *
  compiler_diagnostic_option_manager::
! make_option_name (diagnostics::option_id option_id,
! 		  enum diagnostics::kind orig_diag_kind,
! 		  enum diagnostics::kind diag_kind) const
  {
    if (option_id.m_idx)
      {
        /* A warning classified as an error.  */
!       if ((orig_diag_kind == diagnostics::kind::warning
! 	   || orig_diag_kind == diagnostics::kind::pedwarn)
! 	  && diag_kind == diagnostics::kind::error)
  	return concat (cl_options[OPT_Werror_].opt_text,
  		       /* Skip over "-W".  */
  		       cl_options[option_id.m_idx].opt_text + 2,
*************** make_option_name (diagnostic_option_id o
*** 3754,3761 ****
  	return xstrdup (cl_options[option_id.m_idx].opt_text);
      }
    /* A warning without option classified as an error.  */
!   else if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN
! 	    || diag_kind == DK_WARNING)
  	   && m_context.warning_as_error_requested_p ())
      return xstrdup (cl_options[OPT_Werror].opt_text);
    else
--- 3764,3772 ----
  	return xstrdup (cl_options[option_id.m_idx].opt_text);
      }
    /* A warning without option classified as an error.  */
!   else if ((orig_diag_kind == diagnostics::kind::warning
! 	    || orig_diag_kind == diagnostics::kind::pedwarn
! 	    || diag_kind == diagnostics::kind::warning)
  	   && m_context.warning_as_error_requested_p ())
      return xstrdup (cl_options[OPT_Werror].opt_text);
    else
*************** get_option_url_suffix (int option_index,
*** 3813,3819 ****
  
  char *
  gcc_diagnostic_option_manager::
! make_option_url (diagnostic_option_id option_id) const
  {
    if (option_id.m_idx)
      {
--- 3824,3830 ----
  
  char *
  gcc_diagnostic_option_manager::
! make_option_url (diagnostics::option_id option_id) const
  {
    if (option_id.m_idx)
      {
diff -Nrcpad gcc-16-20250720/gcc/opts.h gcc-16-20250727/gcc/opts.h
*** gcc-16-20250720/gcc/opts.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/opts.h	Sun Jul 27 22:32:09 2025
*************** struct cl_option_handler_func
*** 313,319 ****
  		   const struct cl_decoded_option *decoded,
  		   unsigned int lang_mask, int kind, location_t loc,
  		   const struct cl_option_handlers *handlers,
! 		   diagnostic_context *dc,
  		   void (*target_option_override_hook) (void));
  
    /* The mask that must have some bit in common with the flags for the
--- 313,319 ----
  		   const struct cl_decoded_option *decoded,
  		   unsigned int lang_mask, int kind, location_t loc,
  		   const struct cl_option_handlers *handlers,
! 		   diagnostics::context *dc,
  		   void (*target_option_override_hook) (void));
  
    /* The mask that must have some bit in common with the flags for the
*************** extern void decode_options (struct gcc_o
*** 390,396 ****
  			    struct cl_decoded_option *decoded_options,
  			    unsigned int decoded_options_count,
  			    location_t loc,
! 			    diagnostic_context *dc,
  			    void (*target_option_override_hook) (void));
  extern int option_enabled (int opt_idx, unsigned lang_mask, void *opts);
  
--- 390,396 ----
  			    struct cl_decoded_option *decoded_options,
  			    unsigned int decoded_options_count,
  			    location_t loc,
! 			    diagnostics::context *dc,
  			    void (*target_option_override_hook) (void));
  extern int option_enabled (int opt_idx, unsigned lang_mask, void *opts);
  
*************** extern bool get_option_state (struct gcc
*** 399,405 ****
  extern void set_option (struct gcc_options *opts,
  			struct gcc_options *opts_set,
  			size_t opt_index, HOST_WIDE_INT value, const char *arg,
! 			int kind, location_t loc, diagnostic_context *dc,
  			HOST_WIDE_INT = 0);
  extern void *option_flag_var (int opt_index, struct gcc_options *opts);
  bool handle_generated_option (struct gcc_options *opts,
--- 399,405 ----
  extern void set_option (struct gcc_options *opts,
  			struct gcc_options *opts_set,
  			size_t opt_index, HOST_WIDE_INT value, const char *arg,
! 			int kind, location_t loc, diagnostics::context *dc,
  			HOST_WIDE_INT = 0);
  extern void *option_flag_var (int opt_index, struct gcc_options *opts);
  bool handle_generated_option (struct gcc_options *opts,
*************** bool handle_generated_option (struct gcc
*** 408,414 ****
  			      HOST_WIDE_INT value,
  			      unsigned int lang_mask, int kind, location_t loc,
  			      const struct cl_option_handlers *handlers,
! 			      bool generated_p, diagnostic_context *dc);
  void generate_option (size_t opt_index, const char *arg, HOST_WIDE_INT value,
  		      unsigned int lang_mask,
  		      struct cl_decoded_option *decoded);
--- 408,414 ----
  			      HOST_WIDE_INT value,
  			      unsigned int lang_mask, int kind, location_t loc,
  			      const struct cl_option_handlers *handlers,
! 			      bool generated_p, diagnostics::context *dc);
  void generate_option (size_t opt_index, const char *arg, HOST_WIDE_INT value,
  		      unsigned int lang_mask,
  		      struct cl_decoded_option *decoded);
*************** extern void read_cmdline_option (struct
*** 420,433 ****
  				 location_t loc,
  				 unsigned int lang_mask,
  				 const struct cl_option_handlers *handlers,
! 				 diagnostic_context *dc);
  extern void control_warning_option (unsigned int opt_index, int kind,
  				    const char *arg, bool imply, location_t loc,
  				    unsigned int lang_mask,
  				    const struct cl_option_handlers *handlers,
  				    struct gcc_options *opts,
  				    struct gcc_options *opts_set,
! 				    diagnostic_context *dc);
  extern char *write_langs (unsigned int mask);
  extern void print_ignored_options (void);
  extern void handle_common_deferred_options (void);
--- 420,433 ----
  				 location_t loc,
  				 unsigned int lang_mask,
  				 const struct cl_option_handlers *handlers,
! 				 diagnostics::context *dc);
  extern void control_warning_option (unsigned int opt_index, int kind,
  				    const char *arg, bool imply, location_t loc,
  				    unsigned int lang_mask,
  				    const struct cl_option_handlers *handlers,
  				    struct gcc_options *opts,
  				    struct gcc_options *opts_set,
! 				    diagnostics::context *dc);
  extern char *write_langs (unsigned int mask);
  extern void print_ignored_options (void);
  extern void handle_common_deferred_options (void);
*************** extern bool common_handle_option (struct
*** 442,448 ****
  				  unsigned int lang_mask, int kind,
  				  location_t loc,
  				  const struct cl_option_handlers *handlers,
! 				  diagnostic_context *dc,
  				  void (*target_option_override_hook) (void));
  extern bool target_handle_option (struct gcc_options *opts,
  				  struct gcc_options *opts_set,
--- 442,448 ----
  				  unsigned int lang_mask, int kind,
  				  location_t loc,
  				  const struct cl_option_handlers *handlers,
! 				  diagnostics::context *dc,
  				  void (*target_option_override_hook) (void));
  extern bool target_handle_option (struct gcc_options *opts,
  				  struct gcc_options *opts_set,
*************** extern bool target_handle_option (struct
*** 450,456 ****
  				  unsigned int lang_mask, int kind,
  				  location_t loc,
  				  const struct cl_option_handlers *handlers,
! 				  diagnostic_context *dc,
  				  void (*target_option_override_hook) (void));
  extern void finish_options (struct gcc_options *opts,
  			    struct gcc_options *opts_set,
--- 450,456 ----
  				  unsigned int lang_mask, int kind,
  				  location_t loc,
  				  const struct cl_option_handlers *handlers,
! 				  diagnostics::context *dc,
  				  void (*target_option_override_hook) (void));
  extern void finish_options (struct gcc_options *opts,
  			    struct gcc_options *opts_set,
*************** extern void default_options_optimization
*** 466,472 ****
  					  location_t loc,
  					  unsigned int lang_mask,
  					  const struct cl_option_handlers *handlers,
! 					  diagnostic_context *dc);
  extern void set_struct_debug_option (struct gcc_options *opts,
  				     location_t loc,
  				     const char *value);
--- 466,472 ----
  					  location_t loc,
  					  unsigned int lang_mask,
  					  const struct cl_option_handlers *handlers,
! 					  diagnostics::context *dc);
  extern void set_struct_debug_option (struct gcc_options *opts,
  				     location_t loc,
  				     const char *value);
diff -Nrcpad gcc-16-20250720/gcc/output.h gcc-16-20250727/gcc/output.h
*** gcc-16-20250720/gcc/output.h	Sun Jul 20 22:32:09 2025
--- gcc-16-20250727/gcc/output.h	Sun Jul 27 22:32:09 2025
*************** extern int default_address_cost (rtx, ma
*** 639,642 ****
--- 639,644 ----
  /* Stack usage.  */
  extern void output_stack_usage (void);
  
+ extern void verify_reg_names_in_constraints ();
+ 
  #endif /* ! GCC_OUTPUT_H */
diff -Nrcpad gcc-16-20250720/gcc/pretty-print-format-impl.h gcc-16-20250727/gcc/pretty-print-format-impl.h
*** gcc-16-20250720/gcc/pretty-print-format-impl.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/pretty-print-format-impl.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 22,28 ****
  #define GCC_PRETTY_PRINT_FORMAT_IMPL_H
  
  #include "pretty-print.h"
! #include "diagnostic-event-id.h"
  
  /* A struct representing a pending item to be printed within
     pp_format.
--- 22,28 ----
  #define GCC_PRETTY_PRINT_FORMAT_IMPL_H
  
  #include "pretty-print.h"
! #include "diagnostics/event-id.h"
  
  /* A struct representing a pending item to be printed within
     pp_format.
*************** struct pp_token_end_url : public pp_toke
*** 224,237 ****
  
  struct pp_token_event_id : public pp_token
  {
!   pp_token_event_id (diagnostic_event_id_t event_id)
    : pp_token (kind::event_id),
      m_event_id (event_id)
    {
      gcc_assert (event_id.known_p ());
    }
  
!   diagnostic_event_id_t m_event_id;
  };
  
  template <>
--- 224,237 ----
  
  struct pp_token_event_id : public pp_token
  {
!   pp_token_event_id (diagnostics::paths::event_id_t event_id)
    : pp_token (kind::event_id),
      m_event_id (event_id)
    {
      gcc_assert (event_id.known_p ());
    }
  
!   diagnostics::paths::event_id_t m_event_id;
  };
  
  template <>
diff -Nrcpad gcc-16-20250720/gcc/pretty-print-markup.h gcc-16-20250727/gcc/pretty-print-markup.h
*** gcc-16-20250720/gcc/pretty-print-markup.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/pretty-print-markup.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 20,26 ****
  #ifndef GCC_PRETTY_PRINT_MARKUP_H
  #define GCC_PRETTY_PRINT_MARKUP_H
  
! #include "diagnostic-color.h"
  
  class pp_token_list;
  
--- 20,26 ----
  #ifndef GCC_PRETTY_PRINT_MARKUP_H
  #define GCC_PRETTY_PRINT_MARKUP_H
  
! #include "diagnostics/color.h"
  
  class pp_token_list;
  
diff -Nrcpad gcc-16-20250720/gcc/pretty-print.cc gcc-16-20250727/gcc/pretty-print.cc
*** gcc-16-20250720/gcc/pretty-print.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/pretty-print.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 27,34 ****
  #include "pretty-print-format-impl.h"
  #include "pretty-print-markup.h"
  #include "pretty-print-urlifier.h"
! #include "diagnostic-color.h"
! #include "diagnostic-event-id.h"
  #include "diagnostic-highlight-colors.h"
  #include "auto-obstack.h"
  #include "selftest.h"
--- 27,34 ----
  #include "pretty-print-format-impl.h"
  #include "pretty-print-markup.h"
  #include "pretty-print-urlifier.h"
! #include "diagnostics/color.h"
! #include "diagnostics/event-id.h"
  #include "diagnostic-highlight-colors.h"
  #include "auto-obstack.h"
  #include "selftest.h"
*************** test_pp_format ()
*** 3413,3420 ****
  			    "foo", 0x12345678);
    /* Verify "%@".  */
    {
!     diagnostic_event_id_t first (2);
!     diagnostic_event_id_t second (7);
  
      ASSERT_PP_FORMAT_2 ("first `free' at (3); second `free' at (8)",
  			"first %<free%> at %@; second %<free%> at %@",
--- 3413,3420 ----
  			    "foo", 0x12345678);
    /* Verify "%@".  */
    {
!     diagnostics::paths::event_id_t first (2);
!     diagnostics::paths::event_id_t second (7);
  
      ASSERT_PP_FORMAT_2 ("first `free' at (3); second `free' at (8)",
  			"first %<free%> at %@; second %<free%> at %@",
diff -Nrcpad gcc-16-20250720/gcc/pretty-print.h gcc-16-20250727/gcc/pretty-print.h
*** gcc-16-20250720/gcc/pretty-print.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/pretty-print.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 23,29 ****
  
  #include "obstack.h"
  #include "rich-location.h"
! #include "diagnostic-url.h"
  
  /* Maximum number of format string arguments.  */
  #define PP_NL_ARGMAX   30
--- 23,29 ----
  
  #include "obstack.h"
  #include "rich-location.h"
! #include "diagnostics/url.h"
  
  /* Maximum number of format string arguments.  */
  #define PP_NL_ARGMAX   30
diff -Nrcpad gcc-16-20250720/gcc/recog.cc gcc-16-20250727/gcc/recog.cc
*** gcc-16-20250720/gcc/recog.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/recog.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 25,30 ****
--- 25,31 ----
  #include "target.h"
  #include "rtl.h"
  #include "tree.h"
+ #include "stmt.h"
  #include "cfghooks.h"
  #include "df.h"
  #include "memmodel.h"
*************** asm_operand_ok (rtx op, const char *cons
*** 2363,2369 ****
  	    {
  	    case CT_REGISTER:
  	      if (!result
! 		  && reg_class_for_constraint (cn) != NO_REGS
  		  && GET_MODE (op) != BLKmode
  		  && register_operand (op, VOIDmode))
  		result = 1;
--- 2364,2371 ----
  	    {
  	    case CT_REGISTER:
  	      if (!result
! 		  && (reg_class_for_constraint (cn) != NO_REGS
! 		      || constraint[0] == '{')
  		  && GET_MODE (op) != BLKmode
  		  && register_operand (op, VOIDmode))
  		result = 1;
*************** constrain_operands (int strict, alternat
*** 3304,3309 ****
--- 3306,3318 ----
  		  win = true;
  		break;
  
+ 	      case '{':
+ 		if ((REG_P (op) && HARD_REGISTER_P (op)
+ 		     && (int) REGNO (op) == decode_hard_reg_constraint (p))
+ 		    || !reload_completed)
+ 		  win = true;
+ 		break;
+ 
  	      default:
  		{
  		  enum constraint_num cn = lookup_constraint (p);
diff -Nrcpad gcc-16-20250720/gcc/rtl-error.cc gcc-16-20250727/gcc/rtl-error.cc
*** gcc-16-20250720/gcc/rtl-error.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/rtl-error.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 28,34 ****
  
  static location_t location_for_asm (const rtx_insn *);
  static void diagnostic_for_asm (const rtx_insn *, const char *, va_list *,
! 				diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
  
  /* Figure the location of the given INSN.  */
  static location_t
--- 28,34 ----
  
  static location_t location_for_asm (const rtx_insn *);
  static void diagnostic_for_asm (const rtx_insn *, const char *, va_list *,
! 				enum diagnostics::kind) ATTRIBUTE_GCC_DIAG(2,0);
  
  /* Figure the location of the given INSN.  */
  static location_t
*************** location_for_asm (const rtx_insn *insn)
*** 64,72 ****
     and each ASM_OPERANDS records its own source file and line.  */
  static void
  diagnostic_for_asm (const rtx_insn *insn, const char *msg, va_list *args_ptr,
! 		    diagnostic_t kind)
  {
!   diagnostic_info diagnostic;
    rich_location richloc (line_table, location_for_asm (insn));
  
    diagnostic_set_info (&diagnostic, msg, args_ptr,
--- 64,72 ----
     and each ASM_OPERANDS records its own source file and line.  */
  static void
  diagnostic_for_asm (const rtx_insn *insn, const char *msg, va_list *args_ptr,
! 		    enum diagnostics::kind kind)
  {
!   diagnostics::diagnostic_info diagnostic;
    rich_location richloc (line_table, location_for_asm (insn));
  
    diagnostic_set_info (&diagnostic, msg, args_ptr,
*************** error_for_asm (const rtx_insn *insn, con
*** 80,86 ****
    va_list ap;
  
    va_start (ap, gmsgid);
!   diagnostic_for_asm (insn, gmsgid, &ap, DK_ERROR);
    va_end (ap);
  }
  
--- 80,86 ----
    va_list ap;
  
    va_start (ap, gmsgid);
!   diagnostic_for_asm (insn, gmsgid, &ap, diagnostics::kind::error);
    va_end (ap);
  }
  
*************** warning_for_asm (const rtx_insn *insn, c
*** 90,96 ****
    va_list ap;
  
    va_start (ap, gmsgid);
!   diagnostic_for_asm (insn, gmsgid, &ap, DK_WARNING);
    va_end (ap);
  }
  
--- 90,96 ----
    va_list ap;
  
    va_start (ap, gmsgid);
!   diagnostic_for_asm (insn, gmsgid, &ap, diagnostics::kind::warning);
    va_end (ap);
  }
  
diff -Nrcpad gcc-16-20250720/gcc/rust/ChangeLog gcc-16-20250727/gcc/rust/ChangeLog
*** gcc-16-20250720/gcc/rust/ChangeLog	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/rust/ChangeLog	Sun Jul 27 22:32:09 2025
***************
*** 1,3 ****
--- 1,37 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* resolve/rust-ice-finalizer.cc: Update usage of "diagnostic_info"
+ 	to explicitly refer to "diagnostics::diagnostic_info".
+ 	* resolve/rust-ice-finalizer.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* backend/rust-tree.cc: Update for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 	* backend/rust-tree.h: Likewise.
+ 	* resolve/rust-ast-resolve-expr.cc: Likewise.
+ 	* resolve/rust-ice-finalizer.cc: Likewise.
+ 	* resolve/rust-ice-finalizer.h: Likewise.
+ 	* resolve/rust-late-name-resolver-2.0.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* resolve/rust-ast-resolve-expr.cc: Update for diagnostic_text_finalizer
+ 	becoming diagnostics::text_finalizer.
+ 	* resolve/rust-late-name-resolver-2.0.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* resolve/rust-ice-finalizer.cc: Update for move of diagnostics
+ 	output formats into namespace "diagnostics" as "sinks".
+ 	* resolve/rust-ice-finalizer.h: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* rust-diagnostics.cc: Update #include for move of
+ 	"diagnostic-metadata.h" to "diagnostics/metadata.h", and update
+ 	for move of diagnostic_metadata to diagnostics::metadata.
+ 
  2025-06-26  Martin Jambor  <mjambor@suse.cz>
  
  	* checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
diff -Nrcpad gcc-16-20250720/gcc/rust/backend/rust-tree.cc gcc-16-20250727/gcc/rust/backend/rust-tree.cc
*** gcc-16-20250720/gcc/rust/backend/rust-tree.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/rust/backend/rust-tree.cc	Sun Jul 27 22:32:09 2025
*************** strip_top_quals (tree t)
*** 3848,3863 ****
  /* Print an error message for invalid use of an incomplete type.
     VALUE is the expression that was used (or 0 if that isn't known)
     and TYPE is the type that was invalid.  DIAG_KIND indicates the
!    type of diagnostic (see diagnostic.def).  */
  
  void
  cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
! 				const_tree type, diagnostic_t diag_kind)
  {
    //  bool is_decl = false, complained = false;
  
!   gcc_assert (diag_kind == DK_WARNING || diag_kind == DK_PEDWARN
! 	      || diag_kind == DK_ERROR);
  
    /* Avoid duplicate error message.  */
    if (TREE_CODE (type) == ERROR_MARK)
--- 3848,3865 ----
  /* Print an error message for invalid use of an incomplete type.
     VALUE is the expression that was used (or 0 if that isn't known)
     and TYPE is the type that was invalid.  DIAG_KIND indicates the
!    type of diagnostic (see diagnostics/kinds.def).  */
  
  void
  cxx_incomplete_type_diagnostic (location_t loc, const_tree value,
! 				const_tree type,
! 				enum diagnostics::kind diag_kind)
  {
    //  bool is_decl = false, complained = false;
  
!   gcc_assert (diag_kind == diagnostics::kind::warning
! 	      || diag_kind == diagnostics::kind::pedwarn
! 	      || diag_kind == diagnostics::kind::error);
  
    /* Avoid duplicate error message.  */
    if (TREE_CODE (type) == ERROR_MARK)
*************** complete_type_or_maybe_complain (tree ty
*** 5131,5137 ****
    else if (!COMPLETE_TYPE_P (type))
      {
        if (complain & tf_error)
! 	cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
        note_failed_type_completion_for_satisfaction (type);
        return NULL_TREE;
      }
--- 5133,5139 ----
    else if (!COMPLETE_TYPE_P (type))
      {
        if (complain & tf_error)
! 	cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error);
        note_failed_type_completion_for_satisfaction (type);
        return NULL_TREE;
      }
diff -Nrcpad gcc-16-20250720/gcc/rust/backend/rust-tree.h gcc-16-20250727/gcc/rust/backend/rust-tree.h
*** gcc-16-20250720/gcc/rust/backend/rust-tree.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/rust/backend/rust-tree.h	Sun Jul 27 22:32:09 2025
*************** extern bool reject_gcc_builtin (const_tr
*** 3137,3143 ****
  extern tree resolve_nondeduced_context (tree, tsubst_flags_t);
  
  extern void cxx_incomplete_type_diagnostic (location_t, const_tree, const_tree,
! 					    diagnostic_t);
  
  extern void cxx_incomplete_type_error (location_t, const_tree, const_tree);
  
--- 3137,3143 ----
  extern tree resolve_nondeduced_context (tree, tsubst_flags_t);
  
  extern void cxx_incomplete_type_diagnostic (location_t, const_tree, const_tree,
! 					    enum diagnostics::kind);
  
  extern void cxx_incomplete_type_error (location_t, const_tree, const_tree);
  
*************** null_node_p (const_tree expr)
*** 3430,3436 ****
  
  inline void
  cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
! 				diagnostic_t diag_kind)
  {
    cxx_incomplete_type_diagnostic (rs_expr_loc_or_input_loc (value), value, type,
  				  diag_kind);
--- 3430,3436 ----
  
  inline void
  cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
! 				enum diagnostics::kind diag_kind)
  {
    cxx_incomplete_type_diagnostic (rs_expr_loc_or_input_loc (value), value, type,
  				  diag_kind);
*************** cxx_incomplete_type_diagnostic (const_tr
*** 3439,3445 ****
  inline void
  cxx_incomplete_type_error (const_tree value, const_tree type)
  {
!   cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
  }
  
  extern location_t
--- 3439,3445 ----
  inline void
  cxx_incomplete_type_error (const_tree value, const_tree type)
  {
!   cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error);
  }
  
  extern location_t
diff -Nrcpad gcc-16-20250720/gcc/rust/resolve/rust-ast-resolve-expr.cc gcc-16-20250727/gcc/rust/resolve/rust-ast-resolve-expr.cc
*** gcc-16-20250720/gcc/rust/resolve/rust-ast-resolve-expr.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/rust/resolve/rust-ast-resolve-expr.cc	Sun Jul 27 22:32:09 2025
*************** ResolveExpr::visit (AST::IdentifierExpr
*** 129,136 ****
  	 resolve.  Emit a funny ICE.  We set the finalizer to our custom one,
  	 and use the lower-level emit_diagnostic () instead of the more common
  	 internal_error_no_backtrace () in order to pass our locus.  */
!       diagnostic_text_finalizer (global_dc) = funny_ice_text_finalizer;
!       emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1,
  		       "are you trying to break %s? how dare you?",
  		       expr.as_string ().c_str ());
      }
--- 129,136 ----
  	 resolve.  Emit a funny ICE.  We set the finalizer to our custom one,
  	 and use the lower-level emit_diagnostic () instead of the more common
  	 internal_error_no_backtrace () in order to pass our locus.  */
!       diagnostics::text_finalizer (global_dc) = funny_ice_text_finalizer;
!       emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
  		       "are you trying to break %s? how dare you?",
  		       expr.as_string ().c_str ());
      }
diff -Nrcpad gcc-16-20250720/gcc/rust/resolve/rust-ice-finalizer.cc gcc-16-20250727/gcc/rust/resolve/rust-ice-finalizer.cc
*** gcc-16-20250720/gcc/rust/resolve/rust-ice-finalizer.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/rust/resolve/rust-ice-finalizer.cc	Sun Jul 27 22:32:09 2025
*************** namespace Rust {
*** 22,33 ****
  namespace Resolver {
  
  void ATTRIBUTE_NORETURN
! funny_ice_text_finalizer (diagnostic_text_output_format &text_output,
! 			  const diagnostic_info *diagnostic,
! 			  diagnostic_t diag_kind)
  {
!   gcc_assert (diag_kind == DK_ICE_NOBT);
!   default_diagnostic_text_finalizer (text_output, diagnostic, diag_kind);
    fnotice (stderr, "You have broken GCC Rust. This is a feature.\n");
    exit (ICE_EXIT_CODE);
  }
--- 22,33 ----
  namespace Resolver {
  
  void ATTRIBUTE_NORETURN
! funny_ice_text_finalizer (diagnostics::text_sink &text_output,
! 			  const diagnostics::diagnostic_info *diagnostic,
! 			  enum diagnostics::kind diag_kind)
  {
!   gcc_assert (diag_kind == diagnostics::kind::ice_nobt);
!   diagnostics::default_text_finalizer (text_output, diagnostic, diag_kind);
    fnotice (stderr, "You have broken GCC Rust. This is a feature.\n");
    exit (ICE_EXIT_CODE);
  }
diff -Nrcpad gcc-16-20250720/gcc/rust/resolve/rust-ice-finalizer.h gcc-16-20250727/gcc/rust/resolve/rust-ice-finalizer.h
*** gcc-16-20250720/gcc/rust/resolve/rust-ice-finalizer.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/rust/resolve/rust-ice-finalizer.h	Sun Jul 27 22:32:09 2025
*************** namespace Resolver {
*** 55,63 ****
     the default bug reporting instructions, as there is no bug to report.  */
  
  void ATTRIBUTE_NORETURN
! funny_ice_text_finalizer (diagnostic_text_output_format &text_output,
! 			  const diagnostic_info *diagnostic,
! 			  diagnostic_t diag_kind);
  
  } // namespace Resolver
  } // namespace Rust
--- 55,63 ----
     the default bug reporting instructions, as there is no bug to report.  */
  
  void ATTRIBUTE_NORETURN
! funny_ice_text_finalizer (diagnostics::text_sink &text_output,
! 			  const diagnostics::diagnostic_info *diagnostic,
! 			  enum diagnostics::kind diag_kind);
  
  } // namespace Resolver
  } // namespace Rust
diff -Nrcpad gcc-16-20250720/gcc/rust/resolve/rust-late-name-resolver-2.0.cc gcc-16-20250727/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
*** gcc-16-20250720/gcc/rust/resolve/rust-late-name-resolver-2.0.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/rust/resolve/rust-late-name-resolver-2.0.cc	Sun Jul 27 22:32:09 2025
*************** Late::visit (AST::IdentifierExpr &expr)
*** 375,382 ****
      }
    else if (funny_error)
      {
!       diagnostic_text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer;
!       emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1,
  		       "are you trying to break %s? how dare you?",
  		       expr.as_string ().c_str ());
      }
--- 375,382 ----
      }
    else if (funny_error)
      {
!       diagnostics::text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer;
!       emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
  		       "are you trying to break %s? how dare you?",
  		       expr.as_string ().c_str ());
      }
diff -Nrcpad gcc-16-20250720/gcc/rust/rust-diagnostics.cc gcc-16-20250727/gcc/rust/rust-diagnostics.cc
*** gcc-16-20250720/gcc/rust/rust-diagnostics.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/rust/rust-diagnostics.cc	Sun Jul 27 22:32:09 2025
***************
*** 22,28 ****
  #include "rust-diagnostics.h"
  
  #include "options.h"
! #include "diagnostic-metadata.h"
  
  static std::string
  mformat_value ()
--- 22,28 ----
  #include "rust-diagnostics.h"
  
  #include "options.h"
! #include "diagnostics/metadata.h"
  
  static std::string
  mformat_value ()
*************** rust_error_at (const location_t location
*** 192,198 ****
    va_end (ap);
  }
  
! class rust_error_code_rule : public diagnostic_metadata::rule
  {
  public:
    rust_error_code_rule (const ErrorCode code) : m_code (code) {}
--- 192,198 ----
    va_end (ap);
  }
  
! class rust_error_code_rule : public diagnostics::metadata::rule
  {
  public:
    rust_error_code_rule (const ErrorCode code) : m_code (code) {}
*************** rust_be_error_at (const location_t locat
*** 237,243 ****
  		  const std::string &errmsg)
  {
    rich_location gcc_loc (line_table, location);
!   diagnostic_metadata m;
    rust_error_code_rule rule (code);
    m.add_rule (rule);
    error_meta (&gcc_loc, m, "%s", errmsg.c_str ());
--- 237,243 ----
  		  const std::string &errmsg)
  {
    rich_location gcc_loc (line_table, location);
!   diagnostics::metadata m;
    rust_error_code_rule rule (code);
    m.add_rule (rule);
    error_meta (&gcc_loc, m, "%s", errmsg.c_str ());
*************** rust_be_error_at (const rich_location &l
*** 260,266 ****
  {
    /* TODO: 'error_at' would like a non-'const' 'rich_location *'.  */
    rich_location &gcc_loc = const_cast<rich_location &> (location);
!   diagnostic_metadata m;
    rust_error_code_rule rule (code);
    m.add_rule (rule);
    error_meta (&gcc_loc, m, "%s", errmsg.c_str ());
--- 260,266 ----
  {
    /* TODO: 'error_at' would like a non-'const' 'rich_location *'.  */
    rich_location &gcc_loc = const_cast<rich_location &> (location);
!   diagnostics::metadata m;
    rust_error_code_rule rule (code);
    m.add_rule (rule);
    error_meta (&gcc_loc, m, "%s", errmsg.c_str ());
*************** void
*** 281,287 ****
  rust_be_error_at (rich_location *richloc, const ErrorCode code,
  		  const std::string &errmsg)
  {
!   diagnostic_metadata m;
    rust_error_code_rule rule (code);
    m.add_rule (rule);
    error_meta (richloc, m, "%s", errmsg.c_str ());
--- 281,287 ----
  rust_be_error_at (rich_location *richloc, const ErrorCode code,
  		  const std::string &errmsg)
  {
!   diagnostics::metadata m;
    rust_error_code_rule rule (code);
    m.add_rule (rule);
    error_meta (richloc, m, "%s", errmsg.c_str ());
diff -Nrcpad gcc-16-20250720/gcc/selftest-diagnostic-path.cc gcc-16-20250727/gcc/selftest-diagnostic-path.cc
*** gcc-16-20250720/gcc/selftest-diagnostic-path.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest-diagnostic-path.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,242 ****
- /* Concrete classes for selftests involving diagnostic paths.
-    Copyright (C) 2019-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- 
- #include "config.h"
- #define INCLUDE_VECTOR
- #include "system.h"
- #include "coretypes.h"
- #include "version.h"
- #include "demangle.h"
- #include "backtrace.h"
- #include "diagnostic.h"
- #include "selftest-diagnostic-path.h"
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* class test_diagnostic_path : public diagnostic_path.  */
- 
- test_diagnostic_path::test_diagnostic_path (pretty_printer *event_pp)
- : diagnostic_path (m_test_logical_loc_mgr),
-   m_event_pp (event_pp)
- {
-   add_thread ("main");
- }
- 
- /* Implementation of diagnostic_path::num_events vfunc for
-    test_diagnostic_path: simply get the number of events in the vec.  */
- 
- unsigned
- test_diagnostic_path::num_events () const
- {
-   return m_events.length ();
- }
- 
- /* Implementation of diagnostic_path::get_event vfunc for
-    test_diagnostic_path: simply return the event in the vec.  */
- 
- const diagnostic_event &
- test_diagnostic_path::get_event (int idx) const
- {
-   return *m_events[idx];
- }
- 
- unsigned
- test_diagnostic_path::num_threads () const
- {
-   return m_threads.length ();
- }
- 
- const diagnostic_thread &
- test_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
- {
-   return *m_threads[idx];
- }
- 
- bool
- test_diagnostic_path::same_function_p (int event_idx_a,
- 				       int event_idx_b) const
- {
-   return (m_events[event_idx_a]->get_logical_location ()
- 	  == m_events[event_idx_b]->get_logical_location ());
- }
- 
- diagnostic_thread_id_t
- test_diagnostic_path::add_thread (const char *name)
- {
-   m_threads.safe_push (new test_diagnostic_thread (name));
-   return m_threads.length () - 1;
- }
- 
- /* Add an event to this path at LOC within function FNDECL at
-    stack depth DEPTH.
- 
-    Use m_context's printer to format FMT, as the text of the new
-    event.
- 
-    Return the id of the new event.  */
- 
- diagnostic_event_id_t
- test_diagnostic_path::add_event (location_t loc,
- 				 const char *funcname,
- 				 int depth,
- 				 const char *fmt, ...)
- {
-   pretty_printer *pp = m_event_pp;
-   pp_clear_output_area (pp);
- 
-   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
- 
-   va_list ap;
- 
-   va_start (ap, fmt);
- 
-   /* No localization is done on FMT.  */
-   text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
-   pp_format (pp, &ti);
-   pp_output_formatted_text (pp);
- 
-   va_end (ap);
- 
-   test_diagnostic_event *new_event
-     = new test_diagnostic_event (loc,
- 				 logical_location_from_funcname (funcname),
- 				 depth,
- 				 pp_formatted_text (pp));
-   m_events.safe_push (new_event);
- 
-   pp_clear_output_area (pp);
- 
-   return diagnostic_event_id_t (m_events.length () - 1);
- }
- 
- diagnostic_event_id_t
- test_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
- 					location_t loc,
- 					const char *funcname,
- 					int depth,
- 					const char *fmt, ...)
- {
-   pretty_printer *pp = m_event_pp;
-   pp_clear_output_area (pp);
- 
-   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
- 
-   va_list ap;
- 
-   va_start (ap, fmt);
- 
-   /* No localization is done on FMT.  */
-   text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
- 
-   pp_format (pp, &ti);
-   pp_output_formatted_text (pp);
- 
-   va_end (ap);
- 
-   test_diagnostic_event *new_event
-     = new test_diagnostic_event (loc,
- 				 logical_location_from_funcname (funcname),
- 				 depth,
- 				 pp_formatted_text (pp),
- 				 thread_id);
-   m_events.safe_push (new_event);
- 
-   pp_clear_output_area (pp);
- 
-   return diagnostic_event_id_t (m_events.length () - 1);
- }
- 
- /* Mark the most recent event on this path (which must exist) as being
-    connected to the next one to be added.  */
- 
- void
- test_diagnostic_path::connect_to_next_event ()
- {
-   gcc_assert (m_events.length () > 0);
-   m_events[m_events.length () - 1]->connect_to_next_event ();
- }
- 
- void
- test_diagnostic_path::add_entry (const char *callee_name,
- 				 int stack_depth,
- 				 diagnostic_thread_id_t thread_id)
- {
-   add_thread_event (thread_id, UNKNOWN_LOCATION, callee_name, stack_depth,
- 		    "entering %qs", callee_name);
- }
- 
- void
- test_diagnostic_path::add_return (const char *caller_name,
- 				  int stack_depth,
- 				  diagnostic_thread_id_t thread_id)
- {
-   add_thread_event (thread_id, UNKNOWN_LOCATION, caller_name, stack_depth,
- 		    "returning to %qs", caller_name);
- }
- 
- void
- test_diagnostic_path::add_call (const char *caller_name,
- 				int caller_stack_depth,
- 				const char *callee_name,
- 				diagnostic_thread_id_t thread_id)
- {
-   add_thread_event (thread_id, UNKNOWN_LOCATION,
- 		    caller_name, caller_stack_depth,
- 		    "calling %qs", callee_name);
-   add_entry (callee_name, caller_stack_depth + 1, thread_id);
- }
- 
- logical_location
- test_diagnostic_path::logical_location_from_funcname (const char *funcname)
- {
-   return m_test_logical_loc_mgr.logical_location_from_funcname (funcname);
- }
- 
- /* struct test_diagnostic_event.  */
- 
- /* test_diagnostic_event's ctor.  */
- 
- test_diagnostic_event::
- test_diagnostic_event (location_t loc,
- 		       logical_location logical_loc,
- 		       int depth,
- 		       const char *desc,
- 		       diagnostic_thread_id_t thread_id)
- : m_loc (loc),
-   m_logical_loc (logical_loc),
-   m_depth (depth), m_desc (xstrdup (desc)),
-   m_connected_to_next_event (false),
-   m_thread_id (thread_id)
- {
- }
- 
- /* test_diagnostic_event's dtor.  */
- 
- test_diagnostic_event::~test_diagnostic_event ()
- {
-   free (m_desc);
- }
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/selftest-diagnostic-path.h gcc-16-20250727/gcc/selftest-diagnostic-path.h
*** gcc-16-20250720/gcc/selftest-diagnostic-path.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest-diagnostic-path.h	Thu Jan  1 00:00:00 1970
***************
*** 1,161 ****
- /* Concrete classes for selftests involving diagnostic paths.
-    Copyright (C) 2019-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_SELFTEST_DIAGNOSTIC_PATH_H
- #define GCC_SELFTEST_DIAGNOSTIC_PATH_H
- 
- #include "diagnostic-path.h"
- #include "selftest-logical-location.h"
- 
- /* The selftest code should entirely disappear in a production
-    configuration, hence we guard all of it with #if CHECKING_P.  */
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* Concrete subclasses of the abstract base classes
-    declared in diagnostic-path.h for use in selftests.
- 
-    This code should have no dependency on "tree".  */
- 
- /* An implementation of diagnostic_event.  */
- 
- class test_diagnostic_event : public diagnostic_event
- {
-  public:
-   test_diagnostic_event (location_t loc,
- 			 logical_location logical_loc,
- 			 int depth,
- 			 const char *desc,
- 			 diagnostic_thread_id_t thread_id = 0);
-   ~test_diagnostic_event ();
- 
-   location_t get_location () const final override { return m_loc; }
-   int get_stack_depth () const final override { return m_depth; }
-   void print_desc (pretty_printer &pp) const final override
-   {
-     pp_string (&pp, m_desc);
-   }
-   logical_location get_logical_location () const final override
-   {
-     return m_logical_loc;
-   }
-   meaning get_meaning () const final override
-   {
-     return meaning ();
-   }
-   bool connect_to_next_event_p () const final override
-   {
-     return m_connected_to_next_event;
-   }
-   diagnostic_thread_id_t get_thread_id () const final override
-   {
-     return m_thread_id;
-   }
- 
-   void connect_to_next_event ()
-   {
-     m_connected_to_next_event = true;
-   }
- 
-  private:
-   location_t m_loc;
-   logical_location m_logical_loc;
-   int m_depth;
-   char *m_desc; // has been formatted; doesn't get i18n-ed
-   bool m_connected_to_next_event;
-   diagnostic_thread_id_t m_thread_id;
- };
- 
- /* A simple implementation of diagnostic_thread.  */
- 
- class test_diagnostic_thread : public diagnostic_thread
- {
- public:
-   test_diagnostic_thread (const char *name) : m_name (name) {}
-   label_text get_name (bool) const final override
-   {
-     return label_text::borrow (m_name);
-   }
- 
- private:
-   const char *m_name; // has been i18n-ed and formatted
- };
- 
- /* A concrete subclass of diagnostic_path for implementing selftests
-    - a vector of test_diagnostic_event instances
-    - adds member functions for adding test event
-    - does no translation of its events
-    - has no dependency on "tree".  */
- 
- class test_diagnostic_path : public diagnostic_path
- {
-  public:
-   test_diagnostic_path (pretty_printer *event_pp);
- 
-   unsigned num_events () const final override;
-   const diagnostic_event & get_event (int idx) const final override;
-   unsigned num_threads () const final override;
-   const diagnostic_thread &
-   get_thread (diagnostic_thread_id_t) const final override;
-   bool
-   same_function_p (int event_idx_a,
- 		   int event_idx_b) const final override;
- 
-   diagnostic_thread_id_t add_thread (const char *name);
- 
-   diagnostic_event_id_t add_event (location_t loc, const char *funcname, int depth,
- 				   const char *fmt, ...)
-     ATTRIBUTE_GCC_DIAG(5,6);
-   diagnostic_event_id_t
-   add_thread_event (diagnostic_thread_id_t thread_id,
- 		    location_t loc, const char *funcname, int depth,
- 		    const char *fmt, ...)
-     ATTRIBUTE_GCC_DIAG(6,7);
- 
-   void connect_to_next_event ();
- 
-   void add_entry (const char *callee_name, int stack_depth,
- 		  diagnostic_thread_id_t thread_id = 0);
-   void add_return (const char *caller_name, int stack_depth,
- 		   diagnostic_thread_id_t thread_id = 0);
-   void add_call (const char *caller_name,
- 		 int caller_stack_depth,
- 		 const char *callee_name,
- 		 diagnostic_thread_id_t thread_id = 0);
- 
-  private:
-   logical_location
-   logical_location_from_funcname (const char *funcname);
- 
-   test_logical_location_manager m_test_logical_loc_mgr;
-   auto_delete_vec<test_diagnostic_thread> m_threads;
-   auto_delete_vec<test_diagnostic_event> m_events;
- 
-   /* (for use by add_event).  */
-   pretty_printer *m_event_pp;
- };
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
- 
- #endif /* ! GCC_SELFTEST_DIAGNOSTIC_PATH_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/selftest-diagnostic-show-locus.h gcc-16-20250727/gcc/selftest-diagnostic-show-locus.h
*** gcc-16-20250720/gcc/selftest-diagnostic-show-locus.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest-diagnostic-show-locus.h	Thu Jan  1 00:00:00 1970
***************
*** 1,82 ****
- /* Support for selftests involving diagnostic_show_locus.
-    Copyright (C) 1999-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_SELFTEST_DIAGNOSTIC_SHOW_LOCUS_H
- #define GCC_SELFTEST_DIAGNOSTIC_SHOW_LOCUS_H
- 
- #include "selftest.h"
- 
- /* The selftest code should entirely disappear in a production
-    configuration, hence we guard all of it with #if CHECKING_P.  */
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* RAII class for use in selftests involving diagnostic_show_locus.
- 
-    Manages creating and cleaning up the following:
-    - writing out a temporary .c file containing CONTENT
-    - temporarily override the global "line_table" (using CASE_) and
-      push a line_map starting at the first line of the temporary file
-    - provide a file_cache.  */
- 
- struct diagnostic_show_locus_fixture
- {
-   diagnostic_show_locus_fixture (const line_table_case &case_,
- 				 const char *content);
- 
-   const char *get_filename () const
-   {
-     return m_tmp_source_file.get_filename ();
-   }
- 
-   const char *m_content;
-   temp_source_file m_tmp_source_file;
-   line_table_test m_ltt;
-   file_cache m_fc;
- };
- 
- /* Fixture for one-liner tests exercising multibyte awareness.  For
-    simplicity we stick to using two multibyte characters in the test, U+1F602
-    == "\xf0\x9f\x98\x82", which uses 4 bytes and 2 display columns, and U+03C0
-    == "\xcf\x80", which uses 2 bytes and 1 display column.
- 
-    This works with the following 1-line source file:
- 
-      .0000000001111111111222222   display
-      .1234567890123456789012345   columns
-      "SS_foo = P_bar.SS_fieldP;\n"
-      .0000000111111111222222223   byte
-      .1356789012456789134567891   columns
- 
-    Here SS represents the two display columns for the U+1F602 emoji and
-    P represents the one display column for the U+03C0 pi symbol.  */
- 
- struct diagnostic_show_locus_fixture_one_liner_utf8
-   : public diagnostic_show_locus_fixture
- {
-   diagnostic_show_locus_fixture_one_liner_utf8 (const line_table_case &case_);
- };
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
- 
- #endif /* GCC_SELFTEST_DIAGNOSTIC_SHOW_LOCUS_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/selftest-diagnostic.cc gcc-16-20250727/gcc/selftest-diagnostic.cc
*** gcc-16-20250720/gcc/selftest-diagnostic.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest-diagnostic.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,99 ****
- /* Selftest support for diagnostics.
-    Copyright (C) 2016-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "diagnostic.h"
- #include "diagnostic-format.h"
- #include "selftest.h"
- #include "selftest-diagnostic.h"
- 
- /* The selftest code should entirely disappear in a production
-    configuration, hence we guard all of it with #if CHECKING_P.  */
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* Implementation of class selftest::test_diagnostic_context.  */
- 
- test_diagnostic_context::test_diagnostic_context ()
- {
-   diagnostic_initialize (this, 0);
-   pp_show_color (get_reference_printer ()) = false;
-   m_source_printing.enabled = true;
-   m_source_printing.show_labels_p = true;
-   m_show_column = true;
-   diagnostic_start_span (this) = start_span_cb;
-   m_source_printing.min_margin_width = 6;
-   m_source_printing.max_width = 80;
-   pp_buffer (get_output_format (0).get_printer ())->m_flush_p = false;
- }
- 
- test_diagnostic_context::~test_diagnostic_context ()
- {
-   diagnostic_finish (this);
- }
- 
- /* Implementation of diagnostic_start_span_fn, hiding the
-    real filename (to avoid printing the names of tempfiles).  */
- 
- void
- test_diagnostic_context::
- start_span_cb (const diagnostic_location_print_policy &loc_policy,
- 	       to_text &sink,
- 	       expanded_location exploc)
- {
-   exploc.file = "FILENAME";
-   default_diagnostic_start_span_fn<to_text> (loc_policy, sink, exploc);
- }
- 
- bool
- test_diagnostic_context::report (diagnostic_t kind,
- 				 rich_location &richloc,
- 				 const diagnostic_metadata *metadata,
- 				 diagnostic_option_id option,
- 				 const char * fmt, ...)
- {
-   va_list ap;
-   va_start (ap, fmt);
-   begin_group ();
-   bool result = diagnostic_impl (&richloc, metadata, option, fmt, &ap, kind);
-   end_group ();
-   va_end (ap);
-   return result;
- }
- 
- /* Print RICHLOC's source and annotations to this context's m_printer.
-    Return the text buffer from the printer.  */
- 
- const char *
- test_diagnostic_context::test_show_locus (rich_location &richloc)
- {
-   pretty_printer *pp = get_reference_printer ();
-   gcc_assert (pp);
-   diagnostic_source_print_policy source_policy (*this);
-   source_policy.print (*pp, richloc, DK_ERROR, nullptr);
-   return pp_formatted_text (pp);
- }
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/selftest-diagnostic.h gcc-16-20250727/gcc/selftest-diagnostic.h
*** gcc-16-20250720/gcc/selftest-diagnostic.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest-diagnostic.h	Thu Jan  1 00:00:00 1970
***************
*** 1,63 ****
- /* Selftest support for diagnostics.
-    Copyright (C) 2016-2025 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_SELFTEST_DIAGNOSTIC_H
- #define GCC_SELFTEST_DIAGNOSTIC_H
- 
- /* The selftest code should entirely disappear in a production
-    configuration, hence we guard all of it with #if CHECKING_P.  */
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* Convenience subclass of diagnostic_context for testing
-    the diagnostic subsystem.  */
- 
- class test_diagnostic_context : public diagnostic_context
- {
-  public:
-   test_diagnostic_context ();
-   ~test_diagnostic_context ();
- 
-   /* Implementation of diagnostic_start_span_fn, hiding the
-      real filename (to avoid printing the names of tempfiles).  */
-   static void
-   start_span_cb (const diagnostic_location_print_policy &,
- 		 to_text &sink,
- 		 expanded_location exploc);
- 
-   /* Report a diagnostic to this context.  For a selftest, this
-      should only be called on a context that uses a non-standard formatter
-      that e.g. gathers the results in memory, rather than emits to stderr.  */
-   bool
-   report (diagnostic_t kind,
- 	  rich_location &richloc,
- 	  const diagnostic_metadata *metadata,
- 	  diagnostic_option_id option,
- 	  const char * fmt, ...) ATTRIBUTE_GCC_DIAG(6,7);
- 
-   const char *test_show_locus (rich_location &richloc);
- };
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
- 
- #endif /* GCC_SELFTEST_DIAGNOSTIC_H */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/selftest-logical-location.cc gcc-16-20250727/gcc/selftest-logical-location.cc
*** gcc-16-20250720/gcc/selftest-logical-location.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest-logical-location.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,118 ****
- /* Concrete subclass of logical_location for use in selftests.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "selftest.h"
- #include "selftest-logical-location.h"
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* class test_logical_location_manager : public logical_location_manager.  */
- 
- test_logical_location_manager::~test_logical_location_manager ()
- {
-   for (auto iter : m_name_to_item_map)
-     delete iter.second;
- }
- 
- const char *
- test_logical_location_manager::get_short_name (key k) const
- {
-   auto item = item_from_key (k);
-   if (!item)
-     return nullptr;
-   return item->m_name;
- }
- 
- const char *
- test_logical_location_manager::get_name_with_scope (key k) const
- {
-   auto item = item_from_key (k);
-   return item->m_name;
- }
- 
- const char *
- test_logical_location_manager::get_internal_name (key k) const
- {
-   auto item = item_from_key (k);
-   return item->m_name;
- }
- 
- enum logical_location_kind
- test_logical_location_manager::get_kind (key k) const
- {
-   auto item = item_from_key (k);
-   return item->m_kind;
- }
- 
- label_text
- test_logical_location_manager::get_name_for_path_output (key k) const
- {
-   auto item = item_from_key (k);
-   return label_text::borrow (item->m_name);
- }
- 
- logical_location
- test_logical_location_manager::
- logical_location_from_funcname (const char *funcname)
- {
-   const item *i = item_from_funcname (funcname);
-   return key::from_ptr (i);
- }
- 
- const test_logical_location_manager::item *
- test_logical_location_manager::item_from_funcname (const char *funcname)
- {
-   if (!funcname)
-     return nullptr;
- 
-   if (item **slot = m_name_to_item_map.get (funcname))
-     return *slot;
- 
-   item *i = new item (logical_location_kind::function, funcname);
-   m_name_to_item_map.put (funcname, i);
-   return i;
- }
- 
- /* Run all of the selftests within this file.  */
- 
- void
- selftest_logical_location_cc_tests ()
- {
-   test_logical_location_manager mgr;
- 
-   ASSERT_FALSE (mgr.logical_location_from_funcname (nullptr));
- 
-   logical_location loc_foo = mgr.logical_location_from_funcname ("foo");
-   logical_location loc_bar = mgr.logical_location_from_funcname ("bar");
- 
-   ASSERT_NE (loc_foo, loc_bar);
- 
-   ASSERT_STREQ (mgr.get_short_name (loc_foo), "foo");
-   ASSERT_STREQ (mgr.get_short_name (loc_bar), "bar");
- }
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/selftest-logical-location.h gcc-16-20250727/gcc/selftest-logical-location.h
*** gcc-16-20250720/gcc/selftest-logical-location.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest-logical-location.h	Thu Jan  1 00:00:00 1970
***************
*** 1,83 ****
- /* Concrete subclass of logical_location for use in selftests.
-    Copyright (C) 2024-2025 Free Software Foundation, Inc.
-    Contributed by David Malcolm <dmalcolm@redhat.com>.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3.  If not see
- <http://www.gnu.org/licenses/>.  */
- 
- #ifndef GCC_SELFTEST_LOGICAL_LOCATION_H
- #define GCC_SELFTEST_LOGICAL_LOCATION_H
- 
- #include "logical-location.h"
- 
- /* The selftest code should entirely disappear in a production
-    configuration, hence we guard all of it with #if CHECKING_P.  */
- 
- #if CHECKING_P
- 
- namespace selftest {
- 
- /* Concrete subclass of logical_location_manager for use in selftests.  */
- 
- class test_logical_location_manager : public logical_location_manager
- {
- public:
-   ~test_logical_location_manager ();
- 
-   const char *get_short_name (key) const final override;
-   const char *get_name_with_scope (key) const final override;
-   const char *get_internal_name (key) const final override;
-   enum logical_location_kind get_kind (key) const final override;
-   label_text get_name_for_path_output (key) const final override;
-   key get_parent (key) const final override
-   {
-     return key ();
-   }
- 
-   logical_location
-   logical_location_from_funcname (const char *funcname);
- 
- private:
-   struct item
-   {
-     item (enum logical_location_kind kind,
- 	  const char *name)
-     : m_kind (kind),
-       m_name (name)
-     {
-     }
- 
-     enum logical_location_kind m_kind;
-     const char *m_name;
-   };
- 
-   const item *
-   item_from_funcname (const char *funcname);
- 
-   static const item *item_from_key (logical_location k)
-   {
-     return k.cast_to<const item *> ();
-   }
- 
-   hash_map<nofree_string_hash, item *> m_name_to_item_map;
- };
- 
- } // namespace selftest
- 
- #endif /* #if CHECKING_P */
- 
- 
- #endif /* GCC_SELFTEST_LOGICAL_LOCATION_H.  */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/selftest-run-tests.cc gcc-16-20250727/gcc/selftest-run-tests.cc
*** gcc-16-20250720/gcc/selftest-run-tests.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest-run-tests.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 28,33 ****
--- 28,34 ----
  #include "stringpool.h"
  #include "attribs.h"
  #include "analyzer/analyzer-selftests.h"
+ #include "diagnostics/diagnostics-selftests.h"
  #include "text-art/selftests.h"
  
  /* This function needed to be split out from selftest.cc as it references
*************** selftest::run_tests ()
*** 94,118 ****
    digraph_cc_tests ();
    tristate_cc_tests ();
    ipa_modref_tree_cc_tests ();
!   selftest_logical_location_cc_tests ();
  
    /* Higher-level tests, or for components that other selftests don't
       rely on.  */
-   diagnostic_color_cc_tests ();
-   diagnostic_show_locus_cc_tests ();
-   diagnostic_format_html_cc_tests ();
-   diagnostic_format_sarif_cc_tests ();
-   diagnostic_digraphs_cc_tests ();
-   diagnostic_output_spec_cc_tests ();
-   diagnostic_state_graphs_cc_tests ();
-   edit_context_cc_tests ();
    fold_const_cc_tests ();
    spellcheck_cc_tests ();
    spellcheck_tree_cc_tests ();
    tree_cfg_cc_tests ();
-   diagnostic_path_output_cc_tests ();
    simple_diagnostic_path_cc_tests ();
-   lazy_diagnostic_path_cc_tests ();
    attribs_cc_tests ();
    path_coverage_cc_tests ();
  
--- 95,111 ----
    digraph_cc_tests ();
    tristate_cc_tests ();
    ipa_modref_tree_cc_tests ();
! 
!   /* Run the diagnostics selftests.  */
!   diagnostics::selftest::run_diagnostics_selftests ();
  
    /* Higher-level tests, or for components that other selftests don't
       rely on.  */
    fold_const_cc_tests ();
    spellcheck_cc_tests ();
    spellcheck_tree_cc_tests ();
    tree_cfg_cc_tests ();
    simple_diagnostic_path_cc_tests ();
    attribs_cc_tests ();
    path_coverage_cc_tests ();
  
diff -Nrcpad gcc-16-20250720/gcc/selftest.cc gcc-16-20250727/gcc/selftest.cc
*** gcc-16-20250720/gcc/selftest.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 21,26 ****
--- 21,27 ----
  #include "system.h"
  #include "coretypes.h"
  #include "selftest.h"
+ #include "diagnostics/file-cache.h"
  #include "intl.h"
  
  #if CHECKING_P
*************** assert_str_startswith (const location &l
*** 186,192 ****
  /* Constructor.  Generate a name for the file.  */
  
  named_temp_file::named_temp_file (const char *suffix,
! 				  file_cache *fc)
  {
    m_filename = make_temp_file (suffix);
    ASSERT_NE (m_filename, NULL);
--- 187,193 ----
  /* Constructor.  Generate a name for the file.  */
  
  named_temp_file::named_temp_file (const char *suffix,
! 				  diagnostics::file_cache *fc)
  {
    m_filename = make_temp_file (suffix);
    ASSERT_NE (m_filename, NULL);
*************** named_temp_file::~named_temp_file ()
*** 210,216 ****
  temp_source_file::temp_source_file (const location &loc,
  				    const char *suffix,
  				    const char *content,
! 				    file_cache *fc)
  : named_temp_file (suffix, fc)
  {
    FILE *out = fopen (get_filename (), "w");
--- 211,217 ----
  temp_source_file::temp_source_file (const location &loc,
  				    const char *suffix,
  				    const char *content,
! 				    diagnostics::file_cache *fc)
  : named_temp_file (suffix, fc)
  {
    FILE *out = fopen (get_filename (), "w");
diff -Nrcpad gcc-16-20250720/gcc/selftest.h gcc-16-20250727/gcc/selftest.h
*** gcc-16-20250720/gcc/selftest.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/selftest.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 25,31 ****
  
  #if CHECKING_P
  
! class file_cache;
  
  namespace selftest {
  
--- 25,31 ----
  
  #if CHECKING_P
  
! namespace diagnostics { class file_cache; }
  
  namespace selftest {
  
*************** extern void assert_str_startswith (const
*** 100,112 ****
  class named_temp_file
  {
   public:
!   named_temp_file (const char *suffix, file_cache *fc = nullptr);
    ~named_temp_file ();
    const char *get_filename () const { return m_filename; }
  
   private:
    char *m_filename;
!   file_cache *m_file_cache;
  };
  
  /* A class for writing out a temporary sourcefile for use in selftests
--- 100,112 ----
  class named_temp_file
  {
   public:
!   named_temp_file (const char *suffix, diagnostics::file_cache *fc = nullptr);
    ~named_temp_file ();
    const char *get_filename () const { return m_filename; }
  
   private:
    char *m_filename;
!   diagnostics::file_cache *m_file_cache;
  };
  
  /* A class for writing out a temporary sourcefile for use in selftests
*************** class temp_source_file : public named_te
*** 116,122 ****
  {
   public:
    temp_source_file (const location &loc, const char *suffix,
! 		    const char *content, file_cache *fc = nullptr);
    temp_source_file (const location &loc, const char *suffix,
  		    const char *content, size_t sz);
  };
--- 116,122 ----
  {
   public:
    temp_source_file (const location &loc, const char *suffix,
! 		    const char *content, diagnostics::file_cache *fc = nullptr);
    temp_source_file (const location &loc, const char *suffix,
  		    const char *content, size_t sz);
  };
*************** extern void bitmap_cc_tests ();
*** 221,237 ****
  extern void cgraph_cc_tests ();
  extern void convert_cc_tests ();
  extern void dbgcnt_cc_tests ();
- extern void diagnostic_color_cc_tests ();
- extern void diagnostic_digraphs_cc_tests ();
- extern void diagnostic_format_html_cc_tests ();
- extern void diagnostic_format_sarif_cc_tests ();
- extern void diagnostic_output_spec_cc_tests ();
- extern void diagnostic_path_output_cc_tests ();
- extern void diagnostic_show_locus_cc_tests ();
- extern void diagnostic_state_graphs_cc_tests ();
  extern void digraph_cc_tests ();
  extern void dumpfile_cc_tests ();
- extern void edit_context_cc_tests ();
  extern void et_forest_cc_tests ();
  extern void fibonacci_heap_cc_tests ();
  extern void fold_const_cc_tests ();
--- 221,228 ----
*************** extern void input_cc_tests ();
*** 248,254 ****
  extern void ipa_modref_tree_cc_tests ();
  extern void json_cc_tests ();
  extern void json_parser_cc_tests ();
- extern void lazy_diagnostic_path_cc_tests ();
  extern void opt_suggestions_cc_tests ();
  extern void optinfo_emit_json_cc_tests ();
  extern void opts_cc_tests ();
--- 239,244 ----
*************** extern void relation_tests ();
*** 263,269 ****
  extern void rtl_tests_cc_tests ();
  extern void sbitmap_cc_tests ();
  extern void selftest_cc_tests ();
- extern void selftest_logical_location_cc_tests ();
  extern void simple_diagnostic_path_cc_tests ();
  extern void simplify_rtx_cc_tests ();
  extern void spellcheck_cc_tests ();
--- 253,258 ----
diff -Nrcpad gcc-16-20250720/gcc/simple-diagnostic-path.cc gcc-16-20250727/gcc/simple-diagnostic-path.cc
*** gcc-16-20250720/gcc/simple-diagnostic-path.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/simple-diagnostic-path.cc	Sun Jul 27 22:32:09 2025
***************
*** 1,4 ****
! /* Concrete classes for implementing diagnostic paths.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>
  
--- 1,4 ----
! /* Concrete classes for implementing diagnostic paths, using tree.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>
  
*************** along with GCC; see the file COPYING3.
*** 32,60 ****
  #include "simple-diagnostic-path.h"
  #include "selftest.h"
  
! /* class simple_diagnostic_path : public diagnostic_path.  */
  
  simple_diagnostic_path::
  simple_diagnostic_path (const tree_logical_location_manager &logical_loc_mgr,
  			pretty_printer *event_pp)
! : diagnostic_path (logical_loc_mgr),
    m_event_pp (event_pp),
    m_localize_events (true)
  {
    add_thread ("main");
  }
  
! /* Implementation of diagnostic_path::get_event vfunc for
     simple_diagnostic_path: simply return the event in the vec.  */
  
! const diagnostic_event &
  simple_diagnostic_path::get_event (int idx) const
  {
    return *m_events[idx];
  }
  
! const diagnostic_thread &
! simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
  {
    return *m_threads[idx];
  }
--- 32,62 ----
  #include "simple-diagnostic-path.h"
  #include "selftest.h"
  
! using namespace diagnostics::paths;
! 
! /* class simple_diagnostic_path : public diagnostics::paths::path.  */
  
  simple_diagnostic_path::
  simple_diagnostic_path (const tree_logical_location_manager &logical_loc_mgr,
  			pretty_printer *event_pp)
! : path (logical_loc_mgr),
    m_event_pp (event_pp),
    m_localize_events (true)
  {
    add_thread ("main");
  }
  
! /* Implementation of path::get_event vfunc for
     simple_diagnostic_path: simply return the event in the vec.  */
  
! const event &
  simple_diagnostic_path::get_event (int idx) const
  {
    return *m_events[idx];
  }
  
! const thread &
! simple_diagnostic_path::get_thread (thread_id_t idx) const
  {
    return *m_threads[idx];
  }
*************** simple_diagnostic_path::same_function_p
*** 67,73 ****
  	  == m_events[event_idx_b]->get_fndecl ());
  }
  
! diagnostic_thread_id_t
  simple_diagnostic_path::add_thread (const char *name)
  {
    m_threads.safe_push (new simple_diagnostic_thread (name));
--- 69,75 ----
  	  == m_events[event_idx_b]->get_fndecl ());
  }
  
! thread_id_t
  simple_diagnostic_path::add_thread (const char *name)
  {
    m_threads.safe_push (new simple_diagnostic_thread (name));
*************** simple_diagnostic_path::add_thread (cons
*** 82,88 ****
  
     Return the id of the new event.  */
  
! diagnostic_event_id_t
  simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
  				   const char *fmt, ...)
  {
--- 84,90 ----
  
     Return the id of the new event.  */
  
! event_id_t
  simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
  				   const char *fmt, ...)
  {
*************** simple_diagnostic_path::add_event (locat
*** 108,118 ****
  
    pp_clear_output_area (pp);
  
!   return diagnostic_event_id_t (m_events.length () - 1);
  }
  
! diagnostic_event_id_t
! simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
  					  location_t loc,
  					  tree fndecl,
  					  int depth,
--- 110,120 ----
  
    pp_clear_output_area (pp);
  
!   return event_id_t (m_events.length () - 1);
  }
  
! event_id_t
! simple_diagnostic_path::add_thread_event (thread_id_t thread_id,
  					  location_t loc,
  					  tree fndecl,
  					  int depth,
*************** simple_diagnostic_path::add_thread_event
*** 141,147 ****
  
    pp_clear_output_area (pp);
  
!   return diagnostic_event_id_t (m_events.length () - 1);
  }
  
  /* Mark the most recent event on this path (which must exist) as being
--- 143,149 ----
  
    pp_clear_output_area (pp);
  
!   return event_id_t (m_events.length () - 1);
  }
  
  /* Mark the most recent event on this path (which must exist) as being
*************** simple_diagnostic_event (location_t loc,
*** 163,169 ****
  			 tree fndecl,
  			 int depth,
  			 const char *desc,
! 			 diagnostic_thread_id_t thread_id)
  : m_loc (loc), m_fndecl (fndecl),
    m_logical_loc (tree_logical_location_manager::key_from_tree (fndecl)),
    m_depth (depth), m_desc (xstrdup (desc)),
--- 165,171 ----
  			 tree fndecl,
  			 int depth,
  			 const char *desc,
! 			 thread_id_t thread_id)
  : m_loc (loc), m_fndecl (fndecl),
    m_logical_loc (tree_logical_location_manager::key_from_tree (fndecl)),
    m_depth (depth), m_desc (xstrdup (desc)),
diff -Nrcpad gcc-16-20250720/gcc/simple-diagnostic-path.h gcc-16-20250727/gcc/simple-diagnostic-path.h
*** gcc-16-20250720/gcc/simple-diagnostic-path.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/simple-diagnostic-path.h	Sun Jul 27 22:32:09 2025
***************
*** 1,4 ****
! /* Concrete classes for implementing diagnostic paths.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>
  
--- 1,4 ----
! /* Concrete classes for implementing diagnostic paths, using tree.
     Copyright (C) 2019-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>
  
*************** along with GCC; see the file COPYING3.
*** 21,46 ****
  #ifndef GCC_SIMPLE_DIAGNOSTIC_PATH_H
  #define GCC_SIMPLE_DIAGNOSTIC_PATH_H
  
! #include "diagnostic-path.h"
  #include "tree-logical-location.h"
  
  /* Concrete subclasses of the abstract base classes
     declared in diagnostic-path.h.  */
  
! /* A simple implementation of diagnostic_event.  */
  
! class simple_diagnostic_event : public diagnostic_event
  {
   public:
    simple_diagnostic_event (location_t loc, tree fndecl, int depth,
  			   const char *desc,
! 			   diagnostic_thread_id_t thread_id = 0);
    ~simple_diagnostic_event ();
  
    location_t get_location () const final override { return m_loc; }
    int get_stack_depth () const final override { return m_depth; }
    void print_desc (pretty_printer &pp) const final override;
!   logical_location get_logical_location () const final override
    {
      return tree_logical_location_manager::key_from_tree (m_fndecl);
    }
--- 21,50 ----
  #ifndef GCC_SIMPLE_DIAGNOSTIC_PATH_H
  #define GCC_SIMPLE_DIAGNOSTIC_PATH_H
  
! #include "diagnostics/paths.h"
  #include "tree-logical-location.h"
  
  /* Concrete subclasses of the abstract base classes
     declared in diagnostic-path.h.  */
  
! /* A simple implementation of diagnostic event.
!    This uses "tree" and so is not in "namespace diagnostics".  */
  
! class simple_diagnostic_event : public diagnostics::paths::event
  {
   public:
+   using thread_id_t = diagnostics::paths::thread_id_t;
+ 
    simple_diagnostic_event (location_t loc, tree fndecl, int depth,
  			   const char *desc,
! 			   thread_id_t thread_id = 0);
    ~simple_diagnostic_event ();
  
    location_t get_location () const final override { return m_loc; }
    int get_stack_depth () const final override { return m_depth; }
    void print_desc (pretty_printer &pp) const final override;
!   diagnostics::logical_locations::key
!   get_logical_location () const final override
    {
      return tree_logical_location_manager::key_from_tree (m_fndecl);
    }
*************** class simple_diagnostic_event : public d
*** 52,58 ****
    {
      return m_connected_to_next_event;
    }
!   diagnostic_thread_id_t get_thread_id () const final override
    {
      return m_thread_id;
    }
--- 56,62 ----
    {
      return m_connected_to_next_event;
    }
!   thread_id_t get_thread_id () const final override
    {
      return m_thread_id;
    }
*************** class simple_diagnostic_event : public d
*** 67,82 ****
   private:
    location_t m_loc;
    tree m_fndecl;
!   logical_location m_logical_loc;
    int m_depth;
    char *m_desc; // has been i18n-ed and formatted
    bool m_connected_to_next_event;
!   diagnostic_thread_id_t m_thread_id;
  };
  
! /* A simple implementation of diagnostic_thread.  */
  
! class simple_diagnostic_thread : public diagnostic_thread
  {
  public:
    simple_diagnostic_thread (const char *name) : m_name (name) {}
--- 71,86 ----
   private:
    location_t m_loc;
    tree m_fndecl;
!   diagnostics::logical_locations::key m_logical_loc;
    int m_depth;
    char *m_desc; // has been i18n-ed and formatted
    bool m_connected_to_next_event;
!   thread_id_t m_thread_id;
  };
  
! /* A simple implementation of diagnostics::paths::thread.  */
  
! class simple_diagnostic_thread : public diagnostics::paths::thread
  {
  public:
    simple_diagnostic_thread (const char *name) : m_name (name) {}
*************** private:
*** 92,119 ****
  /* A simple implementation of diagnostic_path, as a vector of
     simple_diagnostic_event instances.  */
  
! class simple_diagnostic_path : public diagnostic_path
  {
   public:
    simple_diagnostic_path (const tree_logical_location_manager &logical_loc_mgr,
  			  pretty_printer *event_pp);
  
    unsigned num_events () const final override { return m_events.length (); }
!   const diagnostic_event & get_event (int idx) const final override;
    unsigned num_threads () const final override { return m_threads.length (); }
!   const diagnostic_thread &
!   get_thread (diagnostic_thread_id_t) const final override;
    bool
    same_function_p (int event_idx_a,
  		   int event_idx_b) const final override;
  
!   diagnostic_thread_id_t add_thread (const char *name);
  
!   diagnostic_event_id_t add_event (location_t loc, tree fndecl, int depth,
! 				   const char *fmt, ...)
      ATTRIBUTE_GCC_DIAG(5,6);
!   diagnostic_event_id_t
!   add_thread_event (diagnostic_thread_id_t thread_id,
  		    location_t loc, tree fndecl, int depth,
  		    const char *fmt, ...)
      ATTRIBUTE_GCC_DIAG(6,7);
--- 96,128 ----
  /* A simple implementation of diagnostic_path, as a vector of
     simple_diagnostic_event instances.  */
  
! class simple_diagnostic_path : public diagnostics::paths::path
  {
   public:
+   using thread = diagnostics::paths::thread;
+   using thread_id_t = diagnostics::paths::thread_id_t;
+   using event = diagnostics::paths::event;
+   using event_id_t = diagnostics::paths::event_id_t;
+ 
    simple_diagnostic_path (const tree_logical_location_manager &logical_loc_mgr,
  			  pretty_printer *event_pp);
  
    unsigned num_events () const final override { return m_events.length (); }
!   const event & get_event (int idx) const final override;
    unsigned num_threads () const final override { return m_threads.length (); }
!   const thread &
!   get_thread (thread_id_t) const final override;
    bool
    same_function_p (int event_idx_a,
  		   int event_idx_b) const final override;
  
!   thread_id_t add_thread (const char *name);
  
!   event_id_t add_event (location_t loc, tree fndecl, int depth,
! 			const char *fmt, ...)
      ATTRIBUTE_GCC_DIAG(5,6);
!   event_id_t
!   add_thread_event (thread_id_t thread_id,
  		    location_t loc, tree fndecl, int depth,
  		    const char *fmt, ...)
      ATTRIBUTE_GCC_DIAG(6,7);
diff -Nrcpad gcc-16-20250720/gcc/stmt.cc gcc-16-20250727/gcc/stmt.cc
*** gcc-16-20250720/gcc/stmt.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/stmt.cc	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 39,44 ****
--- 39,46 ----
  #include "emit-rtl.h"
  #include "pretty-print.h"
  #include "diagnostic-core.h"
+ #include "output.h"
+ #include "gimplify_reg_info.h"
  
  #include "fold-const.h"
  #include "varasm.h"
*************** along with GCC; see the file COPYING3.
*** 53,58 ****
--- 55,61 ----
  #include "dumpfile.h"
  #include "builtins.h"
  #include "cfgexpand.h"
+ #include "output.h"
  
  
  /* Functions and data structures for expanding case statements.  */
*************** expand_label (tree label)
*** 175,180 ****
--- 178,254 ----
      maybe_set_first_label_num (label_r);
  }
  
+ /* Parse a hard register constraint and return its number or -1 in case of an
+    error.  BEGIN should point to a string of the form `{regname}`.  For the
+    sake of simplicity assume that a register name is not longer than 31
+    characters, if not error out.  */
+ 
+ int
+ decode_hard_reg_constraint (const char *begin)
+ {
+   if (*begin != '{')
+     return -1;
+   ++begin;
+   const char *end = begin;
+   while (*end != '}' && *end != '\0')
+     ++end;
+   if (*end != '}' || end == begin)
+     return -1;
+   ptrdiff_t len = end - begin;
+   if (len >= 31)
+     return -1;
+   char regname[32];
+   memcpy (regname, begin, len);
+   regname[len] = '\0';
+   int regno = decode_reg_name (regname);
+   return regno;
+ }
+ 
+ static bool
+ eliminable_regno_p (int regnum)
+ {
+   static const struct
+   {
+     const int from;
+     const int to;
+   } eliminables[] = ELIMINABLE_REGS;
+   for (size_t i = 0; i < ARRAY_SIZE (eliminables); i++)
+     if (regnum == eliminables[i].from)
+       return true;
+   return false;
+ }
+ 
+ /* Perform a similar check as done in make_decl_rtl().  */
+ 
+ static bool
+ hardreg_ok_p (int reg_number, machine_mode mode, int operand_num)
+ {
+   if (mode == BLKmode)
+     error ("data type isn%'t suitable for register %s of operand %i",
+ 	   reg_names[reg_number], operand_num);
+   else if (!in_hard_reg_set_p (accessible_reg_set, mode, reg_number))
+     error ("register %s for operand %i cannot be accessed"
+ 	   " by the current target", reg_names[reg_number], operand_num);
+   else if (!in_hard_reg_set_p (operand_reg_set, mode, reg_number))
+     error ("register %s for operand %i is not general enough"
+ 	   " to be used as a register variable", reg_names[reg_number], operand_num);
+   else if (!targetm.hard_regno_mode_ok (reg_number, mode))
+     error ("register %s for operand %i isn%'t suitable for data type",
+ 	   reg_names[reg_number], operand_num);
+   else if (reg_number != HARD_FRAME_POINTER_REGNUM
+ 	   && (reg_number == FRAME_POINTER_REGNUM
+ #ifdef RETURN_ADDRESS_POINTER_REGNUM
+ 	       || reg_number == RETURN_ADDRESS_POINTER_REGNUM
+ #endif
+ 	       || reg_number == ARG_POINTER_REGNUM)
+ 	   && eliminable_regno_p (reg_number))
+     error ("register for operand %i is an internal GCC "
+ 	   "implementation detail", operand_num);
+   else
+     return true;
+   return false;
+ }
+ 
  /* Parse the output constraint pointed to by *CONSTRAINT_P.  It is the
     OPERAND_NUMth output operand, indexed from zero.  There are NINPUTS
     inputs and NOUTPUTS outputs to this extended-asm.  Upon return,
*************** expand_label (tree label)
*** 191,197 ****
  bool
  parse_output_constraint (const char **constraint_p, int operand_num,
  			 int ninputs, int noutputs, bool *allows_mem,
! 			 bool *allows_reg, bool *is_inout)
  {
    const char *constraint = *constraint_p;
    const char *p;
--- 265,272 ----
  bool
  parse_output_constraint (const char **constraint_p, int operand_num,
  			 int ninputs, int noutputs, bool *allows_mem,
! 			 bool *allows_reg, bool *is_inout,
! 			 gimplify_reg_info *reg_info)
  {
    const char *constraint = *constraint_p;
    const char *p;
*************** parse_output_constraint (const char **co
*** 245,250 ****
--- 320,328 ----
        constraint = *constraint_p;
      }
  
+   unsigned int alt = 0;
+   bool early_clobbered = false;
+ 
    /* Loop through the constraint string.  */
    for (p = constraint + 1; *p; )
      {
*************** parse_output_constraint (const char **co
*** 264,275 ****
  	    }
  	  break;
  
! 	case '?':  case '!':  case '*':  case '&':  case '#':
  	case '$':  case '^':
  	case 'E':  case 'F':  case 'G':  case 'H':
  	case 's':  case 'i':  case 'n':
  	case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
! 	case 'N':  case 'O':  case 'P':  case ',':  case '-':
  	  break;
  
  	case '0':  case '1':  case '2':  case '3':  case '4':
--- 342,362 ----
  	    }
  	  break;
  
! 	case '&':
! 	  early_clobbered = true;
! 	  break;
! 
! 	case '?':  case '!':  case '*':  case '#':
  	case '$':  case '^':
  	case 'E':  case 'F':  case 'G':  case 'H':
  	case 's':  case 'i':  case 'n':
  	case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
! 	case 'N':  case 'O':  case 'P':  case '-':
! 	  break;
! 
! 	case ',':
! 	  ++alt;
! 	  early_clobbered = false;
  	  break;
  
  	case '0':  case '1':  case '2':  case '3':  case '4':
*************** parse_output_constraint (const char **co
*** 294,299 ****
--- 381,440 ----
  	  *allows_mem = true;
  	  break;
  
+ 	case '{':
+ 	  {
+ 	    if (!targetm.lra_p ())
+ 	      {
+ 		error ("hard register constraints are only supported while using LRA");
+ 		return false;
+ 	      }
+ 	    if (reg_info)
+ 	      {
+ 		int regno = decode_hard_reg_constraint (p);
+ 		if (regno < 0)
+ 		  {
+ 		    error ("invalid output constraint: %s", p);
+ 		    return false;
+ 		  }
+ 		int overlap_regno = reg_info->test_alt_output (alt, regno);
+ 		if (overlap_regno < 0)
+ 		  overlap_regno = reg_info->test_reg_asm_output (regno);
+ 		if (overlap_regno >= 0)
+ 		  {
+ 		    error ("multiple outputs to hard register: %s",
+ 			   reg_names[overlap_regno]);
+ 		    return false;
+ 		  }
+ 		reg_info->set_output (alt, regno);
+ 		if (early_clobbered)
+ 		  reg_info->set_early_clobbered (alt, operand_num, regno);
+ 		if (reg_info->is_clobbered (regno))
+ 		  {
+ 		    error ("hard register constraint for output %i conflicts "
+ 			   "with %<asm%> clobber list", operand_num);
+ 		    return false;
+ 		  }
+ 		if (VAR_P (reg_info->operand)
+ 		    && DECL_HARD_REGISTER (reg_info->operand))
+ 		  {
+ 		      tree id = DECL_ASSEMBLER_NAME (reg_info->operand);
+ 		      const char *asmspec = IDENTIFIER_POINTER (id) + 1;
+ 		      int regno_op = decode_reg_name (asmspec);
+ 		      if (regno != regno_op)
+ 			{
+ 			  error ("constraint and register %<asm%> for output "
+ 				 "operand %i are unsatisfiable", operand_num);
+ 			  return false;
+ 			}
+ 		  }
+ 		machine_mode mode = TYPE_MODE (TREE_TYPE (reg_info->operand));
+ 		if (!hardreg_ok_p (regno, mode, operand_num))
+ 		  return false;
+ 	      }
+ 	    *allows_reg = true;
+ 	    break;
+ 	  }
+ 
  	default:
  	  if (!ISALPHA (*p))
  	    break;
*************** parse_output_constraint (const char **co
*** 305,310 ****
--- 446,476 ----
  	    *allows_mem = true;
  	  else
  	    insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);
+ 	  if (reg_info && *allows_reg
+ 	      && VAR_P (reg_info->operand)
+ 	      && DECL_HARD_REGISTER (reg_info->operand))
+ 	    {
+ 		tree id = DECL_ASSEMBLER_NAME (reg_info->operand);
+ 		const char *asmspec = IDENTIFIER_POINTER (id) + 1;
+ 		int regno = decode_reg_name (asmspec);
+ 		if (regno < 0)
+ 		  {
+ 		    location_t loc = DECL_SOURCE_LOCATION (reg_info->operand);
+ 		    error_at (loc, "invalid register name for %q+D",
+ 			      reg_info->operand);
+ 		    return false;
+ 		  }
+ 		int overlap_regno = reg_info->test_alt_output (alt, regno);
+ 		if (overlap_regno >= 0)
+ 		  {
+ 		    error ("multiple outputs to hard register: %s",
+ 			   reg_names[overlap_regno]);
+ 		    return false;
+ 		  }
+ 		reg_info->set_reg_asm_output (regno);
+ 		if (early_clobbered)
+ 		  reg_info->set_early_clobbered (alt, operand_num, regno);
+ 	    }
  	  break;
  	}
  
*************** bool
*** 322,328 ****
  parse_input_constraint (const char **constraint_p, int input_num,
  			int ninputs, int noutputs, int ninout,
  			const char * const * constraints,
! 			bool *allows_mem, bool *allows_reg)
  {
    const char *constraint = *constraint_p;
    const char *orig_constraint = constraint;
--- 488,495 ----
  parse_input_constraint (const char **constraint_p, int input_num,
  			int ninputs, int noutputs, int ninout,
  			const char * const * constraints,
! 			bool *allows_mem, bool *allows_reg,
! 			gimplify_reg_info *reg_info)
  {
    const char *constraint = *constraint_p;
    const char *orig_constraint = constraint;
*************** parse_input_constraint (const char **con
*** 338,343 ****
--- 505,513 ----
  
    /* Make sure constraint has neither `=', `+', nor '&'.  */
  
+   unsigned int alt = 0;
+   unsigned long match = 0;
+ 
    for (j = 0; j < c_len; j += CONSTRAINT_LEN (constraint[j], constraint+j))
      switch (constraint[j])
        {
*************** parse_input_constraint (const char **con
*** 364,370 ****
        case 'E':  case 'F':  case 'G':  case 'H':
        case 's':  case 'i':  case 'n':
        case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
!       case 'N':  case 'O':  case 'P':  case ',':  case '-':
  	break;
  
        case ':':
--- 534,540 ----
        case 'E':  case 'F':  case 'G':  case 'H':
        case 's':  case 'i':  case 'n':
        case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
!       case 'N':  case 'O':  case 'P':  case '-':
  	break;
  
        case ':':
*************** parse_input_constraint (const char **con
*** 382,387 ****
--- 552,561 ----
  	  }
  	break;
  
+       case ',':
+ 	++alt;
+ 	break;
+ 
  	/* Whether or not a numeric constraint allows a register is
  	   decided by the matching constraint, and so there is no need
  	   to do anything special with them.  We must handle them in
*************** parse_input_constraint (const char **con
*** 391,397 ****
        case '5':  case '6':  case '7':  case '8':  case '9':
  	{
  	  char *end;
- 	  unsigned long match;
  
  	  saw_match = true;
  
--- 565,570 ----
*************** parse_input_constraint (const char **con
*** 429,434 ****
--- 602,666 ----
  	*allows_mem = true;
  	break;
  
+       case '{':
+ 	{
+ 	  if (!targetm.lra_p ())
+ 	    {
+ 	      error ("hard register constraints are only supported while using LRA");
+ 	      return false;
+ 	    }
+ 	  if (reg_info)
+ 	    {
+ 	      int regno = decode_hard_reg_constraint (constraint + j);
+ 	      if (regno < 0)
+ 		{
+ 		  error ("invalid input constraint: %s", constraint + j);
+ 		  return false;
+ 		}
+ 	      int overlap_regno = reg_info->test_alt_input (alt, regno);
+ 	      if (overlap_regno < 0)
+ 		overlap_regno = reg_info->test_reg_asm_input (regno);
+ 	      if (overlap_regno >= 0)
+ 		{
+ 		  error ("multiple inputs to hard register: %s",
+ 			    reg_names[overlap_regno]);
+ 		  return false;
+ 		}
+ 	      reg_info->set_input (alt, regno);
+ 	      if (reg_info->is_clobbered (regno))
+ 		{
+ 		  error ("hard register constraint for input %i conflicts "
+ 			 "with %<asm%> clobber list", input_num);
+ 		  return false;
+ 		}
+ 	      if (constraint == orig_constraint
+ 		  && reg_info->test_early_clobbered_alt (alt, regno))
+ 		{
+ 		  error ("invalid hard register usage between earlyclobber "
+ 			 "operand and input operand");
+ 		  return false;
+ 		}
+ 	      if (VAR_P (reg_info->operand)
+ 		  && DECL_HARD_REGISTER (reg_info->operand))
+ 		{
+ 		    tree id = DECL_ASSEMBLER_NAME (reg_info->operand);
+ 		    const char *asmspec = IDENTIFIER_POINTER (id) + 1;
+ 		    int regno_op = decode_reg_name (asmspec);
+ 		    if (regno != regno_op)
+ 		      {
+ 			error ("constraint and register %<asm%> for input "
+ 			       "operand %i are unsatisfiable", input_num);
+ 			return false;
+ 		      }
+ 		}
+ 	      machine_mode mode = TYPE_MODE (TREE_TYPE (reg_info->operand));
+ 	      if (!hardreg_ok_p (regno, mode, input_num))
+ 		return false;
+ 	    }
+ 	  *allows_reg = true;
+ 	  break;
+ 	}
+ 
        default:
  	if (! ISALPHA (constraint[j]))
  	  {
*************** parse_input_constraint (const char **con
*** 445,450 ****
--- 677,715 ----
  	  *allows_mem = true;
  	else
  	  insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);
+ 	if (reg_info && *allows_reg
+ 	    && VAR_P (reg_info->operand)
+ 	    && DECL_HARD_REGISTER (reg_info->operand))
+ 	  {
+ 	      tree id = DECL_ASSEMBLER_NAME (reg_info->operand);
+ 	      const char *asmspec = IDENTIFIER_POINTER (id) + 1;
+ 	      int regno = decode_reg_name (asmspec);
+ 	      if (regno < 0)
+ 		{
+ 		  location_t loc = DECL_SOURCE_LOCATION (reg_info->operand);
+ 		  error_at (loc, "invalid register name for %q+D",
+ 			    reg_info->operand);
+ 		  return false;
+ 		}
+ 	      int overlap_regno = reg_info->test_alt_input (alt, regno);
+ 	      if (overlap_regno >= 0)
+ 		{
+ 		  error ("multiple inputs to hard register: %s",
+ 			 reg_names[overlap_regno]);
+ 		  return false;
+ 		}
+ 	      reg_info->set_reg_asm_input (regno);
+ 	      if ((constraint == orig_constraint
+ 		   && reg_info->test_early_clobbered_alt (alt, regno))
+ 		  || (constraint != orig_constraint
+ 		      && reg_info->is_early_clobbered_in_any_output_unequal
+ 			  (match, regno)))
+ 		{
+ 		  error ("invalid hard register usage between earlyclobber "
+ 			 "operand and input operand");
+ 		  return false;
+ 		}
+ 	  }
  	break;
        }
  
diff -Nrcpad gcc-16-20250720/gcc/stmt.h gcc-16-20250727/gcc/stmt.h
*** gcc-16-20250720/gcc/stmt.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/stmt.h	Sun Jul 27 22:32:09 2025
*************** along with GCC; see the file COPYING3.
*** 20,30 ****
  #ifndef GCC_STMT_H
  #define GCC_STMT_H
  
  extern void expand_label (tree);
  extern bool parse_output_constraint (const char **, int, int, int,
! 				     bool *, bool *, bool *);
  extern bool parse_input_constraint (const char **, int, int, int, int,
! 				    const char * const *, bool *, bool *);
  extern tree resolve_asm_operand_names (tree, tree, tree, tree);
  #ifdef HARD_CONST
  /* Silly ifdef to avoid having all includers depend on hard-reg-set.h.  */
--- 20,35 ----
  #ifndef GCC_STMT_H
  #define GCC_STMT_H
  
+ class gimplify_reg_info;
+ 
  extern void expand_label (tree);
  extern bool parse_output_constraint (const char **, int, int, int,
! 				     bool *, bool *, bool *,
! 				     gimplify_reg_info *);
  extern bool parse_input_constraint (const char **, int, int, int, int,
! 				    const char * const *, bool *, bool *,
! 				    gimplify_reg_info *);
! extern int decode_hard_reg_constraint (const char *);
  extern tree resolve_asm_operand_names (tree, tree, tree, tree);
  #ifdef HARD_CONST
  /* Silly ifdef to avoid having all includers depend on hard-reg-set.h.  */
diff -Nrcpad gcc-16-20250720/gcc/substring-locations.cc gcc-16-20250727/gcc/substring-locations.cc
*** gcc-16-20250720/gcc/substring-locations.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/substring-locations.cc	Sun Jul 27 22:32:09 2025
*************** format_string_diagnostic_t (const substr
*** 151,157 ****
     Return true if a warning was emitted, false otherwise.  */
  
  bool
! format_string_diagnostic_t::emit_warning_n_va (diagnostic_option_id option_id,
  					       unsigned HOST_WIDE_INT n,
  					       const char *singular_gmsgid,
  					       const char *plural_gmsgid,
--- 151,157 ----
     Return true if a warning was emitted, false otherwise.  */
  
  bool
! format_string_diagnostic_t::emit_warning_n_va (diagnostics::option_id option_id,
  					       unsigned HOST_WIDE_INT n,
  					       const char *singular_gmsgid,
  					       const char *plural_gmsgid,
*************** format_string_diagnostic_t::emit_warning
*** 203,209 ****
    if (!err && m_corrected_substring && substring_within_range)
      richloc.add_fixit_replace (fmt_substring_range, m_corrected_substring);
  
!   diagnostic_info diagnostic;
    if (singular_gmsgid != plural_gmsgid)
      {
        unsigned long gtn;
--- 203,209 ----
    if (!err && m_corrected_substring && substring_within_range)
      richloc.add_fixit_replace (fmt_substring_range, m_corrected_substring);
  
!   diagnostics::diagnostic_info diagnostic;
    if (singular_gmsgid != plural_gmsgid)
      {
        unsigned long gtn;
*************** format_string_diagnostic_t::emit_warning
*** 218,229 ****
  
        const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
        diagnostic_set_info_translated (&diagnostic, text, ap, &richloc,
! 				      DK_WARNING);
      }
    else
      diagnostic_set_info (&diagnostic, singular_gmsgid, ap, &richloc,
! 			 DK_WARNING);
!   diagnostic.option_id = option_id;
    bool warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
  
    if (!err && fmt_substring_loc && !substring_within_range)
--- 218,229 ----
  
        const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
        diagnostic_set_info_translated (&diagnostic, text, ap, &richloc,
! 				      diagnostics::kind::warning);
      }
    else
      diagnostic_set_info (&diagnostic, singular_gmsgid, ap, &richloc,
! 			 diagnostics::kind::warning);
!   diagnostic.m_option_id = option_id;
    bool warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
  
    if (!err && fmt_substring_loc && !substring_within_range)
*************** format_string_diagnostic_t::emit_warning
*** 248,254 ****
  /* Singular-only version of the above.  */
  
  bool
! format_string_diagnostic_t::emit_warning_va (diagnostic_option_id option_id,
  					     const char *gmsgid,
  					     va_list *ap) const
  {
--- 248,254 ----
  /* Singular-only version of the above.  */
  
  bool
! format_string_diagnostic_t::emit_warning_va (diagnostics::option_id option_id,
  					     const char *gmsgid,
  					     va_list *ap) const
  {
*************** format_string_diagnostic_t::emit_warning
*** 258,264 ****
  /* Variadic version of the above (singular only).  */
  
  bool
! format_string_diagnostic_t::emit_warning (diagnostic_option_id option_id,
  					  const char *gmsgid,
  					  ...) const
  {
--- 258,264 ----
  /* Variadic version of the above (singular only).  */
  
  bool
! format_string_diagnostic_t::emit_warning (diagnostics::option_id option_id,
  					  const char *gmsgid,
  					  ...) const
  {
*************** format_string_diagnostic_t::emit_warning
*** 273,279 ****
  /* Variadic version of the above (singular vs plural).  */
  
  bool
! format_string_diagnostic_t::emit_warning_n (diagnostic_option_id option_id,
  					    unsigned HOST_WIDE_INT n,
  					    const char *singular_gmsgid,
  					    const char *plural_gmsgid,
--- 273,279 ----
  /* Variadic version of the above (singular vs plural).  */
  
  bool
! format_string_diagnostic_t::emit_warning_n (diagnostics::option_id option_id,
  					    unsigned HOST_WIDE_INT n,
  					    const char *singular_gmsgid,
  					    const char *plural_gmsgid,
diff -Nrcpad gcc-16-20250720/gcc/substring-locations.h gcc-16-20250727/gcc/substring-locations.h
*** gcc-16-20250720/gcc/substring-locations.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/substring-locations.h	Sun Jul 27 22:32:09 2025
*************** class format_string_diagnostic_t
*** 90,112 ****
  
    /* Functions for emitting a warning about a format string.  */
  
!   bool emit_warning_va (diagnostic_option_id option_id,
  			const char *gmsgid,
  			va_list *ap) const
      ATTRIBUTE_GCC_DIAG (3, 0);
  
!   bool emit_warning_n_va (diagnostic_option_id option_id,
  			  unsigned HOST_WIDE_INT n,
  			  const char *singular_gmsgid,
  			  const char *plural_gmsgid,
  			  va_list *ap) const
    ATTRIBUTE_GCC_DIAG (4, 0) ATTRIBUTE_GCC_DIAG (5, 0);
  
!   bool emit_warning (diagnostic_option_id option_id,
  		     const char *gmsgid, ...) const
      ATTRIBUTE_GCC_DIAG (3, 4);
  
!   bool emit_warning_n (diagnostic_option_id option_id,
  		       unsigned HOST_WIDE_INT n,
  		       const char *singular_gmsgid,
  		       const char *plural_gmsgid, ...) const
--- 90,112 ----
  
    /* Functions for emitting a warning about a format string.  */
  
!   bool emit_warning_va (diagnostics::option_id option_id,
  			const char *gmsgid,
  			va_list *ap) const
      ATTRIBUTE_GCC_DIAG (3, 0);
  
!   bool emit_warning_n_va (diagnostics::option_id option_id,
  			  unsigned HOST_WIDE_INT n,
  			  const char *singular_gmsgid,
  			  const char *plural_gmsgid,
  			  va_list *ap) const
    ATTRIBUTE_GCC_DIAG (4, 0) ATTRIBUTE_GCC_DIAG (5, 0);
  
!   bool emit_warning (diagnostics::option_id option_id,
  		     const char *gmsgid, ...) const
      ATTRIBUTE_GCC_DIAG (3, 4);
  
!   bool emit_warning_n (diagnostics::option_id option_id,
  		       unsigned HOST_WIDE_INT n,
  		       const char *singular_gmsgid,
  		       const char *plural_gmsgid, ...) const
*************** class format_string_diagnostic_t
*** 125,131 ****
     LANG_HOOKS_GET_SUBSTRING_LOCATION.  */
  
  extern const char *get_location_within_string (cpp_reader *pfile,
! 					       file_cache &fc,
  					       string_concat_db *concats,
  					       location_t strloc,
  					       enum cpp_ttype type,
--- 125,131 ----
     LANG_HOOKS_GET_SUBSTRING_LOCATION.  */
  
  extern const char *get_location_within_string (cpp_reader *pfile,
! 					       diagnostics::file_cache &fc,
  					       string_concat_db *concats,
  					       location_t strloc,
  					       enum cpp_ttype type,
diff -Nrcpad gcc-16-20250720/gcc/symtab.cc gcc-16-20250727/gcc/symtab.cc
*** gcc-16-20250720/gcc/symtab.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/symtab.cc	Sun Jul 27 22:32:09 2025
*************** symbol_table::change_decl_assembler_name
*** 305,310 ****
--- 305,311 ----
        SET_DECL_ASSEMBLER_NAME (decl, name);
        if (alias)
  	{
+ 	  gcc_assert (!IDENTIFIER_INTERNAL_P (name));
  	  IDENTIFIER_TRANSPARENT_ALIAS (name) = 1;
  	  TREE_CHAIN (name) = alias;
  	}
diff -Nrcpad gcc-16-20250720/gcc/target.def gcc-16-20250727/gcc/target.def
*** gcc-16-20250720/gcc/target.def	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/target.def	Sun Jul 27 22:32:09 2025
*************** implementation approaches itself.",
*** 1918,1934 ****
   NULL)
  
  /* Return true if the target supports misaligned store/load of a
!    specific factor denoted in the third parameter.  The last parameter
!    is true if the access is defined in a packed struct.  */
  DEFHOOK
  (support_vector_misalignment,
   "This hook should return true if the target supports misaligned vector\n\
  store/load of a specific factor denoted in the @var{misalignment}\n\
  parameter.  The vector store/load should be of machine mode @var{mode} and\n\
! the elements in the vectors should be of type @var{type}.  @var{is_packed}\n\
! parameter is true if the memory access is defined in a packed struct.",
   bool,
!  (machine_mode mode, const_tree type, int misalignment, bool is_packed),
   default_builtin_support_vector_misalignment)
  
  /* Returns the preferred mode for SIMD operations for the specified
--- 1918,1938 ----
   NULL)
  
  /* Return true if the target supports misaligned store/load of a
!    specific factor denoted in the third parameter.  The second to the last
!    parameter is true if the access is defined in a packed struct and
!    the last parameter is true if the access is a gather/scatter.  */
  DEFHOOK
  (support_vector_misalignment,
   "This hook should return true if the target supports misaligned vector\n\
  store/load of a specific factor denoted in the @var{misalignment}\n\
  parameter.  The vector store/load should be of machine mode @var{mode} and\n\
! the elements in the vectors should be of type @var{type}.  The\n\
! @var{is_packed} parameter is true if the misalignment is unknown and the\n\
! memory access is defined in a packed struct.  @var{is_gather_scatter} is true\n\
! if the load/store is a gather or scatter.",
   bool,
!  (machine_mode mode, const_tree type, int misalignment, bool is_packed,
!   bool is_gather_scatter),
   default_builtin_support_vector_misalignment)
  
  /* Returns the preferred mode for SIMD operations for the specified
diff -Nrcpad gcc-16-20250720/gcc/target.h gcc-16-20250727/gcc/target.h
*** gcc-16-20250720/gcc/target.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/target.h	Sun Jul 27 22:32:09 2025
*************** class predefined_function_abi;
*** 169,175 ****
  struct store_fwd_info;
  
  /* These are defined in tree-vect-stmts.cc.  */
- extern tree stmt_vectype (class _stmt_vec_info *);
  extern bool stmt_in_inner_loop_p (class vec_info *, class _stmt_vec_info *);
  
  /* Assembler instructions for creating various kinds of integer object.  */
--- 169,174 ----
diff -Nrcpad gcc-16-20250720/gcc/targhooks.cc gcc-16-20250727/gcc/targhooks.cc
*** gcc-16-20250720/gcc/targhooks.cc	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/targhooks.cc	Sun Jul 27 22:32:09 2025
*************** default_builtin_support_vector_misalignm
*** 1556,1561 ****
--- 1556,1563 ----
  					     int misalignment
  					     ATTRIBUTE_UNUSED,
  					     bool is_packed
+ 					     ATTRIBUTE_UNUSED,
+ 					     bool is_gather_scatter
  					     ATTRIBUTE_UNUSED)
  {
    if (optab_handler (movmisalign_optab, mode) != CODE_FOR_nothing)
diff -Nrcpad gcc-16-20250720/gcc/targhooks.h gcc-16-20250727/gcc/targhooks.h
*** gcc-16-20250720/gcc/targhooks.h	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/targhooks.h	Sun Jul 27 22:32:09 2025
*************** extern bool default_builtin_vector_align
*** 114,120 ****
  extern bool
  default_builtin_support_vector_misalignment (machine_mode mode,
  					     const_tree,
! 					     int, bool);
  extern machine_mode default_preferred_simd_mode (scalar_mode mode);
  extern machine_mode default_split_reduction (machine_mode);
  extern unsigned int default_autovectorize_vector_modes (vector_modes *, bool);
--- 114,120 ----
  extern bool
  default_builtin_support_vector_misalignment (machine_mode mode,
  					     const_tree,
! 					     int, bool, bool);
  extern machine_mode default_preferred_simd_mode (scalar_mode mode);
  extern machine_mode default_split_reduction (machine_mode);
  extern unsigned int default_autovectorize_vector_modes (vector_modes *, bool);
diff -Nrcpad gcc-16-20250720/gcc/testsuite/ChangeLog gcc-16-20250727/gcc/testsuite/ChangeLog
*** gcc-16-20250720/gcc/testsuite/ChangeLog	Sun Jul 20 22:32:10 2025
--- gcc-16-20250727/gcc/testsuite/ChangeLog	Sun Jul 27 22:32:09 2025
***************
*** 1,3 ****
--- 1,568 ----
+ 2025-07-27  Nathaniel Shead  <nathanieloshead@gmail.com>
+ 
+ 	* g++.dg/modules/class-11_a.H: New test.
+ 	* g++.dg/modules/class-11_b.C: New test.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/diagnostic_plugin_test_graphs.cc: Eliminate
+ 	digraphs::lazy_digraph and digraphs::lazy_digraphs in favor of
+ 	lazily_created template.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_metadata.cc: Define
+ 	INCLUDE_VECTOR since diagnostics/metadata.h now requires it.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_paths.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/diagnostic_plugin_show_trees.cc: Make
+ 	diagnostics::context::m_source_printing private.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_inlining.cc: Likewise.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_string_literals.cc:
+ 	Likewise.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.cc:
+ 	Likewise.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_paths.cc: Likewise.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc: Likewise.
+ 	* gcc.dg/plugin/expensive_selftests_plugin.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* g++.dg/plugin/show_template_tree_color_plugin.cc: Update usage
+ 	of "diagnostic_info" to explicitly refer to
+ 	"diagnostics::diagnostic_info".
+ 	* gcc.dg/plugin/diagnostic_group_plugin.cc: Likewise.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc: Likewise.
+ 	* gcc.dg/plugin/location_overflow_plugin.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc: Update for
+ 	file_cache and char_span moving from input.h to
+ 	diagnostics/file-cache.h and into the "diagnostics::" namespace.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc: Update for
+ 	diagnostic_t becoming enum class diagnostics::kind.
+ 	* gcc.dg/plugin/expensive_selftests_plugin.cc: Likewise.
+ 	* gcc.dg/plugin/location_overflow_plugin.cc: Likewise.
+ 	* lib/gcc-dg.exp: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/expensive_selftests_plugin.cc: Update for change
+ 	from edit-context.h to changes.h.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/expensive_selftests_plugin.cc: Update for move of
+ 	selftest::test_diagnostic_context to
+ 	diagnostics::selftest::test_context.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/analyzer_cpython_plugin.cc: Update for move of
+ 	diagnostic-color.h to diagnostics/color.h.
+ 	* gcc.dg/plugin/analyzer_kernel_plugin.cc: Likewise.
+ 	* gcc.dg/plugin/analyzer_known_fns_plugin.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/expensive_selftests_plugin.cc: Update for move of
+ 	selftest-diagnostic.h to diagnostics/selftest-context.h.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* g++.dg/plugin/show_template_tree_color_plugin.cc: Update for
+ 	moves to namespace diagnostics.
+ 	* gcc.dg/plugin/diagnostic_group_plugin.cc: Likewise.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc: Likewise.
+ 	* gcc.dg/plugin/location_overflow_plugin.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc: Update to
+ 	add "m_" prefix to fields of diagnostic_info throughout.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* g++.dg/plugin/show-template-tree-color-labels.C: Update for
+ 	moves to "source-printing".
+ 	* gcc.dg/plugin/diagnostic-test-show-locus.py: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/diagnostic_group_plugin.cc: Update for move of
+ 	diagnostics output formats into namespace "diagnostics" as
+ 	"sinks".
+ 	* gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc: Likewise.
+ 	* gcc.dg/plugin/location_overflow_plugin.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/analyzer_gil_plugin.cc: Update #include for
+ 	"diagnostic-path.h" moving to "diagnostics/paths.h",
+ 	diagnostic_thread_id_t to diagnostics::paths::thread_id_t,
+ 	diagnostic_event_id_t to diagnostics::paths::event_id_t,
+ 	diagnostic_path to diagnostics::paths::path, and
+ 	diagnostic_thread to diagnostics::paths::thread, and
+ 	diagnostic_event to diagnostics::paths::event.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_paths.cc: Likewise.
+ 	* lib/sarif.py (get_state_graph): Update property prefix for
+ 	threadFlowLocations from "gcc/diagnostic_event/" to
+ 	"gcc/diagnostics/paths/event/".
+ 	* gcc.dg/sarif-output/include-chain-2.h: Update comment.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/expensive_selftests_plugin.cc: Update #include for
+ 	move of edit-context.h to diagnostics subdir.  Update
+ 	for move of edit_context to diagnostics::edit_context.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/diagnostic_plugin_test_text_art.cc: Update
+ 	#include for move of "diagnostic-diagram.h" to
+ 	"diagnostics/diagram.h". Update for move of diagnostic_diagram to
+ 	diagnostics::diagram.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/analyzer_cpython_plugin.cc: : Update #include for
+ 	move of "diagnostic-metadata.h" to "diagnostics/metadata.h"
+ 	* gcc.dg/plugin/analyzer_kernel_plugin.cc: Likewise.
+ 	* gcc.dg/plugin/analyzer_known_fns_plugin.cc: Likewise.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_graphs.cc: Likewise.  Also
+ 	update for move of diagnostic_metadata to diagnostics::metadata.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_metadata.cc: Likewise.
+ 	* gcc.dg/plugin/diagnostic_plugin_test_paths.cc: Likewise.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* gcc.dg/plugin/diagnostic_plugin_test_graphs.cc: Update #include
+ 	for move of "diagnostic-digraphs.h" to "diagnostics/digraphs.h".
+ 
+ 2025-07-25  Patrick Palka  <ppalka@redhat.com>
+ 
+ 	* g++.dg/lookup/operator-8.C: Remove XFAILs and properly
+ 	suppress all -Wunused-result warnings.
+ 
+ 2025-07-25  Iain Sandoe  <iain@sandoe.co.uk>
+ 
+ 	PR c++/121219
+ 	* g++.dg/coroutines/torture/pr121219.C: New test.
+ 
+ 2025-07-25  Christoph Müllner  <christoph.muellner@vrull.eu>
+ 
+ 	* gcc.target/riscv/interrupt-conflict-mode.c: Remove "user"
+ 	interrupts.
+ 	* gcc.target/riscv/xtheadint-push-pop.c: Likewise.
+ 	* gcc.target/riscv/interrupt-umode.c: Removed.
+ 
+ 2025-07-25  Christoph Müllner  <christoph.muellner@vrull.eu>
+ 
+ 	* gcc.target/riscv/interrupt-rnmi.c: New test.
+ 
+ 2025-07-24  Nathaniel Shead  <nathanieloshead@gmail.com>
+ 
+ 	PR c++/117294
+ 	PR c++/113854
+ 	* g++.dg/cpp2a/concepts-traits3.C: Adjust diagnostics.
+ 	* g++.dg/cpp2a/concepts-traits4.C: New test.
+ 	* g++.dg/diagnostic/static_assert5.C: New test.
+ 	* g++.dg/ext/has_virtual_destructor2.C: New test.
+ 	* g++.dg/ext/is_assignable2.C: New test.
+ 	* g++.dg/ext/is_constructible9.C: New test.
+ 	* g++.dg/ext/is_convertible7.C: New test.
+ 	* g++.dg/ext/is_destructible3.C: New test.
+ 	* g++.dg/ext/is_invocable6.C: New test.
+ 	* g++.dg/ext/is_virtual_base_of_diagnostic2.C: New test.
+ 
+ 2025-07-24  Jason Merrill  <jason@redhat.com>
+ 
+ 	PR c++/114632
+ 	PR c++/101233
+ 	* g++.dg/cpp23/explicit-obj-lambda18.C: New test.
+ 	* g++.dg/cpp23/static-operator-call7.C: New test.
+ 
+ 2025-07-24  Robert Dubner  <rdubner@symas.com>
+ 
+ 	* cobol.dg/group2/_-static__compilation.cob: Modify for -static warning.
+ 	* cobol.dg/group2/_-static__compilation.out: Removed.
+ 
+ 2025-07-24  Robin Dapp  <rdapp@ventanamicro.com>
+ 
+ 	* lib/target-supports.exp: Fix misalignment check.
+ 
+ 2025-07-24  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* g++.target/aarch64/sve/unpacked_cond_binary_bf16_1.C: New test.
+ 	* gcc.target/aarch64/sve/unpacked_cond_builtin_fmax_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_builtin_fmin_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_fadd_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_fdiv_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_fmaxnm_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_fminnm_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_fmul_1.c: Likewise..
+ 	* gcc.target/aarch64/sve/unpacked_cond_fsubr_1.c: Likewise.
+ 
+ 2025-07-24  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* gcc.target/aarch64/sve/unpacked_fdiv_1.c: New test.
+ 	* gcc.target/aarch64/sve/unpacked_fdiv_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fdiv_3.c: Likewise.
+ 
+ 2025-07-24  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* g++.target/aarch64/sve/unpacked_binary_bf16_1.C: New test.
+ 	* g++.target/aarch64/sve/unpacked_binary_bf16_2.C: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_builtin_fmax_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_builtin_fmax_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_builtin_fmin_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_builtin_fmin_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fadd_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fadd_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fmaxnm_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fmaxnm_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fminnm_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fminnm_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fmul_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fmul_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fsubr_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_fsubr_2.c: Likewise.
+ 
+ 2025-07-24  Jeevitha Palanisamy  <jeevitha@linux.ibm.com>
+ 
+ 	PR testsuite/119382
+ 	* gcc.target/powerpc/vsx-builtin-7.c: Add '-fno-ipa-icf' to dg-options.
+ 
+ 2025-07-24  Pan Li  <pan2.li@intel.com>
+ 
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u16.c: New test.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u32.c: New test.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u64.c: New test.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u8.c: New test.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm.h: New test.
+ 
+ 2025-07-24  Nathaniel Shead  <nathanieloshead@gmail.com>
+ 
+ 	PR c++/120412
+ 	* g++.dg/modules/internal-14_a.C: New test.
+ 	* g++.dg/modules/internal-14_b.C: New test.
+ 	* g++.dg/modules/internal-14_c.C: New test.
+ 
+ 2025-07-23  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* gcc.target/aarch64/sve/unpacked_cond_fabs_1.c: New test.
+ 	* gcc.target/aarch64/sve/unpacked_cond_fneg_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_frinta_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_frinta_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_frinti_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_frintm_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_frintp_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_frintx_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_frintz_1.c: Likewise.
+ 
+ 2025-07-23  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* gcc.target/aarch64/sve/unpacked_fabs_1.c: New test.
+ 	* gcc.target/aarch64/sve/unpacked_fneg_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frinta_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frinta_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frinti_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frinti_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frintm_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frintm_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frintp_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frintp_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frintx_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frintx_2.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frintz_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_frintz_2.c: Likewise.
+ 
+ 2025-07-23  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* gcc.target/aarch64/sve/unpacked_cond_cvtf_1.c: New test.
+ 	* gcc.target/aarch64/sve/unpacked_cond_fcvt_1.c: Likewise.
+ 	* gcc.target/aarch64/sve/unpacked_cond_fcvtz_1.c: Likewise.
+ 
+ 2025-07-23  Harald Anlauf  <anlauf@gmx.de>
+ 
+ 	PR fortran/121203
+ 	* gfortran.dg/function_charlen_4.f90: New test.
+ 
+ 2025-07-23  Robin Dapp  <rdapp@ventanamicro.com>
+ 
+ 	PR target/121073
+ 	* gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-6.c: Adjust test
+ 	expectation.
+ 	* gcc.target/riscv/rvv/base/scalar_move-5.c: Ditto.
+ 	* gcc.target/riscv/rvv/base/scalar_move-6.c: Ditto.
+ 	* gcc.target/riscv/rvv/base/scalar_move-7.c: Ditto.
+ 	* gcc.target/riscv/rvv/base/scalar_move-8.c: Ditto.
+ 	* gcc.target/riscv/rvv/base/scalar_move-9.c: Ditto.
+ 	* gcc.target/riscv/rvv/pr121073.c: New test.
+ 
+ 2025-07-23  Robin Dapp  <rdapp@ventanamicro.com>
+ 
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c:
+ 	Add zvfh requirements and options.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c:
+ 	Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c:
+ 	Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c:
+ 	Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c:
+ 	Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c:
+ 	Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c:
+ 	Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c:
+ 	Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmacc-run-1-f16.c:
+ 	Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmsac-run-1-f16.c:
+ 	Ditto.
+ 	* lib/target-supports.exp: Add zvfh options.
+ 
+ 2025-07-23  Andrew Pinski  <quic_apinski@quicinc.com>
+ 
+ 	PR target/120119
+ 	* g++.dg/torture/pr120119-1.C: New test.
+ 
+ 2025-07-23  Patrick Palka  <ppalka@redhat.com>
+ 
+ 	PR c++/121179
+ 	* g++.dg/lookup/operator-8.C: Strengthen test and remove one
+ 	XFAIL.
+ 
+ 2025-07-23  Patrick Palka  <ppalka@redhat.com>
+ 
+ 	PR c++/121055
+ 	* g++.dg/ext/is_invocable5.C: New test.
+ 
+ 2025-07-23  Spencer Abson  <spencer.abson@arm.com>
+ 
+ 	* lib/gcc-defs.exp (aarch64-arg-dg-options): Split add_tune into
+ 	add_tune and add_override, so that specifying -moverride does not
+ 	change the baseline tuning from the testuite's default (generic).
+ 
+ 2025-07-23  Richard Biener  <rguenther@suse.de>
+ 
+ 	PR tree-optimization/121220
+ 	* gcc.dg/tree-ssa/ssa-sink-23.c: New testcase.
+ 
+ 2025-07-23  Martin Jambor  <mjambor@suse.cz>
+ 
+ 	PR tree-optimization/119085
+ 	* gcc.dg/tree-ssa/pr119085.c: New test.
+ 
+ 2025-07-23  Gaius Mulley  <gaiusmod2@gmail.com>
+ 
+ 	PR modula2/121164
+ 	* gm2/switches/pedantic-params/fail/arrayofchar.def: New test.
+ 	* gm2/switches/pedantic-params/fail/arrayofchar.mod: New test.
+ 
+ 2025-07-23  Richard Biener  <rguenther@suse.de>
+ 
+ 	PR middle-end/121216
+ 	* gcc.dg/pr121216.c: New testcase.
+ 
+ 2025-07-23  Andrew Pinski  <quic_apinski@quicinc.com>
+ 
+ 	PR testsuite/120101
+ 	* gcc.dg/tree-ssa/pr81627.c (fn1): Mark as noinline.
+ 
+ 2025-07-23  Siddhesh Poyarekar  <siddhesh@gotplt.org>
+ 
+ 	* gcc.dg/vect/pr116125.c (mem_overlap): Expand A to 10 members.
+ 
+ 2025-07-22  Jason Merrill  <jason@redhat.com>
+ 
+ 	PR c++/121068
+ 	* g++.dg/cpp2a/constexpr-union6.C: Expect x5 to work.
+ 	* g++.dg/cpp26/constexpr-new4.C: New test.
+ 
+ 2025-07-22  Jason Merrill  <jason@redhat.com>
+ 
+ 	* g++.dg/warn/Wmismatched-new-delete-5.C: Fix allocation.
+ 
+ 2025-07-22  Andrew Pinski  <quic_apinski@quicinc.com>
+ 
+ 	PR middle-end/109267
+ 	* lib/target-supports.exp (check_effective_target_trap): New proc.
+ 	* g++.dg/missing-return.C: Update testcase for the !trap case.
+ 	* gcc.dg/pr109267-1.c: New test.
+ 	* gcc.dg/pr109267-2.c: New test.
+ 
+ 2025-07-22  Karl Meakin  <karl.meakin@arm.com>
+ 
+ 	* gcc.target/aarch64/sve/mask_load_2.c: Update tests.
+ 
+ 2025-07-22  Karl Meakin  <karl.meakin@arm.com>
+ 
+ 	* gcc.target/aarch64/sve/mask_load_2.c: New test.
+ 
+ 2025-07-22  Richard Biener  <rguenther@suse.de>
+ 
+ 	PR tree-optimization/121202
+ 	* gcc.dg/pr121202.c: New testcase.
+ 
+ 2025-07-22  Richard Biener  <rguenther@suse.de>
+ 
+ 	* gcc.dg/vect/slp-28.c: Adjust.
+ 
+ 2025-07-21  Andrew Pinski  <quic_apinski@quicinc.com>
+ 
+ 	PR tree-optimization/110949
+ 	PR tree-optimization/95906
+ 	* gcc.dg/tree-ssa/cmp-2.c: New test.
+ 	* gcc.dg/tree-ssa/max-bitcmp-1.c: New test.
+ 
+ 2025-07-21  Pan Li  <pan2.li@intel.com>
+ 
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u64.c: Add asm check.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u64.c: New test.
+ 
+ 2025-07-21  Pan Li  <pan2.li@intel.com>
+ 
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u16.c: Add asm check.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u32.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u8.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u16.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u32.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u8.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u16.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u32.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u8.c: Ditto.
+ 
+ 2025-07-21  Pan Li  <pan2.li@intel.com>
+ 
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u16.c: Add asm check.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u32.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u8.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u16.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u32.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u8.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u16.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u32.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u8.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h: Add test
+ 	helper macros.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h: Add test
+ 	data for run test.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u16.c: New test.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u32.c: New test.
+ 	* gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u8.c: New test.
+ 
+ 2025-07-21  Kyrylo Tkachov  <ktkachov@nvidia.com>
+ 
+ 	* gcc.target/aarch64/simd/mf8_data_1.c (test_set_lane4,
+ 	test_setq_lane4): Relax allowed assembly.
+ 	* gcc.target/aarch64/vec-set-zero.c: Use -Os in flags.
+ 	* gcc.target/aarch64/inszero_split_1.c: New test.
+ 
+ 2025-07-21  Richard Biener  <rguenther@suse.de>
+ 
+ 	PR tree-optimization/121194
+ 	* gcc.dg/torture/pr121194.c: New testcase.
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* gcc.dg/pr87600-2.c: Split test into two files since errors for
+ 	functions test{0,1} are thrown during expand, and for
+ 	test{2,3} during gimplification.
+ 	* lib/scanasm.exp: On s390, skip lines beginning with #.
+ 	* gcc.dg/asm-hard-reg-error-1.c: New test.
+ 	* gcc.dg/asm-hard-reg-error-2.c: New test.
+ 	* gcc.dg/asm-hard-reg-error-3.c: New test.
+ 	* gcc.dg/asm-hard-reg-error-4.c: New test.
+ 	* gcc.dg/asm-hard-reg-error-5.c: New test.
+ 	* gcc.dg/pr87600-3.c: New test.
+ 	* gcc.target/aarch64/asm-hard-reg-2.c: New test.
+ 	* gcc.target/s390/asm-hard-reg-7.c: New test.
+ 
+ 2025-07-21  Stefan Schulze Frielinghaus  <stefansf@gcc.gnu.org>
+ 
+ 	* gcc.dg/asm-hard-reg-1.c: New test.
+ 	* gcc.dg/asm-hard-reg-2.c: New test.
+ 	* gcc.dg/asm-hard-reg-3.c: New test.
+ 	* gcc.dg/asm-hard-reg-4.c: New test.
+ 	* gcc.dg/asm-hard-reg-5.c: New test.
+ 	* gcc.dg/asm-hard-reg-6.c: New test.
+ 	* gcc.dg/asm-hard-reg-7.c: New test.
+ 	* gcc.dg/asm-hard-reg-8.c: New test.
+ 	* gcc.target/aarch64/asm-hard-reg-1.c: New test.
+ 	* gcc.target/i386/asm-hard-reg-1.c: New test.
+ 	* gcc.target/i386/asm-hard-reg-2.c: New test.
+ 	* gcc.target/s390/asm-hard-reg-1.c: New test.
+ 	* gcc.target/s390/asm-hard-reg-2.c: New test.
+ 	* gcc.target/s390/asm-hard-reg-3.c: New test.
+ 	* gcc.target/s390/asm-hard-reg-4.c: New test.
+ 	* gcc.target/s390/asm-hard-reg-5.c: New test.
+ 	* gcc.target/s390/asm-hard-reg-6.c: New test.
+ 	* gcc.target/s390/asm-hard-reg-longdouble.h: New test.
+ 
+ 2025-07-21  Richard Biener  <rguenther@suse.de>
+ 
+ 	* gcc.dg/vect/vect-127.c: New testcase.
+ 
+ 2025-07-21  Andre Vehreschild  <vehre@gcc.gnu.org>
+ 
+ 	PR fortran/119106
+ 	* gfortran.dg/array_constructor_58.f90: New test.
+ 
+ 2025-07-21  panciyan  <panciyan@eswincomputing.com>
+ 
+ 	* gcc.target/riscv/sat/sat_arith.h: Unsigned testcase form8 form9.
+ 	* gcc.target/riscv/sat/sat_u_add-8-u16.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-8-u32.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-8-u64.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-8-u8.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-9-u16.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-9-u32.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-9-u64.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-9-u8.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-run-8-u16.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-run-8-u32.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-run-8-u64.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-run-8-u8.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-run-9-u16.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-run-9-u32.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-run-9-u64.c: New test.
+ 	* gcc.target/riscv/sat/sat_u_add-run-9-u8.c: New test.
+ 
+ 2025-07-20  Andrew Pinski  <quic_apinski@quicinc.com>
+ 
+ 	PR testsuite/120859
+ 	* gcc.dg/tree-prof/afdo-crossmodule-1b.c: Add some dg-*
+ 	commands like what is in afdo-crossmodule-1.c
+ 
+ 2025-07-20  Pan Li  <pan2.li@intel.com>
+ 
+ 	* gcc.target/riscv/rvv/autovec/avg_floor-1-i16-from-i32.c:
+ 	Leverage DEF_AVG_0_WRAP to generate the correct func name.
+ 	* gcc.target/riscv/rvv/autovec/avg_floor-1-i16-from-i64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_floor-1-i32-from-i64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_floor-1-i64-from-i128.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_floor-1-i8-from-i16.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_floor-1-i8-from-i32.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_floor-1-i8-from-i64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_ceil-1-i32-from-i64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i16.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i32.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i64.c: Ditto.
+ 	* gcc.target/riscv/rvv/autovec/avg_ceil-1-i64-from-i128.c: Ditto.
+ 
  2025-07-19  Dimitar Dimitrov  <dimitar@dinux.eu>
  
  	PR target/121124
diff -Nrcpad gcc-16-20250720/gcc/testsuite/cobol.dg/group2/_-static__compilation.cob gcc-16-20250727/gcc/testsuite/cobol.dg/group2/_-static__compilation.cob
*** gcc-16-20250720/gcc/testsuite/cobol.dg/group2/_-static__compilation.cob	Sun Jul 20 22:32:11 2025
--- gcc-16-20250727/gcc/testsuite/cobol.dg/group2/_-static__compilation.cob	Sun Jul 27 22:32:10 2025
***************
*** 1,7 ****
         *> { dg-do run }
         *> { dg-options "-static" }
!        *> { dg-output-file "group2/_-static__compilation.out" }
! 
         IDENTIFICATION DIVISION.
         PROGRAM-ID. prog.
         PROCEDURE DIVISION.
--- 1,7 ----
         *> { dg-do run }
         *> { dg-options "-static" }
!        *> { dg-prune-output {warning} }
!        *> { dg-output {hello, world} }
         IDENTIFICATION DIVISION.
         PROGRAM-ID. prog.
         PROCEDURE DIVISION.
diff -Nrcpad gcc-16-20250720/gcc/testsuite/cobol.dg/group2/_-static__compilation.out gcc-16-20250727/gcc/testsuite/cobol.dg/group2/_-static__compilation.out
*** gcc-16-20250720/gcc/testsuite/cobol.dg/group2/_-static__compilation.out	Sun Jul 20 22:32:11 2025
--- gcc-16-20250727/gcc/testsuite/cobol.dg/group2/_-static__compilation.out	Thu Jan  1 00:00:00 1970
***************
*** 1,2 ****
- hello, world
- 
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/coroutines/torture/pr121219.C gcc-16-20250727/gcc/testsuite/g++.dg/coroutines/torture/pr121219.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/coroutines/torture/pr121219.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/coroutines/torture/pr121219.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,149 ----
+ // PR c++/121219
+ // { dg-do run }
+ 
+ #include <coroutine>
+ #ifdef OUTPUT
+ #include <iostream>
+ #endif
+ #include <stdexcept>
+ 
+ struct Task {
+     struct promise_type;
+     using handle_type = std::coroutine_handle<promise_type>;
+ 
+     struct promise_type {
+         Task* task_;
+         int result_;
+ 
+         static void* operator new(std::size_t size) noexcept {
+             void* p = ::operator new(size, std::nothrow);
+ #ifdef OUTPUT
+             std::cerr << "operator new (no arg) " << size << " -> " << p << std::endl;  
+ #endif
+             return p;
+         }
+         static void operator delete(void* ptr) noexcept {
+             return ::operator delete(ptr, std::nothrow);
+         }
+ #if 1 // change to 0 to fix crash
+         static Task get_return_object_on_allocation_failure() noexcept {
+ #ifdef OUTPUT
+             std::cerr << "get_return_object_on_allocation_failure" << std::endl;
+ #endif
+             return Task(nullptr);
+         }
+ #endif
+ 
+         auto get_return_object() { 
+ #ifdef OUTPUT
+             std::cerr << "get_return_object" << std::endl;
+ #endif
+             return Task{handle_type::from_promise(*this)}; 
+         }
+ 
+         auto initial_suspend() { 
+ #ifdef OUTPUT
+             std::cerr << "initial_suspend" << std::endl;
+ #endif
+             return std::suspend_always{}; 
+         }
+ 
+         auto final_suspend() noexcept { 
+ #ifdef OUTPUT
+             std::cerr << "final_suspend" << std::endl;
+ #endif
+             return std::suspend_never{};  // Coroutine auto-destructs
+         }
+ 
+         ~promise_type() {
+             if (task_) {
+ #ifdef OUTPUT
+                 std::cerr << "promise_type destructor: Clearing Task handle" << std::endl;
+ #endif
+                 task_->h_ = nullptr;
+             }
+         }
+ 
+         void unhandled_exception() { 
+ #ifdef OUTPUT
+             std::cerr << "unhandled_exception" << std::endl;
+ #endif
+             std::terminate(); 
+         }
+ 
+         void return_value(int value) { 
+ #ifdef OUTPUT
+             std::cerr << "return_value: " << value << std::endl;
+ #endif
+             result_ = value;
+             if (task_) {
+                 task_->result_ = value;
+                 task_->completed_ = true;
+             }
+         }
+     };
+ 
+     handle_type h_;
+     int result_;
+     bool completed_ = false;
+ 
+     Task(handle_type h) : h_(h) {
+ #ifdef OUTPUT
+         std::cerr << "Task constructor" << std::endl;
+ #endif
+         if (h_) {
+             h_.promise().task_ = this;  // Link promise to Task
+         }
+     }
+ 
+     ~Task() { 
+ #ifdef OUTPUT
+         std::cerr << "~Task destructor" << std::endl;
+ #endif
+         // Only destroy handle if still valid (coroutine not completed)
+         if (h_) {
+ #ifdef OUTPUT
+             std::cerr << "Destroying coroutine handle" << std::endl;
+ #endif
+             h_.destroy(); 
+         }
+     }
+ 
+     bool done() const { 
+         return completed_ || !h_ || h_.done(); 
+     }
+ 
+     void resume() { 
+ #ifdef OUTPUT
+         std::cerr << "Resuming task" << std::endl;
+ #endif
+         if (h_) h_.resume(); 
+     }
+ 
+     int result() const {
+         if (!done()) throw std::runtime_error("Result not available");
+         return result_;
+     }
+ };
+ 
+ Task my_coroutine() {
+ #ifdef OUTPUT
+     std::cerr << "Inside my_coroutine" << std::endl;
+ #endif
+    co_return 42;
+ }
+ 
+ int main() {
+     auto task = my_coroutine();
+     while (!task.done()) {
+ #ifdef OUTPUT
+         std::cerr << "Resuming task in main" << std::endl;
+ #endif
+         task.resume();
+     }
+ #ifdef OUTPUT
+     std::cerr << "Task completed in main, printing result" << std::endl;
+ #endif
+     if (task.result() != 42)
+       __builtin_abort ();
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C gcc-16-20250727/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,12 ----
+ // PR c++/114632
+ // { dg-do compile { target c++23 } }
+ 
+ struct S {};
+ 
+ auto lambda = [](this auto& self, const int x) /* -> void */ {};
+ 
+ int main()
+ {
+     void (*func)(S&, int) = lambda; // { dg-error "" }
+     return 0;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/cpp23/static-operator-call7.C gcc-16-20250727/gcc/testsuite/g++.dg/cpp23/static-operator-call7.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/cpp23/static-operator-call7.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/cpp23/static-operator-call7.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,12 ----
+ // PR c++/114632
+ // { dg-do compile { target c++23 } }
+ 
+ struct S {};
+ 
+ auto lambda = [](auto, const int x) static /* -> void */ {};
+ 
+ int main()
+ {
+     void (*func)(int, int) = lambda;
+     return 0;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/cpp26/constexpr-new4.C gcc-16-20250727/gcc/testsuite/g++.dg/cpp26/constexpr-new4.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/cpp26/constexpr-new4.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/cpp26/constexpr-new4.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,21 ----
+ // PR c++/121068
+ // { dg-do compile { target c++26 } }
+ 
+ constexpr void *operator new (__SIZE_TYPE__, void *p) { return p; }
+ constexpr void *operator new[] (__SIZE_TYPE__, void *p) { return p; }
+ 
+ consteval int
+ foo()
+ {
+     using T = int;
+     union { T arr[3]; };
+     new(arr) T[3]; // makes arr active
+     for (int i = 0; i < 3; ++i)
+       arr[i].~T();
+ 
+     new (arr + 2) T{10}; // A
+ 
+     return 1;
+ };
+ 
+ constexpr int g = foo();
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C gcc-16-20250727/gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C	Sun Jul 20 22:32:12 2025
--- gcc-16-20250727/gcc/testsuite/g++.dg/cpp2a/concepts-traits3.C	Sun Jul 27 22:32:10 2025
***************
*** 1,49 ****
  // PR c++/100474
  // { dg-do compile { target c++20 } }
  
! struct S { S() = delete; S(const S&); };
  
  template<class T>
  concept Aggregate = __is_aggregate(T);
! // { dg-message "'S' is not an aggregate" "" { target *-*-* } .-1  }
  
  template<class T>
  concept TriviallyCopyable = __is_trivially_copyable(T);
! // { dg-message "'S' is not trivially copyable" "" { target *-*-* } .-1  }
  
  template<class T, class U>
  concept Assignable = __is_assignable(T, U);
! // { dg-message "'S' is not assignable from 'int'" "" { target *-*-* } .-1  }
  
  template<class T, class U>
  concept TriviallyAssignable = __is_trivially_assignable(T, U);
  // { dg-message "'S' is not trivially assignable from 'int'" "" { target *-*-* } .-1  }
  
  template<class T, class U>
  concept NothrowAssignable = __is_nothrow_assignable(T, U);
  // { dg-message "'S' is not nothrow assignable from 'int'" "" { target *-*-* } .-1  }
  
  template<class T, class... Args>
  concept Constructible = __is_constructible(T, Args...);
  // { dg-message "'S' is not default constructible" "" { target *-*-* } .-1  }
! // { dg-message "'S' is not constructible from 'int'" "" { target *-*-* } .-2  }
! // { dg-message "'S' is not constructible from 'int, char'" "" { target *-*-* } .-3  }
  
  template<class T, class... Args>
  concept TriviallyConstructible = __is_trivially_constructible(T, Args...);
  // { dg-message "'S' is not trivially default constructible" "" { target *-*-* } .-1  }
! // { dg-message "'S' is not trivially constructible from 'int'" "" { target *-*-* } .-2  }
! // { dg-message "'S' is not trivially constructible from 'int, char'" "" { target *-*-* } .-3  }
  
  template<class T, class... Args>
  concept NothrowConstructible = __is_nothrow_constructible(T, Args...);
  // { dg-message "'S' is not nothrow default constructible" "" { target *-*-* } .-1  }
! // { dg-message "'S' is not nothrow constructible from 'int'" "" { target *-*-* } .-2  }
! // { dg-message "'S' is not nothrow constructible from 'int, char'" "" { target *-*-* } .-3  }
  
  template<class T>
  concept UniqueObjReps = __has_unique_object_representations(T);
! // { dg-message "'S' does not have unique object representations" "" { target *-*-* } .-1  }
  
  static_assert(Aggregate<S>); // { dg-error "assert" }
  static_assert(TriviallyCopyable<S>); // { dg-error "assert" }
--- 1,58 ----
  // PR c++/100474
  // { dg-do compile { target c++20 } }
  
! struct S { S() = delete; S(const S&); };  // { dg-line S }
  
  template<class T>
  concept Aggregate = __is_aggregate(T);
! // { dg-message "'S' is not an aggregate" "" { target *-*-* } S }
  
  template<class T>
  concept TriviallyCopyable = __is_trivially_copyable(T);
! // { dg-message "'S' is not trivially copyable" "" { target *-*-* } S }
  
  template<class T, class U>
  concept Assignable = __is_assignable(T, U);
! // { dg-message "'S' is not assignable from 'int', because" "" { target *-*-* } .-1  }
! // { dg-error "no match for 'operator='" "" { target *-*-* } .-2 }
  
  template<class T, class U>
  concept TriviallyAssignable = __is_trivially_assignable(T, U);
  // { dg-message "'S' is not trivially assignable from 'int'" "" { target *-*-* } .-1  }
+ // { dg-error "no match for 'operator='" "" { target *-*-* } .-2 }
  
  template<class T, class U>
  concept NothrowAssignable = __is_nothrow_assignable(T, U);
  // { dg-message "'S' is not nothrow assignable from 'int'" "" { target *-*-* } .-1  }
+ // { dg-error "no match for 'operator='" "" { target *-*-* } .-2 }
  
  template<class T, class... Args>
  concept Constructible = __is_constructible(T, Args...);
  // { dg-message "'S' is not default constructible" "" { target *-*-* } .-1  }
! // { dg-error "use of deleted function 'S::S\\(\\)'" "" { target *-*-* } .-2 }
! // { dg-message "'S' is not constructible from 'int'" "" { target *-*-* } .-3  }
! // { dg-message "'S' is not constructible from 'int, char'" "" { target *-*-* } .-4  }
! // { dg-error "no matching function for call to 'S::S" "" { target *-*-* } .-5 }
  
  template<class T, class... Args>
  concept TriviallyConstructible = __is_trivially_constructible(T, Args...);
  // { dg-message "'S' is not trivially default constructible" "" { target *-*-* } .-1  }
! // { dg-error "use of deleted function 'S::S\\(\\)'" "" { target *-*-* } .-2 }
! // { dg-message "'S' is not trivially constructible from 'int'" "" { target *-*-* } .-3  }
! // { dg-message "'S' is not trivially constructible from 'int, char'" "" { target *-*-* } .-4  }
! // { dg-error "no matching function for call to 'S::S" "" { target *-*-* } .-5 }
  
  template<class T, class... Args>
  concept NothrowConstructible = __is_nothrow_constructible(T, Args...);
  // { dg-message "'S' is not nothrow default constructible" "" { target *-*-* } .-1  }
! // { dg-error "use of deleted function 'S::S\\(\\)'" "" { target *-*-* } .-2 }
! // { dg-message "'S' is not nothrow constructible from 'int'" "" { target *-*-* } .-3  }
! // { dg-message "'S' is not nothrow constructible from 'int, char'" "" { target *-*-* } .-4  }
! // { dg-error "no matching function for call to 'S::S" "" { target *-*-* } .-5 }
  
  template<class T>
  concept UniqueObjReps = __has_unique_object_representations(T);
! // { dg-message "'S' does not have unique object representations" "" { target *-*-* } S }
  
  static_assert(Aggregate<S>); // { dg-error "assert" }
  static_assert(TriviallyCopyable<S>); // { dg-error "assert" }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/cpp2a/concepts-traits4.C gcc-16-20250727/gcc/testsuite/g++.dg/cpp2a/concepts-traits4.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/cpp2a/concepts-traits4.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/cpp2a/concepts-traits4.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,77 ----
+ // PR c++/117294
+ // { dg-do compile { target c++20 } }
+ // { dg-additional-options "-fconcepts-diagnostics-depth=2" }
+ 
+ template <typename T> struct norm
+   { static constexpr bool value = __is_constructible(T); };
+ template <typename T> constexpr bool norm_v = __is_constructible(T);
+ 
+ template <typename T> struct part
+   { static constexpr bool value = __is_constructible(T); };
+ template <typename T> struct part<T*>
+   { static constexpr bool value = false; };
+ template <typename T> struct part<const T>
+   { static constexpr bool value = __is_same(T, void); };
+ template <typename T> constexpr bool part_v = __is_constructible(T);
+ template <typename T> constexpr bool part_v<T*> = false;
+ template <typename T> constexpr bool part_v<const T> = __is_same(T, void);
+ 
+ template <typename T> struct expl
+   { static constexpr bool value = __is_constructible(T); };
+ template <> struct expl<int*>
+   { static constexpr bool value = false; };
+ template <> struct expl<const int>
+   { static constexpr bool value = __is_same(int, void); };
+ template <typename T> constexpr bool expl_v = __is_constructible(T);
+ template <> constexpr bool expl_v<int*> = false;
+ template <> constexpr bool expl_v<const int> = __is_same(int, void);
+ 
+ template <typename T> concept test_norm = norm<T>::value;  // { dg-line norm }
+ template <typename T> concept test_part = part<T>::value;  // { dg-line part }
+ template <typename T> concept test_expl = expl<T>::value;  // { dg-line expl }
+ template <typename T> concept test_norm_v = norm_v<T>;  // { dg-line norm_v }
+ template <typename T> concept test_part_v = part_v<T>;  // { dg-line part_v }
+ template <typename T> concept test_expl_v = expl_v<T>;  // { dg-line expl_v }
+ 
+ static_assert(test_norm<void>);  // { dg-error "assert" }
+ static_assert(test_part<void>);  // { dg-error "assert" }
+ static_assert(test_expl<void>);  // { dg-error "assert" }
+ static_assert(test_norm_v<void>);  // { dg-error "assert" }
+ static_assert(test_part_v<void>);  // { dg-error "assert" }
+ static_assert(test_expl_v<void>);  // { dg-error "assert" }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } norm }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } part }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } expl }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } norm_v }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } part_v }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } expl_v }
+ // { dg-prune-output "'void' is incomplete" }
+ 
+ static_assert(test_part<int*>);  // { dg-error "assert" }
+ static_assert(test_expl<int*>);  // { dg-error "assert" }
+ static_assert(test_part_v<int*>);  // { dg-error "assert" }
+ static_assert(test_expl_v<int*>);  // { dg-error "assert" }
+ // { dg-message ".with T = int\\*.. evaluated to .false." "" { target *-*-* } part }
+ // { dg-message ".with T = int\\*.. evaluated to .false." "" { target *-*-* } expl }
+ // { dg-message ".with T = int\\*.. evaluated to .false." "" { target *-*-* } part_v }
+ // { dg-message ".with T = int\\*.. evaluated to .false." "" { target *-*-* } expl_v }
+ 
+ static_assert(test_part<const int>);  // { dg-error "assert" }
+ static_assert(test_part_v<const int>);  // { dg-error "assert" }
+ // { dg-message "'int' is not the same as 'void'" "" { target *-*-* } part }
+ // { dg-message "'int' is not the same as 'void'" "" { target *-*-* } part_v }
+ 
+ struct S { S(int); };
+ static_assert(requires { requires test_norm<S>; });  // { dg-error "assert" }
+ static_assert(requires { requires test_part<S>; });  // { dg-error "assert" }
+ static_assert(requires { requires test_expl<S>; });  // { dg-error "assert" }
+ static_assert(requires { requires test_norm_v<S>; });  // { dg-error "assert" }
+ static_assert(requires { requires test_part_v<S>; });  // { dg-error "assert" }
+ static_assert(requires { requires test_expl_v<S>; });  // { dg-error "assert" }
+ // { dg-message "'S' is not default constructible" "" { target *-*-* } norm }
+ // { dg-message "'S' is not default constructible" "" { target *-*-* } part }
+ // { dg-message "'S' is not default constructible" "" { target *-*-* } expl }
+ // { dg-message "'S' is not default constructible" "" { target *-*-* } norm_v }
+ // { dg-message "'S' is not default constructible" "" { target *-*-* } part_v }
+ // { dg-message "'S' is not default constructible" "" { target *-*-* } expl_v }
+ // { dg-prune-output "no matching function for call" }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C gcc-16-20250727/gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C	Sun Jul 20 22:32:12 2025
--- gcc-16-20250727/gcc/testsuite/g++.dg/cpp2a/constexpr-union6.C	Sun Jul 27 22:32:10 2025
*************** constexpr int test5() {
*** 45,53 ****
    union {
      int data[1];
    } u;
!   std::construct_at(u.data, 0);  // { dg-message "in .constexpr. expansion" }
    return 0;
  }
! constexpr int x5 = test5();  // { dg-message "in .constexpr. expansion" }
  
  // { dg-error "accessing (uninitialized member|.* member instead of)" "" { target *-*-* } 0 }
--- 45,53 ----
    union {
      int data[1];
    } u;
!   std::construct_at(u.data, 0);  // { dg-bogus "in .constexpr. expansion" }
    return 0;
  }
! constexpr int x5 = test5();  // { dg-bogus "in .constexpr. expansion" }
  
  // { dg-error "accessing (uninitialized member|.* member instead of)" "" { target *-*-* } 0 }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/diagnostic/static_assert5.C gcc-16-20250727/gcc/testsuite/g++.dg/diagnostic/static_assert5.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/diagnostic/static_assert5.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/diagnostic/static_assert5.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,70 ----
+ // PR c++/117294
+ // { dg-do compile { target c++14 } }
+ 
+ template <typename T> struct norm
+   { static constexpr bool value = __is_constructible(T); };
+ template <typename T> constexpr bool norm_v = __is_constructible(T);
+ 
+ template <typename T> struct part
+   { static constexpr bool value = __is_constructible(T); };
+ template <typename T> struct part<T*>
+   { static constexpr bool value = false; };
+ template <typename T> struct part<const T>
+   { static constexpr bool value = __is_same(T, void); };
+ template <typename T> constexpr bool part_v = __is_constructible(T);
+ template <typename T> constexpr bool part_v<T*> = false;
+ template <typename T> constexpr bool part_v<const T> = __is_same(T, void);
+ 
+ template <typename T> struct expl
+   { static constexpr bool value = __is_constructible(T); };
+ template <> struct expl<int*>
+   { static constexpr bool value = false; };
+ template <> struct expl<const int>
+   { static constexpr bool value = __is_same(int, void); };
+ template <typename T> constexpr bool expl_v = __is_constructible(T);
+ template <> constexpr bool expl_v<int*> = false;
+ template <> constexpr bool expl_v<const int> = __is_same(int, void);
+ 
+ // === Primary template can give customised diagnostics when using traits
+ static_assert(norm<void>::value);  // { dg-error "assert" }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } .-1 }
+ static_assert(part<void>::value);  // { dg-error "assert" }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } .-1 }
+ static_assert(expl<void>::value);  // { dg-error "assert" }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } .-1 }
+ static_assert(norm_v<void>);  // { dg-error "assert" }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } .-1 }
+ static_assert(part_v<void>);  // { dg-error "assert" }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } .-1 }
+ static_assert(expl_v<void>);  // { dg-error "assert" }
+ // { dg-message "'void' is not default constructible" "" { target *-*-* } .-1 }
+ 
+ // { dg-prune-output "'void' is incomplete" }
+ 
+ 
+ // === Specialisations don't customise just because primary template had trait
+ static_assert(part<int*>::value);  // { dg-error "assert" }
+ // { dg-bogus "default constructible" "" { target *-*-* } .-1 }
+ static_assert(expl<int*>::value);  // { dg-error "assert" }
+ // { dg-bogus "default constructible" "" { target *-*-* } .-1 }
+ static_assert(part_v<int*>);  // { dg-error "assert" }
+ // { dg-bogus "default constructible" "" { target *-*-* } .-1 }
+ static_assert(expl_v<int*>);  // { dg-error "assert" }
+ // { dg-bogus "default constructible" "" { target *-*-* } .-1 }
+ 
+ 
+ // === But partial specialisations actually using a trait can customise
+ static_assert(part<const int>::value);  // { dg-error "assert" }
+ // { dg-message "'int' is not the same as 'void'" "" { target *-*-* } .-1 }
+ static_assert(part_v<const int>);  // { dg-error "assert" }
+ // { dg-message "'int' is not the same as 'void'" "" { target *-*-* } .-1 }
+ 
+ 
+ // === For these cases, we no longer know that the error was caused by the trait
+ // === because it's been folded away before we process the failure.
+ static_assert(expl<const int>::value);  // { dg-error "assert" }
+ // { dg-bogus "because" "" { target *-*-* } .-1 }
+ static_assert(expl_v<const int>);  // { dg-error "assert" }
+ // { dg-bogus "because" "" { target *-*-* } .-1 }
+ static_assert(__is_constructible(void));  // { dg-error "assert" }
+ // { dg-bogus "because" "" { target *-*-* } .-1 }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/ext/has_virtual_destructor2.C gcc-16-20250727/gcc/testsuite/g++.dg/ext/has_virtual_destructor2.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/ext/has_virtual_destructor2.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/ext/has_virtual_destructor2.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,27 ----
+ // { dg-do compile { target c++11 } }
+ 
+ template <typename T> struct has_virtual_destructor {
+   static constexpr bool value = __has_virtual_destructor(T);
+ };
+ 
+ static_assert(has_virtual_destructor<int>::value, "");  // { dg-error "assert" }
+ // { dg-message "'int' does not have a virtual destructor" "" { target *-*-* } .-1 }
+ 
+ struct A {};  // { dg-message "'A' does not have a virtual destructor" }
+ static_assert(has_virtual_destructor<A>::value, "");  // { dg-error "assert" }
+ 
+ struct B {
+   ~B();  // { dg-message "'B' does not have a virtual destructor" }
+ };
+ static_assert(has_virtual_destructor<B>::value, "");  // { dg-error "assert" }
+ 
+ struct C {  // { dg-bogus "" }
+   virtual ~C();  // { dg-bogus "" }
+ };
+ static_assert(has_virtual_destructor<C[5]>::value, "");  // { dg-error "assert" }
+ // { dg-message "'C \\\[5\\\]' does not have a virtual destructor" "" { target *-*-* } .-1 }
+ 
+ union U {  // { dg-message "'U' does not have a virtual destructor" }
+   ~U();
+ };
+ static_assert(has_virtual_destructor<U>::value, "");  // { dg-error "assert" }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_assignable2.C gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_assignable2.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_assignable2.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_assignable2.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,36 ----
+ // { dg-do compile { target c++11 } }
+ 
+ template <typename T>
+ struct is_copy_assignable {
+   static constexpr bool value = __is_assignable(T&, const T&);
+ };
+ 
+ static_assert(is_copy_assignable<const int>::value, "");  // { dg-error "assert" }
+ // { dg-error "assignment to read-only type 'const int'" "" { target *-*-* } .-1 }
+ 
+ struct A {
+   void operator=(A) = delete;  // { dg-message "declared here" }
+ };
+ static_assert(is_copy_assignable<A>::value, "");  // { dg-error "assert" }
+ // { dg-message "is not assignable" "" { target *-*-* } .-1 }
+ // { dg-error "use of deleted function" "" { target *-*-* } .-2 }
+ 
+ template <typename T>
+ struct is_nothrow_copy_assignable {
+   static constexpr bool value = __is_nothrow_assignable(T&, const T&);
+ };
+ struct B {
+   void operator=(const B&);  // { dg-message "noexcept" }
+ };
+ static_assert(is_nothrow_copy_assignable<B>::value, "");  // { dg-error "assert" }
+ // { dg-message "is not nothrow assignable" "" { target *-*-* } .-1 }
+ 
+ template <typename T>
+ struct is_trivially_copy_assignable {
+   static constexpr bool value = __is_trivially_assignable(T&, const T&);
+ };
+ struct C {
+   void operator=(const C&);  // { dg-message "non-trivial" }
+ };
+ static_assert(is_trivially_copy_assignable<C>::value, "");  // { dg-error "assert" }
+ // { dg-message "is not trivially assignable" "" { target *-*-* } .-1 }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_constructible9.C gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_constructible9.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_constructible9.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_constructible9.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,60 ----
+ // { dg-do compile { target c++11 } }
+ 
+ template <typename T, typename... Args>
+ struct is_constructible {
+   static constexpr bool value = __is_constructible(T, Args...);
+ };
+ 
+ static_assert(is_constructible<void>::value, "");  // { dg-error "assert" }
+ // { dg-message "'void' is not default constructible, because" "" { target *-*-* } .-1 }
+ // { dg-error "'void' is incomplete" "" { target *-*-* } .-2 }
+ 
+ static_assert(is_constructible<int&, const int&>::value, "");  // { dg-error "assert" }
+ // { dg-message "'int&' is not constructible from 'const int&', because" "" { target *-*-* } .-1 }
+ // { dg-error "discards qualifiers" "" { target *-*-* } .-2 }
+ 
+ static_assert(is_constructible<int, int, int>::value, "");  // { dg-error "assert" }
+ // { dg-message "'int' is not constructible from 'int, int', because" "" { target *-*-* } .-1 }
+ // { dg-error "too many initializers for non-class type 'int'" "" { target *-*-* } .-2 }
+ 
+ struct A {
+   A(int);  // { dg-message "candidate" }
+ };
+ static_assert(is_constructible<A, int, int>::value, "");  // { dg-error "assert" }
+ // { dg-message "'A' is not constructible from 'int, int', because" "" { target *-*-* } .-1 }
+ // { dg-error "no matching function for call to" "" { target *-*-* } .-2 }
+ 
+ template <typename T, typename... Args>
+ struct is_nothrow_constructible {
+   static constexpr bool value = __is_nothrow_constructible(T, Args...);
+ };
+ 
+ struct B {
+   B(int);  // { dg-message "candidate" }
+ };
+ static_assert(is_nothrow_constructible<B>::value, "");  // { dg-error "assert" }
+ // { dg-message "'B' is not nothrow default constructible, because" "" { target *-*-* } .-1 }
+ // { dg-error "no matching function for call to" "" { target *-*-* } .-2 }
+ 
+ struct C {
+   C(int);  // { dg-message "noexcept" }
+ };
+ static_assert(is_nothrow_constructible<C, int>::value, "");  // { dg-error "assert" }
+ // { dg-message "'C' is not nothrow constructible from 'int', because" "" { target *-*-* } .-1 }
+ 
+ template <typename T, typename... Args>
+ struct is_trivially_constructible {
+   static constexpr bool value = __is_trivially_constructible(T, Args...);
+ };
+ 
+ struct D {
+   D();  // { dg-message "non-trivial" }
+ };
+ static_assert(is_trivially_constructible<D>::value, "");  // { dg-error "assert" }
+ // { dg-message "'D' is not trivially default constructible, because" "" { target *-*-* } .-1 }
+ 
+ struct E {
+   operator int();  // { dg-message "non-trivial" }
+ };
+ static_assert(is_trivially_constructible<int, E>::value, "");  // { dg-error "assert" }
+ // { dg-message "'int' is not trivially constructible from 'E', because" "" { target *-*-* } .-1 }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_convertible7.C gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_convertible7.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_convertible7.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_convertible7.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,29 ----
+ // { dg-do compile { target c++11 } }
+ 
+ template <typename T, typename U>
+ struct is_convertible {
+   static constexpr bool value = __is_convertible(T, U);
+ };
+ 
+ static_assert(is_convertible<int*, int>::value, "");  // { dg-error "assert" }
+ // { dg-error "invalid conversion" "" { target *-*-* } .-1 }
+ 
+ static_assert(is_convertible<int(), double (*)()>::value, "");  // { dg-error "assert" }
+ // { dg-error "invalid conversion" "" { target *-*-* } .-1 }
+ 
+ struct A {
+   explicit A(int);
+ };
+ static_assert(is_convertible<int, A>::value, "");  // { dg-error "assert" }
+ // { dg-error "could not convert 'int' to 'A'" "" { target *-*-* } .-1 }
+ 
+ template <typename T, typename U>
+ struct is_nothrow_convertible {
+   static constexpr bool value = __is_nothrow_convertible(T, U);
+ };
+ 
+ struct B {
+   B(int);  // { dg-message "noexcept" }
+ };
+ static_assert(is_nothrow_convertible<int, B>::value, "");  // { dg-error "assert" }
+ // { dg-message "'int' is not nothrow convertible from 'B', because" "" { target *-*-* } .-1 }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_destructible3.C gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_destructible3.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_destructible3.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_destructible3.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,65 ----
+ // { dg-do compile { target c++11 } }
+ 
+ template <typename T>
+ struct is_destructible {
+   static constexpr bool value = __is_destructible(T);
+ };
+ 
+ static_assert(is_destructible<void>::value, "");  // { dg-error "assert" }
+ // { dg-message "'void' is not destructible, because" "" { target *-*-* } .-1 }
+ // { dg-error "'void' is incomplete" "" { target *-*-* } .-2 }
+ 
+ struct A {
+   ~A() = delete;  // { dg-message "declared here" }
+ };
+ static_assert(is_destructible<A>::value, "");  // { dg-error "assert" }
+ // { dg-message "'A' is not destructible, because" "" { target *-*-* } .-1 }
+ // { dg-error "use of deleted function" "" { target *-*-* } .-2 }
+ 
+ struct B {
+ private:
+   ~B();  // { dg-message "declared private here" }
+ };
+ static_assert(is_destructible<B>::value, "");  // { dg-error "assert" }
+ // { dg-message "'B' is not destructible, because" "" { target *-*-* } .-1 }
+ // { dg-error "private within this context" "" { target *-*-* } .-2 }
+ 
+ template <typename T>
+ struct is_nothrow_destructible {
+   static constexpr bool value = __is_nothrow_destructible(T);
+ };
+ 
+ struct C {
+   ~C() noexcept(false);  // { dg-message "noexcept" }
+ };
+ static_assert(is_nothrow_destructible<C>::value, "");  // { dg-error "assert" }
+ // { dg-message "'C' is not nothrow destructible, because" "" { target *-*-* } .-1 }
+ 
+ struct D {
+ private:
+   ~D() {}  // { dg-message "declared private here" }
+ };
+ static_assert(is_nothrow_destructible<D>::value, "");  // { dg-error "assert" }
+ // { dg-message "'D' is not nothrow destructible, because" "" { target *-*-* } .-1 }
+ // { dg-error "private within this context" "" { target *-*-* } .-2 }
+ 
+ template <typename T>
+ struct is_trivially_destructible {
+   static constexpr bool value = __is_trivially_destructible(T);
+ };
+ 
+ struct E {
+   ~E();
+ };
+ struct F { E d; };  // { dg-message "non-trivial" }
+ static_assert(is_trivially_destructible<F>::value, "");  // { dg-error "assert" }
+ // { dg-message "'F' is not trivially destructible, because" "" { target *-*-* } .-1 }
+ 
+ struct G {
+ private:
+   ~G();  // { dg-message "declared private here" }
+ };
+ struct H { G g; };  // { dg-error "private within this context" }
+ static_assert(is_trivially_destructible<H>::value, "");  // { dg-error "assert" }
+ // { dg-message "'H' is not trivially destructible, because" "" { target *-*-* } .-1 }
+ // { dg-error "use of deleted function" "" { target *-*-* } .-2 }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_invocable5.C gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_invocable5.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_invocable5.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_invocable5.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,15 ----
+ // PR c++/121055
+ // { dg-do compile { target c++11 } }
+ // { dg-skip-if "requires hosted libstdc++ for functional function" { ! hostedlib } }
+ 
+ #include <functional>
+ 
+ #define SA(X) static_assert((X),#X)
+ 
+ struct F;
+ 
+ SA( __is_invocable(void (F::*)() &, std::reference_wrapper<F>) );
+ SA( ! __is_invocable(void (F::*)() &&, std::reference_wrapper<F>) );
+ 
+ SA( __is_invocable(void (F::*)(int) &, std::reference_wrapper<F>, int) );
+ SA( ! __is_invocable(void (F::*)(int) &&, std::reference_wrapper<F>, int) );
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_invocable6.C gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_invocable6.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_invocable6.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_invocable6.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,45 ----
+ // { dg-do compile { target c++11 } }
+ 
+ template <typename F, typename... Args>
+ struct is_invocable {
+   static constexpr bool value = __is_invocable(F, Args...);
+ };
+ 
+ static_assert(is_invocable<int>::value, "");  // { dg-error "assert" }
+ // { dg-message "'int' is not invocable, because" "" { target *-*-* } .-1 }
+ // { dg-error "'int' cannot be used as a function" "" { target *-*-* } .-2 }
+ 
+ static_assert(is_invocable<void(*)(), int>::value, "");  // { dg-error "assert" }
+ // { dg-message "'void \[^'\]*' is not invocable by 'int', because" "" { target *-*-* } .-1 }
+ // { dg-error "too many arguments" "" { target *-*-* } .-2 }
+ 
+ static_assert(is_invocable<void(void*), void() const>::value, "");  // { dg-error "assert" }
+ // { dg-message "'void.void..' is not invocable by 'void.. const', because" "" { target *-*-* } .-1 }
+ // { dg-error "qualified function type" "" { target *-*-* } .-2 }
+ 
+ struct A {};
+ static_assert(is_invocable<const A&&, int, double>::value, "");  // { dg-error "assert" }
+ // { dg-message "'const A&&' is not invocable by 'int, double', because" "" { target *-*-* } .-1 }
+ // { dg-error "no match for call to " "" { target *-*-* } .-2 }
+ 
+ struct B {
+   void operator()() = delete;  // { dg-message "declared here" }
+ };
+ static_assert(is_invocable<B>::value, "");  // { dg-error "assert" }
+ // { dg-message "'B' is not invocable, because" "" { target *-*-* } .-1 }
+ // { dg-error "use of deleted function" "" { target *-*-* } .-2 }
+ 
+ template <typename F, typename... Args>
+ struct is_nothrow_invocable {
+   static constexpr bool value = __is_nothrow_invocable(F, Args...);
+ };
+ 
+ static_assert(is_nothrow_invocable<void(*)()>::value, "");  // { dg-error "assert" }
+ // { dg-message "'void \[^'\]*' is not nothrow invocable, because" "" { target *-*-* } .-1 }
+ // { dg-message "'void \[^'\]*' is not 'noexcept'" "" { target *-*-* } .-2 }
+ 
+ struct C {
+   int operator()(int, double) const;  // { dg-message "noexcept" }
+ };
+ static_assert(is_nothrow_invocable<const C&, int, int>::value, "");  // { dg-error "assert" }
+ // { dg-message "'const C&' is not nothrow invocable by 'int, int', because" "" { target *-*-* } .-1 }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_virtual_base_of_diagnostic2.C gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_virtual_base_of_diagnostic2.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/ext/is_virtual_base_of_diagnostic2.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/ext/is_virtual_base_of_diagnostic2.C	Sun Jul 27 22:32:10 2025
***************
*** 0 ****
--- 1,13 ----
+ // { dg-do compile { target c++11 } }
+ 
+ template <typename T, typename U>
+ struct is_virtual_base_of {
+   static constexpr bool value = __builtin_is_virtual_base_of(T, U);
+ };
+ 
+ static_assert(is_virtual_base_of<int, int>::value, "");  // { dg-error "assert" }
+ // { dg-message "'int' is not a virtual base of 'int'" "" { target *-*-* } .-1 }
+ 
+ struct A {};  // { dg-message "'A' is not a virtual base of 'B'" }
+ struct B : A {};  // { dg-message "declared here" }
+ static_assert(is_virtual_base_of<A, B>::value, "");  // { dg-error "assert" }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/lookup/operator-8.C gcc-16-20250727/gcc/testsuite/g++.dg/lookup/operator-8.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/lookup/operator-8.C	Sun Jul 20 22:32:12 2025
--- gcc-16-20250727/gcc/testsuite/g++.dg/lookup/operator-8.C	Sun Jul 27 22:32:11 2025
*************** struct A {
*** 16,26 ****
  template<class T>
  void f() {
    A a;
!   (void)(a != 0, 0 != a); // { dg-bogus "deleted" "" { xfail *-*-* } }
!   (void)(a < 0, 0 < a);   // { dg-bogus "deleted" "" { xfail *-*-* } }
!   (void)(a <= 0, 0 <= a); // { dg-bogus "deleted" "" { xfail *-*-* } }
!   (void)(a > 0, 0 > a);   // { dg-bogus "deleted" "" { xfail *-*-* } }
!   (void)(a >= 0, 0 >= a); // { dg-bogus "deleted" "" { xfail *-*-* } }
  }
  
  // These later-declared namespace-scope overloads shouldn't be considered
--- 16,31 ----
  template<class T>
  void f() {
    A a;
!   (void)(a != 0);
!   (void)(0 != a);
!   (void)(a < 0);
!   (void)(0 < a);
!   (void)(a <= 0);
!   (void)(0 <= a);
!   (void)(a > 0);
!   (void)(0 > a);
!   (void)(a >= 0);
!   (void)(0 >= a);
  }
  
  // These later-declared namespace-scope overloads shouldn't be considered
*************** bool operator<=(A, int) = delete;
*** 31,34 ****
--- 36,45 ----
  bool operator>(A, int) = delete;
  bool operator>=(A, int) = delete;
  
+ bool operator!=(int, A) = delete;
+ bool operator<(int, A) = delete;
+ bool operator<=(int, A) = delete;
+ bool operator>(int, A) = delete;
+ bool operator>=(int, A) = delete;
+ 
  template void f<int>();
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/missing-return.C gcc-16-20250727/gcc/testsuite/g++.dg/missing-return.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/missing-return.C	Sun Jul 20 22:32:12 2025
--- gcc-16-20250727/gcc/testsuite/g++.dg/missing-return.C	Sun Jul 27 22:32:11 2025
*************** int foo(int a)
*** 5,8 ****
  {
  } /* { dg-warning "no return statement" } */
  
! /* { dg-final { scan-tree-dump "__builtin_unreachable" "optimized" } } */
--- 5,10 ----
  {
  } /* { dg-warning "no return statement" } */
  
! /* For targets without traps, it will be an infinite loop */
! /* { dg-final { scan-tree-dump "__builtin_unreachable" "optimized" { target trap } } } */
! /* { dg-final { scan-tree-dump "goto <" "optimized" { target { ! trap } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/modules/class-11_a.H gcc-16-20250727/gcc/testsuite/g++.dg/modules/class-11_a.H
*** gcc-16-20250720/gcc/testsuite/g++.dg/modules/class-11_a.H	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/modules/class-11_a.H	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,36 ----
+ // Check for some additional lang_type flags that we'd missed.
+ // { dg-additional-options "-fmodule-header -fabi-version=21 -Wabi=15" }
+ // { dg-module-cmi {} }
+ 
+ #if __cpp_trivial_relocatability < 202502L
+ #define trivially_relocatable_if_eligible __trivially_relocatable_if_eligible
+ #define replaceable_if_eligible __replaceable_if_eligible
+ #endif
+ 
+ struct A trivially_relocatable_if_eligible { A(A&&); };
+ struct B replaceable_if_eligible { B(B&&); B& operator=(B&&); };
+ struct C {};
+ static_assert(__builtin_is_trivially_relocatable(C) && __builtin_is_replaceable(C), "");
+ 
+ 
+ struct pr106381 {
+   long l;
+   char c = -1;
+ };
+ struct L1 : pr106381 {
+   char x;  // { dg-warning "offset" "" { target c++14 } }
+ };
+ static_assert(sizeof(L1) == sizeof(pr106381));
+ 
+ 
+ struct pr120012 {
+   pr120012(const pr120012&) = default;
+   pr120012(pr120012&&) = default;
+   pr120012& operator=(pr120012&&) = default;
+   unsigned int a;
+   unsigned char b;
+ };
+ struct L2 : pr120012 {
+   unsigned char y;  // { dg-warning "offset" "" { target c++20 } }
+ };
+ static_assert(sizeof(L2) > sizeof(pr120012));
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/modules/class-11_b.C gcc-16-20250727/gcc/testsuite/g++.dg/modules/class-11_b.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/modules/class-11_b.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/modules/class-11_b.C	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,15 ----
+ // { dg-additional-options "-fmodules -fabi-version=21 -Wabi=15" }
+ 
+ import "class-11_a.H";
+ 
+ static_assert(__builtin_is_trivially_relocatable(A), "");
+ static_assert(__builtin_is_replaceable(B), "");
+ static_assert(__builtin_is_trivially_relocatable(C) && __builtin_is_replaceable(C), "");
+ 
+ struct M1 : pr106381 {
+   char x;  // { dg-warning "offset" "" { target c++14 } }
+ };
+ 
+ struct M2 : pr120012 {
+   unsigned char y;  // { dg-warning "offset" "" { target c++20 } }
+ };
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/modules/internal-14_a.C gcc-16-20250727/gcc/testsuite/g++.dg/modules/internal-14_a.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/modules/internal-14_a.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/modules/internal-14_a.C	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,17 ----
+ // PR c++/120412
+ // { dg-additional-options "-fmodules -std=c++20 -Wtemplate-names-tu-local" }
+ // { dg-module-cmi m:part }
+ 
+ export module m:part;
+ 
+ export template <typename F>
+ auto fun1(F) {
+   return true;
+ }
+ 
+ using Dodgy = decltype([]{});
+ 
+ export template <typename T>
+ auto fun2(T&&) {  // { dg-warning "TU-local" }
+   return fun1(Dodgy{});
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/modules/internal-14_b.C gcc-16-20250727/gcc/testsuite/g++.dg/modules/internal-14_b.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/modules/internal-14_b.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/modules/internal-14_b.C	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,6 ----
+ // PR c++/120412
+ // { dg-additional-options "-fmodules -std=c++20 -Wtemplate-names-tu-local" }
+ // { dg-module-cmi m }
+ 
+ export module m;
+ export import :part;
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/modules/internal-14_c.C gcc-16-20250727/gcc/testsuite/g++.dg/modules/internal-14_c.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/modules/internal-14_c.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/modules/internal-14_c.C	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,9 ----
+ // PR c++/120412
+ // { dg-additional-options "-fmodules -std=c++20" }
+ 
+ import m;
+ 
+ int main() {
+   // { dg-error "instantiation exposes TU-local entity '(fun1|Dodgy)'" "" { target *-*-* } 0 }
+   fun2(123);  // { dg-message "required from here" }
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C gcc-16-20250727/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C	Sun Jul 20 22:32:13 2025
--- gcc-16-20250727/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C	Sun Jul 27 22:32:11 2025
***************
*** 1,4 ****
! /* Verify colorization of the labels in diagnostic-show-locus.c
     for template comparisons.
     Doing so requires a plugin; see the comments in the plugin for the
     rationale.  */
--- 1,4 ----
! /* Verify colorization of the labels in diagnostics/source-printing.cc
     for template comparisons.
     Doing so requires a plugin; see the comments in the plugin for the
     rationale.  */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/plugin/show_template_tree_color_plugin.cc gcc-16-20250727/gcc/testsuite/g++.dg/plugin/show_template_tree_color_plugin.cc
*** gcc-16-20250720/gcc/testsuite/g++.dg/plugin/show_template_tree_color_plugin.cc	Sun Jul 20 22:32:13 2025
--- gcc-16-20250727/gcc/testsuite/g++.dg/plugin/show_template_tree_color_plugin.cc	Sun Jul 27 22:32:11 2025
***************
*** 21,27 ****
  int plugin_is_GPL_compatible;
  
  void
! noop_text_starter_fn (diagnostic_text_output_format &, const diagnostic_info *)
  {
  }
  
--- 21,28 ----
  int plugin_is_GPL_compatible;
  
  void
! noop_text_starter_fn (diagnostics::text_sink &,
! 		      const diagnostics::diagnostic_info *)
  {
  }
  
*************** plugin_init (struct plugin_name_args *pl
*** 32,38 ****
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   diagnostic_text_starter (global_dc) = noop_text_starter_fn;
  
    return 0;
  }
--- 33,39 ----
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   diagnostics::text_starter (global_dc) = noop_text_starter_fn;
  
    return 0;
  }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/torture/pr120119-1.C gcc-16-20250727/gcc/testsuite/g++.dg/torture/pr120119-1.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/torture/pr120119-1.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.dg/torture/pr120119-1.C	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,15 ----
+ // { dg-do compile }
+ // { dg-additional-options "-mcpu=cortex-a57" { target aarch64*-*-* } }
+ 
+ // PR target/120119
+ 
+ struct a {
+   float operator()(int b, int c) { return d[c * 4 + b]; }
+   float *d;
+ };
+ float e(float *);
+ auto f(a b) {
+   float g[]{b(1, 1), b(2, 1), b(3, 1), b(1, 2), b(2, 2), b(3, 2), b(1, 3),
+             b(2, 3), b(3, 3), b(3, 2), b(1, 3), b(2, 3), b(3, 3)};
+   return b.d[0] * e(g);
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C gcc-16-20250727/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C
*** gcc-16-20250720/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C	Sun Jul 20 22:32:13 2025
--- gcc-16-20250727/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete-5.C	Sun Jul 27 22:32:11 2025
*************** void warn_placement_new ()
*** 31,37 ****
  
  void warn_placement_array_new ()
  {
!   void *p = malloc (sizeof (int));
    int *q = new (p) int[2];
    delete q;                   // { dg-warning "-Wmismatched-new-delete" }
  }
--- 31,37 ----
  
  void warn_placement_array_new ()
  {
!   void *p = malloc (sizeof (int) * 2);
    int *q = new (p) int[2];
    delete q;                   // { dg-warning "-Wmismatched-new-delete" }
  }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_1.C gcc-16-20250727/gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_1.C
*** gcc-16-20250720/gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_1.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_1.C	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,35 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fno-signed-zeros -ffinite-math-only -msve-vector-bits=2048" } */
+ 
+ #pragma GCC target "arch=armv9-a+sve-b16b16"
+ 
+ #define ADD(a, b) a + b
+ #define SUB(a, b) a - b
+ #define MUL(a, b) a * b
+ #define MAX(a, b) (a > b) ? a : b
+ #define MIN(a, b) (a > b) ? b : a
+ 
+ #define TEST_OP(TYPE, OP)                                        \
+   TYPE test_##TYPE##_##OP (TYPE a, TYPE b) { return OP (a, b); } \
+ 
+ #define TEST_ALL(TYPE, SIZE)                                        \
+   typedef TYPE TYPE##SIZE __attribute__((vector_size(SIZE)));       \
+   TEST_OP (TYPE##SIZE, ADD)                                         \
+   TEST_OP (TYPE##SIZE, SUB)                                         \
+   TEST_OP (TYPE##SIZE, MUL)                                         \
+   TEST_OP (TYPE##SIZE, MIN)                                         \
+   TEST_OP (TYPE##SIZE, MAX)
+ 
+ TEST_ALL (__bf16, 64)
+ 
+ TEST_ALL (__bf16, 128)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 5 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 5 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tbfadd\tz[0-9]+\.h, p[0-7]/m. z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tbfsub\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tbfmul\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tbfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tbfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_2.C gcc-16-20250727/gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_2.C
*** gcc-16-20250720/gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_2.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.target/aarch64/sve/unpacked_binary_bf16_2.C	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile }*/
+ /* { dg-options "-O2 -ffinite-math-only -fno-signed-zeros -fno-trapping-math -msve-vector-bits=2048 " } */
+ 
+ #include "unpacked_binary_bf16_1.C"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 10 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tbfadd\tz[0-9]+\.h, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tbfsub\tz[0-9]+\.h, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tbfmul\tz[0-9]+\.h, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tbfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tbfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/g++.target/aarch64/sve/unpacked_cond_binary_bf16_1.C gcc-16-20250727/gcc/testsuite/g++.target/aarch64/sve/unpacked_cond_binary_bf16_1.C
*** gcc-16-20250720/gcc/testsuite/g++.target/aarch64/sve/unpacked_cond_binary_bf16_1.C	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/g++.target/aarch64/sve/unpacked_cond_binary_bf16_1.C	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,46 ----
+ /* { dg-do compile }*/
+ /* { dg-options "-O -ffinite-math-only -fno-signed-zeros -fno-trapping-math -msve-vector-bits=2048 " } */
+ 
+ #include <stdint.h>
+ #pragma GCC target "arch=armv9-a+sve-b16b16"
+ 
+ #define ADD(a, b) a + b
+ #define SUB(a, b) a - b
+ #define MUL(a, b) a * b
+ #define MAX(a, b) (a > b) ? a : b
+ #define MIN(a, b) (a > b) ? b : a
+ 
+ #define COND_OP(OP, TYPE, PRED_TYPE, ARG2, MERGE)                                  \
+   TYPE test_##OP##_##TYPE##_##ARG2##_##MERGE (TYPE a, TYPE b, TYPE c, PRED_TYPE p) \
+   {return p ? OP (a, ARG2) : MERGE; }
+ 
+ #define TEST_OP(OP, TYPE, PRED_TYPE, T)     \
+   T (OP, TYPE, PRED_TYPE, b, a)             \
+   T (OP, TYPE, PRED_TYPE, b, b)             \
+   T (OP, TYPE, PRED_TYPE, b, c)
+ 
+ #define TEST_ALL(TYPE, PRED_TYPE, T) \
+   TEST_OP (ADD, TYPE, PRED_TYPE, T)  \
+   TEST_OP (SUB, TYPE, PRED_TYPE, T)  \
+   TEST_OP (MUL, TYPE, PRED_TYPE, T)  \
+   TEST_OP (MAX, TYPE, PRED_TYPE, T)  \
+   TEST_OP (MIN, TYPE, PRED_TYPE, T)
+ 
+ #define TEST(TYPE, PTYPE, SIZE)                                   \
+   typedef TYPE TYPE##SIZE __attribute__ ((vector_size (SIZE)));   \
+   typedef PTYPE PTYPE##SIZE __attribute__ ((vector_size (SIZE))); \
+   TEST_ALL (TYPE##SIZE, PTYPE##SIZE, COND_OP)
+ 
+ TEST (__bf16, uint16_t, 128)
+ 
+ TEST (__bf16, uint16_t, 64)
+ 
+ /* { dg-final { scan-assembler-times {\tbfadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tbfsub\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tbfmul\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tbfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tbfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ 
+ // There's no BFSUBR.
+ /* { dg-final { scan-assembler-times {\tsel\t} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-1.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-1.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-1.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,85 ----
+ /* { dg-do compile { target aarch64*-*-* arm*-*-* i?86-*-* powerpc*-*-* riscv*-*-* s390*-*-* x86_64-*-* } } */
+ 
+ #if defined (__aarch64__)
+ # define GPR "{x4}"
+ /* { dg-final { scan-assembler-times "foo\tx4" 8 { target { aarch64*-*-* } } } } */
+ #elif defined (__arm__)
+ # define GPR "{r4}"
+ /* { dg-final { scan-assembler-times "foo\tr4" 8 { target { arm*-*-* } } } } */
+ #elif defined (__i386__)
+ # define GPR "{ecx}"
+ /* { dg-final { scan-assembler-times "foo\t%cl" 2 { target { i?86-*-* } } } } */
+ /* { dg-final { scan-assembler-times "foo\t%cx" 2 { target { i?86-*-* } } } } */
+ /* { dg-final { scan-assembler-times "foo\t%ecx" 4 { target { i?86-*-* } } } } */
+ #elif defined (__powerpc__) || defined (__POWERPC__)
+ # define GPR "{r5}"
+ /* { dg-final { scan-assembler-times "foo\t5" 8 { target { powerpc*-*-* } } } } */
+ #elif defined (__riscv)
+ # define GPR "{t5}"
+ /* { dg-final { scan-assembler-times "foo\tt5" 8 { target { riscv*-*-* } } } } */
+ #elif defined (__s390__)
+ # define GPR "{r4}"
+ /* { dg-final { scan-assembler-times "foo\t%r4" 8 { target { s390*-*-* } } } } */
+ #elif defined (__x86_64__)
+ # define GPR "{rcx}"
+ /* { dg-final { scan-assembler-times "foo\t%cl" 2 { target { x86_64-*-* } } } } */
+ /* { dg-final { scan-assembler-times "foo\t%cx" 2 { target { x86_64-*-* } } } } */
+ /* { dg-final { scan-assembler-times "foo\t%ecx" 2 { target { x86_64-*-* } } } } */
+ /* { dg-final { scan-assembler-times "foo\t%rcx" 2 { target { x86_64-*-* } } } } */
+ #endif
+ 
+ char
+ test_char (char x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (x));
+   return x;
+ }
+ 
+ char
+ test_char_from_mem (char *x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (*x));
+   return *x;
+ }
+ 
+ short
+ test_short (short x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (x));
+   return x;
+ }
+ 
+ short
+ test_short_from_mem (short *x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (*x));
+   return *x;
+ }
+ 
+ int
+ test_int (int x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (x));
+   return x;
+ }
+ 
+ int
+ test_int_from_mem (int *x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (*x));
+   return *x;
+ }
+ 
+ long
+ test_long (long x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (x));
+   return x;
+ }
+ 
+ long
+ test_long_from_mem (long *x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (*x));
+   return *x;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-2.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-2.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-2.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,33 ----
+ /* { dg-do compile { target aarch64*-*-* powerpc64*-*-* riscv64-*-* s390*-*-* x86_64-*-* } } */
+ /* { dg-options "-std=c99" } we need long long */
+ 
+ #if defined (__aarch64__)
+ # define GPR "{x4}"
+ /* { dg-final { scan-assembler-times "foo\tx4" 2 { target { aarch64*-*-* } } } } */
+ #elif defined (__powerpc__) || defined (__POWERPC__)
+ # define GPR "{r5}"
+ /* { dg-final { scan-assembler-times "foo\t5" 2 { target { powerpc64*-*-* } } } } */
+ #elif defined (__riscv)
+ # define GPR "{t5}"
+ /* { dg-final { scan-assembler-times "foo\tt5" 2 { target { riscv64-*-* } } } } */
+ #elif defined (__s390__)
+ # define GPR "{r4}"
+ /* { dg-final { scan-assembler-times "foo\t%r4" 2 { target { s390*-*-* } } } } */
+ #elif defined (__x86_64__)
+ # define GPR "{rcx}"
+ /* { dg-final { scan-assembler-times "foo\t%rcx" 2 { target { x86_64-*-* } } } } */
+ #endif
+ 
+ long long
+ test_longlong (long long x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (x));
+   return x;
+ }
+ 
+ long long
+ test_longlong_from_mem (long long *x)
+ {
+   __asm__ ("foo\t%0" : "+"GPR (*x));
+   return *x;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-3.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-3.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-3.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-3.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,25 ----
+ /* { dg-do compile { target { { aarch64*-*-* powerpc64*-*-* riscv64-*-* s390*-*-* x86_64-*-* } && int128 } } } */
+ /* { dg-options "-O2" } get rid of -ansi since we use __int128 */
+ 
+ #if defined (__aarch64__)
+ # define REG "{x4}"
+ /* { dg-final { scan-assembler-times "foo\tx4" 1 { target { aarch64*-*-* } } } } */
+ #elif defined (__powerpc__) || defined (__POWERPC__)
+ # define REG "{r5}"
+ /* { dg-final { scan-assembler-times "foo\t5" 1 { target { powerpc*-*-* } } } } */
+ #elif defined (__riscv)
+ # define REG "{t5}"
+ /* { dg-final { scan-assembler-times "foo\tt5" 1 { target { riscv*-*-* } } } } */
+ #elif defined (__s390__)
+ # define REG "{r4}"
+ /* { dg-final { scan-assembler-times "foo\t%r4" 1 { target { s390*-*-* } } } } */
+ #elif defined (__x86_64__)
+ # define REG "{xmm0}"
+ /* { dg-final { scan-assembler-times "foo\t%xmm0" 1 { target { x86_64-*-* } } } } */
+ #endif
+ 
+ void
+ test (void)
+ {
+   __asm__ ("foo\t%0" :: REG ((__int128) 42));
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-4.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-4.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-4.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-4.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,50 ----
+ /* { dg-do compile { target aarch64*-*-* arm*-*-* powerpc*-*-* riscv*-*-* s390*-*-* x86_64-*-* } } */
+ 
+ #if defined (__aarch64__)
+ # define FPR "{d5}"
+ /* { dg-final { scan-assembler-times "foo\tv5" 4 { target { aarch64*-*-* } } } } */
+ #elif defined (__arm__)
+ # define FPR "{d5}"
+ /* { dg-additional-options "-march=armv7-a+fp -mfloat-abi=hard" { target arm*-*-* } } */
+ /* { dg-final { scan-assembler-times "foo\ts10" 4 { target { arm*-*-* } } } } */
+ #elif defined (__powerpc__) || defined (__POWERPC__)
+ # define FPR "{5}"
+ /* { dg-final { scan-assembler-times "foo\t5" 4 { target { powerpc*-*-* } } } } */
+ #elif defined (__riscv)
+ # define FPR "{fa5}"
+ /* { dg-final { scan-assembler-times "foo\tfa5" 4 { target { rsicv*-*-* } } } } */
+ #elif defined (__s390__)
+ # define FPR "{f5}"
+ /* { dg-final { scan-assembler-times "foo\t%f5" 4 { target { s390*-*-* } } } } */
+ #elif defined (__x86_64__)
+ # define FPR "{xmm5}"
+ /* { dg-final { scan-assembler-times "foo\t%xmm5" 4 { target { x86_64-*-* } } } } */
+ #endif
+ 
+ float
+ test_float (float x)
+ {
+   __asm__ ("foo\t%0" : "+"FPR (x));
+   return x;
+ }
+ 
+ float
+ test_float_from_mem (float *x)
+ {
+   __asm__ ("foo\t%0" : "+"FPR (*x));
+   return *x;
+ }
+ 
+ double
+ test_double (double x)
+ {
+   __asm__ ("foo\t%0" : "+"FPR (x));
+   return x;
+ }
+ 
+ double
+ test_double_from_mem (double *x)
+ {
+   __asm__ ("foo\t%0" : "+"FPR (*x));
+   return *x;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-5.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-5.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-5.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-5.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,36 ----
+ /* { dg-do compile { target aarch64*-*-* powerpc64*-*-* riscv64-*-* s390*-*-* x86_64-*-* } } */
+ 
+ typedef int V __attribute__ ((vector_size (4 * sizeof (int))));
+ 
+ #if defined (__aarch64__)
+ # define VR "{v20}"
+ /* { dg-final { scan-assembler-times "foo\tv20" 2 { target { aarch64*-*-* } } } } */
+ #elif defined (__powerpc__) || defined (__POWERPC__)
+ # define VR "{v5}"
+ /* { dg-final { scan-assembler-times "foo\t5" 2 { target { powerpc64*-*-* } } } } */
+ #elif defined (__riscv)
+ # define VR "{v5}"
+ /* { dg-additional-options "-march=rv64imv" { target riscv64-*-* } } */
+ /* { dg-final { scan-assembler-times "foo\tv5" 2 { target { riscv*-*-* } } } } */
+ #elif defined (__s390__)
+ # define VR "{v5}"
+ /* { dg-require-effective-target s390_mvx { target s390*-*-* } } */
+ /* { dg-final { scan-assembler-times "foo\t%v5" 2 { target s390*-*-* } } } */
+ #elif defined (__x86_64__)
+ # define VR "{xmm9}"
+ /* { dg-final { scan-assembler-times "foo\t%xmm9" 2 { target { x86_64-*-* } } } } */
+ #endif
+ 
+ V
+ test (V x)
+ {
+   __asm__ ("foo\t%0" : "+"VR (x));
+   return x;
+ }
+ 
+ V
+ test_from_mem (V *x)
+ {
+   __asm__ ("foo\t%0" : "+"VR (*x));
+   return *x;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-6.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-6.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-6.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-6.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,60 ----
+ /* { dg-do compile { target aarch64*-*-* arm*-*-* i?86-*-* powerpc*-*-* riscv*-*-* s390*-*-* x86_64-*-* } } */
+ /* { dg-options "-O2" } */
+ 
+ /* Test multiple alternatives.  */
+ 
+ #if defined (__aarch64__)
+ # define GPR1 "{x1}"
+ # define GPR2 "{x2}"
+ # define GPR3 "{x3}"
+ /* { dg-final { scan-assembler-times "foo\tx1,x3" 1 { target { aarch64*-*-* } } } } */
+ /* { dg-final { scan-assembler-times "bar\tx2,\\\[x1\\\]" 1 { target { aarch64*-*-* } } } } */
+ #elif defined (__arm__)
+ # define GPR1 "{r1}"
+ # define GPR2 "{r2}"
+ # define GPR3 "{r3}"
+ /* { dg-final { scan-assembler-times "foo\tr1,r3" 1 { target { arm*-*-* } } } } */
+ /* { dg-final { scan-assembler-times "bar\tr2,\\\[r1\\\]" 1 { target { arm*-*-* } } } } */
+ #elif defined (__i386__)
+ # define GPR1 "{eax}"
+ # define GPR2 "{ebx}"
+ # define GPR3 "{ecx}"
+ /* { dg-final { scan-assembler-times "foo\t4\\(%esp\\),%ecx" 1 { target { i?86-*-* } } } } */
+ /* { dg-final { scan-assembler-times "bar\t%ebx,\\(%eax\\)" 1 { target { i?86-*-* } } } } */
+ #elif defined (__powerpc__) || defined (__POWERPC__)
+ # define GPR1 "{r4}"
+ # define GPR2 "{r5}"
+ # define GPR3 "{r6}"
+ /* { dg-final { scan-assembler-times "foo\t4,6" 1 { target { powerpc*-*-* } } } } */
+ /* { dg-final { scan-assembler-times "bar\t5,0\\(4\\)" 1 { target { powerpc*-*-* } } } } */
+ #elif defined (__riscv)
+ # define GPR1 "{t1}"
+ # define GPR2 "{t2}"
+ # define GPR3 "{t3}"
+ /* { dg-final { scan-assembler-times "foo\tt1,t3" 1 { target { riscv*-*-* } } } } */
+ /* { dg-final { scan-assembler-times "bar\tt2,0\\(a1\\)" 1 { target { riscv*-*-* } } } } */
+ #elif defined (__s390__)
+ # define GPR1 "{r0}"
+ # define GPR2 "{r1}"
+ # define GPR3 "{r2}"
+ /* { dg-final { scan-assembler-times "foo\t%r0,%r2" 1 { target { s390*-*-* } } } } */
+ /* { dg-final { scan-assembler-times "bar\t%r1,0\\(%r3\\)" 1 { target { s390*-*-* } } } } */
+ #elif defined (__x86_64__)
+ # define GPR1 "{eax}"
+ # define GPR2 "{ebx}"
+ # define GPR3 "{rcx}"
+ /* { dg-final { scan-assembler-times "foo\t%eax,%rcx" 1 { target { x86_64-*-* } } } } */
+ /* { dg-final { scan-assembler-times "bar\t%ebx,\\(%rsi\\)" 1 { target { x86_64-*-* } } } } */
+ #endif
+ 
+ void
+ test_reg_reg (int x, long long *y)
+ {
+   __asm__ ("foo\t%0,%1" :: GPR1"m,"GPR2 (x), GPR3",m" (y));
+ }
+ 
+ void
+ test_reg_mem (int x, long long *y)
+ {
+   __asm__ ("bar\t%0,%1" :: GPR1"m,"GPR2 (x), GPR3",m" (*y));
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-7.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-7.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-7.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-7.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,41 ----
+ /* { dg-do compile { target aarch64*-*-* arm*-*-* i?86-*-* powerpc*-*-* riscv*-*-* s390*-*-* x86_64-*-* } } */
+ /* { dg-options "-O2" } */
+ 
+ /* Test multiple alternatives.  */
+ 
+ #if defined (__aarch64__)
+ # define GPR "{x1}"
+ /* { dg-final { scan-assembler-times "foo\tx1,x1" 2 { target { aarch64*-*-* } } } } */
+ #elif defined (__arm__)
+ # define GPR "{r1}"
+ /* { dg-final { scan-assembler-times "foo\tr1,r1" 2 { target { arm*-*-* } } } } */
+ #elif defined (__i386__)
+ # define GPR "{eax}"
+ /* { dg-final { scan-assembler-times "foo\t%eax,%eax" 2 { target { i?86-*-* } } } } */
+ #elif defined (__powerpc__) || defined (__POWERPC__)
+ # define GPR "{r4}"
+ /* { dg-final { scan-assembler-times "foo\t4,4" 2 { target { powerpc*-*-* } } } } */
+ #elif defined (__riscv)
+ # define GPR "{t1}"
+ /* { dg-final { scan-assembler-times "foo\tt1,t1" 2 { target { riscv*-*-* } } } } */
+ #elif defined (__s390__)
+ # define GPR "{r0}"
+ /* { dg-final { scan-assembler-times "foo\t%r0,%r0" 2 { target { s390*-*-* } } } } */
+ #elif defined (__x86_64__)
+ # define GPR "{eax}"
+ /* { dg-final { scan-assembler-times "foo\t%eax,%eax" 2 { target { x86_64-*-* } } } } */
+ #endif
+ 
+ int
+ test_1 (int x)
+ {
+   __asm__ ("foo\t%0,%0" : "+"GPR (x));
+   return x;
+ }
+ 
+ int
+ test_2 (int x, int y)
+ {
+   __asm__ ("foo\t%0,%1" : "="GPR (x) : GPR (y));
+   return x;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-8.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-8.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-8.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-8.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,49 ----
+ /* { dg-do compile { target aarch64*-*-* arm*-*-* i?86-*-* powerpc*-*-* riscv*-*-* s390*-*-* x86_64-*-* } } */
+ 
+ /* Due to hard register constraints, X must be copied.  */
+ 
+ #if defined (__aarch64__)
+ # define GPR1 "{x1}"
+ # define GPR2 "{x2}"
+ #elif defined (__arm__)
+ # define GPR1 "{r1}"
+ # define GPR2 "{r2}"
+ #elif defined (__i386__)
+ # define GPR1 "{eax}"
+ # define GPR2 "{ebx}"
+ #elif defined (__powerpc__) || defined (__POWERPC__)
+ # define GPR1 "{r4}"
+ # define GPR2 "{r5}"
+ #elif defined (__riscv)
+ # define GPR1 "{t1}"
+ # define GPR2 "{t2}"
+ #elif defined (__s390__)
+ # define GPR1 "{r0}"
+ # define GPR2 "{r1}"
+ #elif defined (__x86_64__)
+ # define GPR1 "{eax}"
+ # define GPR2 "{ebx}"
+ #endif
+ 
+ #define TEST(T) \
+ int \
+ test_##T (T x) \
+ { \
+   int out; \
+   __asm__ ("foo" : "=r" (out) : GPR1 (x), GPR2 (x)); \
+   return out; \
+ }
+ 
+ TEST(char)
+ TEST(short)
+ TEST(int)
+ TEST(long)
+ 
+ int
+ test_subreg (long x)
+ {
+   int out;
+   short subreg_x = x;
+   __asm__ ("foo" : "=r" (out) : GPR1 (x), GPR2 (subreg_x));
+   return out;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-1.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,83 ----
+ /* { dg-do compile { target aarch64*-*-* arm*-*-* i?86-*-* powerpc*-*-* riscv*-*-* s390*-*-* x86_64-*-* } } */
+ 
+ #if defined (__aarch64__)
+ # define GPR1_RAW "x0"
+ # define GPR2 "{x1}"
+ # define GPR3 "{x2}"
+ # define INVALID_GPR_A "{x31}"
+ #elif defined (__arm__)
+ # define GPR1_RAW "r0"
+ # define GPR2 "{r1}"
+ # define GPR3 "{r2}"
+ # define INVALID_GPR_A "{r16}"
+ #elif defined (__i386__)
+ # define GPR1_RAW "%eax"
+ # define GPR2 "{%ebx}"
+ # define GPR3 "{%edx}"
+ # define INVALID_GPR_A "{%eex}"
+ #elif defined (__powerpc__) || defined (__POWERPC__)
+ # define GPR1_RAW "r4"
+ # define GPR2 "{r5}"
+ # define GPR3 "{r6}"
+ # define INVALID_GPR_A "{r33}"
+ #elif defined (__riscv)
+ # define GPR1_RAW "t4"
+ # define GPR2 "{t5}"
+ # define GPR3 "{t6}"
+ # define INVALID_GPR_A "{t7}"
+ #elif defined (__s390__)
+ # define GPR1_RAW "r4"
+ # define GPR2 "{r5}"
+ # define GPR3 "{r6}"
+ # define INVALID_GPR_A "{r17}"
+ #elif defined (__x86_64__)
+ # define GPR1_RAW "rax"
+ # define GPR2 "{rbx}"
+ # define GPR3 "{rcx}"
+ # define INVALID_GPR_A "{rex}"
+ #endif
+ 
+ #define GPR1 "{"GPR1_RAW"}"
+ #define INVALID_GPR_B "{"GPR1_RAW
+ 
+ struct { int a[128]; } s = {0};
+ 
+ void
+ test (void)
+ {
+   int x, y;
+   register int gpr1 __asm__ (GPR1_RAW) = 0;
+ 
+   __asm__ ("" :: "{}" (42)); /* { dg-error "invalid input constraint: \{\}" } */
+   __asm__ ("" :: INVALID_GPR_A (42)); /* { dg-error "invalid input constraint" } */
+   __asm__ ("" :: INVALID_GPR_B (42)); /* { dg-error "invalid input constraint" } */
+ 
+   __asm__ ("" :: GPR1 (s)); /* { dg-error "data type isn't suitable for register .* of operand 0" } */
+ 
+   __asm__ ("" :: "r" (gpr1), GPR1 (42)); /* { dg-error "multiple inputs to hard register" } */
+   __asm__ ("" :: GPR1 (42), "r" (gpr1)); /* { dg-error "multiple inputs to hard register" } */
+   __asm__ ("" :: GPR1 (42), GPR1 (42)); /* { dg-error "multiple inputs to hard register" } */
+   __asm__ ("" :: GPR1","GPR2 (42), GPR2","GPR3 (42));
+   __asm__ ("" :: GPR1","GPR2 (42), GPR3","GPR2 (42)); /* { dg-error "multiple inputs to hard register" } */
+   __asm__ ("" :: GPR1","GPR2 (42), GPR1","GPR3 (42)); /* { dg-error "multiple inputs to hard register" } */
+   __asm__ ("" :: GPR1 GPR2 (42), GPR2 (42)); /* { dg-error "multiple inputs to hard register" } */
+   __asm__ ("" : "+"GPR1 (x), "="GPR1 (y)); /* { dg-error "multiple outputs to hard register" } */
+   __asm__ ("" : "="GPR1 (y) : GPR1 (42), "0" (42)); /* { dg-error "multiple inputs to hard register" } */
+   __asm__ ("" : "+"GPR1 (x) : GPR1 (42)); /* { dg-error "multiple inputs to hard register" } */
+ 
+   __asm__ ("" : "="GPR1 (gpr1));
+   __asm__ ("" : "="GPR2 (gpr1)); /* { dg-error "constraint and register 'asm' for output operand 0 are unsatisfiable" } */
+   __asm__ ("" :: GPR2 (gpr1)); /* { dg-error "constraint and register 'asm' for input operand 0 are unsatisfiable" } */
+   __asm__ ("" : "="GPR1 (x) : "0" (gpr1));
+   __asm__ ("" : "="GPR1 GPR2 (x) : "0" (gpr1)); /* { dg-error "constraint and register 'asm' for input operand 0 are unsatisfiable" } */
+ 
+   __asm__ ("" : "=&"GPR1 (x) : "0" (gpr1));
+   __asm__ ("" : "=&"GPR1 (x) : "0" (42));
+   __asm__ ("" : "=&"GPR2","GPR1 (x) : "r,"GPR1 (42));
+   __asm__ ("" : "="GPR2",&"GPR1 (x) : "r,"GPR1 (42)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
+   __asm__ ("" : "=&"GPR1 (x) : GPR1 (42)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
+   __asm__ ("" : "=&"GPR2","GPR1 (x) : "r,r" (gpr1));
+   __asm__ ("" : "="GPR2",&"GPR1 (x) : "r,r" (gpr1)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
+   __asm__ ("" : "=&r" (gpr1) : GPR1 (42)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
+   __asm__ ("" : "=&"GPR1 (x),  "=r" (y) : "1" (gpr1)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-2.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-2.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-2.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do compile { target { { aarch64*-*-* s390x-*-* } && int128 } } } */
+ /* { dg-options "-O2" } get rid of -ansi since we use __int128 */
+ 
+ /* Test register pairs.  */
+ 
+ #if defined (__aarch64__)
+ # define GPR1 "{x4}"
+ # define GPR2_RAW "x5"
+ #elif defined (__s390__)
+ # define GPR1 "{r4}"
+ # define GPR2_RAW "r5"
+ #endif
+ 
+ #define GPR2 "{"GPR2_RAW"}"
+ 
+ void
+ test (void)
+ {
+   __asm__ ("" :: GPR1 ((__int128) 42));
+   __asm__ ("" :: GPR2 ((__int128) 42)); /* { dg-error "register .* for operand 0 isn't suitable for data type" } */
+   __asm__ ("" :: GPR1 ((__int128) 42), GPR2 (42)); /* { dg-error "multiple inputs to hard register" } */
+ 
+   __int128 x;
+   __asm__ ("" : "="GPR1 (x) :: GPR2_RAW); /* { dg-error "hard register constraint for output 0 conflicts with 'asm' clobber list" } */
+   __asm__ ("" : "=r" (x) : GPR1 (x) : GPR2_RAW); /* { dg-error "hard register constraint for input 0 conflicts with 'asm' clobber list" } */
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-3.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-3.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-3.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-3.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,27 ----
+ /* { dg-do compile { target arm-*-* s390-*-* } } */
+ /* { dg-options "-std=c99" } we need long long */
+ /* { dg-additional-options "-march=armv7-a" { target arm-*-* } } */
+ 
+ /* Test register pairs.  */
+ 
+ #if defined (__arm__)
+ # define GPR1 "{r4}"
+ # define GPR2_RAW "r5"
+ #elif defined (__s390__)
+ # define GPR1 "{r4}"
+ # define GPR2_RAW "r5"
+ #endif
+ 
+ #define GPR2 "{"GPR2_RAW"}"
+ 
+ void
+ test (void)
+ {
+   __asm__ ("" :: GPR1 (42ll));
+   __asm__ ("" :: GPR2 (42ll)); /* { dg-error "register .* for operand 0 isn't suitable for data type" } */
+   __asm__ ("" :: GPR1 (42ll), GPR2 (42)); /* { dg-error "multiple inputs to hard register" } */
+ 
+   long long x;
+   __asm__ ("" : "="GPR1 (x) :: GPR2_RAW); /* { dg-error "hard register constraint for output 0 conflicts with 'asm' clobber list" } */
+   __asm__ ("" : "=r" (x) : GPR1 (x) : GPR2_RAW); /* { dg-error "hard register constraint for input 0 conflicts with 'asm' clobber list" } */
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-4.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-4.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-4.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-4.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,21 ----
+ /* { dg-do compile } */
+ 
+ /* Verify output operands.  */
+ 
+ int
+ test (void)
+ {
+   int x;
+   register int y __asm__ ("0");
+ 
+   /* Preserve status quo and don't error out.  */
+   __asm__ ("" : "=r" (x), "=r" (x));
+ 
+   /* Be more strict for hard register constraints and error out.  */
+   __asm__ ("" : "={0}" (x), "={1}" (x)); /* { dg-error "multiple outputs to lvalue 'x'" } */
+ 
+   /* Still error out in case of a mixture.  */
+   __asm__ ("" : "=r" (x), "={1}" (x)); /* { dg-error "multiple outputs to lvalue 'x'" } */
+ 
+   return x + y;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-5.c gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-5.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/asm-hard-reg-error-5.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/asm-hard-reg-error-5.c	Sun Jul 27 22:32:11 2025
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ 
+ /* Test clobbers.
+    See asm-hard-reg-error-{2,3}.c for tests involving register pairs.  */
+ 
+ int
+ test (void)
+ {
+   int x, y;
+   __asm__ ("" : "={0}" (x), "={1}" (y) : : "1"); /* { dg-error "hard register constraint for output 1 conflicts with 'asm' clobber list" } */
+   __asm__ ("" : "={0}" (x) : "{0}" (y), "{1}" (y) : "1"); /* { dg-error "hard register constraint for input 1 conflicts with 'asm' clobber list" } */
+   return x + y;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc	Sun Jul 27 22:32:12 2025
***************
*** 23,30 ****
  #include "target.h"
  #include "fold-const.h"
  #include "tree-pretty-print.h"
! #include "diagnostic-color.h"
! #include "diagnostic-metadata.h"
  #include "tristate.h"
  #include "bitmap.h"
  #include "selftest.h"
--- 23,30 ----
  #include "target.h"
  #include "fold-const.h"
  #include "tree-pretty-print.h"
! #include "diagnostics/color.h"
! #include "diagnostics/metadata.h"
  #include "tristate.h"
  #include "bitmap.h"
  #include "selftest.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc	Sun Jul 27 22:32:12 2025
***************
*** 16,22 ****
  #include "gimple.h"
  #include "gimple-iterator.h"
  #include "gimple-walk.h"
! #include "diagnostic-event-id.h"
  #include "analyzer/common.h"
  #include "analyzer/analyzer-logging.h"
  #include "json.h"
--- 16,22 ----
  #include "gimple.h"
  #include "gimple-iterator.h"
  #include "gimple-walk.h"
! #include "diagnostics/event-id.h"
  #include "analyzer/common.h"
  #include "analyzer/analyzer-logging.h"
  #include "json.h"
*************** public:
*** 120,139 ****
      return false;
    }
  
!   diagnostic_event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
      if (change.is_global_p ())
        {
  	if (change.m_new_state == m_sm.m_released_gil)
! 	  return diagnostic_event::meaning (diagnostic_event::verb::release,
! 					    diagnostic_event::noun::lock);
  	else if (change.m_new_state == m_sm.get_start_state ())
! 	  return diagnostic_event::meaning (diagnostic_event::verb::acquire,
! 					    diagnostic_event::noun::lock);
        }
!     return diagnostic_event::meaning ();
    }
   protected:
    gil_diagnostic (const gil_state_machine &sm) : m_sm (sm)
--- 120,141 ----
      return false;
    }
  
!   diagnostics::paths::event::meaning
    get_meaning_for_state_change (const evdesc::state_change &change)
      const final override
    {
+     using event = diagnostics::paths::event;
+ 
      if (change.is_global_p ())
        {
  	if (change.m_new_state == m_sm.m_released_gil)
! 	  return event::meaning (event::verb::release,
! 				 event::noun::lock);
  	else if (change.m_new_state == m_sm.get_start_state ())
! 	  return event::meaning (event::verb::acquire,
! 				 event::noun::lock);
        }
!     return event::meaning ();
    }
   protected:
    gil_diagnostic (const gil_state_machine &sm) : m_sm (sm)
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc	Sun Jul 27 22:32:12 2025
***************
*** 23,30 ****
  #include "target.h"
  #include "fold-const.h"
  #include "tree-pretty-print.h"
! #include "diagnostic-color.h"
! #include "diagnostic-metadata.h"
  #include "tristate.h"
  #include "bitmap.h"
  #include "selftest.h"
--- 23,30 ----
  #include "target.h"
  #include "fold-const.h"
  #include "tree-pretty-print.h"
! #include "diagnostics/color.h"
! #include "diagnostics/metadata.h"
  #include "tristate.h"
  #include "bitmap.h"
  #include "selftest.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc	Sun Jul 27 22:32:12 2025
***************
*** 23,30 ****
  #include "target.h"
  #include "fold-const.h"
  #include "tree-pretty-print.h"
! #include "diagnostic-color.h"
! #include "diagnostic-metadata.h"
  #include "tristate.h"
  #include "bitmap.h"
  #include "selftest.h"
--- 23,30 ----
  #include "target.h"
  #include "fold-const.h"
  #include "tree-pretty-print.h"
! #include "diagnostics/color.h"
! #include "diagnostics/metadata.h"
  #include "tristate.h"
  #include "bitmap.h"
  #include "selftest.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus.py gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus.py
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus.py	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus.py	Sun Jul 27 22:32:12 2025
***************
*** 1,4 ****
! # Verify that diagnostic-show-locus.cc works with HTML output.
  
  from htmltest import *
  
--- 1,4 ----
! # Verify that diagnostics/source-printing.cc works with HTML output.
  
  from htmltest import *
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_group_plugin.cc	Sun Jul 27 22:32:12 2025
***************
*** 27,33 ****
  #include "plugin-version.h"
  #include "c-family/c-common.h"
  #include "diagnostic.h"
! #include "diagnostic-format-text.h"
  #include "context.h"
  
  int plugin_is_GPL_compatible;
--- 27,33 ----
  #include "plugin-version.h"
  #include "c-family/c-common.h"
  #include "diagnostic.h"
! #include "diagnostics/text-sink.h"
  #include "context.h"
  
  int plugin_is_GPL_compatible;
*************** pass_test_groups::execute (function *fun
*** 165,172 ****
     expected output.  */
  
  void
! test_diagnostic_text_starter (diagnostic_text_output_format &text_output,
! 			      const diagnostic_info *diagnostic)
  {
    pp_set_prefix (text_output.get_printer (), xstrdup ("PREFIX: "));
  }
--- 165,172 ----
     expected output.  */
  
  void
! test_diagnostic_text_starter (diagnostics::text_sink &text_output,
! 			      const diagnostics::diagnostic_info *diagnostic)
  {
    pp_set_prefix (text_output.get_printer (), xstrdup ("PREFIX: "));
  }
*************** test_diagnostic_text_starter (diagnostic
*** 175,196 ****
     expected output.  */
  
  void
! test_diagnostic_start_span_fn (const diagnostic_location_print_policy &,
! 			       to_text &sink,
  			       expanded_location)
  {
!   pretty_printer *pp = get_printer (sink);
    pp_string (pp, "START_SPAN_FN: ");
    pp_newline (pp);
  }
  
! /* Custom output format subclass.  */
  
! class test_output_format : public diagnostic_text_output_format
  {
   public:
!   test_output_format (diagnostic_context &context)
!   : diagnostic_text_output_format (context)
    {}
  
    void on_begin_group () final override
--- 175,196 ----
     expected output.  */
  
  void
! test_diagnostic_start_span_fn (const diagnostics::location_print_policy &,
! 			       diagnostics::to_text &sink,
  			       expanded_location)
  {
!   pretty_printer *pp = diagnostics::get_printer (sink);
    pp_string (pp, "START_SPAN_FN: ");
    pp_newline (pp);
  }
  
! /* Custom text_sink subclass.  */
  
! class custom_test_sink : public diagnostics::text_sink
  {
   public:
!   custom_test_sink (diagnostics::context &context)
!   : diagnostics::text_sink (context)
    {}
  
    void on_begin_group () final override
*************** plugin_init (struct plugin_name_args *pl
*** 228,237 ****
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   diagnostic_text_starter (global_dc) = test_diagnostic_text_starter;
!   diagnostic_start_span (global_dc) = test_diagnostic_start_span_fn;
!   global_dc->set_output_format
!     (::std::make_unique<test_output_format> (*global_dc));
  
    pass_info.pass = new pass_test_groups (g);
    pass_info.reference_pass_name = "*warn_function_noreturn";
--- 228,236 ----
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   diagnostics::text_starter (global_dc) = test_diagnostic_text_starter;
!   diagnostics::start_span (global_dc) = test_diagnostic_start_span_fn;
!   global_dc->set_sink (::std::make_unique<custom_test_sink> (*global_dc));
  
    pass_info.pass = new pass_test_groups (g);
    pass_info.reference_pass_name = "*warn_function_noreturn";
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_show_trees.cc	Sun Jul 27 22:32:12 2025
*************** plugin_init (struct plugin_name_args *pl
*** 115,121 ****
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->m_source_printing.max_width = 80;
  
    register_callback (plugin_name,
  		     PLUGIN_PRE_GENERICIZE,
--- 115,121 ----
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->get_source_printing_options ().max_width = 80;
  
    register_callback (plugin_name,
  		     PLUGIN_PRE_GENERICIZE,
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc	Sun Jul 27 22:32:12 2025
***************
*** 33,40 ****
  #include "diagnostic.h"
  #include "context.h"
  #include "gcc-rich-location.h"
! #include "diagnostic-metadata.h"
! #include "diagnostic-digraphs.h"
  #include "pass_manager.h"
  
  
--- 33,40 ----
  #include "diagnostic.h"
  #include "context.h"
  #include "gcc-rich-location.h"
! #include "diagnostics/metadata.h"
! #include "diagnostics/digraphs.h"
  #include "pass_manager.h"
  
  
*************** check_for_named_call (gimple *stmt,
*** 97,103 ****
    return call;
  }
  
! class lazy_passes_graph : public diagnostics::digraphs::lazy_digraph
  {
  public:
    lazy_passes_graph (const ::gcc::pass_manager &pass_manager_)
--- 97,103 ----
    return call;
  }
  
! class lazy_passes_graph : public lazily_created<diagnostics::digraphs::digraph>
  {
  public:
    lazy_passes_graph (const ::gcc::pass_manager &pass_manager_)
*************** public:
*** 105,112 ****
    {
    }
  
    std::unique_ptr<diagnostics::digraphs::digraph>
!   create_digraph () const final override
    {
      auto g = std::make_unique<diagnostics::digraphs::digraph> ();
      g->set_description ("Optimization Passes");
--- 105,113 ----
    {
    }
  
+ private:
    std::unique_ptr<diagnostics::digraphs::digraph>
!   create_object () const final override
    {
      auto g = std::make_unique<diagnostics::digraphs::digraph> ();
      g->set_description ("Optimization Passes");
*************** public:
*** 176,189 ****
      return result;
    }
  
- private:
    const ::gcc::pass_manager &m_pass_manager;
  };
  
  static void
  report_diag_with_graphs (location_t loc)
  {
!   class my_lazy_digraphs : public diagnostics::digraphs::lazy_digraphs
    {
    public:
      using diagnostic_graph = diagnostics::digraphs::digraph;
--- 177,189 ----
      return result;
    }
  
    const ::gcc::pass_manager &m_pass_manager;
  };
  
  static void
  report_diag_with_graphs (location_t loc)
  {
!   class my_lazy_digraphs : public diagnostics::metadata::lazy_digraphs
    {
    public:
      using diagnostic_graph = diagnostics::digraphs::digraph;
*************** report_diag_with_graphs (location_t loc)
*** 191,197 ****
      using diagnostic_edge = diagnostics::digraphs::edge;
  
      std::unique_ptr<std::vector<std::unique_ptr<diagnostic_graph>>>
!     create_digraphs () const final override
      {
        auto graphs
  	= std::make_unique<std::vector<std::unique_ptr<diagnostic_graph>>> ();
--- 191,197 ----
      using diagnostic_edge = diagnostics::digraphs::edge;
  
      std::unique_ptr<std::vector<std::unique_ptr<diagnostic_graph>>>
!     create_object () const final override
      {
        auto graphs
  	= std::make_unique<std::vector<std::unique_ptr<diagnostic_graph>>> ();
*************** report_diag_with_graphs (location_t loc)
*** 230,236 ****
    };
  
    gcc_rich_location rich_loc (loc);
!   diagnostic_metadata meta;
    my_lazy_digraphs ldg;
    meta.set_lazy_digraphs (&ldg);
    error_meta (&rich_loc, meta,
--- 230,236 ----
    };
  
    gcc_rich_location rich_loc (loc);
!   diagnostics::metadata meta;
    my_lazy_digraphs ldg;
    meta.set_lazy_digraphs (&ldg);
    error_meta (&rich_loc, meta,
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_inlining.cc	Sun Jul 27 22:32:12 2025
*************** plugin_init (struct plugin_name_args *pl
*** 169,175 ****
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->m_source_printing.max_width = 80;
  
    pass_info.pass = new pass_test_inlining (g);
    pass_info.reference_pass_name = "*warn_function_noreturn";
--- 169,175 ----
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->get_source_printing_options ().max_width = 80;
  
    pass_info.pass = new pass_test_inlining (g);
    pass_info.reference_pass_name = "*warn_function_noreturn";
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_metadata.cc	Sun Jul 27 22:32:12 2025
***************
*** 1,5 ****
! /* This plugin exercises diagnostic_metadata.  */
  
  #include "gcc-plugin.h"
  #include "config.h"
  #include "system.h"
--- 1,6 ----
! /* This plugin exercises diagnostics::metadata.  */
  
+ #define INCLUDE_VECTOR
  #include "gcc-plugin.h"
  #include "config.h"
  #include "system.h"
***************
*** 28,34 ****
  #include "diagnostic.h"
  #include "context.h"
  #include "gcc-rich-location.h"
! #include "diagnostic-metadata.h"
  
  int plugin_is_GPL_compatible;
  
--- 29,35 ----
  #include "diagnostic.h"
  #include "context.h"
  #include "gcc-rich-location.h"
! #include "diagnostics/metadata.h"
  
  int plugin_is_GPL_compatible;
  
*************** check_for_named_call (gimple *stmt,
*** 89,95 ****
    return call;
  }
  
! /* Exercise diagnostic_metadata.  */
  
  unsigned int
  pass_test_metadata::execute (function *fun)
--- 90,96 ----
    return call;
  }
  
! /* Exercise diagnostics::metadata.  */
  
  unsigned int
  pass_test_metadata::execute (function *fun)
*************** pass_test_metadata::execute (function *f
*** 106,118 ****
  	if (gcall *call = check_for_named_call (stmt, "gets", 1))
  	  {
  	    gcc_rich_location richloc (gimple_location (call));
! 	    diagnostic_metadata m;
  
  	    /* CWE-242: Use of Inherently Dangerous Function.  */
  	    m.add_cwe (242);
  
! 	    /* Example of a diagnostic_metadata::rule.  */
! 	    diagnostic_metadata::precanned_rule
  	      test_rule ("STR34-C", "https://example.com/");
  	    m.add_rule (test_rule);
  
--- 107,119 ----
  	if (gcall *call = check_for_named_call (stmt, "gets", 1))
  	  {
  	    gcc_rich_location richloc (gimple_location (call));
! 	    diagnostics::metadata m;
  
  	    /* CWE-242: Use of Inherently Dangerous Function.  */
  	    m.add_cwe (242);
  
! 	    /* Example of a diagnostics::metadata::rule.  */
! 	    diagnostics::metadata::precanned_rule
  	      test_rule ("STR34-C", "https://example.com/");
  	    m.add_rule (test_rule);
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc	Sun Jul 27 22:32:12 2025
***************
*** 6,11 ****
--- 6,12 ----
     specific tests within the compiler's IR.  We can't use any real
     diagnostics for this, so we have to fake it, hence this plugin.  */
  
+ #define INCLUDE_VECTOR
  #include "gcc-plugin.h"
  #include "config.h"
  #include "system.h"
***************
*** 32,39 ****
  #include "intl.h"
  #include "plugin-version.h"
  #include "diagnostic.h"
! #include "diagnostic-path.h"
! #include "diagnostic-metadata.h"
  #include "context.h"
  #include "print-tree.h"
  #include "gcc-rich-location.h"
--- 33,39 ----
  #include "intl.h"
  #include "plugin-version.h"
  #include "diagnostic.h"
! #include "diagnostics/metadata.h"
  #include "context.h"
  #include "print-tree.h"
  #include "gcc-rich-location.h"
*************** class test_diagnostic_path : public simp
*** 223,229 ****
    diagnostic_event_id_t
    add_event_2 (event_location_t evloc, int stack_depth,
  	       const char *desc,
! 	       diagnostic_thread_id_t thread_id = 0)
    {
      gcc_assert (evloc.m_fun);
      return add_thread_event (thread_id, evloc.m_loc, evloc.m_fun->decl,
--- 223,229 ----
    diagnostic_event_id_t
    add_event_2 (event_location_t evloc, int stack_depth,
  	       const char *desc,
! 	       diagnostics::paths::thread_id_t thread_id = 0)
    {
      gcc_assert (evloc.m_fun);
      return add_thread_event (thread_id, evloc.m_loc, evloc.m_fun->decl,
*************** class test_diagnostic_path : public simp
*** 232,238 ****
    diagnostic_event_id_t
    add_event_2_with_event_id (event_location_t evloc, int stack_depth,
  			     const char *fmt,
! 			     diagnostic_thread_id_t thread_id,
  			     diagnostic_event_id_t event_id)
    {
      gcc_assert (evloc.m_fun);
--- 232,238 ----
    diagnostic_event_id_t
    add_event_2_with_event_id (event_location_t evloc, int stack_depth,
  			     const char *fmt,
! 			     diagnostics::paths::thread_id_t thread_id,
  			     diagnostic_event_id_t event_id)
    {
      gcc_assert (evloc.m_fun);
*************** class test_diagnostic_path : public simp
*** 242,248 ****
    }
    void add_entry (event_location_t evloc, int stack_depth,
  		  const char *funcname,
! 		  diagnostic_thread_id_t thread_id = 0)
    {
      gcc_assert (evloc.m_fun);
      add_thread_event (thread_id, evloc.m_loc, evloc.m_fun->decl, stack_depth,
--- 242,248 ----
    }
    void add_entry (event_location_t evloc, int stack_depth,
  		  const char *funcname,
! 		  diagnostics::paths::thread_id_t thread_id = 0)
    {
      gcc_assert (evloc.m_fun);
      add_thread_event (thread_id, evloc.m_loc, evloc.m_fun->decl, stack_depth,
*************** example_2 ()
*** 363,369 ****
  
        richloc.set_path (&path);
  
!       diagnostic_metadata m;
        m.add_cwe (415); /* CWE-415: Double Free.  */
  
        warning_meta (&richloc, m, 0,
--- 363,369 ----
  
        richloc.set_path (&path);
  
!       diagnostics::metadata m;
        m.add_cwe (415); /* CWE-415: Double Free.  */
  
        warning_meta (&richloc, m, 0,
*************** example_3 ()
*** 441,447 ****
  
        richloc.set_path (&path);
  
!       diagnostic_metadata m;
        /* CWE-479: Signal Handler Use of a Non-reentrant Function.  */
        m.add_cwe (479);
  
--- 441,447 ----
  
        richloc.set_path (&path);
  
!       diagnostics::metadata m;
        /* CWE-479: Signal Handler Use of a Non-reentrant Function.  */
        m.add_cwe (479);
  
*************** example_4 ()
*** 502,509 ****
  
        gcc_rich_location richloc (call_to_acquire_lock_a_in_bar.m_loc);
        test_diagnostic_path path (global_dc->get_reference_printer ());
!       diagnostic_thread_id_t thread_1 = path.add_thread ("Thread 1");
!       diagnostic_thread_id_t thread_2 = path.add_thread ("Thread 2");
        path.add_entry (entry_to_foo, 0, "foo", thread_1);
        diagnostic_event_id_t event_a_acquired
  	= path.add_event_2 (call_to_acquire_lock_a_in_foo, 1,
--- 502,509 ----
  
        gcc_rich_location richloc (call_to_acquire_lock_a_in_bar.m_loc);
        test_diagnostic_path path (global_dc->get_reference_printer ());
!       diagnostics::paths::thread_id_t thread_1 = path.add_thread ("Thread 1");
!       diagnostics::paths::thread_id_t thread_2 = path.add_thread ("Thread 2");
        path.add_entry (entry_to_foo, 0, "foo", thread_1);
        diagnostic_event_id_t event_a_acquired
  	= path.add_event_2 (call_to_acquire_lock_a_in_foo, 1,
*************** example_4 ()
*** 524,530 ****
  	 thread_2, event_a_acquired);
        richloc.set_path (&path);
  
!       diagnostic_metadata m;
        warning_meta (&richloc, m, 0,
  		    "deadlock due to inconsistent lock acquisition order");
      }
--- 524,530 ----
  	 thread_2, event_a_acquired);
        richloc.set_path (&path);
  
!       diagnostics::metadata m;
        warning_meta (&richloc, m, 0,
  		    "deadlock due to inconsistent lock acquisition order");
      }
*************** plugin_init (struct plugin_name_args *pl
*** 559,565 ****
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->m_source_printing.max_width = 80;
  
    pass_info.pass = make_pass_test_show_path (g);
    pass_info.reference_pass_name = "whole-program";
--- 559,565 ----
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->get_source_printing_options ().max_width = 80;
  
    pass_info.pass = make_pass_test_show_path (g);
    pass_info.reference_pass_name = "whole-program";
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.cc	Sun Jul 27 22:32:12 2025
***************
*** 62,68 ****
  #include "print-tree.h"
  #include "gcc-rich-location.h"
  #include "text-range-label.h"
! #include "diagnostic-format-text.h"
  
  int plugin_is_GPL_compatible;
  
--- 62,69 ----
  #include "print-tree.h"
  #include "gcc-rich-location.h"
  #include "text-range-label.h"
! #include "diagnostics/text-sink.h"
! #include "diagnostics/file-cache.h"
  
  int plugin_is_GPL_compatible;
  
*************** static bool force_show_locus_color = fal
*** 125,138 ****
  /* We want to verify the colorized output of diagnostic_show_locus,
     but turning on colorization for everything confuses "dg-warning" etc.
     Hence we special-case it within this plugin by using this modified
!    version of default_diagnostic_text_finalizer, which, if "color" is
     passed in as a plugin argument turns on colorization, but just
     for diagnostic_show_locus.  */
  
  static void
! custom_diagnostic_text_finalizer (diagnostic_text_output_format &text_output,
! 				  const diagnostic_info *diagnostic,
! 				  diagnostic_t)
  {
    pretty_printer *const pp = text_output.get_printer ();
    bool old_show_color = pp_show_color (pp);
--- 126,139 ----
  /* We want to verify the colorized output of diagnostic_show_locus,
     but turning on colorization for everything confuses "dg-warning" etc.
     Hence we special-case it within this plugin by using this modified
!    version of diagnostics::default_text_finalizer, which, if "color" is
     passed in as a plugin argument turns on colorization, but just
     for diagnostic_show_locus.  */
  
  static void
! custom_diagnostic_text_finalizer (diagnostics::text_sink &text_output,
! 				  const diagnostics::diagnostic_info *diag,
! 				  enum diagnostics::kind)
  {
    pretty_printer *const pp = text_output.get_printer ();
    bool old_show_color = pp_show_color (pp);
*************** custom_diagnostic_text_finalizer (diagno
*** 143,149 ****
    pp_newline (pp);
    diagnostic_show_locus (&text_output.get_context (),
  			 text_output.get_source_printing_options (),
! 			 diagnostic->richloc, diagnostic->kind, pp);
    pp_show_color (pp) = old_show_color;
    pp_set_prefix (pp, saved_prefix);
    pp_flush (pp);
--- 144,150 ----
    pp_newline (pp);
    diagnostic_show_locus (&text_output.get_context (),
  			 text_output.get_source_printing_options (),
! 			 diag->m_richloc, diag->m_kind, pp);
    pp_show_color (pp) = old_show_color;
    pp_set_prefix (pp, saved_prefix);
    pp_flush (pp);
*************** test_show_locus (function *fun)
*** 176,186 ****
    location_t fnstart = fun->function_start_locus;
    int fnstart_line = LOCATION_LINE (fnstart);
  
!   diagnostic_text_finalizer (global_dc) = custom_diagnostic_text_finalizer;
  
    /* Hardcode the "terminal width", to verify the behavior of
       very wide lines.  */
!   global_dc->m_source_printing.max_width = 71;
  
    if (0 == strcmp (fnname, "test_simple"))
      {
--- 177,187 ----
    location_t fnstart = fun->function_start_locus;
    int fnstart_line = LOCATION_LINE (fnstart);
  
!   diagnostics::text_finalizer (global_dc) = custom_diagnostic_text_finalizer;
  
    /* Hardcode the "terminal width", to verify the behavior of
       very wide lines.  */
!   global_dc->get_source_printing_options ().max_width = 71;
  
    if (0 == strcmp (fnname, "test_simple"))
      {
*************** test_show_locus (function *fun)
*** 251,257 ****
    if (0 == strcmp (fnname, "test_very_wide_line"))
      {
        const int line = fnstart_line + 2;
!       global_dc->m_source_printing.show_ruler_p = true;
        text_range_label label0 ("label 0");
        text_range_label label1 ("label 1");
        rich_location richloc (line_table,
--- 252,258 ----
    if (0 == strcmp (fnname, "test_very_wide_line"))
      {
        const int line = fnstart_line + 2;
!       global_dc->get_source_printing_options ().show_ruler_p = true;
        text_range_label label0 ("label 0");
        text_range_label label1 ("label 1");
        rich_location richloc (line_table,
*************** test_show_locus (function *fun)
*** 263,269 ****
  			 &label1);
        richloc.add_fixit_replace ("bar * foo");
        warning_at (&richloc, 0, "test");
!       global_dc->m_source_printing.show_ruler_p = false;
      }
  
    /* Likewise, but with a secondary location that's immediately before
--- 264,270 ----
  			 &label1);
        richloc.add_fixit_replace ("bar * foo");
        warning_at (&richloc, 0, "test");
!       global_dc->get_source_printing_options ().show_ruler_p = false;
      }
  
    /* Likewise, but with a secondary location that's immediately before
*************** test_show_locus (function *fun)
*** 271,277 ****
    if (0 == strcmp (fnname, "test_very_wide_line_2"))
      {
        const int line = fnstart_line + 2;
!       global_dc->m_source_printing.show_ruler_p = true;
        text_range_label label0 ("label 0");
        text_range_label label1 ("label 1");
        rich_location richloc (line_table,
--- 272,278 ----
    if (0 == strcmp (fnname, "test_very_wide_line_2"))
      {
        const int line = fnstart_line + 2;
!       global_dc->get_source_printing_options ().show_ruler_p = true;
        text_range_label label0 ("label 0");
        text_range_label label1 ("label 1");
        rich_location richloc (line_table,
*************** test_show_locus (function *fun)
*** 283,289 ****
        richloc.add_range (get_loc (line, 34), SHOW_RANGE_WITHOUT_CARET,
  			 &label1);
        warning_at (&richloc, 0, "test");
!       global_dc->m_source_printing.show_ruler_p = false;
      }
  
    /* Example of multiple carets.  */
--- 284,290 ----
        richloc.add_range (get_loc (line, 34), SHOW_RANGE_WITHOUT_CARET,
  			 &label1);
        warning_at (&richloc, 0, "test");
!       global_dc->get_source_printing_options ().show_ruler_p = false;
      }
  
    /* Example of multiple carets.  */
*************** test_show_locus (function *fun)
*** 294,304 ****
        location_t caret_b = get_loc (line, 11);
        rich_location richloc (line_table, caret_a);
        add_range (&richloc, caret_b, caret_b, SHOW_RANGE_WITH_CARET);
!       global_dc->m_source_printing.caret_chars[0] = 'A';
!       global_dc->m_source_printing.caret_chars[1] = 'B';
        warning_at (&richloc, 0, "test");
!       global_dc->m_source_printing.caret_chars[0] = '^';
!       global_dc->m_source_printing.caret_chars[1] = '^';
      }
  
    /* Tests of rendering fixit hints.  */
--- 295,305 ----
        location_t caret_b = get_loc (line, 11);
        rich_location richloc (line_table, caret_a);
        add_range (&richloc, caret_b, caret_b, SHOW_RANGE_WITH_CARET);
!       global_dc->get_source_printing_options ().caret_chars[0] = 'A';
!       global_dc->get_source_printing_options ().caret_chars[1] = 'B';
        warning_at (&richloc, 0, "test");
!       global_dc->get_source_printing_options ().caret_chars[0] = '^';
!       global_dc->get_source_printing_options ().caret_chars[1] = '^';
      }
  
    /* Tests of rendering fixit hints.  */
*************** test_show_locus (function *fun)
*** 412,422 ****
        location_t caret_b = get_loc (line - 1, 19);
        rich_location richloc (line_table, caret_a);
        richloc.add_range (caret_b, SHOW_RANGE_WITH_CARET);
!       global_dc->m_source_printing.caret_chars[0] = '1';
!       global_dc->m_source_printing.caret_chars[1] = '2';
        warning_at (&richloc, 0, "test");
!       global_dc->m_source_printing.caret_chars[0] = '^';
!       global_dc->m_source_printing.caret_chars[1] = '^';
      }
  
    /* Example of using the "%q+D" format code, which as well as printing
--- 413,423 ----
        location_t caret_b = get_loc (line - 1, 19);
        rich_location richloc (line_table, caret_a);
        richloc.add_range (caret_b, SHOW_RANGE_WITH_CARET);
!       global_dc->get_source_printing_options ().caret_chars[0] = '1';
!       global_dc->get_source_printing_options ().caret_chars[1] = '2';
        warning_at (&richloc, 0, "test");
!       global_dc->get_source_printing_options ().caret_chars[0] = '^';
!       global_dc->get_source_printing_options ().caret_chars[1] = '^';
      }
  
    /* Example of using the "%q+D" format code, which as well as printing
*************** test_show_locus (function *fun)
*** 443,450 ****
        rich_location richloc (line_table, loc);
        for (int line = start_line; line <= finish_line; line++)
  	{
! 	  file_cache &fc = global_dc->get_file_cache ();
! 	  char_span content = fc.get_source_line (file, line);
  	  gcc_assert (content);
  	  /* Split line up into words.  */
  	  for (int idx = 0; idx < content.length (); idx++)
--- 444,451 ----
        rich_location richloc (line_table, loc);
        for (int line = start_line; line <= finish_line; line++)
  	{
! 	  diagnostics::file_cache &fc = global_dc->get_file_cache ();
! 	  diagnostics::char_span content = fc.get_source_line (file, line);
  	  gcc_assert (content);
  	  /* Split line up into words.  */
  	  for (int idx = 0; idx < content.length (); idx++)
*************** test_show_locus (function *fun)
*** 464,470 ****
  		      richloc.add_range (word, SHOW_RANGE_WITH_CARET, &label);
  
  		      /* Add a fixit, converting to upper case.  */
! 		      char_span word_span = content.subspan (start_idx, idx - start_idx);
  		      char *copy = word_span.xstrdup ();
  		      for (char *ch = copy; *ch; ch++)
  			*ch = TOUPPER (*ch);
--- 465,472 ----
  		      richloc.add_range (word, SHOW_RANGE_WITH_CARET, &label);
  
  		      /* Add a fixit, converting to upper case.  */
! 		      diagnostics::char_span word_span
! 			= content.subspan (start_idx, idx - start_idx);
  		      char *copy = word_span.xstrdup ();
  		      for (char *ch = copy; *ch; ch++)
  			*ch = TOUPPER (*ch);
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.cc	Sun Jul 27 22:32:12 2025
*************** plugin_init (struct plugin_name_args *pl
*** 208,214 ****
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->m_source_printing.max_width = 80;
  
    pass_info.pass = new pass_test_string_literals (g);
    pass_info.reference_pass_name = "ssa";
--- 208,214 ----
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->get_source_printing_options ().max_width = 80;
  
    pass_info.pass = new pass_test_string_literals (g);
    pass_info.reference_pass_name = "ssa";
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.cc	Sun Jul 27 22:32:12 2025
***************
*** 9,15 ****
  #include "coretypes.h"
  #include "plugin-version.h"
  #include "diagnostic.h"
! #include "diagnostic-diagram.h"
  #include "text-art/canvas.h"
  #include "text-art/table.h"
  
--- 9,15 ----
  #include "coretypes.h"
  #include "plugin-version.h"
  #include "diagnostic.h"
! #include "diagnostics/diagram.h"
  #include "text-art/canvas.h"
  #include "text-art/table.h"
  
*************** using namespace text_art;
*** 22,28 ****
  static void
  emit_canvas (const canvas &c, const char *alt_text)
  {
!   diagnostic_diagram diagram (c, alt_text);
    global_dc->emit_diagram (diagram);
  }
  
--- 22,28 ----
  static void
  emit_canvas (const canvas &c, const char *alt_text)
  {
!   diagnostics::diagram diagram (c, alt_text);
    global_dc->emit_diagram (diagram);
  }
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_tree_expression_range.cc	Sun Jul 27 22:32:12 2025
*************** plugin_init (struct plugin_name_args *pl
*** 89,95 ****
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->m_source_printing.max_width = 130;
  
    register_callback (plugin_name,
  		     PLUGIN_PRE_GENERICIZE,
--- 89,95 ----
    if (!plugin_default_version_check (version, &gcc_version))
      return 1;
  
!   global_dc->get_source_printing_options ().max_width = 130;
  
    register_callback (plugin_name,
  		     PLUGIN_PRE_GENERICIZE,
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/expensive_selftests_plugin.cc	Sun Jul 27 22:32:12 2025
***************
*** 6,14 ****
  #include "system.h"
  #include "coretypes.h"
  #include "diagnostic.h"
! #include "edit-context.h"
  #include "selftest.h"
! #include "selftest-diagnostic.h"
  
  int plugin_is_GPL_compatible;
  
--- 6,14 ----
  #include "system.h"
  #include "coretypes.h"
  #include "diagnostic.h"
! #include "diagnostics/changes.h"
  #include "selftest.h"
! #include "diagnostics/selftest-context.h"
  
  int plugin_is_GPL_compatible;
  
*************** static void
*** 47,60 ****
  test_richloc (rich_location *richloc)
  {
    /* Run the diagnostic and fix-it printing code.  */
!   test_diagnostic_context dc;
!   diagnostic_show_locus (&dc, dc.m_source_printing,
! 			 richloc, DK_ERROR, dc.get_reference_printer ());
  
    /* Generate a diff.  */
!   edit_context ec (global_dc->get_file_cache ());
!   ec.add_fixits (richloc);
!   char *diff = ec.generate_diff (true);
    free (diff);
  }
  
--- 47,61 ----
  test_richloc (rich_location *richloc)
  {
    /* Run the diagnostic and fix-it printing code.  */
!   diagnostics::selftest::test_context dc;
!   diagnostic_show_locus (&dc, dc.get_source_printing_options (),
! 			 richloc, diagnostics::kind::error,
! 			 dc.get_reference_printer ());
  
    /* Generate a diff.  */
!   diagnostics::changes::change_set edit (global_dc->get_file_cache ());
!   edit.add_fixits (richloc);
!   char *diff = edit.generate_diff (true);
    free (diff);
  }
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.cc gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.cc
*** gcc-16-20250720/gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.cc	Sun Jul 20 22:32:18 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.cc	Sun Jul 27 22:32:12 2025
***************
*** 7,13 ****
  #include "coretypes.h"
  #include "spellcheck.h"
  #include "diagnostic.h"
! #include "diagnostic-format-text.h"
  
  int plugin_is_GPL_compatible;
  
--- 7,13 ----
  #include "coretypes.h"
  #include "spellcheck.h"
  #include "diagnostic.h"
! #include "diagnostics/text-sink.h"
  
  int plugin_is_GPL_compatible;
  
*************** on_pragma_registration (void */*gcc_data
*** 39,50 ****
  /* We add some extra testing during diagnostics by chaining up
     to the text finalizer.  */
  
! static diagnostic_text_finalizer_fn original_text_finalizer = NULL;
  
  static void
! verify_unpacked_ranges  (diagnostic_text_output_format &text_output,
! 			 const diagnostic_info *diagnostic,
! 			 diagnostic_t orig_diag_kind)
  {
    /* Verify that the locations are ad-hoc, not packed. */
    location_t loc = diagnostic_location (diagnostic);
--- 39,50 ----
  /* We add some extra testing during diagnostics by chaining up
     to the text finalizer.  */
  
! static diagnostics::text_finalizer_fn original_text_finalizer = NULL;
  
  static void
! verify_unpacked_ranges  (diagnostics::text_sink &text_output,
! 			 const diagnostics::diagnostic_info *diagnostic,
! 			 enum diagnostics::kind orig_diag_kind)
  {
    /* Verify that the locations are ad-hoc, not packed. */
    location_t loc = diagnostic_location (diagnostic);
*************** verify_unpacked_ranges  (diagnostic_text
*** 56,64 ****
  }
  
  static void
! verify_no_columns  (diagnostic_text_output_format &text_output,
! 		    const diagnostic_info *diagnostic,
! 		    diagnostic_t orig_diag_kind)
  {
    /* Verify that the locations have no columns. */
    location_t loc = diagnostic_location (diagnostic);
--- 56,64 ----
  }
  
  static void
! verify_no_columns  (diagnostics::text_sink &text_output,
! 		    const diagnostics::diagnostic_info *diagnostic,
! 		    enum diagnostics::kind orig_diag_kind)
  {
    /* Verify that the locations have no columns. */
    location_t loc = diagnostic_location (diagnostic);
*************** plugin_init (struct plugin_name_args *pl
*** 104,118 ****
  		     NULL); /* void *user_data */
  
    /* Hack in additional testing, based on the exact value supplied.  */
!   original_text_finalizer = diagnostic_text_finalizer (global_dc);
    switch (base_location)
      {
      case LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES + 1:
!       diagnostic_text_finalizer (global_dc) = verify_unpacked_ranges;
        break;
  
      case LINE_MAP_MAX_LOCATION_WITH_COLS + 1:
!       diagnostic_text_finalizer (global_dc) = verify_no_columns;
        break;
  
      default:
--- 104,118 ----
  		     NULL); /* void *user_data */
  
    /* Hack in additional testing, based on the exact value supplied.  */
!   original_text_finalizer = diagnostics::text_finalizer (global_dc);
    switch (base_location)
      {
      case LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES + 1:
!       diagnostics::text_finalizer (global_dc) = verify_unpacked_ranges;
        break;
  
      case LINE_MAP_MAX_LOCATION_WITH_COLS + 1:
!       diagnostics::text_finalizer (global_dc) = verify_no_columns;
        break;
  
      default:
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/pr109267-1.c gcc-16-20250727/gcc/testsuite/gcc.dg/pr109267-1.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/pr109267-1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/pr109267-1.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-optimized" } */
+ 
+ /* PR middle-end/109267 */
+ 
+ int f(void)
+ {
+   __builtin_unreachable();
+ }
+ 
+ /* This unreachable should be changed to be a trap. */
+ 
+ /* { dg-final { scan-tree-dump-times "__builtin_unreachable trap \\\(" 1 "optimized" { target trap }  } } */
+ /* { dg-final { scan-tree-dump-times "goto <" 1 "optimized" { target { ! trap } } } } */
+ /* { dg-final { scan-tree-dump-not "__builtin_unreachable \\\(" "optimized"} } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/pr109267-2.c gcc-16-20250727/gcc/testsuite/gcc.dg/pr109267-2.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/pr109267-2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/pr109267-2.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-optimized" } */
+ 
+ /* PR middle-end/109267 */
+ void g(void);
+ int f(int *t)
+ {
+   g();
+   __builtin_unreachable();
+ }
+ 
+ /* The unreachable should stay a unreachable. */
+ /* { dg-final { scan-tree-dump-not "__builtin_unreachable trap \\\(" "optimized"} } */
+ /* { dg-final { scan-tree-dump-times "__builtin_unreachable \\\(" 1 "optimized"} } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/pr121202.c gcc-16-20250727/gcc/testsuite/gcc.dg/pr121202.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/pr121202.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/pr121202.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,11 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O3 -fno-tree-copy-prop" } */
+ 
+ int a, b, c;
+ int e(int f, int g) { return f >> g; }
+ int h(int f) { return a > 1 ? 0 : f << a; }
+ int main() {
+   while (c--)
+     b = e(h(1), a);
+   return 0;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/pr121216.c gcc-16-20250727/gcc/testsuite/gcc.dg/pr121216.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/pr121216.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/pr121216.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "" } */
+ 
+ int foo (void)
+ {
+     const char *key = "obscurelevelofabstraction";
+     const char reverse_key[__builtin_strlen(key)] = {'\0'}; /* { dg-error "variable-sized object may not be initialized except with an empty initializer" } */
+     return __builtin_strlen(reverse_key);
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/pr87600-2.c gcc-16-20250727/gcc/testsuite/gcc.dg/pr87600-2.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/pr87600-2.c	Sun Jul 20 22:32:20 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/pr87600-2.c	Sun Jul 27 22:32:12 2025
*************** test1 (void)
*** 23,44 ****
    asm ("blah %0 %1" : "=r" (var1) : "0" (var2)); /* { dg-error "invalid hard register usage between output operand and matching constraint operand" } */
    return var1;
  }
- 
- long
- test2 (void)
- {
-   register long var1 asm (REG1);
-   register long var2 asm (REG1);
-   asm ("blah %0 %1" : "=&r" (var1) : "r" (var2)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
-   return var1;
- }
- 
- long
- test3 (void)
- {
-   register long var1 asm (REG1);
-   register long var2 asm (REG1);
-   long var3;
-   asm ("blah %0 %1" : "=&r" (var1), "=r" (var3) : "1" (var2)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
-   return var1 + var3;
- }
--- 23,25 ----
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/pr87600-3.c gcc-16-20250727/gcc/testsuite/gcc.dg/pr87600-3.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/pr87600-3.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/pr87600-3.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,26 ----
+ /* PR rtl-optimization/87600  */
+ /* { dg-do compile { target aarch64*-*-* arm*-*-* i?86-*-* powerpc*-*-* s390*-*-* x86_64-*-* } } */
+ /* { dg-options "-O2" } */
+ 
+ #include "pr87600.h"
+ 
+ /* The following are all invalid uses of local register variables.  */
+ 
+ long
+ test2 (void)
+ {
+   register long var1 asm (REG1);
+   register long var2 asm (REG1);
+   asm ("blah %0 %1" : "=&r" (var1) : "r" (var2)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
+   return var1;
+ }
+ 
+ long
+ test3 (void)
+ {
+   register long var1 asm (REG1);
+   register long var2 asm (REG1);
+   long var3;
+   asm ("blah %0 %1" : "=&r" (var1), "=r" (var3) : "1" (var2)); /* { dg-error "invalid hard register usage between earlyclobber operand and input operand" } */
+   return var1 + var3;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/sarif-output/include-chain-2.h gcc-16-20250727/gcc/testsuite/gcc.dg/sarif-output/include-chain-2.h
*** gcc-16-20250720/gcc/testsuite/gcc.dg/sarif-output/include-chain-2.h	Sun Jul 20 22:32:20 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/sarif-output/include-chain-2.h	Sun Jul 27 22:32:12 2025
***************
*** 1,4 ****
! /* Generate a warning with a diagnostic_path within a header.  */
  
  void test (void *ptr)
  {
--- 1,4 ----
! /* Generate a warning with a diagnostic path within a header.  */
  
  void test (void *ptr)
  {
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/torture/pr121194.c gcc-16-20250727/gcc/testsuite/gcc.dg/torture/pr121194.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/torture/pr121194.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/torture/pr121194.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do compile } */
+ 
+ int a, b, c, d;
+ void e() {
+   int *f = &b;
+   for (a = 0; a < 8; a++) {
+     *f = 0;
+     for (c = 0; c < 2; c++)
+       *f = *f == 0;
+   }
+ }
+ int main() {
+   e();
+   int *g = &b;
+   *g = *g == (d == 0);
+   return 0;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/cmp-2.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O1 -fdump-tree-forwprop" } */
+ 
+ /* PR tree-optimization/110949 */
+ /* Transform `(cmp) - 1` into `-icmp`. */
+ 
+ int f1(int a)
+ {
+   int t = a == 115;
+   return t - 1;
+ }
+ 
+ /* { dg-final { scan-tree-dump " != 115" "forwprop1" } } */
+ /* { dg-final { scan-tree-dump-not " == 115" "forwprop1" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/max-bitcmp-1.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,19 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O1 -fdump-tree-forwprop -fdump-tree-optimized" } */
+ 
+ /* PR tree-optimization/95906 */
+ /* this should become MAX_EXPR<a,b> */
+ 
+ int f2(int a, int b)
+ {
+     int cmp = -(a > b);
+     return (cmp & a) | (~cmp & b);
+ }
+ 
+ /*  we should not end up with -_2 */
+ /*  we should not end up and & nor a `+ -1` */
+ /* In optimized we should have a max.  */
+ /* { dg-final { scan-tree-dump-not " -\[a-zA-Z_\]" "forwprop1" } } */
+ /* { dg-final { scan-tree-dump-not " & " "forwprop1" } } */
+ /* { dg-final { scan-tree-dump-not " . -1" "forwprop1" } } */
+ /* { dg-final { scan-tree-dump-times "MAX_EXPR " 1 "optimized" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/pr119085.c gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/pr119085.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/pr119085.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/pr119085.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do run } */
+ /* { dg-options "-O1" } */
+ 
+ struct with_hole {
+   int x;
+   long y;
+ };
+ struct without_hole {
+   int x;
+   int y;
+ };
+ union u {
+   struct with_hole with_hole;
+   struct without_hole without_hole;
+ };
+ 
+ void __attribute__((noinline))
+ test (union u *up, union u u)
+ {
+   union u u2;
+   volatile int f = 0;
+   u2 = u;
+   if (f)
+     u2.with_hole = u.with_hole;
+   *up = u2;
+ }
+ 
+ int main(void)
+ {
+   union u u;
+   union u u2;
+   u2.without_hole.y = -1;
+   test (&u, u2);
+   if (u.without_hole.y != -1)
+     __builtin_abort ();
+   return 0;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/pr81627.c gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/pr81627.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/pr81627.c	Sun Jul 20 22:32:22 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/pr81627.c	Sun Jul 27 22:32:12 2025
***************
*** 4,9 ****
--- 4,10 ----
  int a, b, c, d[6], e = 3, f;
  
  void abort (void);
+ void fn1 () __attribute__((noinline));
  void fn1 ()
  {
    for (b = 1; b < 5; b++)
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-23.c gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-23.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-23.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-23.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,21 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-sink1-details" } */
+ 
+ struct S {
+     int* x;
+     int* y;
+ };
+ 
+ void __attribute__((noreturn)) bar(const struct S* s);
+ 
+ void foo(int a, int b) {
+     struct S s;
+     s.x = &a;
+     s.y = &b;
+     if (a < b) {
+         bar(&s);
+     }
+ }
+ 
+ /* { dg-final { scan-tree-dump "Sinking.*s.y" "sink1" } } */
+ /* { dg-final { scan-tree-dump "Sinking.*s.x" "sink1" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/vect/pr116125.c gcc-16-20250727/gcc/testsuite/gcc.dg/vect/pr116125.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/vect/pr116125.c	Sun Jul 20 22:32:22 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/vect/pr116125.c	Sun Jul 27 22:32:12 2025
*************** main (void)
*** 17,28 ****
  {
    check_vect ();
  
!   struct st a[9] = {};
  
!   // input a = 0, 0, 0, 0, 0, 0, 0, 0, 0
    mem_overlap (&a[1], a);
  
!   // output a = 0, 1, 2, 3, 4, 5, 6, 7, 8
    if (a[2].num == 2)
      return 0;
    else
--- 17,28 ----
  {
    check_vect ();
  
!   struct st a[10] = {};
  
!   // input a = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    mem_overlap (&a[1], a);
  
!   // output a = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
    if (a[2].num == 2)
      return 0;
    else
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/vect/slp-28.c gcc-16-20250727/gcc/testsuite/gcc.dg/vect/slp-28.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/vect/slp-28.c	Sun Jul 20 22:32:22 2025
--- gcc-16-20250727/gcc/testsuite/gcc.dg/vect/slp-28.c	Sun Jul 27 22:32:12 2025
*************** main1 ()
*** 59,66 ****
          abort ();
      }
    
!   /* Not vectorizable because of data dependencies: distance 3 is greater than 
!      the actual VF with SLP (2), but the analysis fail to detect that for now.  */
    for (i = 3; i < N/4; i++)
      {
        in3[i*4] = in3[(i-3)*4] + 5;
--- 59,66 ----
          abort ();
      }
    
!   /* Dependence distance 3 is greater than the actual VF with SLP (2),
!      thus vectorizable.  */
    for (i = 3; i < N/4; i++)
      {
        in3[i*4] = in3[(i-3)*4] + 5;
*************** int main (void)
*** 91,97 ****
    return 0;
  }
  
! /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! vect32 } } } } */
! /* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target vect32 } } } */
! /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { ! vect32 } } } } */
    
--- 91,96 ----
    return 0;
  }
  
! /* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
! /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" } } */
    
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.dg/vect/vect-127.c gcc-16-20250727/gcc/testsuite/gcc.dg/vect/vect-127.c
*** gcc-16-20250720/gcc/testsuite/gcc.dg/vect/vect-127.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.dg/vect/vect-127.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,15 ----
+ // { dg-do compile }
+ // { dg-require-effective-target vect_int }
+ 
+ void foo (int *p)
+ {
+   for (int i = 0; i < 1024; ++i)
+     {
+       int a0 = p[2*i + 0];
+       int a1 = p[2*i + 1];
+       p[2*i + 4] = a0;
+       p[2*i + 5] = a1;
+     }
+ }
+ 
+ /* { dg-final { scan-tree-dump "loop vectorized using 16 byte vectors" "vect" { target { vect128 && vect_hw_misalign } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/asm-hard-reg-1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/asm-hard-reg-1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/asm-hard-reg-1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/asm-hard-reg-1.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,55 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2" } */
+ 
+ /* Ensure that we error out in case no hard regs are available for an operand
+    with constraint y.  The position/order of the y-constrained operand does not
+    matter.  */
+ 
+ void
+ test (void)
+ {
+   int x, a, b, c, d, e, f, g, h;
+ 
+   __asm__ __volatile__ ("" :
+       "={v0}" (a),
+       "={v1}" (b),
+       "={v2}" (c),
+       "={v3}" (d),
+       "={v4}" (e),
+       "={v5}" (f),
+       "={v6}" (g),
+       "={v7}" (h));
+ 
+   __asm__ __volatile__ ("" : /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+       "=y" (x),
+       "={v0}" (a),
+       "={v1}" (b),
+       "={v2}" (c),
+       "={v3}" (d),
+       "={v4}" (e),
+       "={v5}" (f),
+       "={v6}" (g),
+       "={v7}" (h));
+ 
+   __asm__ __volatile__ ("" : /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+       "={v0}" (a),
+       "={v1}" (b),
+       "={v2}" (c),
+       "={v3}" (d),
+       "=y" (x),
+       "={v4}" (e),
+       "={v5}" (f),
+       "={v6}" (g),
+       "={v7}" (h));
+ 
+   __asm__ __volatile__ ("" : /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+       "={v0}" (a),
+       "={v1}" (b),
+       "={v2}" (c),
+       "={v3}" (d),
+       "={v4}" (e),
+       "={v5}" (f),
+       "={v6}" (g),
+       "={v7}" (h),
+       "=y" (x));
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/asm-hard-reg-2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/asm-hard-reg-2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/asm-hard-reg-2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/asm-hard-reg-2.c	Sun Jul 27 22:32:12 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -march=armv8-a+sve" } */
+ 
+ /* Test register pairs.  */
+ 
+ #include <arm_sve.h>
+ 
+ void
+ test (void)
+ {
+   svuint32x2_t x, y;
+   svuint32x4_t z;
+ 
+   __asm__ __volatile__ ("" : "={z4}" (x), "={z6}" (y));
+   __asm__ __volatile__ ("" : "={z5}" (x), "={z6}" (y));  /* { dg-error "multiple outputs to hard register: v6" } */
+   __asm__ __volatile__ ("" : "={z4}" (z), "={z6}" (y));  /* { dg-error "multiple outputs to hard register: v6" } */
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/inszero_split_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/inszero_split_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/inszero_split_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/inszero_split_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,18 ----
+ /* { dg-do compile } */
+ /* { dg-additional-options "-O2" } */
+ /* { dg-final { check-function-bodies "**" "" "" } } */
+ 
+ /* Avoid INS from WZR register when optimizing for speed.  */
+ 
+ #include <arm_neon.h>
+ 
+ /*
+ ** foo:
+ **	movi?	[vdz]([0-9]+)\.?(?:[0-9]*[bhsd])?, #?0
+ **	ins	v0.h\[2\], v(\1).h\[0\]
+ **	ret
+ */
+ uint16x8_t foo(uint16x8_t a) {
+   a[2] = 0;
+   return a;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/simd/mf8_data_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/simd/mf8_data_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/simd/mf8_data_1.c	Sun Jul 20 22:32:22 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/simd/mf8_data_1.c	Sun Jul 27 22:32:13 2025
*************** mfloat8x8_t test_set_lane3(mfloat8x8_t a
*** 1016,1022 ****
--- 1016,1027 ----
  
  /*
  ** test_set_lane4:
+ **	(
  **	ins	v0.b\[6\], wzr
+ **	|
+ **	movi?	[vdz]([0-9]+)\.?(?:[0-9]*[bhsd])?, #?0
+ **	ins	v0.b\[6\], v(\1).b\[0\]
+ **	)
  **	ret
  */
  mfloat8x8_t test_set_lane4(mfloat8x8_t a)
*************** mfloat8x16_t test_setq_lane3(mfloat8x16_
*** 1056,1062 ****
--- 1061,1072 ----
  
  /*
  ** test_setq_lane4:
+ **	(
  **	ins	v0.b\[14\], wzr
+ **	|
+ **	movi?	[vdz]([0-9]+)\.?(?:[0-9]*[bhsd])?, #?0
+ **	ins	v0.b\[14\], v(\1).b\[0\]
+ **	)
  **	ret
  */
  mfloat8x16_t test_setq_lane4(mfloat8x16_t a)
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/mask_load_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/mask_load_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/mask_load_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/mask_load_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,23 ----
+ // { dg-do compile }
+ // { dg-options "-march=armv8-a+sve -msve-vector-bits=128 -O3" }
+ 
+ typedef struct Array {
+     int elems[3];
+ } Array;
+ 
+ int loop(Array **pp, int len, int idx) {
+     int nRet = 0;
+ 
+     #pragma GCC unroll 0
+     for (int i = 0; i < len; i++) {
+         Array *p = pp[i];
+         if (p) {
+             nRet += p->elems[idx];
+         }
+     }
+ 
+     return nRet;
+ }
+ 
+ // { dg-final { scan-assembler-times {ld1w\tz[0-9]+\.d, p[0-7]/z} 1 } }
+ // { dg-final { scan-assembler-times {add\tz[0-9]+\.s, p[0-7]/m}  1 } }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,44 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define b_i b[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##RHS (TYPE1 *__restrict out,	\
+ 				      TYPE0 *__restrict a,      \
+ 				      TYPE0 *__restrict b,      \
+                                       TYPE0 *__restrict c)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       if (FN (a[i], RHS) > c[i])				\
+ 	out[i] = 3;						\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1)
+ 
+ TEST_ALL (__builtin_fmaxf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_fmaxf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_fmaxf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 6 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 7 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmax_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include "unpacked_builtin_fmax_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 9 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 7 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,44 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048" } */
+ 
+ #include <stdint.h>
+ 
+ #define b_i b[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##RHS (TYPE1 *__restrict out,	\
+ 				      TYPE0 *__restrict a,      \
+ 				      TYPE0 *__restrict b,      \
+                                       TYPE0 *__restrict c)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       if (FN (a[i], RHS) > c[i])				\
+ 	out[i] = 3;						\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1)
+ 
+ TEST_ALL (__builtin_fminf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_fminf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_fminf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 6 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 7 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_builtin_fmin_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include "unpacked_builtin_fmin_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 9 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 7 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmax_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmax_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmax_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmax_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,51 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ #define c_i c[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS, MERGE)		\
+   void								\
+   f_##TYPE0##_##TYPE1##_##RHS##_##MERGE (TYPE0 *__restrict out,	\
+ 					 TYPE0 *__restrict a,	\
+ 					 TYPE0 *__restrict b,	\
+ 					 TYPE0 *__restrict c,	\
+ 					 TYPE1 *__restrict p)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i], (TYPE0)RHS) : MERGE;		\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)     \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, a_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, c_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0, a_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0, b_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, a_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, b_i)
+ 
+ TEST_ALL (__builtin_fmaxf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_fmaxf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_fmaxf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 13 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmin_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmin_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmin_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_builtin_fmin_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,51 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ #define c_i c[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS, MERGE)		\
+   void								\
+   f_##TYPE0##_##TYPE1##_##RHS##_##MERGE (TYPE0 *__restrict out,	\
+ 					 TYPE0 *__restrict a,	\
+ 					 TYPE0 *__restrict b,	\
+ 					 TYPE0 *__restrict c,	\
+ 					 TYPE1 *__restrict p)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i], (TYPE0)RHS) : MERGE;		\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)     \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, a_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, c_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0, a_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0, b_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, a_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, b_i)
+ 
+ TEST_ALL (__builtin_fminf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_fminf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_fminf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 13 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_cvtf_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_cvtf_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_cvtf_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_cvtf_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,51 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define COND_CVT(TYPE0, TYPE1, TYPE2, COUNT)		    \
+   void                                                      \
+   test_##TYPE0##_##TYPE1##_##TYPE2 (TYPE0 *__restrict out,  \
+ 				    TYPE1 *__restrict a,    \
+ 				    TYPE0 *__restrict b,    \
+ 				    TYPE2 *__restrict p)    \
+   {							    \
+     for (unsigned int i = 0; i < COUNT; i++)                \
+       out[i] = p[i] ?  (TYPE0)a[i] : b[i];		    \
+   }
+ 
+ #define TEST_CVTF(PFX, T)		   \
+   T (_Float16, PFX##int16_t, uint64_t, 32) \
+   T (_Float16, PFX##int16_t, uint32_t, 64) \
+   T (_Float16, PFX##int32_t, uint64_t, 32) \
+   T (_Float16, PFX##int32_t, uint32_t, 64) \
+   T (_Float16, PFX##int64_t, uint64_t, 32) \
+   T (float, PFX##int32_t, uint64_t, 32)    \
+   T (float, PFX##int64_t, uint64_t, 32)
+ 
+ #define TEST_ALL(T) \
+   TEST_CVTF (, T)   \
+   TEST_CVTF (u, T)
+ 
+ TEST_ALL (COND_CVT)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 8 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 6 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 8 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tscvtf\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tucvtf\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tscvtf\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tucvtf\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tscvtf\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.d\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tucvtf\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.d\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tscvtf\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tucvtf\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tscvtf\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.d\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tucvtf\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.d\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fabs_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fabs_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fabs_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fabs_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, MERGE)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##MERGE (TYPE1 *__restrict p,	\
+     					TYPE0 *__restrict out,	\
+ 					TYPE0 *__restrict a,	\
+ 					TYPE0 *__restrict b)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i]) : MERGE;			\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)
+ 
+ TEST_ALL (__builtin_fabsf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_fabsf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_fabsf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfabs\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfabs\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fadd_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fadd_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fadd_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fadd_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,62 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ #define c_i c[i]
+ #define imm_p5 0.5
+ 
+ #define ADD(A, B) A + B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, NAME, RHS, MERGE)	 \
+   void								 \
+   f_##TYPE0##_##TYPE1##_##NAME##_##MERGE (TYPE0 *__restrict out, \
+ 					 TYPE0 *__restrict a,	 \
+ 					 TYPE0 *__restrict b,	 \
+ 					 TYPE0 *__restrict c,	 \
+ 					 TYPE1 *__restrict p)	 \
+   {								 \
+     for (unsigned int i = 0; i < COUNT; i++)			 \
+       out[i] = p[i] ? FN (a[i], (TYPE0)RHS) : MERGE;		 \
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)	     \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b[i], a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b[i], b_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b[i], c_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, one, 1, a_i)     \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, one, 1, b_i)     \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, none, -1, a_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, none, -1, b_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, p5, 0.5, a_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, p5, 0.5, b_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, np5, -0.5, a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, np5, -0.5, b_i)
+ 
+ TEST_ALL (ADD, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (ADD, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (ADD, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 19 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 19 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 19 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 5 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 10 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvt_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvt_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvt_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvt_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,41 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define COND_CVT(TYPE0, TYPE1, TYPE2, COUNT)		    \
+   void                                                      \
+   test_##TYPE0##_##TYPE1##_##TYPE2 (TYPE0 *__restrict out,  \
+ 				    TYPE1 *__restrict a,    \
+ 				    TYPE0 *__restrict b,    \
+ 				    TYPE2 *__restrict p)    \
+   {							    \
+     for (unsigned int i = 0; i < COUNT; i++)                \
+       out[i] = p[i] ?  (TYPE0)a[i] : b[i];		    \
+   }
+ 
+ #define TEST_FCVT(T)		     \
+   T (_Float16, float, uint64_t, 32)  \
+   T (_Float16, float, uint32_t, 64)  \
+   T (_Float16, double, uint64_t, 32) \
+   T (float, double, uint64_t, 32)    \
+   T (float, _Float16, uint64_t, 32)  \
+   T (float, _Float16, uint32_t, 64)  \
+   T (double, _Float16, uint64_t,32)  \
+   T (double, float, uint64_t, 32)
+ 
+ TEST_FCVT (COND_CVT)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 4 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 4 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfcvt\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.d\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfcvt\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.d\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfcvt\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfcvt\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.h\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfcvt\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfcvt\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvtz_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvtz_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvtz_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fcvtz_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,55 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define COND_CVT(TYPE0, TYPE1, TYPE2, COUNT)		    \
+   void                                                      \
+   test_##TYPE0##_##TYPE1##_##TYPE2 (TYPE0 *__restrict out,  \
+ 				    TYPE1 *__restrict a,    \
+ 				    TYPE0 *__restrict b,    \
+ 				    TYPE2 *__restrict p)    \
+   {							    \
+     for (unsigned int i = 0; i < COUNT; i++)                \
+       out[i] = p[i] ?  (TYPE0)a[i] : b[i];		    \
+   }
+ 
+ #define TEST_FCVTZ(PFX, T)		   \
+   T (PFX##int16_t, _Float16, uint64_t, 32) \
+   T (PFX##int16_t, _Float16, uint32_t, 64) \
+   T (PFX##int32_t, _Float16, uint64_t, 32) \
+   T (PFX##int32_t, _Float16, uint32_t, 64) \
+   T (PFX##int64_t, _Float16, uint64_t, 32) \
+   T (PFX##int32_t, float, uint64_t, 32)    \
+   T (PFX##int64_t, float, uint64_t, 32)    \
+   T (PFX##int32_t, double, uint64_t, 32)
+ 
+ #define TEST_ALL(T) \
+   TEST_FCVTZ (, T)  \
+   TEST_FCVTZ (u, T)
+ 
+ TEST_ALL (COND_CVT)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 10 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 6 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 8 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfcvtzs\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfcvtzu\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfcvtzs\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfcvtzu\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfcvtzs\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.h\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfcvtzu\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.h\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfcvtzs\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfcvtzu\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfcvtzs\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfcvtzu\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfcvtzs\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.d\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfcvtzu\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.d\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fdiv_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fdiv_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fdiv_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fdiv_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,47 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ #define c_i c[i]
+ 
+ #define DIV(A, B) A / B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS, MERGE)		\
+   void								\
+   f_##TYPE0##_##TYPE1##_##RHS##_##MERGE (TYPE0 *__restrict out,	\
+ 					 TYPE0 *__restrict a,	\
+ 					 TYPE0 *__restrict b,	\
+ 					 TYPE0 *__restrict c,	\
+ 					 TYPE1 *__restrict p)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i], (TYPE0)RHS) : MERGE;		\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)	 \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, a_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, c_i)
+ 
+ TEST_ALL (DIV, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (DIV, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (DIV, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 7 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfdivr\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfdiv\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfdivr\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfdiv\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmaxnm_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmaxnm_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmaxnm_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmaxnm_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,53 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-signed-zeros -ffinite-math-only -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ #define c_i c[i]
+ 
+ #define MAX(A, B) (A > B) ? A : B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS, MERGE)		\
+   void								\
+   f_##TYPE0##_##TYPE1##_##RHS##_##MERGE (TYPE0 *__restrict out,	\
+ 					 TYPE0 *__restrict a,	\
+ 					 TYPE0 *__restrict b,	\
+ 					 TYPE0 *__restrict c,	\
+ 					 TYPE1 *__restrict p)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i], (TYPE0)RHS) : MERGE;		\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)     \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, a_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, c_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0, a_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0, b_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, a_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, b_i)
+ 
+ TEST_ALL (MAX, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (MAX, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (MAX, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 13 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fminnm_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fminnm_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fminnm_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fminnm_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,53 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-signed-zeros -ffinite-math-only -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ #define c_i c[i]
+ 
+ #define MIN(A, B) (A < B) ? A : B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS, MERGE)		\
+   void								\
+   f_##TYPE0##_##TYPE1##_##RHS##_##MERGE (TYPE0 *__restrict out,	\
+ 					 TYPE0 *__restrict a,	\
+ 					 TYPE0 *__restrict b,	\
+ 					 TYPE0 *__restrict c,	\
+ 					 TYPE1 *__restrict p)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i], (TYPE0)RHS) : MERGE;		\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)     \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, a_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, c_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0, a_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0, b_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, a_i)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, b_i)
+ 
+ TEST_ALL (MIN, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (MIN, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (MIN, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 13 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmul_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmul_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmul_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fmul_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,50 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ #define c_i c[i]
+ #define imm_p5 0.5
+ 
+ #define MUL(A, B) A * B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS, MERGE)		\
+   void								\
+   f_##TYPE0##_##TYPE1##_##RHS##_##MERGE (TYPE0 *__restrict out,	\
+ 					 TYPE0 *__restrict a,	\
+ 					 TYPE0 *__restrict b,	\
+ 					 TYPE0 *__restrict c,	\
+ 					 TYPE1 *__restrict p)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i], (TYPE0)RHS) : MERGE;		\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)	 \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, a_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, c_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, imm_p5, a_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, imm_p5, b_i)
+ 
+ TEST_ALL (MUL, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (MUL, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (MUL, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 10 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 10 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 10 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fneg_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fneg_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fneg_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fneg_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,39 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ 
+ #define NEG(X) -X
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, MERGE)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##MERGE (TYPE1 *__restrict p,	\
+     					TYPE0 *__restrict out,	\
+ 					TYPE0 *__restrict a,	\
+ 					TYPE0 *__restrict b)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i]) : MERGE;			\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)
+ 
+ TEST_ALL (NEG, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (NEG, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (NEG, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfneg\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfneg\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, MERGE)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##MERGE (TYPE1 *__restrict p,	\
+     					TYPE0 *__restrict out,	\
+ 					TYPE0 *__restrict a,	\
+ 					TYPE0 *__restrict b)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i]) : MERGE;			\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)
+ 
+ TEST_ALL (__builtin_roundf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_roundf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_roundf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrinta\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfrinta\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinta_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,18 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -mtune=generic -ftree-vectorize" } */
+ 
+ #include "unpacked_cond_frinta_1.c"
+ 
+ /* Test that we don't drop SELs without -fno-trapping-math.  */
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-9]+\.d} 4 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrinta\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfrinta\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tsel\t} 6 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinti_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinti_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinti_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frinti_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, MERGE)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##MERGE (TYPE1 *__restrict p,	\
+     					TYPE0 *__restrict out,	\
+ 					TYPE0 *__restrict a,	\
+ 					TYPE0 *__restrict b)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i]) : MERGE;			\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)
+ 
+ TEST_ALL (__builtin_nearbyintf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_nearbyintf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_nearbyintf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrinti\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfrinti\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintm_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintm_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintm_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintm_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, MERGE)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##MERGE (TYPE1 *__restrict p,	\
+     					TYPE0 *__restrict out,	\
+ 					TYPE0 *__restrict a,	\
+ 					TYPE0 *__restrict b)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i]) : MERGE;			\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)
+ 
+ TEST_ALL (__builtin_floorf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_floorf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_floorf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfrintm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintp_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintp_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintp_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintp_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, MERGE)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##MERGE (TYPE1 *__restrict p,	\
+     					TYPE0 *__restrict out,	\
+ 					TYPE0 *__restrict a,	\
+ 					TYPE0 *__restrict b)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i]) : MERGE;			\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)
+ 
+ TEST_ALL (__builtin_ceilf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_ceilf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_ceilf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintp\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfrintp\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintx_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintx_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintx_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintx_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, MERGE)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##MERGE (TYPE1 *__restrict p,	\
+     					TYPE0 *__restrict out,	\
+ 					TYPE0 *__restrict a,	\
+ 					TYPE0 *__restrict b)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i]) : MERGE;			\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)
+ 
+ TEST_ALL (__builtin_rintf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_rintf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_rintf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfrintx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintz_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintz_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintz_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_frintz_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, MERGE)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##MERGE (TYPE1 *__restrict p,	\
+     					TYPE0 *__restrict out,	\
+ 					TYPE0 *__restrict a,	\
+ 					TYPE0 *__restrict b)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i]) : MERGE;			\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, a_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)
+ 
+ TEST_ALL (__builtin_truncf16, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (__builtin_truncf16, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (__builtin_truncf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintz\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfrintz\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fsubr_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fsubr_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fsubr_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_cond_fsubr_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,56 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include <stdint.h>
+ 
+ #define a_i a[i]
+ #define b_i b[i]
+ #define c_i c[i]
+ #define imm_p5 0.5
+ 
+ #define SUBR(A, B) B - A
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS, MERGE)		\
+   void								\
+   f_##TYPE0##_##TYPE1##_##RHS##_##MERGE (TYPE0 *__restrict out,	\
+ 					 TYPE0 *__restrict a,	\
+ 					 TYPE0 *__restrict b,	\
+ 					 TYPE0 *__restrict c,	\
+ 					 TYPE1 *__restrict p)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       out[i] = p[i] ? FN (a[i], (TYPE0)RHS) : MERGE;		\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)	 \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, a_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, c_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, a_i)	 \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1, b_i)	 \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, imm_p5, a_i) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, imm_p5, b_i)
+ 
+ TEST_ALL (SUBR, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (SUBR, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (SUBR, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 13 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 13 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 6 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 4 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 4 } } */
+ 
+ /* { dg-final { scan-assembler-not {\tsel\t} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fabs_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fabs_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fabs_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fabs_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT)		\
+   void							\
+   f_##FN##_##TYPE0##_##TYPE1 (TYPE1 *__restrict out,	\
+ 			      TYPE0 *__restrict a,      \
+ 			      TYPE0 *__restrict b)      \
+   {							\
+     for (unsigned int i = 0; i < COUNT; i++)		\
+       if (FN (a[i]) > b[i])				\
+ 	out[i] = 3;					\
+   }
+ 
+ TEST_FN (__builtin_fabsf16, _Float16, uint64_t, 32)
+ 
+ TEST_FN (__builtin_fabsf16, _Float16, uint32_t, 64)
+ 
+ TEST_FN (__builtin_fabsf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfabs\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfabs\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,52 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048" } */
+ 
+ #include <stdint.h>
+ 
+ #define ADD(A, B)  A + B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, NAME, RHS)		\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##NAME (TYPE1 *__restrict out,	\
+ 				       TYPE0 *__restrict a,     \
+ 				       TYPE0 *__restrict b,     \
+                                        TYPE0 *__restrict c)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       if (FN (a[i], (TYPE0)RHS) > c[i])				\
+ 	out[i] = 3;						\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)      \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i, b[i]) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, p5, 0.5)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, np5, -0.5) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, one, 1)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, none, -1)
+ 
+ TEST_ALL (ADD, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (ADD, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (ADD, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 5 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 10 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 11 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 11 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 11 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fadd_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do compile }*/
+ /* { dg-options "-O2 -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include "unpacked_fadd_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 12 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 11 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 11 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 11 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.s, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.h, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,38 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048" } */
+ 
+ #include <stdint.h>
+ 
+ #define b_i b[i]
+ #define DIV(A, B) A / B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##RHS (TYPE1 *__restrict out,	\
+ 				      TYPE0 *__restrict a,      \
+ 				      TYPE0 *__restrict b,      \
+                                       TYPE0 *__restrict c)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       if (FN (a[i], (TYPE0)RHS) > c[i])				\
+ 	out[i] = 3;						\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)
+ 
+ TEST_ALL (DIV, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (DIV, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (DIV, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 1 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfdivr?\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfdivr?\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include "unpacked_fdiv_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfdivr?\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfdivr?\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_3.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_3.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_3.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fdiv_3.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-Ofast -moverride=sve_width=2048 -mlow-precision-div" } */
+ 
+ #include "unpacked_fdiv_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tfrecpe\tz[0-9]+\.h} } } */
+ /* { dg-final { scan-assembler-not {\tfrecps\tz[0-9]+\.h} } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfrecpe\tz[0-9]+\.s} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrecps\tz[0-9]+\.s} 1 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,45 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fno-signed-zeros -ffinite-math-only -moverride=sve_width=2048" } */
+ 
+ #include <stdint.h>
+ 
+ #define b_i b[i]
+ #define MAX(A, B) (A > B) ? A : B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##RHS (TYPE1 *__restrict out,	\
+ 				      TYPE0 *__restrict a,      \
+ 				      TYPE0 *__restrict b,      \
+                                       TYPE0 *__restrict c)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       if (c[i] = FN (a[i], RHS))				\
+ 	out[i] = 3;						\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1)
+ 
+ TEST_ALL (MAX, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (MAX, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (MAX, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 6 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 4 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 4 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 4 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmaxnm_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fno-signed-zeros -ffinite-math-only -fno-trapping-math -moverride=sve_width=2048" } */
+ 
+ #include "unpacked_fmaxnm_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 9 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 4 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 4 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 4 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,46 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fno-signed-zeros -ffinite-math-only -moverride=sve_width=2048" } */
+ 
+ #include <stdint.h>
+ 
+ #define b_i b[i]
+ #define MIN(A, B) (A < B) ? A : B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##RHS (TYPE1 *__restrict out,	\
+ 				      TYPE0 *__restrict a,      \
+ 				      TYPE0 *__restrict b,      \
+                                       TYPE0 *__restrict c)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       if (c[i] = FN (a[i], RHS) )				\
+ 	out[i] = 3;						\
+   }
+ 
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT) \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 0)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1)
+ 
+ TEST_ALL (MIN, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (MIN, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (MIN, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 6 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 4 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 4 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 4 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fminnm_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fno-signed-zeros -ffinite-math-only -fno-trapping-math -moverride=sve_width=2048" } */
+ 
+ #include "unpacked_fminnm_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 9 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 4 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 4 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 4 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.0\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.0\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,43 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048" } */
+ 
+ #include <stdint.h>
+ 
+ #define b_i b[i]
+ #define immp5 0.5
+ #define MUL(A, B) A * B
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##RHS (TYPE1 *__restrict out,	\
+ 				      TYPE0 *__restrict a,      \
+ 				      TYPE0 *__restrict b,      \
+                                       TYPE0 *__restrict c)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       if (FN (a[i], (TYPE0)RHS) > c[i])				\
+ 	out[i] = 3;						\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, immp5)
+ 
+ TEST_ALL (MUL, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (MUL, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (MUL, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 4 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 5 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 5 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 5 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fmul_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,18 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include "unpacked_fmul_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 5 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 5 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 5 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.h, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfmul\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fneg_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fneg_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fneg_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fneg_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,30 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define NEG(X) -X
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT)		\
+   void							\
+   f_##FN##_##TYPE0##_##TYPE1 (TYPE1 *__restrict out,	\
+ 			      TYPE0 *__restrict a,      \
+ 			      TYPE0 *__restrict b)      \
+   {							\
+     for (unsigned int i = 0; i < COUNT; i++)		\
+       if (FN (a[i]) > b[i])				\
+ 	out[i] = 3;					\
+   }
+ 
+ TEST_FN (NEG, _Float16, uint64_t, 32)
+ 
+ TEST_FN (NEG, _Float16, uint32_t, 64)
+ 
+ TEST_FN (NEG, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfneg\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfneg\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT)		\
+   void							\
+   f_##FN##_##TYPE0##_##TYPE1 (TYPE1 *__restrict out,	\
+ 			      TYPE0 *__restrict a,      \
+ 			      TYPE0 *__restrict b)      \
+   {							\
+     for (unsigned int i = 0; i < COUNT; i++)		\
+       if (FN (a[i]) > b[i])				\
+ 	out[i] = 3;					\
+   }
+ 
+ TEST_FN (__builtin_roundf16, _Float16, uint64_t, 32)
+ 
+ TEST_FN (__builtin_roundf16, _Float16, uint32_t, 64)
+ 
+ TEST_FN (__builtin_roundf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 1 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrinta\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrinta\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinta_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include "unpacked_frinta_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrinta\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrinta\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT)		\
+   void							\
+   f_##FN##_##TYPE0##_##TYPE1 (TYPE1 *__restrict out,	\
+ 			      TYPE0 *__restrict a,      \
+ 			      TYPE0 *__restrict b)      \
+   {							\
+     for (unsigned int i = 0; i < COUNT; i++)		\
+       if (FN (a[i]) > b[i])				\
+ 	out[i] = 3;					\
+   }
+ 
+ TEST_FN (__builtin_nearbyintf16, _Float16, uint64_t, 32)
+ 
+ TEST_FN (__builtin_nearbyintf16, _Float16, uint32_t, 64)
+ 
+ TEST_FN (__builtin_nearbyintf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 1 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrinti\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrinti\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frinti_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include "unpacked_frinti_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrinti\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrinti\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT)		\
+   void							\
+   f_##FN##_##TYPE0##_##TYPE1 (TYPE1 *__restrict out,	\
+ 			      TYPE0 *__restrict a,      \
+ 			      TYPE0 *__restrict b)      \
+   {							\
+     for (unsigned int i = 0; i < COUNT; i++)		\
+       if (FN (a[i]) > b[i])				\
+ 	out[i] = 3;					\
+   }
+ 
+ TEST_FN (__builtin_floorf16, _Float16, uint64_t, 32)
+ 
+ TEST_FN (__builtin_floorf16, _Float16, uint32_t, 64)
+ 
+ TEST_FN (__builtin_floorf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 1 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrintm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintm_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include "unpacked_frintm_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrintm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT)		\
+   void							\
+   f_##FN##_##TYPE0##_##TYPE1 (TYPE1 *__restrict out,	\
+ 			      TYPE0 *__restrict a,      \
+ 			      TYPE0 *__restrict b)      \
+   {							\
+     for (unsigned int i = 0; i < COUNT; i++)		\
+       if (FN (a[i]) > b[i])				\
+ 	out[i] = 3;					\
+   }
+ 
+ TEST_FN (__builtin_ceilf16, _Float16, uint64_t, 32)
+ 
+ TEST_FN (__builtin_ceilf16, _Float16, uint32_t, 64)
+ 
+ TEST_FN (__builtin_ceilf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 1 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintp\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrintp\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintp_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include "unpacked_frintp_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintp\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrintp\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT)		\
+   void							\
+   f_##FN##_##TYPE0##_##TYPE1 (TYPE1 *__restrict out,	\
+ 			      TYPE0 *__restrict a,      \
+ 			      TYPE0 *__restrict b)      \
+   {							\
+     for (unsigned int i = 0; i < COUNT; i++)		\
+       if (FN (a[i]) > b[i])				\
+ 	out[i] = 3;					\
+   }
+ 
+ TEST_FN (__builtin_rintf16, _Float16, uint64_t, 32)
+ 
+ TEST_FN (__builtin_rintf16, _Float16, uint32_t, 64)
+ 
+ TEST_FN (__builtin_rintf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 1 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrintx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintx_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include "unpacked_frintx_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrintx\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize" } */
+ 
+ #include <stdint.h>
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT)		\
+   void							\
+   f_##FN##_##TYPE0##_##TYPE1 (TYPE1 *__restrict out,	\
+ 			      TYPE0 *__restrict a,      \
+ 			      TYPE0 *__restrict b)      \
+   {							\
+     for (unsigned int i = 0; i < COUNT; i++)		\
+       if (FN (a[i]) > b[i])				\
+ 	out[i] = 3;					\
+   }
+ 
+ TEST_FN (__builtin_truncf16, _Float16, uint64_t, 32)
+ 
+ TEST_FN (__builtin_truncf16, _Float16, uint32_t, 64)
+ 
+ TEST_FN (__builtin_truncf32, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 1 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintz\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrintz\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_frintz_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048 -ftree-vectorize -fno-trapping-math" } */
+ 
+ #include "unpacked_frintz_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 3 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 2 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 2 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfrintz\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfrintz\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_1.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,46 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -moverride=sve_width=2048" } */
+ 
+ #include <stdint.h>
+ 
+ #define b_i b[i]
+ #define immp5 0.5
+ #define SUBR(A, B) B - A
+ 
+ #define TEST_FN(FN, TYPE0, TYPE1, COUNT, RHS)			\
+   void								\
+   f_##FN##_##TYPE0##_##TYPE1##_##RHS (TYPE1 *__restrict out,	\
+ 				      TYPE0 *__restrict a,      \
+ 				      TYPE0 *__restrict b,      \
+                                       TYPE0 *__restrict c)	\
+   {								\
+     for (unsigned int i = 0; i < COUNT; i++)			\
+       if (FN (a[i], (TYPE0)RHS) > c[i])				\
+ 	out[i] = 3;						\
+   }
+ 
+ #define TEST_ALL(FN, TYPE0, TYPE1, COUNT)   \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, b_i)    \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, immp5)  \
+   TEST_FN (FN, TYPE0, TYPE1, COUNT, 1)
+ 
+ TEST_ALL (SUBR, _Float16, uint64_t, 32)
+ 
+ TEST_ALL (SUBR, _Float16, uint32_t, 64)
+ 
+ TEST_ALL (SUBR, float, uint64_t, 32)
+ 
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s} 3 } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.d} 6 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 7 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfsubr?\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfsubr?\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_2.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fsubr_2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile }*/
+ /* { dg-options "-O2 -moverride=sve_width=2048 -fno-trapping-math" } */
+ 
+ #include "unpacked_fsubr_1.c"
+ 
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */
+ /* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */
+ /* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b} 6 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 7 } } */
+ /* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 7 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.s, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0.5\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1.0\n} 1 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tfsub\tz[0-9]+\.h, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0.5\n} 2 } } */
+ /* { dg-final { scan-assembler-times {\tfsubr\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1.0\n} 2 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/vec-set-zero.c gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/vec-set-zero.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/aarch64/vec-set-zero.c	Sun Jul 20 22:32:23 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/aarch64/vec-set-zero.c	Sun Jul 27 22:32:13 2025
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O2" } */
  
  #include "arm_neon.h"
  
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-Os" } */
  
  #include "arm_neon.h"
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/i386/asm-hard-reg-1.c gcc-16-20250727/gcc/testsuite/gcc.target/i386/asm-hard-reg-1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/i386/asm-hard-reg-1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/i386/asm-hard-reg-1.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,80 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2" } */
+ 
+ void
+ test (void)
+ {
+   int x, y;
+ 
+   __asm__ __volatile__ ("" : "=a" (x), "={rbx}" (y));
+   __asm__ __volatile__ ("" : "=a" (x), "={rax}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=a" (x) : "{rax}" (y));
+   __asm__ __volatile__ ("" : "=&a" (x) : "{rax}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "a" (x), "{rax}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "={rbx}" (x), "=a" (y));
+   __asm__ __volatile__ ("" : "={rax}" (x), "=a" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "={rax}" (x) : "a" (y));
+   __asm__ __volatile__ ("" : "=&{rax}" (x) : "a" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "{rax}" (x), "a" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "=b" (x), "={rax}" (y));
+   __asm__ __volatile__ ("" : "=b" (x), "={rbx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=b" (x) : "{rbx}" (y));
+   __asm__ __volatile__ ("" : "=&b" (x) : "{rbx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "b" (x), "{rbx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "={rax}" (x), "=b" (y));
+   __asm__ __volatile__ ("" : "={rbx}" (x), "=b" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "={rbx}" (x) : "b" (y));
+   __asm__ __volatile__ ("" : "=&{rbx}" (x) : "b" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "{rbx}" (x), "b" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "=c" (x), "={rax}" (y));
+   __asm__ __volatile__ ("" : "=c" (x), "={rcx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=c" (x) : "{rcx}" (y));
+   __asm__ __volatile__ ("" : "=&c" (x) : "{rcx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "c" (x), "{rcx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "={rax}" (x), "=c" (y));
+   __asm__ __volatile__ ("" : "={rcx}" (x), "=c" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "={rcx}" (x) : "c" (y));
+   __asm__ __volatile__ ("" : "=&{rcx}" (x) : "c" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "{rcx}" (x), "c" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "=d" (x), "={rax}" (y));
+   __asm__ __volatile__ ("" : "=d" (x), "={rdx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=d" (x) : "{rdx}" (y));
+   __asm__ __volatile__ ("" : "=&d" (x) : "{rdx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "d" (x), "{rdx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "={rax}" (x), "=d" (y));
+   __asm__ __volatile__ ("" : "={rdx}" (x), "=d" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "={rdx}" (x) : "d" (y));
+   __asm__ __volatile__ ("" : "=&{rdx}" (x) : "d" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "{rdx}" (x), "d" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "=S" (x), "={rax}" (y));
+   __asm__ __volatile__ ("" : "=S" (x), "={rsi}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=S" (x) : "{rsi}" (y));
+   __asm__ __volatile__ ("" : "=&S" (x) : "{rsi}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "S" (x), "{rsi}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "={rax}" (x), "=S" (y));
+   __asm__ __volatile__ ("" : "={rsi}" (x), "=S" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "={rsi}" (x) : "S" (y));
+   __asm__ __volatile__ ("" : "=&{rsi}" (x) : "S" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "{rsi}" (x), "S" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "=D" (x), "={rax}" (y));
+   __asm__ __volatile__ ("" : "=D" (x), "={rdi}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=D" (x) : "{rdi}" (y));
+   __asm__ __volatile__ ("" : "=&D" (x) : "{rdi}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "D" (x), "{rdi}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "={rax}" (x), "=D" (y));
+   __asm__ __volatile__ ("" : "={rdi}" (x), "=D" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "={rdi}" (x) : "D" (y));
+   __asm__ __volatile__ ("" : "=&{rdi}" (x) : "D" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "{rdi}" (x), "D" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/i386/asm-hard-reg-2.c gcc-16-20250727/gcc/testsuite/gcc.target/i386/asm-hard-reg-2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/i386/asm-hard-reg-2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/i386/asm-hard-reg-2.c	Sun Jul 27 22:32:13 2025
***************
*** 0 ****
--- 1,43 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2" } */
+ 
+ void
+ test (void)
+ {
+   int x, y, yy;
+ #ifdef __x86_64__
+   int z __attribute__ ((mode (TI)));
+ #else
+   long z;
+ #endif
+ 
+   __asm__ __volatile__ ("" : "=A" (z), "={rbx}" (y));
+   __asm__ __volatile__ ("" : "=A" (z), "={rax}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=A" (z), "={rdx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=A" (z) : "{rax}" (y));
+   __asm__ __volatile__ ("" : "=A" (z) : "{rdx}" (y));
+   __asm__ __volatile__ ("" : "=&A" (z) : "{rax}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=&A" (z) : "{rdx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "A" (z), "{rax}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "A" (z), "{rdx}" (y)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   __asm__ __volatile__ ("" : "={rbx}" (y), "=A" (z));
+   __asm__ __volatile__ ("" : "={rax}" (y), "=A" (z)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "={rdx}" (y), "=A" (z)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "={rax}" (y) : "A" (z));
+   __asm__ __volatile__ ("" : "={rdx}" (y) : "A" (z));
+   __asm__ __volatile__ ("" : "=&{rax}" (y) : "A" (z)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=&{rdx}" (y) : "A" (z)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "{rax}" (y), "A" (z)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" :: "{rdx}" (y), "A" (z)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ 
+   /* Note, we do not error for */
+   __asm__ __volatile__ ("" : "=A" (x), "={rax}" (y));
+   __asm__ __volatile__ ("" : "=A" (x), "={rdx}" (y));
+   /* This is due to how constraint A is implemented.  RA has the freedom to
+      choose between rax or rdx for operand 0 since x fits into a single
+      register and does not require a register pair.  Of course, we error out if
+      rax and rdx are taken by other operands as in the following:  */
+   __asm__ __volatile__ ("" : "=A" (x), "={rax}" (y), "={rdx}" (yy)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+   __asm__ __volatile__ ("" : "=A" (x), "={rdx}" (y), "={rax}" (yy)); /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c gcc-16-20250727/gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/powerpc/vsx-builtin-7.c	Sun Jul 27 22:32:14 2025
***************
*** 1,8 ****
  /* { dg-do compile { target { powerpc*-*-* } } } */
  /* { dg-skip-if "" { powerpc*-*-darwin* } } */
! /* { dg-options "-O2 -mdejagnu-cpu=power7 -fno-inline-functions" } */
  /* { dg-require-effective-target powerpc_vsx } */
  
  /* Test simple extract/insert/slat operations.  Make sure all types are
     supported with various options.  */
  
--- 1,16 ----
  /* { dg-do compile { target { powerpc*-*-* } } } */
  /* { dg-skip-if "" { powerpc*-*-darwin* } } */
! /* { dg-options "-O2 -mdejagnu-cpu=power7 -fno-inline-functions -fno-ipa-icf" } */
  /* { dg-require-effective-target powerpc_vsx } */
  
+ /* PR testsuite/119382
+    Note: Added -fno-ipa-icf to disable Interprocedural Identical Code
+    Folding (ICF). Without this, insert_di_0_v2 is merged with insert_di_0
+    due to improved alias analysis introduced in commit r15-7961-gdc47161c1f32c3.
+    This results in the compiler replacing insert_di_0_v2 with a tail call to
+    insert_di_0, altering expected test behavior. Disabling ICF ensures correct
+    execution of the test.  */
+ 
  /* Test simple extract/insert/slat operations.  Make sure all types are
     supported with various options.  */
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c	Sun Jul 27 22:32:14 2025
***************
*** 1,7 ****
  /* Verify proper errors are generated for conflicted interrupt type.  */
  /* { dg-do compile } */
  /* { dg-options "" } */
! void __attribute__ ((interrupt ("user")))
  foo(void);
  
  void __attribute__ ((interrupt ("machine")))
--- 1,7 ----
  /* Verify proper errors are generated for conflicted interrupt type.  */
  /* { dg-do compile } */
  /* { dg-options "" } */
! void __attribute__ ((interrupt ("supervisor")))
  foo(void);
  
  void __attribute__ ((interrupt ("machine")))
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,11 ----
+ /* Verify the return instruction is mnret.  */
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv32gc_smrnmi" { target { rv32 } } } */
+ /* { dg-options "-march=rv64gc_smrnmi" { target { rv64 } } } */
+ 
+ void __attribute__ ((interrupt ("rnmi")))
+ foo (void)
+ {
+ }
+ 
+ /* { dg-final { scan-assembler {\mmnret} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/interrupt-umode.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/interrupt-umode.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/interrupt-umode.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/interrupt-umode.c	Thu Jan  1 00:00:00 1970
***************
*** 1,8 ****
- /* Verify the return instruction is mret.  */
- /* { dg-do compile } */
- /* { dg-options "" } */
- void __attribute__ ((interrupt ("user")))
- foo (void)
- {
- }
- /* { dg-final { scan-assembler {\muret} } } */
--- 0 ----
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-6.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-6.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-6.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/repeat-6.c	Sun Jul 27 22:32:14 2025
*************** f_vnx128qi (int8_t *out)
*** 72,78 ****
    *(vnx128qi *) out = v;
  }
  
! /* { dg-final { scan-assembler-times {vmv.v.x\tv[0-9]+,\s*[a-x0-9]+} 6 } } */
  /* { dg-final { scan-assembler-times {slli\t[a-x0-9]+,\s*[a-x0-9]+,\s*8} 6 } } */
  /* { dg-final { scan-assembler-times {or\t[a-x0-9]+,\s*[a-x0-9]+,\s*[a-x0-9]+} 6 } } */
  /* { dg-final { scan-assembler-times {vslide1down\.vx\tv[0-9]+,\s*v[0-9]+,\s*[a-x0-9]+} 1 } } */
--- 72,78 ----
    *(vnx128qi *) out = v;
  }
  
! /* { dg-final { scan-assembler-times {vmv.v.x\tv[0-9]+,\s*[a-x0-9]+} 7 } } */
  /* { dg-final { scan-assembler-times {slli\t[a-x0-9]+,\s*[a-x0-9]+,\s*8} 6 } } */
  /* { dg-final { scan-assembler-times {or\t[a-x0-9]+,\s*[a-x0-9]+,\s*[a-x0-9]+} 6 } } */
  /* { dg-final { scan-assembler-times {vslide1down\.vx\tv[0-9]+,\s*v[0-9]+,\s*[a-x0-9]+} 1 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  #include "vf_mulop_data.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmacc-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmacc-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmacc-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmacc-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmsac-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmsac-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmsac-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwmsac-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmacc-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmacc-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmacc-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmacc-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmsac-run-1-f16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmsac-run-1-f16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmsac-run-1-f16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmsac-run-1-f16.c	Sun Jul 27 22:32:14 2025
***************
*** 1,5 ****
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  
--- 1,9 ----
  /* { dg-do run { target { riscv_v } } } */
! /* { dg-require-effective-target riscv_v_ok } */
! /* { dg-require-effective-target riscv_zvfh } */
! /* { dg-add-options "riscv_v" } */
! /* { dg-add-options "riscv_zvfh" } */
! /* { dg-additional-options "--param=fpr2vr-cost=0" } */
  
  #include "vf_mulop.h"
  
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-times {vmin.vx} 2 } } */
  /* { dg-final { scan-assembler-times {vsadd.vx} 1 } } */
  /* { dg-final { scan-assembler-times {vssub.vx} 1 } } */
+ /* { dg-final { scan-assembler-times {vaadd.vx} 1 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-times {vmin.vx} 2 } } */
  /* { dg-final { scan-assembler-times {vsadd.vx} 1 } } */
  /* { dg-final { scan-assembler-times {vssub.vx} 1 } } */
+ /* { dg-final { scan-assembler-times {vaadd.vx} 1 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-times {vmin.vx} 2 } } */
  /* { dg-final { scan-assembler-times {vsadd.vx} 1 } } */
  /* { dg-final { scan-assembler-times {vssub.vx} 1 } } */
+ /* { dg-final { scan-assembler-times {vaadd.vx} 1 { target { no-opts "-O3 -mrvv-vector-bits=zvl -mrvv-max-lmul=m2" "-O3 -mrvv-vector-bits=zvl -mrvv-max-lmul=m4" } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-times {vmin.vx} 2 } } */
  /* { dg-final { scan-assembler-times {vsadd.vx} 1 } } */
  /* { dg-final { scan-assembler-times {vssub.vx} 1 } } */
+ /* { dg-final { scan-assembler-times {vaadd.vx} 1 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u16.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-times {vminu.vx} 2 } } */
  /* { dg-final { scan-assembler-times {vsaddu.vx} 1 } } */
  /* { dg-final { scan-assembler-times {vssubu.vx} 1 } } */
+ /* { dg-final { scan-assembler-times {vaaddu.vx} 1 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u32.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-times {vminu.vx} 2 } } */
  /* { dg-final { scan-assembler-times {vsaddu.vx} 1 } } */
  /* { dg-final { scan-assembler-times {vssubu.vx} 1 } } */
+ /* { dg-final { scan-assembler-times {vaaddu.vx} 1 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u64.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-times {vminu.vx} 2 } } */
  /* { dg-final { scan-assembler-times {vsaddu.vx} 1 } } */
  /* { dg-final { scan-assembler-times {vssubu.vx} 1 } } */
+ /* { dg-final { scan-assembler-times {vaaddu.vx} 1 { target { no-opts "-O3 -mrvv-vector-bits=zvl -mrvv-max-lmul=m2" "-O3 -mrvv-vector-bits=zvl -mrvv-max-lmul=m4" } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-u8.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-times {vminu.vx} 2 } } */
  /* { dg-final { scan-assembler-times {vsaddu.vx} 1 } } */
  /* { dg-final { scan-assembler-times {vssubu.vx} 1 } } */
+ /* { dg-final { scan-assembler-times {vaaddu.vx} 1 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-not {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler-not {vaadd.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-not {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler-not {vaadd.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-not {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler-not {vaadd.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-not {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler-not {vaadd.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u16.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-not {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u32.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-not {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u64.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-not {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-u8.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-not {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-not {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler-not {vaadd.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-not {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler-not {vaadd.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-not {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler-not {vaadd.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_SIGNED_0(T)
*** 20,22 ****
--- 20,23 ----
  /* { dg-final { scan-assembler-not {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler-not {vaadd.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u16.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-not {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u32.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-not {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u64.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-not {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-u8.c	Sun Jul 27 22:32:14 2025
*************** TEST_BINARY_VX_UNSIGNED_0(T)
*** 19,21 ****
--- 19,22 ----
  /* { dg-final { scan-assembler-not {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,43 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler {vsadd.vx} } } */
  /* { dg-final { scan-assembler {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { any-opts {
+      "-mrvv-vector-bits=scalable -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X4)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X4)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,42 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler {vsadd.vx} } } */
  /* { dg-final { scan-assembler {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { any-opts {
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,38 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { no-opts "-O3 -mrvv-vector-bits=zvl -mrvv-max-lmul=m2" "-O3 -mrvv-vector-bits=zvl -mrvv-max-lmul=m4" } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,42 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler {vsadd.vx} } } */
  /* { dg-final { scan-assembler {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { any-opts {
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u16.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler {vsaddu.vx} } } */
  /* { dg-final { scan-assembler {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u32.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X4)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X4)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 31,33 ****
--- 32,35 ----
  /* { dg-final { scan-assembler {vmaxu.vx} } } */
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u64.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} { target { no-opts "-O3 -mrvv-vector-bits=zvl -mrvv-max-lmul=m2" "-O3 -mrvv-vector-bits=zvl -mrvv-max-lmul=m4" } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-u8.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler {vsaddu.vx} } } */
  /* { dg-final { scan-assembler {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler-not {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,42 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler {vsadd.vx} } } */
  /* { dg-final { scan-assembler {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { any-opts {
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X4)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X4)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,42 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { no-opts {
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,38 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler-not {vaadd.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler-not {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,42 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler {vsadd.vx} } } */
  /* { dg-final { scan-assembler {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { no-opts {
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u16.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler {vsaddu.vx} } } */
  /* { dg-final { scan-assembler {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u32.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X4)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X4)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u64.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u8.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler {vsaddu.vx} } } */
  /* { dg-final { scan-assembler {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler-not {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,42 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler {vsadd.vx} } } */
  /* { dg-final { scan-assembler {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { any-opts {
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X4)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X4)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,42 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { any-opts {
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY)
  
  /* { dg-final { scan-assembler-not {vadd.vx} } } */
  /* { dg-final { scan-assembler-not {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,42 ----
  /* { dg-final { scan-assembler-not {vmin.vx} } } */
  /* { dg-final { scan-assembler-not {vsadd.vx} } } */
  /* { dg-final { scan-assembler-not {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { any-opts {
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 20,25 ****
--- 20,26 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler-not {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_F
*** 34,36 ****
--- 35,42 ----
  /* { dg-final { scan-assembler {vmin.vx} } } */
  /* { dg-final { scan-assembler {vsadd.vx} } } */
  /* { dg-final { scan-assembler {vssub.vx} } } */
+ /* { dg-final { scan-assembler {vaadd.vx} { target { any-opts {
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m1"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m2"
+      "-mrvv-vector-bits=zvl -mrvv-max-lmul=m4"
+    } } } } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u16.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u16.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler {vsaddu.vx} } } */
  /* { dg-final { scan-assembler {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u32.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u32.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X4)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X4)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X4)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u64.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u64.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY)
  
  /* { dg-final { scan-assembler-not {vadd.vx} } } */
  /* { dg-final { scan-assembler-not {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler-not {vminu.vx} } } */
  /* { dg-final { scan-assembler-not {vsaddu.vx} } } */
  /* { dg-final { scan-assembler-not {vssubu.vx} } } */
+ /* { dg-final { scan-assembler-not {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-u8.c	Sun Jul 27 22:32:14 2025
*************** DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_
*** 19,24 ****
--- 19,25 ----
  DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8)
  DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8)
+ DEF_VX_BINARY_CASE_3_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor, VX_BINARY_FUNC_BODY_X8)
  
  /* { dg-final { scan-assembler {vadd.vx} } } */
  /* { dg-final { scan-assembler {vsub.vx} } } */
*************** DEF_VX_BINARY_CASE_3_WRAP(T, SAT_U_SUB_F
*** 32,34 ****
--- 33,36 ----
  /* { dg-final { scan-assembler {vminu.vx} } } */
  /* { dg-final { scan-assembler {vsaddu.vx} } } */
  /* { dg-final { scan-assembler {vssubu.vx} } } */
+ /* { dg-final { scan-assembler {vaaddu.vx} } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+ 
+ #define VL        8
+ 
+ #include "vx-fixed-vxrm.h"
+ 
+ #define VT        vint16m1_t
+ #define T         int16_t
+ #define ELEM_SIZE 16
+ #define SUFFIX    i16
+ #define FUNC      __riscv_vaadd_vv_i16m1
+ 
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+ 
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+ /* { dg-final { scan-assembler-times {vaadd.vx} 4 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+ 
+ #define VL        4
+ 
+ #include "vx-fixed-vxrm.h"
+ 
+ #define VT        vint32m1_t
+ #define T         int32_t
+ #define ELEM_SIZE 32
+ #define SUFFIX    i32
+ #define FUNC      __riscv_vaadd_vv_i32m1
+ 
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+ 
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+ /* { dg-final { scan-assembler-times {vaadd.vx} 4 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+ 
+ #define VL        2
+ 
+ #include "vx-fixed-vxrm.h"
+ 
+ #define VT        vint64m1_t
+ #define T         int64_t
+ #define ELEM_SIZE 64
+ #define SUFFIX    i64
+ #define FUNC      __riscv_vaadd_vv_i64m1
+ 
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+ 
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+ /* { dg-final { scan-assembler-times {vaadd.vx} 4 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+ 
+ #define VL        16
+ 
+ #include "vx-fixed-vxrm.h"
+ 
+ #define VT        vint8m1_t
+ #define T         int8_t
+ #define ELEM_SIZE 8
+ #define SUFFIX    i8
+ #define FUNC      __riscv_vaadd_vv_i8m1
+ 
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+ 
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+ /* { dg-final { scan-assembler-times {vaadd.vx} 4 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u16.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u16.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+ 
+ #define VL        8
+ 
+ #include "vx-fixed-vxrm.h"
+ 
+ #define VT        vuint16m1_t
+ #define T         uint16_t
+ #define ELEM_SIZE 16
+ #define SUFFIX    u16
+ #define FUNC      __riscv_vaaddu_vv_u16m1
+ 
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+ 
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+ /* { dg-final { scan-assembler-times {vaaddu.vx} 4 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u32.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u32.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+ 
+ #define VL        4
+ 
+ #include "vx-fixed-vxrm.h"
+ 
+ #define VT        vuint32m1_t
+ #define T         uint32_t
+ #define ELEM_SIZE 32
+ #define SUFFIX    u32
+ #define FUNC      __riscv_vaaddu_vv_u32m1
+ 
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+ 
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+ /* { dg-final { scan-assembler-times {vaaddu.vx} 4 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u64.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u64.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+ 
+ #define VL        2
+ 
+ #include "vx-fixed-vxrm.h"
+ 
+ #define VT        vuint64m1_t
+ #define T         uint64_t
+ #define ELEM_SIZE 64
+ #define SUFFIX    u64
+ #define FUNC      __riscv_vaaddu_vv_u64m1
+ 
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+ 
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+ /* { dg-final { scan-assembler-times {vaaddu.vx} 4 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u8.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-u8.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+ 
+ #define VL        16
+ 
+ #include "vx-fixed-vxrm.h"
+ 
+ #define VT        vuint8m1_t
+ #define T         uint8_t
+ #define ELEM_SIZE 8
+ #define SUFFIX    u8
+ #define FUNC      __riscv_vaaddu_vv_u8m1
+ 
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+ DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+ 
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+ /* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+ /* { dg-final { scan-assembler-times {vaaddu.vx} 4 } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm.h gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm.h
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm.h	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,28 ----
+ #ifndef HAVE_DEFINED_VX_FIXED_VXRM_H
+ #define HAVE_DEFINED_VX_FIXED_VXRM_H
+ 
+ #include <riscv_vector.h>
+ 
+ int64_t go[VL] = {};
+ int64_t ga[VL] = {};
+ 
+ #define DEF_FIXED_BINARY_VX(VT, T, ES, SX, VXRM, FUNC)       \
+ void __attribute__((noinline))                               \
+ test_fixed_binary_##VT##_##VXRM##_##FUNC##_vx () {           \
+   VT a = __riscv_vle##ES##_v_##SX##m1((T *)ga, VL);          \
+   VT b;                                                      \
+   T *bp = (T *)&b;                                           \
+                                                              \
+   for (int i = 0; i < VL; i++) {                             \
+     bp[i] = 123;                                             \
+   }                                                          \
+                                                              \
+   VT d = FUNC (a, b, VXRM, VL);                              \
+                                                              \
+   __riscv_vse##ES##_v_##SX##m1((T *)&go, d, VL);             \
+ }
+ 
+ #define DEF_FIXED_BINARY_VX_WRAP(VT, T, ES, SX, VXRM, FUNC) \
+   DEF_FIXED_BINARY_VX(VT, T, ES, SX, VXRM, FUNC)
+ 
+ #endif
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h	Sun Jul 27 22:32:14 2025
***************
*** 3,8 ****
--- 3,16 ----
  
  #include <stdint.h>
  
+ #undef HAS_INT128
+ 
+ #if __riscv_xlen == 64
+ #define HAS_INT128
+ typedef unsigned __int128 uint128_t;
+ typedef signed __int128 int128_t;
+ #endif
+ 
  #define DEF_VX_BINARY_CASE_0(T, OP, NAME)                                \
  void                                                                     \
  test_vx_binary_##NAME##_##T##_case_0 (T * restrict out, T * restrict in, \
*************** DEF_SAT_S_SUB(int64_t, uint64_t, INT64_M
*** 340,376 ****
  #define SAT_S_SUB_FUNC(T) test_##T##_sat_sub
  #define SAT_S_SUB_FUNC_WRAP(T) SAT_S_SUB_FUNC(T)
  
! #define TEST_BINARY_VX_SIGNED_0(T)                         \
!   DEF_VX_BINARY_CASE_0_WRAP(T, +, add)                     \
!   DEF_VX_BINARY_CASE_0_WRAP(T, -, sub)                     \
!   DEF_VX_BINARY_REVERSE_CASE_0_WRAP(T, -, rsub)            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, &, and)                     \
!   DEF_VX_BINARY_CASE_0_WRAP(T, |, or)                      \
!   DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)                     \
!   DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)                     \
!   DEF_VX_BINARY_CASE_0_WRAP(T, /, div)                     \
!   DEF_VX_BINARY_CASE_0_WRAP(T, %, rem)                     \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_0_WARP(T), max)    \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_1_WARP(T), max)    \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_0_WARP(T), min)    \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_1_WARP(T), min)    \
!   DEF_VX_BINARY_CASE_2_WRAP(T, SAT_S_ADD_FUNC(T), sat_add) \
!   DEF_VX_BINARY_CASE_2_WRAP(T, SAT_S_SUB_FUNC(T), sat_sub) \
  
! #define TEST_BINARY_VX_UNSIGNED_0(T)                       \
!   DEF_VX_BINARY_CASE_0_WRAP(T, +, add)                     \
!   DEF_VX_BINARY_CASE_0_WRAP(T, -, sub)                     \
!   DEF_VX_BINARY_REVERSE_CASE_0_WRAP(T, -, rsub)            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, &, and)                     \
!   DEF_VX_BINARY_CASE_0_WRAP(T, |, or)                      \
!   DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)                     \
!   DEF_VX_BINARY_CASE_0_WRAP(T, /, div)                     \
!   DEF_VX_BINARY_CASE_0_WRAP(T, %, rem)                     \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_0_WARP(T), max)    \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_1_WARP(T), max)    \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_0_WARP(T), min)    \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_1_WARP(T), min)    \
!   DEF_VX_BINARY_CASE_2_WRAP(T, SAT_U_ADD_FUNC(T), sat_add) \
!   DEF_VX_BINARY_CASE_2_WRAP(T, SAT_U_SUB_FUNC(T), sat_sub) \
  
  #endif
--- 348,409 ----
  #define SAT_S_SUB_FUNC(T) test_##T##_sat_sub
  #define SAT_S_SUB_FUNC_WRAP(T) SAT_S_SUB_FUNC(T)
  
! #define DEF_AVG_FLOOR(NT, WT)        \
! NT                                   \
! test_##NT##_avg_floor(NT x, NT y)    \
! {                                    \
!   return (NT)(((WT)x + (WT)y) >> 1); \
! }
  
! DEF_AVG_FLOOR(uint8_t, uint16_t)
! DEF_AVG_FLOOR(uint16_t, uint32_t)
! DEF_AVG_FLOOR(uint32_t, uint64_t)
! 
! DEF_AVG_FLOOR(int8_t, int16_t)
! DEF_AVG_FLOOR(int16_t, int32_t)
! DEF_AVG_FLOOR(int32_t, int64_t)
! 
! #ifdef HAS_INT128
!   DEF_AVG_FLOOR(uint64_t, uint128_t)
!   DEF_AVG_FLOOR(int64_t, int128_t)
! #endif
! 
! #define AVG_FLOOR_FUNC(T)      test_##T##_avg_floor
! #define AVG_FLOOR_FUNC_WRAP(T) AVG_FLOOR_FUNC(T)
! 
! #define TEST_BINARY_VX_SIGNED_0(T)                                \
!   DEF_VX_BINARY_CASE_0_WRAP(T, +, add)                            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, -, sub)                            \
!   DEF_VX_BINARY_REVERSE_CASE_0_WRAP(T, -, rsub)                   \
!   DEF_VX_BINARY_CASE_0_WRAP(T, &, and)                            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, |, or)                             \
!   DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)                            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)                            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, /, div)                            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, %, rem)                            \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_0_WARP(T), max)           \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_1_WARP(T), max)           \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_0_WARP(T), min)           \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_1_WARP(T), min)           \
!   DEF_VX_BINARY_CASE_2_WRAP(T, SAT_S_ADD_FUNC(T), sat_add)        \
!   DEF_VX_BINARY_CASE_2_WRAP(T, SAT_S_SUB_FUNC(T), sat_sub)        \
!   DEF_VX_BINARY_CASE_2_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor) \
! 
! #define TEST_BINARY_VX_UNSIGNED_0(T)                              \
!   DEF_VX_BINARY_CASE_0_WRAP(T, +, add)                            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, -, sub)                            \
!   DEF_VX_BINARY_REVERSE_CASE_0_WRAP(T, -, rsub)                   \
!   DEF_VX_BINARY_CASE_0_WRAP(T, &, and)                            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, |, or)                             \
!   DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)                            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, /, div)                            \
!   DEF_VX_BINARY_CASE_0_WRAP(T, %, rem)                            \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_0_WARP(T), max)           \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MAX_FUNC_1_WARP(T), max)           \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_0_WARP(T), min)           \
!   DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_1_WARP(T), min)           \
!   DEF_VX_BINARY_CASE_2_WRAP(T, SAT_U_ADD_FUNC(T), sat_add)        \
!   DEF_VX_BINARY_CASE_2_WRAP(T, SAT_U_SUB_FUNC(T), sat_sub)        \
!   DEF_VX_BINARY_CASE_2_WRAP(T, AVG_FLOOR_FUNC_WRAP(T), avg_floor) \
  
  #endif
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h	Sun Jul 27 22:32:14 2025
*************** int64_t TEST_BINARY_DATA(int64_t, sat_su
*** 4906,4909 ****
--- 4906,5301 ----
    },
  };
  
+ uint8_t TEST_BINARY_DATA(uint8_t, avg_floor)[][3][N] =
+ {
+   {
+     { 0 },
+     {
+        2,  2,  2,  2,
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        4,  4,  4,  4,
+     },
+     {
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        2,  2,  2,  2,
+     },
+   },
+   {
+     { 127 },
+     {
+        127,  127,  127,  127,
+        128,  128,  128,  128,
+        255,  255,  255,  255,
+          1,    1,    1,    1,
+     },
+     {
+        127,  127,  127,  127,
+        127,  127,  127,  127,
+        191,  191,  191,  191,
+         64,   64,   64,   64,
+     },
+   },
+   {
+     { 255 },
+     {
+          0,    0,    0,    0,
+        255,  255,  255,  255,
+        254,  254,  254,  254,
+          1,    1,    1,    1,
+     },
+     {
+        127,  127,  127,  127,
+        255,  255,  255,  255,
+        254,  254,  254,  254,
+        128,  128,  128,  128,
+     },
+   },
+ };
+ 
+ uint16_t TEST_BINARY_DATA(uint16_t, avg_floor)[][3][N] =
+ {
+   {
+     { 0 },
+     {
+        2,  2,  2,  2,
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        4,  4,  4,  4,
+     },
+     {
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        2,  2,  2,  2,
+     },
+   },
+   {
+     { 32767 },
+     {
+        32767,  32767,  32767,  32767,
+        32768,  32768,  32768,  32768,
+        65535,  65535,  65535,  65535,
+            1,      1,      1,      1,
+     },
+     {
+        32767,  32767,  32767,  32767,
+        32767,  32767,  32767,  32767,
+        49151,  49151,  49151,  49151,
+        16384,  16384,  16384,  16384,
+     },
+   },
+   {
+     { 65535 },
+     {
+            0,      0,      0,      0,
+        65535,  65535,  65535,  65535,
+        65534,  65534,  65534,  65534,
+            1,      1,      1,      1,
+     },
+     {
+        32767,  32767,  32767,  32767,
+        65535,  65535,  65535,  65535,
+        65534,  65534,  65534,  65534,
+        32768,  32768,  32768,  32768,
+     },
+   },
+ };
+ 
+ uint32_t TEST_BINARY_DATA(uint32_t, avg_floor)[][3][N] =
+ {
+   {
+     { 0 },
+     {
+        2,  2,  2,  2,
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        4,  4,  4,  4,
+     },
+     {
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        2,  2,  2,  2,
+     },
+   },
+   {
+     { 2147483647 },
+     {
+        2147483647,  2147483647,  2147483647,  2147483647,
+        2147483648,  2147483648,  2147483648,  2147483648,
+        4294967295,  4294967295,  4294967295,  4294967295,
+                 1,           1,           1,           1,
+     },
+     {
+        2147483647,  2147483647,  2147483647,  2147483647,
+        2147483647,  2147483647,  2147483647,  2147483647,
+        3221225471,  3221225471,  3221225471,  3221225471,
+        1073741824,  1073741824,  1073741824,  1073741824,
+     },
+   },
+   {
+     { 4294967295 },
+     {
+                 0,           0,           0,           0,
+        4294967295,  4294967295,  4294967295,  4294967295,
+        4294967294,  4294967294,  4294967294,  4294967294,
+                 1,           1,           1,           1,
+     },
+     {
+        2147483647,  2147483647,  2147483647,  2147483647,
+        4294967295,  4294967295,  4294967295,  4294967295,
+        4294967294,  4294967294,  4294967294,  4294967294,
+        2147483648,  2147483648,  2147483648,  2147483648,
+     },
+   },
+ };
+ 
+ uint64_t TEST_BINARY_DATA(uint64_t, avg_floor)[][3][N] =
+ {
+   {
+     { 0 },
+     {
+        2,  2,  2,  2,
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        4,  4,  4,  4,
+     },
+     {
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        2,  2,  2,  2,
+     },
+   },
+   {
+     { 9223372036854775807ull },
+     {
+        9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,
+        9223372036854775808ull,  9223372036854775808ull,  9223372036854775808ull,  9223372036854775808ull,
+        18446744073709551615ull,  18446744073709551615ull,  18446744073709551615ull,  18446744073709551615ull,
+          1,    1,    1,    1,
+     },
+     {
+        9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,
+        9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,
+       13835058055282163711ull, 13835058055282163711ull, 13835058055282163711ull, 13835058055282163711ull,
+        4611686018427387904ull,  4611686018427387904ull,  4611686018427387904ull,  4611686018427387904ull,
+     },
+   },
+   {
+     { 18446744073709551615ull },
+     {
+          0,    0,    0,    0,
+        18446744073709551615ull,  18446744073709551615ull,  18446744073709551615ull,  18446744073709551615ull,
+        18446744073709551614ull,  18446744073709551614ull,  18446744073709551614ull,  18446744073709551614ull,
+          1,    1,    1,    1,
+     },
+     {
+        9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,
+       18446744073709551615ull, 18446744073709551615ull, 18446744073709551615ull, 18446744073709551615ull,
+       18446744073709551614ull, 18446744073709551614ull, 18446744073709551614ull, 18446744073709551614ull,
+        9223372036854775808ull,  9223372036854775808ull,  9223372036854775808ull,  9223372036854775808ull,
+     },
+   },
+ };
+ 
+ int8_t TEST_BINARY_DATA(int8_t, avg_floor)[][3][N] =
+ {
+   {
+     { 0 },
+     {
+        2,  2,  2,  2,
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        4,  4,  4,  4,
+     },
+     {
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        2,  2,  2,  2,
+     },
+   },
+   {
+     { 127 },
+     {
+        127,  127,  127,  127,
+       -128, -128, -128, -128,
+       -127, -127, -127, -127,
+          1,    1,    1,    1,
+     },
+     {
+        127,  127,  127,  127,
+         -1,   -1,   -1,   -1,
+          0,    0,    0,    0,
+         64,   64,   64,   64,
+     },
+   },
+   {
+     {-128 },
+     {
+          0,    0,    0,    0,
+       -128, -128, -128, -128,
+        126,  126,  126,  126,
+        127,  127,  127,  127,
+     },
+     {
+        -64,  -64,  -64,  -64,
+       -128, -128, -128, -128,
+         -1,   -1,   -1,   -1,
+         -1,   -1,   -1,   -1,
+     },
+   },
+ };
+ 
+ int16_t TEST_BINARY_DATA(int16_t, avg_floor)[][3][N] =
+ {
+   {
+     { 0 },
+     {
+        2,  2,  2,  2,
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        4,  4,  4,  4,
+     },
+     {
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        2,  2,  2,  2,
+     },
+   },
+   {
+     { 32767 },
+     {
+        32767,  32767,  32767,  32767,
+       -32768, -32768, -32768, -32768,
+       -32767, -32767, -32767, -32767,
+            1,      1,      1,      1,
+     },
+     {
+        32767,  32767,  32767,  32767,
+           -1,     -1,     -1,     -1,
+            0,      0,      0,      0,
+        16384,  16384,  16384,  16384,
+     },
+   },
+   {
+     {-32768 },
+     {
+            0,      0,      0,      0,
+       -32768, -32768, -32768, -32768,
+        32766,  32766,  32766,  32766,
+        32767,  32767,  32767,  32767,
+     },
+     {
+        -16384, -16384, -16384, -16384,
+        -32768, -32768, -32768, -32768,
+            -1,     -1,     -1,     -1,
+            -1,     -1,     -1,     -1,
+     },
+   },
+ };
+ 
+ int32_t TEST_BINARY_DATA(int32_t, avg_floor)[][3][N] =
+ {
+   {
+     { 0 },
+     {
+        2,  2,  2,  2,
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        4,  4,  4,  4,
+     },
+     {
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        2,  2,  2,  2,
+     },
+   },
+   {
+     { 2147483647 },
+     {
+        2147483647,  2147483647,  2147483647,  2147483647,
+       -2147483648, -2147483648, -2147483648, -2147483648,
+       -2147483647, -2147483647, -2147483647, -2147483647,
+                 1,           1,           1,           1,
+     },
+     {
+        2147483647,  2147483647,  2147483647,  2147483647,
+                -1,          -1,          -1,          -1,
+                 0,           0,           0,           0,
+        1073741824,  1073741824,  1073741824,  1073741824,
+     },
+   },
+   {
+     {-2147483648 },
+     {
+                 0,           0,           0,           0,
+       -2147483648, -2147483648, -2147483648, -2147483648,
+        2147483646,  2147483646,  2147483646,  2147483646,
+        2147483647,  2147483647,  2147483647,  2147483647,
+     },
+     {
+       -1073741824, -1073741824, -1073741824, -1073741824,
+       -2147483648, -2147483648, -2147483648, -2147483648,
+                -1,          -1,          -1,          -1,
+                -1,          -1,          -1,          -1,
+     },
+   },
+ };
+ 
+ int64_t TEST_BINARY_DATA(int64_t, avg_floor)[][3][N] =
+ {
+   {
+     { 0 },
+     {
+        2,  2,  2,  2,
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        4,  4,  4,  4,
+     },
+     {
+        1,  1,  1,  1,
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        2,  2,  2,  2,
+     },
+   },
+   {
+     { 9223372036854775807ull },
+     {
+        9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,
+       -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+       -9223372036854775807ull, -9223372036854775807ull, -9223372036854775807ull, -9223372036854775807ull,
+                             1,                       1,                       1,                       1,
+     },
+     {
+        9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,
+                            -1,                      -1,                      -1,                      -1,
+                             0,                       0,                       0,                       0,
+       4611686018427387904ull,   4611686018427387904ull,  4611686018427387904ull,  4611686018427387904ull,
+     },
+   },
+   {
+     {-9223372036854775808ull },
+     {
+                             0,                       0,                       0,                       0,
+       -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+        9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,
+        9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,  9223372036854775807ull,
+     },
+     {
+       -4611686018427387904ull, -4611686018427387904ull, -4611686018427387904ull, -4611686018427387904ull,
+       -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+                            -1,                      -1,                      -1,                      -1,
+                            -1,                      -1,                      -1,                      -1,
+     },
+   },
+ };
+ 
  #endif
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i16.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i16.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do run { target { riscv_v } } } */
+ /* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+ 
+ #include "vx_binary.h"
+ #include "vx_binary_data.h"
+ 
+ #define T          int16_t
+ #define NAME       avg_floor
+ #define FUNC       AVG_FLOOR_FUNC_WRAP(T)
+ #define TEST_DATA  TEST_BINARY_DATA_WRAP(T, NAME)
+ 
+ DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME)
+ 
+ #define TEST_RUN(T, NAME, out, in, x, n) \
+   RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n)
+ 
+ #include "vx_binary_run.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i32.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i32.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do run { target { riscv_v } } } */
+ /* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+ 
+ #include "vx_binary.h"
+ #include "vx_binary_data.h"
+ 
+ #define T          int32_t
+ #define NAME       avg_floor
+ #define FUNC       AVG_FLOOR_FUNC_WRAP(T)
+ #define TEST_DATA  TEST_BINARY_DATA_WRAP(T, NAME)
+ 
+ DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME)
+ 
+ #define TEST_RUN(T, NAME, out, in, x, n) \
+   RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n)
+ 
+ #include "vx_binary_run.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i64.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i64.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do run { target { riscv_v && rv64 } } } */
+ /* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+ 
+ #include "vx_binary.h"
+ #include "vx_binary_data.h"
+ 
+ #define T          int64_t
+ #define NAME       avg_floor
+ #define FUNC       AVG_FLOOR_FUNC_WRAP(T)
+ #define TEST_DATA  TEST_BINARY_DATA_WRAP(T, NAME)
+ 
+ DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME)
+ 
+ #define TEST_RUN(T, NAME, out, in, x, n) \
+   RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n)
+ 
+ #include "vx_binary_run.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i8.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i8.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do run { target { riscv_v } } } */
+ /* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+ 
+ #include "vx_binary.h"
+ #include "vx_binary_data.h"
+ 
+ #define T          int8_t
+ #define NAME       avg_floor
+ #define FUNC       AVG_FLOOR_FUNC_WRAP(T)
+ #define TEST_DATA  TEST_BINARY_DATA_WRAP(T, NAME)
+ 
+ DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME)
+ 
+ #define TEST_RUN(T, NAME, out, in, x, n) \
+   RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n)
+ 
+ #include "vx_binary_run.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u16.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u16.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do run { target { riscv_v } } } */
+ /* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+ 
+ #include "vx_binary.h"
+ #include "vx_binary_data.h"
+ 
+ #define T          uint16_t
+ #define NAME       avg_floor
+ #define FUNC       AVG_FLOOR_FUNC_WRAP(T)
+ #define TEST_DATA  TEST_BINARY_DATA_WRAP(T, NAME)
+ 
+ DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME)
+ 
+ #define TEST_RUN(T, NAME, out, in, x, n) \
+   RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n)
+ 
+ #include "vx_binary_run.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u32.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u32.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do run { target { riscv_v } } } */
+ /* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+ 
+ #include "vx_binary.h"
+ #include "vx_binary_data.h"
+ 
+ #define T          uint32_t
+ #define NAME       avg_floor
+ #define FUNC       AVG_FLOOR_FUNC_WRAP(T)
+ #define TEST_DATA  TEST_BINARY_DATA_WRAP(T, NAME)
+ 
+ DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME)
+ 
+ #define TEST_RUN(T, NAME, out, in, x, n) \
+   RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n)
+ 
+ #include "vx_binary_run.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u64.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u64.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do run { target { riscv_v && rv64 } } } */
+ /* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+ 
+ #include "vx_binary.h"
+ #include "vx_binary_data.h"
+ 
+ #define T          uint64_t
+ #define NAME       avg_floor
+ #define FUNC       AVG_FLOOR_FUNC_WRAP(T)
+ #define TEST_DATA  TEST_BINARY_DATA_WRAP(T, NAME)
+ 
+ DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME)
+ 
+ #define TEST_RUN(T, NAME, out, in, x, n) \
+   RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n)
+ 
+ #include "vx_binary_run.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u8.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-u8.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do run { target { riscv_v } } } */
+ /* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+ 
+ #include "vx_binary.h"
+ #include "vx_binary_data.h"
+ 
+ #define T          uint8_t
+ #define NAME       avg_floor
+ #define FUNC       AVG_FLOOR_FUNC_WRAP(T)
+ #define TEST_DATA  TEST_BINARY_DATA_WRAP(T, NAME)
+ 
+ DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME)
+ 
+ #define TEST_RUN(T, NAME, out, in, x, n) \
+   RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n)
+ 
+ #include "vx_binary_run.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-5.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-5.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-5.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-5.c	Sun Jul 27 22:32:14 2025
***************
*** 6,14 ****
  
  /*
  ** foo:
! ** addi\t[a-x0-9]+,\s*[a-x0-9]+,100
  ** vsetvli\tzero,a2,e64,m2,t[au],m[au]
! ** vlse64.v\tv[0-9]+,0\([a-x0-9]+\),zero
  ** vs2r.v\tv[0-9]+,0\([a-x0-9]+\)
  ** ret
  */
--- 6,14 ----
  
  /*
  ** foo:
! ** ...
  ** vsetvli\tzero,a2,e64,m2,t[au],m[au]
! ** vmv.s.x\tv[0-9]+.*
  ** vs2r.v\tv[0-9]+,0\([a-x0-9]+\)
  ** ret
  */
*************** void foo (void *base, void *out, size_t
*** 23,29 ****
  ** foo2:
  ** fld\tfa[0-9]+,\s*100\(a0\)
  ** vsetvli\tzero,a2,e64,m2,t[au],m[au]
! ** vfmv\.v\.f\tv[0-9]+,\s*fa[0-9]+
  ** vs2r.v\tv[0-9]+,0\([a-x0-9]+\)
  ** ret
  */
--- 23,29 ----
  ** foo2:
  ** fld\tfa[0-9]+,\s*100\(a0\)
  ** vsetvli\tzero,a2,e64,m2,t[au],m[au]
! ** vfmv\.s\.f\tv[0-9]+,\s*fa[0-9]+
  ** vs2r.v\tv[0-9]+,0\([a-x0-9]+\)
  ** ret
  */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-6.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-6.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-6.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-6.c	Sun Jul 27 22:32:14 2025
*************** void foo (void *base, void *out, size_t
*** 23,29 ****
  ** foo2:
  ** fld\tfa[0-9]+,\s*100\(a0\)
  ** vsetvli\tzero,a2,e64,m2,t[au],m[au]
! ** vfmv\.v\.f\tv[0-9]+,\s*fa[0-9]+
  ** vs2r.v\tv[0-9]+,0\([a-x0-9]+\)
  ** ret
  */
--- 23,29 ----
  ** foo2:
  ** fld\tfa[0-9]+,\s*100\(a0\)
  ** vsetvli\tzero,a2,e64,m2,t[au],m[au]
! ** vfmv\.s\.f\tv[0-9]+,\s*fa[0-9]+
  ** vs2r.v\tv[0-9]+,0\([a-x0-9]+\)
  ** ret
  */
*************** void foo3 (void *base, void *out, size_t
*** 52,58 ****
  /*
  ** foo4:
  ** ...
! ** vfmv\.v\.f\tv[0-9]+,\s*fa[0-9]+
  ** ...
  ** ret
  */
--- 52,58 ----
  /*
  ** foo4:
  ** ...
! ** vfmv\.s\.f\tv[0-9]+,\s*fa[0-9]+
  ** ...
  ** ret
  */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-7.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-7.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-7.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-7.c	Sun Jul 27 22:32:14 2025
***************
*** 6,14 ****
  
  /*
  ** foo:
! ** addi\t[a-x0-9]+,\s*[a-x0-9]+,100
  ** vsetvli\tzero,a2,e64,m2,t[au],m[au]
! ** vlse64.v\tv[0-9]+,0\([a-x0-9]+\),zero
  ** vs2r.v\tv[0-9]+,0\([a-x0-9]+\)
  ** ret
  */
--- 6,14 ----
  
  /*
  ** foo:
! ** ...
  ** vsetvli\tzero,a2,e64,m2,t[au],m[au]
! ** vmv\.v\.x\tv[0-9]+,\s*a[0-9]+
  ** vs2r.v\tv[0-9]+,0\([a-x0-9]+\)
  ** ret
  */
*************** void foo2 (void *base, void *out, size_t
*** 37,43 ****
  /*
  ** foo3:
  ** ...
! ** vlse64.v\tv[0-9]+,0\([a-x0-9]+\),zero
  ** ...
  ** ret
  */
--- 37,43 ----
  /*
  ** foo3:
  ** ...
! ** vmv\.v\.x\tv[0-9]+,\s*a[0-9]+
  ** ...
  ** ret
  */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-8.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-8.c	Sun Jul 27 22:32:14 2025
*************** void foo12 (void *base, void *out, size_
*** 175,183 ****
  /*
  ** foo13:
  ** ...
! ** vmv.v.x\tv[0-9]+,\s*[a-x0-9]+
  ** ...
- ** ret
  */
  void foo13 (void *base, void *out, size_t vl)
  {
--- 175,182 ----
  /*
  ** foo13:
  ** ...
! ** vlse64.v\tv[0-9]+,0\([a-x0-9]+\),zero
  ** ...
  */
  void foo13 (void *base, void *out, size_t vl)
  {
*************** void foo13 (void *base, void *out, size_
*** 189,195 ****
  /*
  ** foo14:
  ** ...
! ** vmv.v.x\tv[0-9]+,\s*[a-x0-9]+
  ** ...
  */
  void foo14 (void *base, void *out, size_t vl)
--- 188,194 ----
  /*
  ** foo14:
  ** ...
! ** vlse64.v\tv[0-9]+,0\([a-x0-9]+\),zero
  ** ...
  */
  void foo14 (void *base, void *out, size_t vl)
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-9.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-9.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-9.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-9.c	Sun Jul 27 22:32:14 2025
*************** vuint64m2_t f3(vuint64m2_t var_17, uint6
*** 23,26 ****
  
  /* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*0,\s*e64,\s*m2,\s*t[au],\s*m[au]} 1 } } */
  /* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*1,\s*e64,\s*m2,\s*t[au],\s*m[au]} 1 } } */
- /* { dg-final { scan-assembler-times {sgtu} 1 } } */
--- 23,25 ----
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/pr121073.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/pr121073.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/rvv/pr121073.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/rvv/pr121073.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-vector-bits=zvl -fsigned-char -fno-strict-aliasing -fwrapv -Wno-stringop-overflow -Wno-aggressive-loop-optimizations" } */
+ 
+ int a;
+ unsigned char p[1][21];
+ void init() {
+   for (int s = 0; s < 21; ++s)
+     for (int t = 0; t < 21; ++t)
+       p[s][t] = 39;
+   for (short t = 0; t < 9; t += -5077966496202321318LL + 28071)
+     a = p[3][t] && p[2][t];
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h	Sun Jul 27 22:32:14 2025
*************** sat_u_add_##WT##_##T##_fmt_7(T x, T y) \
*** 73,78 ****
--- 73,94 ----
  }
  #define DEF_SAT_U_ADD_FMT_7_WRAP(WT, T) DEF_SAT_U_ADD_FMT_7(WT, T)
  
+ #define DEF_SAT_U_ADD_FMT_8(T)                \
+ T __attribute__((noinline))                   \
+ sat_u_add_##T##_fmt_8(T x, T y)               \
+ {                                             \
+   return x <= (T)(x + y) ? (x + y) : -1;      \
+ }
+ #define DEF_SAT_U_ADD_FMT_8_WRAP(T) DEF_SAT_U_ADD_FMT_8(T)
+ 
+ #define DEF_SAT_U_ADD_FMT_9(T)               \
+ T __attribute__((noinline))                  \
+ sat_u_add_##T##_fmt_9(T x, T y)              \
+ {                                            \
+   return x > (T)(x + y) ? -1 : (x + y);      \
+ }
+ #define DEF_SAT_U_ADD_FMT_9_WRAP(T) DEF_SAT_U_ADD_FMT_9(T)
+ 
  #define RUN_SAT_U_ADD_FMT_1(T, x, y) sat_u_add_##T##_fmt_1(x, y)
  #define RUN_SAT_U_ADD_FMT_1_WRAP(T, x, y) RUN_SAT_U_ADD_FMT_1(T, x, y)
  #define RUN_SAT_U_ADD_FMT_2(T, x, y) sat_u_add_##T##_fmt_2(x, y)
*************** sat_u_add_##WT##_##T##_fmt_7(T x, T y) \
*** 97,102 ****
--- 113,122 ----
    sat_u_add_uint64_t_##T##_fmt_7(x, y)
  #define RUN_SAT_U_ADD_FMT_7_FROM_U64_WRAP(T, x, y) \
    RUN_SAT_U_ADD_FMT_7_FROM_U64(T, x, y)
+ #define RUN_SAT_U_ADD_FMT_8(T, x, y) sat_u_add_##T##_fmt_8(x, y)
+ #define RUN_SAT_U_ADD_FMT_8_WRAP(T, x, y) RUN_SAT_U_ADD_FMT_8(T, x, y)
+ #define RUN_SAT_U_ADD_FMT_9(T, x, y) sat_u_add_##T##_fmt_9(x, y)
+ #define RUN_SAT_U_ADD_FMT_9_WRAP(T, x, y) RUN_SAT_U_ADD_FMT_9(T, x, y)
  
  #define DEF_SAT_U_ADD_IMM_FMT_1(T, IMM)      \
  T __attribute__((noinline))                  \
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u16.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u16.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+ 
+ #include "sat_arith.h"
+ 
+ DEF_SAT_U_ADD_FMT_8(uint16_t)
+ 
+ /* { dg-final { scan-tree-dump-times ".SAT_ADD " 1 "optimized" } } */
+ /* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u32.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u32.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+ 
+ #include "sat_arith.h"
+ 
+ DEF_SAT_U_ADD_FMT_8(uint32_t)
+ 
+ /* { dg-final { scan-tree-dump-times ".SAT_ADD " 1 "optimized" } } */
+ /* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u64.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u64.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+ 
+ #include "sat_arith.h"
+ 
+ DEF_SAT_U_ADD_FMT_8(uint64_t)
+ 
+ /* { dg-final { scan-tree-dump-times ".SAT_ADD " 1 "optimized" } } */
+ /* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u8.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-8-u8.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+ 
+ #include "sat_arith.h"
+ 
+ DEF_SAT_U_ADD_FMT_8(uint8_t)
+ 
+ /* { dg-final { scan-tree-dump-times ".SAT_ADD " 1 "optimized" } } */
+ /* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u16.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u16.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+ 
+ #include "sat_arith.h"
+ 
+ DEF_SAT_U_ADD_FMT_9(uint16_t)
+ 
+ /* { dg-final { scan-tree-dump-times ".SAT_ADD " 1 "optimized" } } */
+ /* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u32.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u32.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+ 
+ #include "sat_arith.h"
+ 
+ DEF_SAT_U_ADD_FMT_9(uint32_t)
+ 
+ /* { dg-final { scan-tree-dump-times ".SAT_ADD " 1 "optimized" } } */
+ /* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u64.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u64.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+ 
+ #include "sat_arith.h"
+ 
+ DEF_SAT_U_ADD_FMT_9(uint64_t)
+ 
+ /* { dg-final { scan-tree-dump-times ".SAT_ADD " 1 "optimized" } } */
+ /* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u8.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-9-u8.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+ 
+ #include "sat_arith.h"
+ 
+ DEF_SAT_U_ADD_FMT_9(uint8_t)
+ 
+ /* { dg-final { scan-tree-dump-times ".SAT_ADD " 1 "optimized" } } */
+ /* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u16.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u16.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do run { target { rv32 || rv64 } } } */
+ /* { dg-additional-options "-std=c99" } */
+ 
+ #include "sat_arith.h"
+ #include "sat_arith_data.h"
+ 
+ #define T1               uint16_t
+ #define DATA             TEST_BINARY_DATA_WRAP(T1, usadd)
+ #define T                TEST_BINARY_STRUCT_DECL(T1, usadd)
+ 
+ DEF_SAT_U_ADD_FMT_8_WRAP(T1)
+ 
+ #define RUN_BINARY(x, y) RUN_SAT_U_ADD_FMT_8_WRAP(T1, x, y)
+ 
+ #include "scalar_sat_binary_run_xxx.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u32.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u32.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do run { target { rv32 || rv64 } } } */
+ /* { dg-additional-options "-std=c99" } */
+ 
+ #include "sat_arith.h"
+ #include "sat_arith_data.h"
+ 
+ #define T1               uint32_t
+ #define DATA             TEST_BINARY_DATA_WRAP(T1, usadd)
+ #define T                TEST_BINARY_STRUCT_DECL(T1, usadd)
+ 
+ DEF_SAT_U_ADD_FMT_8_WRAP(T1)
+ 
+ #define RUN_BINARY(x, y) RUN_SAT_U_ADD_FMT_8_WRAP(T1, x, y)
+ 
+ #include "scalar_sat_binary_run_xxx.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u64.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u64.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do run { target { rv32 || rv64 } } } */
+ /* { dg-additional-options "-std=c99" } */
+ 
+ #include "sat_arith.h"
+ #include "sat_arith_data.h"
+ 
+ #define T1               uint64_t
+ #define DATA             TEST_BINARY_DATA_WRAP(T1, usadd)
+ #define T                TEST_BINARY_STRUCT_DECL(T1, usadd)
+ 
+ DEF_SAT_U_ADD_FMT_8_WRAP(T1)
+ 
+ #define RUN_BINARY(x, y) RUN_SAT_U_ADD_FMT_8_WRAP(T1, x, y)
+ 
+ #include "scalar_sat_binary_run_xxx.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u8.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-8-u8.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do run { target { rv32 || rv64 } } } */
+ /* { dg-additional-options "-std=c99" } */
+ 
+ #include "sat_arith.h"
+ #include "sat_arith_data.h"
+ 
+ #define T1               uint8_t
+ #define DATA             TEST_BINARY_DATA_WRAP(T1, usadd)
+ #define T                TEST_BINARY_STRUCT_DECL(T1, usadd)
+ 
+ DEF_SAT_U_ADD_FMT_8_WRAP(T1)
+ 
+ #define RUN_BINARY(x, y) RUN_SAT_U_ADD_FMT_8_WRAP(T1, x, y)
+ 
+ #include "scalar_sat_binary_run_xxx.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u16.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u16.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u16.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u16.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do run { target { rv32 || rv64 } } } */
+ /* { dg-additional-options "-std=c99" } */
+ 
+ #include "sat_arith.h"
+ #include "sat_arith_data.h"
+ 
+ #define T1               uint16_t
+ #define DATA             TEST_BINARY_DATA_WRAP(T1, usadd)
+ #define T                TEST_BINARY_STRUCT_DECL(T1, usadd)
+ 
+ DEF_SAT_U_ADD_FMT_9_WRAP(T1)
+ 
+ #define RUN_BINARY(x, y) RUN_SAT_U_ADD_FMT_9_WRAP(T1, x, y)
+ 
+ #include "scalar_sat_binary_run_xxx.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u32.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u32.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u32.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u32.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do run { target { rv32 || rv64 } } } */
+ /* { dg-additional-options "-std=c99" } */
+ 
+ #include "sat_arith.h"
+ #include "sat_arith_data.h"
+ 
+ #define T1               uint32_t
+ #define DATA             TEST_BINARY_DATA_WRAP(T1, usadd)
+ #define T                TEST_BINARY_STRUCT_DECL(T1, usadd)
+ 
+ DEF_SAT_U_ADD_FMT_9_WRAP(T1)
+ 
+ #define RUN_BINARY(x, y) RUN_SAT_U_ADD_FMT_9_WRAP(T1, x, y)
+ 
+ #include "scalar_sat_binary_run_xxx.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u64.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u64.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u64.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u64.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do run { target { rv32 || rv64 } } } */
+ /* { dg-additional-options "-std=c99" } */
+ 
+ #include "sat_arith.h"
+ #include "sat_arith_data.h"
+ 
+ #define T1               uint64_t
+ #define DATA             TEST_BINARY_DATA_WRAP(T1, usadd)
+ #define T                TEST_BINARY_STRUCT_DECL(T1, usadd)
+ 
+ DEF_SAT_U_ADD_FMT_9_WRAP(T1)
+ 
+ #define RUN_BINARY(x, y) RUN_SAT_U_ADD_FMT_9_WRAP(T1, x, y)
+ 
+ #include "scalar_sat_binary_run_xxx.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u8.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u8.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u8.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-9-u8.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do run { target { rv32 || rv64 } } } */
+ /* { dg-additional-options "-std=c99" } */
+ 
+ #include "sat_arith.h"
+ #include "sat_arith_data.h"
+ 
+ #define T1               uint8_t
+ #define DATA             TEST_BINARY_DATA_WRAP(T1, usadd)
+ #define T                TEST_BINARY_STRUCT_DECL(T1, usadd)
+ 
+ DEF_SAT_U_ADD_FMT_9_WRAP(T1)
+ 
+ #define RUN_BINARY(x, y) RUN_SAT_U_ADD_FMT_9_WRAP(T1, x, y)
+ 
+ #include "scalar_sat_binary_run_xxx.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c gcc-16-20250727/gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c	Sun Jul 20 22:32:25 2025
--- gcc-16-20250727/gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c	Sun Jul 27 22:32:14 2025
*************** void func_machine (void)
*** 20,31 ****
  /* { dg-final { scan-assembler-times {\mth\.ipop\M} 2 { target { rv32 } } } } */
  
  
- __attribute__ ((interrupt ("user")))
- void func_usr (void)
- {
-   f ();
- }
- 
  __attribute__ ((interrupt ("supervisor")))
  void func_supervisor (void)
  {
--- 20,25 ----
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-1.c gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-1.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-1.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-1.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,103 ----
+ /* { dg-do compile { target { lp64 } } } */
+ /* { dg-options "-O2 -march=z13 -mzarch" } */
+ /* { dg-final { check-function-bodies "**" "" "" } } */
+ 
+ /*
+ ** test_in_1:
+ **     foo	%r2
+ **     br	%r14
+ */
+ 
+ int
+ test_in_1 (int x)
+ {
+   asm ("foo	%0" :: "{r2}" (x));
+   return x;
+ }
+ 
+ /*
+ ** test_in_2:
+ **     lgr	(%r[0-9]+),%r2
+ **     lr	%r2,%r3
+ **     foo	%r2
+ **     lgr	%r2,\1
+ **     br	%r14
+ */
+ 
+ int
+ test_in_2 (int x, int y)
+ {
+   asm ("foo	%0" :: "{r2}" (y));
+   return x;
+ }
+ 
+ /*
+ ** test_in_3:
+ **     stmg	%r12,%r15,96\(%r15\)
+ **     lay	%r15,-160\(%r15\)
+ **     lgr	(%r[0-9]+),%r2
+ **     ahi	%r2,1
+ **     lgfr	%r2,%r2
+ **     brasl	%r14,foo@PLT
+ **     lr	%r3,%r2
+ **     lr	%r2,\1
+ **     foo	%r3,%r2
+ **     lgr	%r2,\1
+ **     lmg	%r12,%r15,256\(%r15\)
+ **     br	%r14
+ */
+ 
+ extern int foo (int);
+ 
+ int
+ test_in_3 (int x)
+ {
+   asm ("foo	%0,%1\n" :: "{r3}" (foo (x + 1)), "{r2}" (x));
+   return x;
+ }
+ 
+ /*
+ ** test_out_1:
+ **     foo	%r3
+ **     lgfr	%r2,%r3
+ **     br	%r14
+ */
+ 
+ int
+ test_out_1 (void)
+ {
+   int x;
+   asm ("foo	%0" : "={r3}" (x));
+   return x;
+ }
+ 
+ /*
+ ** test_out_2:
+ **     lgr	(%r[0-9]+),%r2
+ **     foo	%r2
+ **     ark	(%r[0-9]+),\1,%r2
+ **     lgfr	%r2,\2
+ **     br	%r14
+ */
+ 
+ int
+ test_out_2 (int x)
+ {
+   int y;
+   asm ("foo	%0" : "={r2}" (y));
+   return x + y;
+ }
+ 
+ /*
+ ** test_inout_1:
+ **     foo	%r2
+ **     lgfr	%r2,%r2
+ **     br	%r14
+ */
+ 
+ int
+ test_inout_1 (int x)
+ {
+   asm ("foo	%0" : "+{r2}" (x));
+   return x;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-2.c gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-2.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-2.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-2.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,43 ----
+ /* { dg-do compile { target { lp64 } } } */
+ /* { dg-options "-O2 -march=z13 -mzarch" } */
+ /* { dg-final { check-function-bodies "**" "" "" } } */
+ /* { dg-final { scan-assembler {\.LC0:\n\t\.long\t1078523331\n} } } */
+ 
+ 
+ /*
+ ** test_float_into_gpr:
+ **     lrl	%r4,.LC0
+ **     foo	%r4
+ **     br	%r14
+ */
+ 
+ void
+ test_float_into_gpr (void)
+ {
+   // This is the counterpart to
+   //   register float x asm ("r4") = 3.14f;
+   //   asm ("foo	%0" :: "r" (x));
+   // where the bit-pattern of 3.14f is loaded into GPR.
+   asm ("foo	%0" :: "{r4}" (3.14f));
+ }
+ 
+ /*
+ ** test_float:
+ ** (
+ **     ldr	%f4,%f0
+ **     ldr	%f5,%f2
+ ** |
+ **     ldr	%f5,%f2
+ **     ldr	%f4,%f0
+ ** )
+ **     aebr	%f5,%f4
+ **     ldr	%f0,%f5
+ **     br	%r14
+ */
+ 
+ float
+ test_float (float x, float y)
+ {
+   asm ("aebr	%0,%1" : "+{f5}" (y) : "{f4}" (x));
+   return y;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-3.c gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-3.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-3.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-3.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,42 ----
+ /* { dg-do compile { target lp64 } } */
+ /* { dg-options "-O2 -march=z13 -mzarch" } */
+ /* { dg-final { check-function-bodies "**" "" "" } } */
+ /* { dg-final { scan-assembler {\.LC0:\n\t\.long\t1074339512\n\t\.long\t1374389535\n} } } */
+ 
+ /*
+ ** test_double_into_gpr:
+ **     lgrl	%r4,.LC0
+ **     foo	%r4
+ **     br	%r14
+ */
+ 
+ void
+ test_double_into_gpr (void)
+ {
+   // This is the counterpart to
+   //   register double x asm ("r4") = 3.14;
+   //   asm ("foo	%0" :: "r" (x));
+   // where the bit-pattern of 3.14 is loaded into GPR.
+   asm ("foo	%0" :: "{r4}" (3.14));
+ }
+ 
+ /*
+ ** test_double:
+ ** (
+ **     ldr	%f4,%f0
+ **     ldr	%f5,%f2
+ ** |
+ **     ldr	%f5,%f2
+ **     ldr	%f4,%f0
+ ** )
+ **     adbr	%f5,%f4
+ **     ldr	%f0,%f5
+ **     br	%r14
+ */
+ 
+ double
+ test_double (double x, double y)
+ {
+   asm ("adbr	%0,%1" : "+{f5}" (y) : "{f4}" (x));
+   return y;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-4.c gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-4.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-4.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-4.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,6 ----
+ /* { dg-do run { target lp64 } } */
+ /* { dg-options "-O2 -march=z13 -mzarch" } */
+ 
+ /* Test TARGET_MD_ASM_ADJUST for z13 and long double.  */
+ 
+ #include "asm-hard-reg-longdouble.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-5.c gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-5.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-5.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-5.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,6 ----
+ /* { dg-do run { target lp64 } } */
+ /* { dg-options "-O2 -march=z14 -mzarch" } */
+ 
+ /* Test TARGET_MD_ASM_ADJUST for z14 and long double.  */
+ 
+ #include "asm-hard-reg-longdouble.h"
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-6.c gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-6.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-6.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-6.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,152 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2" } */
+ 
+ void
+ test (void)
+ {
+   // GPRs
+   {
+     int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
+     __asm__ __volatile__ ("%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14"
+         : "=r" (a),
+           "=r" (b),
+           "=r" (c),
+           "=r" (d),
+           "=r" (e),
+           "=r" (f),
+           "=r" (g),
+           "=r" (h),
+           "=r" (i),
+           "=r" (j),
+           "=r" (k),
+           "=r" (l),
+           "=r" (m),
+           "=r" (n),
+           "=r" (o));
+     __asm__ __volatile__ ("%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14"
+         : "={r0}" (a),
+           "={r1}" (b),
+           "={r2}" (c),
+           "={r3}" (d),
+           "={r4}" (e),
+           "={r5}" (f),
+           "={r6}" (g),
+           "={r7}" (h),
+           "={r8}" (i),
+           "={r9}" (j),
+           "={r10}" (k),
+           "={r11}" (l),
+           "={r12}" (m),
+           "={r13}" (n),
+           "={r14}" (o));
+     __asm__ __volatile__ ("%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15" /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+         : "=r" (a),
+           "=r" (b),
+           "=r" (c),
+           "=r" (d),
+           "=r" (e),
+           "=r" (f),
+           "=r" (g),
+           "=r" (h),
+           "=r" (i),
+           "=r" (j),
+           "=r" (k),
+           "=r" (l),
+           "=r" (m),
+           "=r" (n),
+           "=r" (o),
+           "=r" (p));
+     __asm__ __volatile__ ("%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15" /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+         : "=r" (a),
+           "=r" (b),
+           "=r" (c),
+           "=r" (d),
+           "=r" (e),
+           "=r" (f),
+           "=r" (g),
+           "=r" (h),
+           "=r" (i),
+           "=r" (j),
+           "=r" (k),
+           "=r" (l),
+           "=r" (m),
+           "=r" (n),
+           "=r" (o),
+           "={r4}" (p));
+   }
+ 
+   // FPRs
+   {
+     float a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q;
+     __asm__ __volatile__ ("%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15"
+         : "=f" (a),
+           "=f" (b),
+           "=f" (c),
+           "=f" (d),
+           "=f" (e),
+           "=f" (f),
+           "=f" (g),
+           "=f" (h),
+           "=f" (i),
+           "=f" (j),
+           "=f" (k),
+           "=f" (l),
+           "=f" (m),
+           "=f" (n),
+           "=f" (o),
+           "=f" (p));
+     __asm__ __volatile__ ("%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15"
+         : "={f0}" (a),
+           "={f1}" (b),
+           "={f2}" (c),
+           "={f3}" (d),
+           "={f4}" (e),
+           "={f5}" (f),
+           "={f6}" (g),
+           "={f7}" (h),
+           "={f8}" (i),
+           "={f9}" (j),
+           "={f10}" (k),
+           "={f11}" (l),
+           "={f12}" (m),
+           "={f13}" (n),
+           "={f14}" (o),
+           "={f15}" (p));
+     __asm__ __volatile__ ("%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16" /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+         : "=f" (a),
+           "=f" (b),
+           "=f" (c),
+           "=f" (d),
+           "=f" (e),
+           "=f" (f),
+           "=f" (g),
+           "=f" (h),
+           "=f" (i),
+           "=f" (j),
+           "=f" (k),
+           "=f" (l),
+           "=f" (m),
+           "=f" (n),
+           "=f" (o),
+           "=f" (p),
+           "=f" (q));
+     __asm__ __volatile__ ("%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16" /* { dg-error "'asm' operand has impossible constraints or there are not enough registers" } */
+         : "=f" (a),
+           "=f" (b),
+           "=f" (c),
+           "=f" (d),
+           "=f" (e),
+           "=f" (f),
+           "=f" (g),
+           "=f" (h),
+           "=f" (i),
+           "=f" (j),
+           "=f" (k),
+           "=f" (l),
+           "=f" (m),
+           "=f" (n),
+           "=f" (o),
+           "=f" (p),
+           "={f4}" (q));
+   }
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-7.c gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-7.c
*** gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-7.c	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-7.c	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,34 ----
+ /* { dg-do compile } */
+ /* { dg-options "-march=z13" } */
+ 
+ /* Test register pairs.  */
+ 
+ void
+ test (void)
+ {
+   register double f0 __asm__ ("f0");
+   register double f2 __asm__ ("f2");
+   register long double f0f2 __asm__ ("f0");
+   double x;
+   long double y;
+ 
+   /* Outputs */
+   __asm__ __volatile__ ("" : "=r" (f0), "=r" (f0f2));
+   __asm__ __volatile__ ("" : "=r" (f0f2), "={f0}" (y));  /* { dg-error "multiple outputs to hard register: %f0" } */
+   __asm__ __volatile__ ("" : "={f0}" (x), "=r" (f0f2));  /* { dg-error "multiple outputs to hard register: %f0" } */
+ 
+   __asm__ __volatile__ ("" : "=r" (f2), "=r" (f0f2));
+   __asm__ __volatile__ ("" : "={f2}" (x), "={f0}" (y));  /* { dg-error "multiple outputs to hard register: %f2" } */
+   __asm__ __volatile__ ("" : "=r" (f2), "={f0}" (y));  /* { dg-error "multiple outputs to hard register: %f2" } */
+   __asm__ __volatile__ ("" : "={f2}" (x), "=r" (f0f2));  /* { dg-error "multiple outputs to hard register: %f2" } */
+ 
+   /* Inputs */
+   __asm__ __volatile__ ("" :: "r" (f0), "r" (f0f2));
+   __asm__ __volatile__ ("" :: "r" (f0f2), "{f0}" (y));  /* { dg-error "multiple inputs to hard register: %f0" } */
+   __asm__ __volatile__ ("" :: "{f0}" (x), "r" (f0f2));  /* { dg-error "multiple inputs to hard register: %f0" } */
+ 
+   __asm__ __volatile__ ("" :: "r" (f2), "r" (f0f2));
+   __asm__ __volatile__ ("" :: "{f2}" (x), "{f0}" (y));  /* { dg-error "multiple inputs to hard register: %f2" } */
+   __asm__ __volatile__ ("" :: "r" (f2), "{f0}" (y));  /* { dg-error "multiple inputs to hard register: %f2" } */
+   __asm__ __volatile__ ("" :: "{f2}" (x), "r" (f0f2));  /* { dg-error "multiple inputs to hard register: %f2" } */
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-longdouble.h gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-longdouble.h
*** gcc-16-20250720/gcc/testsuite/gcc.target/s390/asm-hard-reg-longdouble.h	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gcc.target/s390/asm-hard-reg-longdouble.h	Sun Jul 27 22:32:14 2025
***************
*** 0 ****
--- 1,18 ----
+ __attribute__ ((noipa))
+ long double
+ test_longdouble (long double x)
+ {
+   long double y;
+   asm ("sqxbr\t%0,%1" : "={f4}" (y) : "{f5}" (x));
+   return y;
+ }
+ 
+ int
+ main (void)
+ {
+   long double x = test_longdouble (42.L);
+   long double y = 6.48074069840786023096596743608799656681773277430814773408787249757445105002862106857719481922686100006103515625L;
+   if (x != y)
+     __builtin_abort ();
+   return 0;
+ }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gfortran.dg/array_constructor_58.f90 gcc-16-20250727/gcc/testsuite/gfortran.dg/array_constructor_58.f90
*** gcc-16-20250720/gcc/testsuite/gfortran.dg/array_constructor_58.f90	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gfortran.dg/array_constructor_58.f90	Sun Jul 27 22:32:15 2025
***************
*** 0 ****
--- 1,17 ----
+ !{ dg-do run }
+ 
+ ! Contributed by  Federico Perini <federico.perini@gmail.com>
+ ! Check that PR fortran/119106 is fixed.
+ 
+ program char_param_array
+ implicit none
+ character, parameter :: p(5) = ['1','2','3','4','5']
+ character, save      :: n(5) = ['1','2','3','4','5']
+ integer :: i(10), j
+ 
+ i = 4
+ if (any([(n(i(j)),j=1,10)] /= '4')) stop 1 ! OK
+ if (any([(p(i(j)),j=1,10)] /= '4')) stop 2 ! used to runtime out-of-bounds error
+ 
+ end program char_param_array
+ 
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gfortran.dg/assign_13.f90 gcc-16-20250727/gcc/testsuite/gfortran.dg/assign_13.f90
*** gcc-16-20250720/gcc/testsuite/gfortran.dg/assign_13.f90	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gfortran.dg/assign_13.f90	Sun Jul 27 22:32:15 2025
***************
*** 0 ****
--- 1,25 ----
+ ! { dg-do run }
+ !
+ ! PR fortran/121185
+ ! The assignment to Y%X in CHECK_T was using a polymorphic array access on the
+ ! left hand side, using the virtual table of Y.
+ 
+ program p
+   implicit none
+   type t
+      complex, allocatable :: x(:)
+   end type t
+   real :: trace = 2.
+   type(t) :: z
+   z%x = [1,2] * trace
+   call check_t (z)
+ contains
+   subroutine check_t (y)
+     class(t) :: y
+     ! print *, y% x
+     if (any(y%x /= [2., 4.])) error stop 11
+     y%x = y%x / trace
+     ! print *, y% x
+     if (any(y%x /= [1., 2.])) error stop 12
+   end subroutine
+ end
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gfortran.dg/assign_14.f90 gcc-16-20250727/gcc/testsuite/gfortran.dg/assign_14.f90
*** gcc-16-20250720/gcc/testsuite/gfortran.dg/assign_14.f90	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gfortran.dg/assign_14.f90	Sun Jul 27 22:32:15 2025
***************
*** 0 ****
--- 1,24 ----
+ ! { dg-do compile }
+ ! { dg-additional-options {-fdump-tree-original} }
+ !
+ ! PR fortran/121185
+ ! Check that an intermediary variable is used to reference component a.
+ ! { dg-final { scan-tree-dump-not {->b->a} original } }
+ 
+ program p
+   implicit none
+   type t
+      integer, allocatable :: a(:)
+   end type t
+   type u
+      type(t), allocatable :: b
+   end type u
+   type v
+      type(u), allocatable :: c
+   end type v
+   type(v) :: z
+   z%c = u()
+   z%c%b = t()
+   z%c%b%a = [1,2]
+   z%c%b%a = z%c%b%a * 2
+ end
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gfortran.dg/function_charlen_4.f90 gcc-16-20250727/gcc/testsuite/gfortran.dg/function_charlen_4.f90
*** gcc-16-20250720/gcc/testsuite/gfortran.dg/function_charlen_4.f90	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gfortran.dg/function_charlen_4.f90	Sun Jul 27 22:32:15 2025
***************
*** 0 ****
--- 1,34 ----
+ ! { dg-do run }
+ ! { dg-options "-O2 -std=legacy -fdump-tree-optimized" }
+ !
+ ! PR fortran/121203 - fix passing of character length of function to procedure
+ 
+ program p
+   character(10), external :: f
+   call eval (f,"abc")
+   call eval2(f,"abc")
+ contains
+   subroutine eval2(func,c_arg)
+     character(*) c_arg
+     character(*) func
+     external func
+     ! These tests should get optimized:
+     if (len      (c_arg)  /=  3) stop 1
+     if (len (func(c_arg)) /= 10) stop 2
+   end subroutine
+ end
+ 
+ character(10) function f(arg)
+   character(*) arg
+   f=arg
+ end
+ 
+ subroutine eval(func,c_arg)
+   character(*) c_arg
+   character(*) func
+   external func
+   if (len      (c_arg)  /=  3) error stop 3
+   if (len (func(c_arg)) /= 10) error stop 4
+ end subroutine
+ 
+ ! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "optimized" } }
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.def gcc-16-20250727/gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.def
*** gcc-16-20250720/gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.def	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.def	Sun Jul 27 22:32:16 2025
***************
*** 0 ****
--- 1,12 ----
+ DEFINITION MODULE arrayofchar ;
+ 
+ FROM FIO IMPORT File ;
+ 
+ (*
+    Description: provides write procedures for ARRAY OF CHAR.
+ *)
+ 
+ PROCEDURE Write (f: File; str: ARRAY OF CHAR) ;
+ PROCEDURE WriteLn (f: File) ;
+ 
+ END arrayofchar.
diff -Nrcpad gcc-16-20250720/gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.mod gcc-16-20250727/gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.mod
*** gcc-16-20250720/gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.mod	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/gcc/testsuite/gm2/switches/pedantic-params/fail/arrayofchar.mod	Sun Jul 27 22:32:16 2025
***************
*** 0 ****
--- 1,30 ----
+ IMPLEMENTATION MODULE arrayofchar ;
+ 
+ FROM FIO IMPORT WriteChar, WriteLine ;
+ IMPORT StrLib ;
+ 
+ 
+ (*
+    Write - writes a string to file f.
+ *)
+ 
+ PROCEDURE Write (f: File; a: ARRAY OF CHAR) ;
+ VAR
+    len, i: CARDINAL ;
+ BEGIN
+    len := StrLib.StrLen (a) ;
+    i := 0 ;
+    WHILE i < len DO
+       WriteChar (f, a[i]) ;
+       INC (i)
+    END
+ END Write ;
+ 
+ 
+ PROCEDURE WriteLn (f: File) ;
+ BEGIN
+    WriteLine (f)
+ END WriteLn ;
+ 
+ 
+ END arrayofchar.
diff -Nrcpad gcc-16-20250720/gcc/testsuite/lib/gcc-defs.exp gcc-16-20250727/gcc/testsuite/lib/gcc-defs.exp
*** gcc-16-20250720/gcc/testsuite/lib/gcc-defs.exp	Sun Jul 20 22:32:30 2025
--- gcc-16-20250727/gcc/testsuite/lib/gcc-defs.exp	Sun Jul 27 22:32:16 2025
*************** proc aarch64-arch-dg-options { args } {
*** 599,613 ****
  
      set add_arch 1
      set add_tune 1
      set checks_output [string equal [lindex $do_what 0] "compile"]
      set options [lindex $args 1]
  
      foreach option [split $options] {
  	switch -glob -- $option {
  	    -march=* { set add_arch 0 }
! 	    -mcpu=* { set add_arch 0; set add_tune 0 }
! 	    -mtune=* { set add_tune 0 }
! 	    -moverride=* { set add_tune 0 }
  	    -save-temps { set checks_output 1 }
  	    --save-temps { set checks_output 1 }
  	    -fdump* { set checks_output 1 }
--- 599,614 ----
  
      set add_arch 1
      set add_tune 1
+     set add_override 1
      set checks_output [string equal [lindex $do_what 0] "compile"]
      set options [lindex $args 1]
  
      foreach option [split $options] {
  	switch -glob -- $option {
  	    -march=* { set add_arch 0 }
! 	    -mcpu=* { set add_arch 0; set add_tune 0; set add_override 0}
! 	    -mtune=* { set add_tune 0; set add_override 0 }
! 	    -moverride=* { set add_override 0 }
  	    -save-temps { set checks_output 1 }
  	    --save-temps { set checks_output 1 }
  	    -fdump* { set checks_output 1 }
*************** proc aarch64-arch-dg-options { args } {
*** 619,627 ****
  	append options " $aarch64_default_testing_arch"
      }
  
!     if { $add_tune && $checks_output } {
  	# Turn off any default tuning and codegen tweaks.
! 	append options " -mtune=generic -moverride=tune=none"
      }
  
      uplevel 1 aarch64-old-dg-options [lreplace $args 1 1 $options]
--- 620,633 ----
  	append options " $aarch64_default_testing_arch"
      }
  
!     if { $checks_output } {
  	# Turn off any default tuning and codegen tweaks.
!         if { $add_tune } {
!             append options " -mtune=generic"
!         }
!         if { $add_override } {
!             append options " -moverride=tune=none"
!         }
      }
  
      uplevel 1 aarch64-old-dg-options [lreplace $args 1 1 $options]
diff -Nrcpad gcc-16-20250720/gcc/testsuite/lib/gcc-dg.exp gcc-16-20250727/gcc/testsuite/lib/gcc-dg.exp
*** gcc-16-20250720/gcc/testsuite/lib/gcc-dg.exp	Sun Jul 20 22:32:30 2025
--- gcc-16-20250727/gcc/testsuite/lib/gcc-dg.exp	Sun Jul 27 22:32:16 2025
*************** proc dg-missed { args } {
*** 1338,1345 ****
  }
  
  # Look for messages with 'note: ' prefixes.
! # In addition to standard compiler diagnostics ('DK_NOTE', 'inform' functions,
! # "for additional details on an error message"),
  # this also includes output from '-fopt-info' for 'MSG_NOTE':
  # a general optimization info.
  # By default, any *excess* notes are pruned, meaning their appearance doesn't
--- 1338,1345 ----
  }
  
  # Look for messages with 'note: ' prefixes.
! # In addition to standard compiler diagnostics (diagnostics::kind::note,
! # 'inform' functions, "for additional details on an error message"),
  # this also includes output from '-fopt-info' for 'MSG_NOTE':
  # a general optimization info.
  # By default, any *excess* notes are pruned, meaning their appearance doesn't
diff -Nrcpad gcc-16-20250720/gcc/testsuite/lib/sarif.py gcc-16-20250727/gcc/testsuite/lib/sarif.py
*** gcc-16-20250720/gcc/testsuite/lib/sarif.py	Sun Jul 20 22:32:30 2025
--- gcc-16-20250727/gcc/testsuite/lib/sarif.py	Sun Jul 27 22:32:16 2025
*************** def get_result_by_index(sarif, idx):
*** 30,36 ****
      return results[idx]
      
  def get_state_graph(events, event_idx):
!     graph = events[event_idx]['properties']['gcc/diagnostic_event/state_graph']
      if 0:
          print(graph)
      assert graph is not None
--- 30,36 ----
      return results[idx]
      
  def get_state_graph(events, event_idx):
!     graph = events[event_idx]['properties']['gcc/diagnostics/paths/event/state_graph']
      if 0:
          print(graph)
      assert graph is not None
diff -Nrcpad gcc-16-20250720/gcc/testsuite/lib/scanasm.exp gcc-16-20250727/gcc/testsuite/lib/scanasm.exp
*** gcc-16-20250720/gcc/testsuite/lib/scanasm.exp	Sun Jul 20 22:32:30 2025
--- gcc-16-20250727/gcc/testsuite/lib/scanasm.exp	Sun Jul 27 22:32:16 2025
*************** proc configure_check-function-bodies { c
*** 896,901 ****
--- 896,905 ----
  	set up_config(fluff) {^\s*(?://)}
      } elseif { [istarget *-*-darwin*] } {
  	set up_config(fluff) {^\s*(?:\.|//|@)|^L[0-9ABCESV]}
+     } elseif { [istarget s390*-*-*] } {
+ 	# Additionally to the defaults skip lines beginning with a # resulting
+ 	# from inline asm.
+ 	set up_config(fluff) {^\s*(?:\.|//|@|$|#)}
      } else {
  	# Skip lines beginning with labels ('.L[...]:') or other directives
  	# ('.align', '.cfi_startproc', '.quad [...]', '.text', etc.), '//' or
diff -Nrcpad gcc-16-20250720/gcc/testsuite/lib/target-supports.exp gcc-16-20250727/gcc/testsuite/lib/target-supports.exp
*** gcc-16-20250720/gcc/testsuite/lib/target-supports.exp	Sun Jul 20 22:32:30 2025
--- gcc-16-20250727/gcc/testsuite/lib/target-supports.exp	Sun Jul 27 22:32:16 2025
*************** proc check_effective_target_label_values
*** 1017,1022 ****
--- 1017,1034 ----
      return 1
  }
  
+ 
+ # Return 1 if builtin_trap expands not into a call but an instruction,
+ # 0 otherwise.
+ proc check_effective_target_trap { } {
+     return [check_no_messages_and_pattern trap "!\\(call" rtl-expand {
+ 	void foo ()
+ 	  {
+ 	    return __builtin_trap ();
+ 	  }
+     } "" ]
+ }
+ 
  # Return 1 if builtin_return_address and builtin_frame_address are
  # supported, 0 otherwise.
  
*************** proc check_effective_target_riscv_v_misa
*** 2428,2434 ****
  		= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  	      asm ("vsetivli zero,7,e8,m1,ta,ma");
  	      asm ("addi a7,%0,1" : : "r" (a) : "a7" );
! 	      asm ("vle8.v v8,0(a7)" : : : "v8");
  	      return 0; } } "-march=${gcc_march}"] } {
  	return 1
      }
--- 2440,2446 ----
  		= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  	      asm ("vsetivli zero,7,e8,m1,ta,ma");
  	      asm ("addi a7,%0,1" : : "r" (a) : "a7" );
! 	      asm ("vle16.v v8,0(a7)" : : : "v8");
  	      return 0; } } "-march=${gcc_march}"] } {
  	return 1
      }
*************** proc remove_options_for_riscv_zvbb { fla
*** 2685,2690 ****
--- 2697,2710 ----
      return [add_options_for_riscv_z_ext zvbb $flags]
  }
  
+ proc add_options_for_riscv_zvfh { flags } {
+     return [add_options_for_riscv_z_ext zvfh $flags]
+ }
+ 
+ proc remove_options_for_riscv_zvfh { flags } {
+     return [add_options_for_riscv_z_ext zvfh $flags]
+ }
+ 
  # Return 1 if the target is ia32 or x86_64.
  
  proc check_effective_target_x86 { } {
diff -Nrcpad gcc-16-20250720/gcc/text-art/style.cc gcc-16-20250727/gcc/text-art/style.cc
*** gcc-16-20250720/gcc/text-art/style.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/text-art/style.cc	Sun Jul 27 22:32:17 2025
*************** along with GCC; see the file COPYING3.
*** 29,35 ****
  #include "text-art/selftests.h"
  #include "text-art/types.h"
  #include "color-macros.h"
! #include "diagnostic-color.h"
  
  using namespace text_art;
  
--- 29,35 ----
  #include "text-art/selftests.h"
  #include "text-art/types.h"
  #include "color-macros.h"
! #include "diagnostics/color.h"
  
  using namespace text_art;
  
diff -Nrcpad gcc-16-20250720/gcc/toplev.cc gcc-16-20250727/gcc/toplev.cc
*** gcc-16-20250720/gcc/toplev.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/toplev.cc	Sun Jul 27 22:32:17 2025
*************** along with GCC; see the file COPYING3.
*** 81,87 ****
  #include "ipa-utils.h"
  #include "gcse.h"
  #include "omp-offload.h"
! #include "edit-context.h"
  #include "tree-pass.h"
  #include "dumpfile.h"
  #include "ipa-fnsummary.h"
--- 81,88 ----
  #include "ipa-utils.h"
  #include "gcse.h"
  #include "omp-offload.h"
! #include "diagnostics/changes.h"
! #include "diagnostics/file-cache.h"
  #include "tree-pass.h"
  #include "dumpfile.h"
  #include "ipa-fnsummary.h"
*************** announce_function (tree decl)
*** 230,236 ****
  		 identifier_to_locale (lang_hooks.decl_printable_name (decl, 2)));
        fflush (stderr);
        pp_needs_newline (global_dc->get_reference_printer ()) = true;
!       diagnostic_set_last_function (global_dc, (diagnostic_info *) NULL);
      }
  }
  
--- 231,238 ----
  		 identifier_to_locale (lang_hooks.decl_printable_name (decl, 2)));
        fflush (stderr);
        pp_needs_newline (global_dc->get_reference_printer ()) = true;
!       diagnostic_set_last_function (global_dc,
! 				    (diagnostics::diagnostic_info *) nullptr);
      }
  }
  
*************** open_auxiliary_file (const char *ext)
*** 1017,1023 ****
  /* Alternative diagnostics callback for reentered ICE reporting.  */
  
  static void
! internal_error_reentered (diagnostic_context *, const char *, va_list *)
  {
    /* Flush the dump file if emergency_dump_function itself caused an ICE.  */
    if (dump_file)
--- 1019,1025 ----
  /* Alternative diagnostics callback for reentered ICE reporting.  */
  
  static void
! internal_error_reentered (diagnostics::context *, const char *, va_list *)
  {
    /* Flush the dump file if emergency_dump_function itself caused an ICE.  */
    if (dump_file)
*************** internal_error_reentered (diagnostic_con
*** 1027,1033 ****
  /* Auxiliary callback for the diagnostics code.  */
  
  static void
! internal_error_function (diagnostic_context *, const char *, va_list *)
  {
    global_dc->set_internal_error_callback (internal_error_reentered);
    warn_if_plugins ();
--- 1029,1035 ----
  /* Auxiliary callback for the diagnostics code.  */
  
  static void
! internal_error_function (diagnostics::context *, const char *, va_list *)
  {
    global_dc->set_internal_error_callback (internal_error_reentered);
    warn_if_plugins ();
*************** general_init (const char *argv0, bool in
*** 1068,1080 ****
  
    global_dc->set_original_argv (std::move (original_argv));
  
!   global_dc->m_source_printing.enabled
      = global_options_init.x_flag_diagnostics_show_caret;
!   global_dc->m_source_printing.show_event_links_p
      = global_options_init.x_flag_diagnostics_show_event_links;
!   global_dc->m_source_printing.show_labels_p
      = global_options_init.x_flag_diagnostics_show_labels;
!   global_dc->m_source_printing.show_line_numbers_p
      = global_options_init.x_flag_diagnostics_show_line_numbers;
    global_dc->set_show_cwe (global_options_init.x_flag_diagnostics_show_cwe);
    global_dc->set_show_rules (global_options_init.x_flag_diagnostics_show_rules);
--- 1070,1083 ----
  
    global_dc->set_original_argv (std::move (original_argv));
  
!   auto &source_printing_opts = global_dc->get_source_printing_options ();
!   source_printing_opts.enabled
      = global_options_init.x_flag_diagnostics_show_caret;
!   source_printing_opts.show_event_links_p
      = global_options_init.x_flag_diagnostics_show_event_links;
!   source_printing_opts.show_labels_p
      = global_options_init.x_flag_diagnostics_show_labels;
!   source_printing_opts.show_line_numbers_p
      = global_options_init.x_flag_diagnostics_show_line_numbers;
    global_dc->set_show_cwe (global_options_init.x_flag_diagnostics_show_cwe);
    global_dc->set_show_rules (global_options_init.x_flag_diagnostics_show_rules);
*************** general_init (const char *argv0, bool in
*** 1085,1091 ****
      (global_options_init.x_flag_diagnostics_show_path_depths);
    global_dc->set_show_option_requested
      (global_options_init.x_flag_diagnostics_show_option);
!   global_dc->m_source_printing.min_margin_width
      = global_options_init.x_diagnostics_minimum_margin_width;
    global_dc->m_show_column
      = global_options_init.x_flag_show_column;
--- 1088,1094 ----
      (global_options_init.x_flag_diagnostics_show_path_depths);
    global_dc->set_show_option_requested
      (global_options_init.x_flag_diagnostics_show_option);
!   source_printing_opts.min_margin_width
      = global_options_init.x_diagnostics_minimum_margin_width;
    global_dc->m_show_column
      = global_options_init.x_flag_show_column;
*************** process_options ()
*** 1285,1291 ****
    input_location = saved_location;
  
    if (flag_diagnostics_generate_patch)
!     global_dc->create_edit_context ();
  
    /* Avoid any informative notes in the second run of -fcompare-debug.  */
    if (flag_compare_debug)
--- 1288,1294 ----
    input_location = saved_location;
  
    if (flag_diagnostics_generate_patch)
!     global_dc->initialize_fixits_change_set ();
  
    /* Avoid any informative notes in the second run of -fcompare-debug.  */
    if (flag_compare_debug)
*************** process_options ()
*** 1748,1758 ****
        if (warn_coverage_mismatch
  	  && option_unspecified_p (OPT_Wcoverage_mismatch))
  	diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_mismatch,
! 					DK_ERROR, UNKNOWN_LOCATION);
        if (warn_coverage_invalid_linenum
  	  && option_unspecified_p (OPT_Wcoverage_invalid_line_number))
  	diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_invalid_line_number,
! 					DK_ERROR, UNKNOWN_LOCATION);
      }
  
    /* Save the current optimization options.  */
--- 1751,1763 ----
        if (warn_coverage_mismatch
  	  && option_unspecified_p (OPT_Wcoverage_mismatch))
  	diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_mismatch,
! 					diagnostics::kind::error,
! 					UNKNOWN_LOCATION);
        if (warn_coverage_invalid_linenum
  	  && option_unspecified_p (OPT_Wcoverage_invalid_line_number))
  	diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_invalid_line_number,
! 					diagnostics::kind::error,
! 					UNKNOWN_LOCATION);
      }
  
    /* Save the current optimization options.  */
*************** backend_init_target (void)
*** 1815,1820 ****
--- 1820,1829 ----
  static void
  backend_init (void)
  {
+ #if CHECKING_P
+   verify_reg_names_in_constraints ();
+ #endif
+ 
    init_emit_once ();
  
    init_rtlanal ();
*************** toplev::main (int argc, char **argv)
*** 2385,2395 ****
       emit some diagnostics here.  */
    invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
  
!   if (auto edit_context_ptr = global_dc->get_edit_context ())
      {
        pretty_printer pp;
        pp_show_color (&pp) = pp_show_color (global_dc->get_reference_printer ());
!       edit_context_ptr->print_diff (&pp, true);
        pp_flush (&pp);
      }
  
--- 2394,2404 ----
       emit some diagnostics here.  */
    invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
  
!   if (auto change_set_ptr = global_dc->get_fixits_change_set ())
      {
        pretty_printer pp;
        pp_show_color (&pp) = pp_show_color (global_dc->get_reference_printer ());
!       change_set_ptr->print_diff (&pp, true);
        pp_flush (&pp);
      }
  
diff -Nrcpad gcc-16-20250720/gcc/tree-cfgcleanup.cc gcc-16-20250727/gcc/tree-cfgcleanup.cc
*** gcc-16-20250720/gcc/tree-cfgcleanup.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-cfgcleanup.cc	Sun Jul 27 22:32:17 2025
*************** along with GCC; see the file COPYING3.
*** 47,52 ****
--- 47,53 ----
  #include "tree-into-ssa.h"
  #include "tree-cfgcleanup.h"
  #include "gimple-pretty-print.h"
+ #include "target.h"
  
  
  /* The set of blocks in that at least one of the following changes happened:
*************** execute_cleanup_cfg_post_optimizing (voi
*** 1569,1574 ****
--- 1570,1598 ----
    cleanup_dead_labels ();
    if (group_case_labels ())
      todo |= TODO_cleanup_cfg;
+ 
+   basic_block bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+   gimple_stmt_iterator gsi = gsi_start_nondebug_after_labels_bb (bb);
+   /* If the first (and only) bb and the only non debug
+      statement is __builtin_unreachable call, then replace it with a trap
+      so the function is at least one instruction in size.  */
+   if (!gsi_end_p (gsi)
+       && gimple_call_builtin_p (gsi_stmt (gsi), BUILT_IN_UNREACHABLE))
+     {
+       if (targetm.have_trap ())
+ 	{
+ 	  gimple_call_set_fndecl (gsi_stmt (gsi), builtin_decl_implicit (BUILT_IN_UNREACHABLE_TRAP));
+ 	  update_stmt (gsi_stmt (gsi));
+ 	}
+       /* If the target does not have a trap, convert it into an infinite loop. */
+       else
+ 	{
+ 	  gsi_remove (&gsi, true);
+ 	  make_single_succ_edge (bb, bb, EDGE_FALLTHRU);
+ 	  fix_loop_structure (NULL);
+ 	}
+     }
+ 
    if ((flag_compare_debug_opt || flag_compare_debug)
        && flag_dump_final_insns)
      {
diff -Nrcpad gcc-16-20250720/gcc/tree-diagnostic-client-data-hooks.cc gcc-16-20250727/gcc/tree-diagnostic-client-data-hooks.cc
*** gcc-16-20250720/gcc/tree-diagnostic-client-data-hooks.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-diagnostic-client-data-hooks.cc	Sun Jul 27 22:32:17 2025
***************
*** 1,4 ****
! /* Implementation of diagnostic_client_data_hooks for the compilers
     (e.g. with knowledge of "tree", lang_hooks, and timevars).
     Copyright (C) 2022-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
--- 1,4 ----
! /* Implementation of diagnostics::client_data_hooks for the compilers
     (e.g. with knowledge of "tree", lang_hooks, and timevars).
     Copyright (C) 2022-2025 Free Software Foundation, Inc.
     Contributed by David Malcolm <dmalcolm@redhat.com>.
*************** along with GCC; see the file COPYING3.
*** 26,43 ****
  #include "tree.h"
  #include "diagnostic.h"
  #include "tree-logical-location.h"
! #include "diagnostic-client-data-hooks.h"
! #include "diagnostic-format-sarif.h"
  #include "langhooks.h"
  #include "plugin.h"
  #include "timevar.h"
  
! /* Concrete class for supplying a diagnostic_context with information
     about a specific plugin within the client, when the client is the
     compiler (i.e. a GCC plugin).  */
  
  class compiler_diagnostic_client_plugin_info
!   : public diagnostic_client_plugin_info
  {
  public:
    compiler_diagnostic_client_plugin_info (const plugin_name_args *args)
--- 26,43 ----
  #include "tree.h"
  #include "diagnostic.h"
  #include "tree-logical-location.h"
! #include "diagnostics/client-data-hooks.h"
! #include "diagnostics/sarif-sink.h"
  #include "langhooks.h"
  #include "plugin.h"
  #include "timevar.h"
  
! /* Concrete class for supplying a diagnostics::context with information
     about a specific plugin within the client, when the client is the
     compiler (i.e. a GCC plugin).  */
  
  class compiler_diagnostic_client_plugin_info
!   : public diagnostics::client_plugin_info
  {
  public:
    compiler_diagnostic_client_plugin_info (const plugin_name_args *args)
*************** private:
*** 67,73 ****
  /* Concrete subclass of client_version_info for use by compilers proper,
     (i.e. using lang_hooks, and with knowledge of GCC plugins).  */
  
! class compiler_version_info : public client_version_info
  {
  public:
    const char *get_tool_name () const final override
--- 67,73 ----
  /* Concrete subclass of client_version_info for use by compilers proper,
     (i.e. using lang_hooks, and with knowledge of GCC plugins).  */
  
! class compiler_version_info : public diagnostics::client_version_info
  {
  public:
    const char *get_tool_name () const final override
*************** private:
*** 112,134 ****
    }
  };
  
! /* Subclass of diagnostic_client_data_hooks for use by compilers proper
     i.e. with knowledge of "tree", access to langhooks, timevars etc.  */
  
! class compiler_data_hooks : public diagnostic_client_data_hooks
  {
  public:
!   const client_version_info *get_any_version_info () const final override
    {
      return &m_version_info;
    }
  
!   const logical_location_manager *get_logical_location_manager () const final override
    {
      return &m_logical_location_manager;
    }
  
!   logical_location_manager::key get_current_logical_location () const final override
    {
      return m_logical_location_manager.key_from_tree (current_function_decl);
    }
--- 112,137 ----
    }
  };
  
! /* Subclass of diagnostics::client_data_hooks for use by compilers proper
     i.e. with knowledge of "tree", access to langhooks, timevars etc.  */
  
! class compiler_data_hooks : public diagnostics::client_data_hooks
  {
  public:
!   const diagnostics::client_version_info *
!   get_any_version_info () const final override
    {
      return &m_version_info;
    }
  
!   const diagnostics::logical_locations::manager *
!   get_logical_location_manager () const final override
    {
      return &m_logical_location_manager;
    }
  
!   diagnostics::logical_locations::key
!   get_current_logical_location () const final override
    {
      return m_logical_location_manager.key_from_tree (current_function_decl);
    }
*************** public:
*** 140,152 ****
    }
  
    void
!   add_sarif_invocation_properties (sarif_object &invocation_obj)
      const final override
    {
      if (g_timer)
        if (auto timereport_val = g_timer->make_json ())
  	{
! 	  sarif_property_bag &bag_obj
  	    = invocation_obj.get_or_create_properties ();
  	  bag_obj.set ("gcc/timeReport", std::move (timereport_val));
  
--- 143,155 ----
    }
  
    void
!   add_sarif_invocation_properties (diagnostics::sarif_object &invocation_obj)
      const final override
    {
      if (g_timer)
        if (auto timereport_val = g_timer->make_json ())
  	{
! 	  auto &bag_obj
  	    = invocation_obj.get_or_create_properties ();
  	  bag_obj.set ("gcc/timeReport", std::move (timereport_val));
  
*************** private:
*** 167,173 ****
  /* Create a compiler_data_hooks (so that the class can be local
     to this file).  */
  
! std::unique_ptr<diagnostic_client_data_hooks>
  make_compiler_data_hooks ()
  {
    return std::make_unique<compiler_data_hooks> ();
--- 170,176 ----
  /* Create a compiler_data_hooks (so that the class can be local
     to this file).  */
  
! std::unique_ptr<diagnostics::client_data_hooks>
  make_compiler_data_hooks ()
  {
    return std::make_unique<compiler_data_hooks> ();
diff -Nrcpad gcc-16-20250720/gcc/tree-diagnostic.cc gcc-16-20250727/gcc/tree-diagnostic.cc
*** gcc-16-20250720/gcc/tree-diagnostic.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-diagnostic.cc	Sun Jul 27 22:32:17 2025
*************** along with GCC; see the file COPYING3.
*** 27,55 ****
  #include "tree-pretty-print.h"
  #include "gimple-pretty-print.h"
  #include "tree-diagnostic.h"
! #include "diagnostic-client-data-hooks.h"
  #include "langhooks.h"
  #include "intl.h"
! #include "diagnostic-format-text.h"
  
  /* Prints out, if necessary, the name of the current function
     that caused an error.  */
  void
! diagnostic_report_current_function (diagnostic_text_output_format &text_output,
! 				    const diagnostic_info *diagnostic)
  {
!   location_t loc = diagnostic_location (diagnostic);
    text_output.report_current_module (loc);
!   lang_hooks.print_error_function (text_output, LOCATION_FILE (loc), diagnostic);
  }
  
  static void
! default_tree_diagnostic_text_starter (diagnostic_text_output_format &text_output,
! 				      const diagnostic_info *diagnostic)
  {
    pretty_printer *const pp = text_output.get_printer ();
!   diagnostic_report_current_function (text_output, diagnostic);
!   pp_set_prefix (pp, text_output.build_prefix (*diagnostic));
  }
  
  /* Default tree printer.   Handles declarations only.  */
--- 27,55 ----
  #include "tree-pretty-print.h"
  #include "gimple-pretty-print.h"
  #include "tree-diagnostic.h"
! #include "diagnostics/client-data-hooks.h"
  #include "langhooks.h"
  #include "intl.h"
! #include "diagnostics/text-sink.h"
  
  /* Prints out, if necessary, the name of the current function
     that caused an error.  */
  void
! diagnostic_report_current_function (diagnostics::text_sink &text_output,
! 				    const diagnostics::diagnostic_info *diag)
  {
!   location_t loc = diagnostic_location (diag);
    text_output.report_current_module (loc);
!   lang_hooks.print_error_function (text_output, LOCATION_FILE (loc), diag);
  }
  
  static void
! default_tree_diagnostic_text_starter (diagnostics::text_sink &text_output,
! 				      const diagnostics::diagnostic_info *diag)
  {
    pretty_printer *const pp = text_output.get_printer ();
!   diagnostic_report_current_function (text_output, diag);
!   pp_set_prefix (pp, text_output.build_prefix (*diag));
  }
  
  /* Default tree printer.   Handles declarations only.  */
*************** default_tree_printer (pretty_printer *pp
*** 110,117 ****
     to the DIAGNOSTIC location.  */
  
  static void
! set_inlining_locations (diagnostic_context *,
! 			diagnostic_info *diagnostic)
  {
    location_t loc = diagnostic_location (diagnostic);
    tree block = LOCATION_BLOCK (loc);
--- 110,117 ----
     to the DIAGNOSTIC location.  */
  
  static void
! set_inlining_locations (diagnostics::context *,
! 			diagnostics::diagnostic_info *diagnostic)
  {
    location_t loc = diagnostic_location (diagnostic);
    tree block = LOCATION_BLOCK (loc);
*************** set_inlining_locations (diagnostic_conte
*** 169,184 ****
    /* Set if all locations are in a system header.  */
    diagnostic->m_iinfo.m_allsyslocs = nsyslocs == ilocs.length ();
  
!   if (tree *ao = pp_ti_abstract_origin (&diagnostic->message))
      *ao = (tree)diagnostic->m_iinfo.m_ao;
  }
  
  /* Sets CONTEXT to use language independent diagnostics.  */
  void
! tree_diagnostics_defaults (diagnostic_context *context)
  {
!   diagnostic_text_starter (context) = default_tree_diagnostic_text_starter;
!   diagnostic_text_finalizer (context) = default_diagnostic_text_finalizer;
    context->set_format_decoder (default_tree_printer);
    context->set_set_locations_callback (set_inlining_locations);
    context->set_client_data_hooks (make_compiler_data_hooks ());
--- 169,184 ----
    /* Set if all locations are in a system header.  */
    diagnostic->m_iinfo.m_allsyslocs = nsyslocs == ilocs.length ();
  
!   if (tree *ao = pp_ti_abstract_origin (&diagnostic->m_message))
      *ao = (tree)diagnostic->m_iinfo.m_ao;
  }
  
  /* Sets CONTEXT to use language independent diagnostics.  */
  void
! tree_diagnostics_defaults (diagnostics::context *context)
  {
!   diagnostics::text_starter (context) = default_tree_diagnostic_text_starter;
!   diagnostics::text_finalizer (context) = diagnostics::default_text_finalizer;
    context->set_format_decoder (default_tree_printer);
    context->set_set_locations_callback (set_inlining_locations);
    context->set_client_data_hooks (make_compiler_data_hooks ());
diff -Nrcpad gcc-16-20250720/gcc/tree-diagnostic.h gcc-16-20250727/gcc/tree-diagnostic.h
*** gcc-16-20250720/gcc/tree-diagnostic.h	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-diagnostic.h	Sun Jul 27 22:32:17 2025
*************** along with GCC; see the file COPYING3.
*** 48,57 ****
         ? diagnostic_abstract_origin (DI)		\
         : current_function_decl)
  
! void diagnostic_report_current_function (diagnostic_context *,
! 					 const diagnostic_info *);
  
! void tree_diagnostics_defaults (diagnostic_context *context);
  bool default_tree_printer (pretty_printer *, text_info *, const char *,
  			   int, bool, bool, bool, bool *, pp_token_list &);
  
--- 48,57 ----
         ? diagnostic_abstract_origin (DI)		\
         : current_function_decl)
  
! void diagnostic_report_current_function (diagnostics::context *,
! 					 const diagnostics::diagnostic_info *);
  
! void tree_diagnostics_defaults (diagnostics::context *);
  bool default_tree_printer (pretty_printer *, text_info *, const char *,
  			   int, bool, bool, bool, bool *, pp_token_list &);
  
diff -Nrcpad gcc-16-20250720/gcc/tree-logical-location.cc gcc-16-20250727/gcc/tree-logical-location.cc
*** gcc-16-20250720/gcc/tree-logical-location.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-logical-location.cc	Sun Jul 27 22:32:17 2025
*************** along with GCC; see the file COPYING3.
*** 27,32 ****
--- 27,34 ----
  #include "langhooks.h"
  #include "intl.h"
  
+ using namespace diagnostics::logical_locations;
+ 
  static void
  assert_valid_tree (const_tree node)
  {
*************** assert_valid_tree (const_tree node)
*** 35,41 ****
    gcc_assert (TREE_CODE (node) != TRANSLATION_UNIT_DECL);
  }
  
! /* class tree_logical_location_manager : public logical_location_manager.  */
  
  const char *
  tree_logical_location_manager::get_short_name (key k) const
--- 37,44 ----
    gcc_assert (TREE_CODE (node) != TRANSLATION_UNIT_DECL);
  }
  
! /* class tree_logical_location_manager
!    : public diagnostics::logical_locations::manager.  */
  
  const char *
  tree_logical_location_manager::get_short_name (key k) const
*************** tree_logical_location_manager::get_inter
*** 81,87 ****
    return NULL;
  }
  
! enum logical_location_kind
  tree_logical_location_manager::get_kind (key k) const
  {
    tree node = tree_from_key (k);
--- 84,90 ----
    return NULL;
  }
  
! enum kind
  tree_logical_location_manager::get_kind (key k) const
  {
    tree node = tree_from_key (k);
*************** tree_logical_location_manager::get_kind
*** 90,107 ****
    switch (TREE_CODE (node))
      {
      default:
!       return logical_location_kind::unknown;
      case FUNCTION_DECL:
!       return logical_location_kind::function;
      case PARM_DECL:
!       return logical_location_kind::parameter;
      case VAR_DECL:
!       return logical_location_kind::variable;
      case NAMESPACE_DECL:
!       return logical_location_kind::namespace_;
  
      case RECORD_TYPE:
!       return logical_location_kind::type;
      }
  }
  
--- 93,110 ----
    switch (TREE_CODE (node))
      {
      default:
!       return kind::unknown;
      case FUNCTION_DECL:
!       return kind::function;
      case PARM_DECL:
!       return kind::parameter;
      case VAR_DECL:
!       return kind::variable;
      case NAMESPACE_DECL:
!       return kind::namespace_;
  
      case RECORD_TYPE:
!       return kind::type;
      }
  }
  
*************** tree_logical_location_manager::get_name_
*** 123,129 ****
    return label_text ();
  }
  
! logical_location
  tree_logical_location_manager::get_parent (key k) const
  {
    tree node = tree_from_key (k);
--- 126,132 ----
    return label_text ();
  }
  
! key
  tree_logical_location_manager::get_parent (key k) const
  {
    tree node = tree_from_key (k);
*************** tree_logical_location_manager::get_paren
*** 132,147 ****
    if (DECL_P (node))
      {
        if (!DECL_CONTEXT (node))
! 	return logical_location ();
        if (TREE_CODE (DECL_CONTEXT (node)) == TRANSLATION_UNIT_DECL)
! 	return logical_location ();
        return key_from_tree (DECL_CONTEXT (node));
      }
    else if (TYPE_P (node))
      {
        if (!TYPE_CONTEXT (node))
! 	return logical_location ();
        return key_from_tree (TYPE_CONTEXT (node));
      }
!   return logical_location ();
  }
--- 135,150 ----
    if (DECL_P (node))
      {
        if (!DECL_CONTEXT (node))
! 	return key ();
        if (TREE_CODE (DECL_CONTEXT (node)) == TRANSLATION_UNIT_DECL)
! 	return key ();
        return key_from_tree (DECL_CONTEXT (node));
      }
    else if (TYPE_P (node))
      {
        if (!TYPE_CONTEXT (node))
! 	return key ();
        return key_from_tree (TYPE_CONTEXT (node));
      }
!   return key ();
  }
diff -Nrcpad gcc-16-20250720/gcc/tree-logical-location.h gcc-16-20250727/gcc/tree-logical-location.h
*** gcc-16-20250720/gcc/tree-logical-location.h	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-logical-location.h	Sun Jul 27 22:32:17 2025
*************** along with GCC; see the file COPYING3.
*** 21,49 ****
  #ifndef GCC_TREE_LOGICAL_LOCATION_H
  #define GCC_TREE_LOGICAL_LOCATION_H
  
! #include "logical-location.h"
  
! /* A subclass of logical_location_manager in which the keys are
!    "tree".
     Note that there is no integration with the garbage collector,
!    and so logical_location instances can only be short-lived.  */
! class tree_logical_location_manager : public logical_location_manager
  {
  public:
    const char *get_short_name (key) const final override;
    const char *get_name_with_scope (key) const final override;
    const char *get_internal_name (key) const final override;
!   enum logical_location_kind get_kind (key) const final override;
    label_text get_name_for_path_output (key) const final override;
    key get_parent (key) const final override;
  
!   static tree tree_from_key (logical_location k)
    {
      return const_cast<tree> (k.cast_to<const_tree> ());
    }
!   static logical_location key_from_tree (tree node)
    {
!     return logical_location::from_ptr (node);
    }
  };
  
--- 21,53 ----
  #ifndef GCC_TREE_LOGICAL_LOCATION_H
  #define GCC_TREE_LOGICAL_LOCATION_H
  
! #include "diagnostics/logical-locations.h"
  
! /* A subclass of diagnostics::logical_locations::manager in which the
!    keys are "tree".
     Note that there is no integration with the garbage collector,
!    and so key instances can only be short-lived.  */
! class tree_logical_location_manager
!   : public diagnostics::logical_locations::manager
  {
  public:
+   using key = diagnostics::logical_locations::key;
+   using kind = diagnostics::logical_locations::kind;
+ 
    const char *get_short_name (key) const final override;
    const char *get_name_with_scope (key) const final override;
    const char *get_internal_name (key) const final override;
!   kind get_kind (key) const final override;
    label_text get_name_for_path_output (key) const final override;
    key get_parent (key) const final override;
  
!   static tree tree_from_key (key k)
    {
      return const_cast<tree> (k.cast_to<const_tree> ());
    }
!   static key key_from_tree (tree node)
    {
!     return key::from_ptr (node);
    }
  };
  
diff -Nrcpad gcc-16-20250720/gcc/tree-sra.cc gcc-16-20250727/gcc/tree-sra.cc
*** gcc-16-20250720/gcc/tree-sra.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-sra.cc	Sun Jul 27 22:32:17 2025
*************** sort_and_splice_var_accesses (tree var)
*** 2504,2509 ****
--- 2504,2515 ----
  		}
  	      unscalarizable_region = true;
  	    }
+ 	  /* If there the same place is accessed with two incompatible
+ 	     aggregate types, trying to base total scalarization on either of
+ 	     them can be wrong.  */
+ 	  if (!first_scalar && !types_compatible_p (access->type, ac2->type))
+ 	    bitmap_set_bit (cannot_scalarize_away_bitmap,
+ 			    DECL_UID (access->base));
  
  	  if (grp_same_access_path
  	      && (!ac2->grp_same_access_path
diff -Nrcpad gcc-16-20250720/gcc/tree-ssa-operands.cc gcc-16-20250727/gcc/tree-ssa-operands.cc
*** gcc-16-20250720/gcc/tree-ssa-operands.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-ssa-operands.cc	Sun Jul 27 22:32:17 2025
*************** operands_scanner::get_asm_stmt_operands
*** 721,727 ****
        constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
        oconstraints[i] = constraint;
        parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 	                       &allows_reg, &is_inout);
  
        /* This should have been split in gimplify_asm_expr.  */
        gcc_assert (!allows_reg || !is_inout);
--- 721,727 ----
        constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
        oconstraints[i] = constraint;
        parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 			       &allows_reg, &is_inout, nullptr);
  
        /* This should have been split in gimplify_asm_expr.  */
        gcc_assert (!allows_reg || !is_inout);
*************** operands_scanner::get_asm_stmt_operands
*** 740,746 ****
        tree link = gimple_asm_input_op (stmt, i);
        constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
        parse_input_constraint (&constraint, 0, 0, noutputs, 0, oconstraints,
! 	                      &allows_mem, &allows_reg);
  
        /* Memory operands are addressable.  Note that STMT needs the
  	 address of this operand.  */
--- 740,746 ----
        tree link = gimple_asm_input_op (stmt, i);
        constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
        parse_input_constraint (&constraint, 0, 0, noutputs, 0, oconstraints,
! 			      &allows_mem, &allows_reg, nullptr);
  
        /* Memory operands are addressable.  Note that STMT needs the
  	 address of this operand.  */
diff -Nrcpad gcc-16-20250720/gcc/tree-ssa-sink.cc gcc-16-20250727/gcc/tree-ssa-sink.cc
*** gcc-16-20250720/gcc/tree-ssa-sink.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-ssa-sink.cc	Sun Jul 27 22:32:17 2025
*************** statement_sink_location (gimple *stmt, b
*** 356,392 ****
  
    use = NULL;
  
!   /* If stmt is a store the one and only use needs to be the VOP
!      merging PHI node.  */
    if (virtual_operand_p (DEF_FROM_PTR (def_p)))
      {
        FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
  	{
  	  gimple *use_stmt = USE_STMT (use_p);
  
  	  /* A killing definition is not a use.  */
! 	  if ((gimple_has_lhs (use_stmt)
! 	       && operand_equal_p (gimple_get_lhs (stmt),
! 				   gimple_get_lhs (use_stmt), 0))
! 	      || stmt_kills_ref_p (use_stmt, gimple_get_lhs (stmt)))
  	    {
  	      /* If use_stmt is or might be a nop assignment then USE_STMT
  	         acts as a use as well as definition.  */
  	      if (stmt != use_stmt
! 		  && ref_maybe_used_by_stmt_p (use_stmt,
! 					       gimple_get_lhs (stmt)))
! 		return false;
  	      continue;
  	    }
  
! 	  if (gimple_code (use_stmt) != GIMPLE_PHI)
! 	    return false;
! 
! 	  if (use
! 	      && use != use_stmt)
! 	    return false;
  
! 	  use = use_stmt;
  	}
        if (!use)
  	return false;
--- 356,409 ----
  
    use = NULL;
  
!   /* If stmt is a store the one and only use needs to be a VUSE on
!      the live path.  */
    if (virtual_operand_p (DEF_FROM_PTR (def_p)))
      {
+       tree lhs = gimple_get_lhs (stmt);
+       ao_ref ref;
+       ao_ref_init (&ref, lhs);
        FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
  	{
  	  gimple *use_stmt = USE_STMT (use_p);
  
  	  /* A killing definition is not a use.  */
! 	  if (gimple_vdef (use_stmt)
! 	      && ((gimple_has_lhs (use_stmt)
! 		   && operand_equal_p (lhs,
! 				       gimple_get_lhs (use_stmt), 0))
! 		  || stmt_kills_ref_p (use_stmt, &ref)))
  	    {
  	      /* If use_stmt is or might be a nop assignment then USE_STMT
  	         acts as a use as well as definition.  */
  	      if (stmt != use_stmt
! 		  && ref_maybe_used_by_stmt_p (use_stmt, &ref))
! 		{
! 		  if (use && use != use_stmt)
! 		    return false;
! 		  use = use_stmt;
! 		}
  	      continue;
  	    }
  
! 	  if (is_a <gphi *> (use_stmt)
! 	      || ref_maybe_used_by_stmt_p (use_stmt, &ref))
! 	    {
! 	      if (use && use != use_stmt)
! 		return false;
! 	      use = use_stmt;
! 	      continue;
! 	    }
  
! 	  if (gimple_vdef (use_stmt))
! 	    {
! 	      if (stmt_may_clobber_ref_p_1 (use_stmt, &ref, false))
! 		return false;
! 	      /* We do not look past VDEFs, so treat them as sink location.  */
! 	      if (use && use != use_stmt)
! 		return false;
! 	      use = use_stmt;
! 	    }
  	}
        if (!use)
  	return false;
*************** statement_sink_location (gimple *stmt, b
*** 448,465 ****
  	  break;
  	}
        use = USE_STMT (one_use);
  
!       if (gimple_code (use) != GIMPLE_PHI)
! 	{
! 	  sinkbb = select_best_block (frombb, gimple_bb (use), stmt);
  
! 	  if (sinkbb == frombb)
! 	    return false;
  
! 	  *togsi = gsi_after_labels (sinkbb);
  
! 	  return true;
! 	}
      }
  
    sinkbb = find_bb_for_arg (as_a <gphi *> (use), DEF_FROM_PTR (def_p));
--- 465,490 ----
  	  break;
  	}
        use = USE_STMT (one_use);
+     }
  
!   if (gimple_code (use) != GIMPLE_PHI)
!     {
!       sinkbb = select_best_block (frombb, gimple_bb (use), stmt);
  
!       if (sinkbb == frombb)
! 	return false;
  
!       /* The SSA update for sinking of stores cannot insert PHIs, the
! 	 sink location has to lead to exit without crossing any CFG
! 	 merge points to paths not dominated by the sink location.  */
!       if (gimple_vdef (stmt)
! 	  && (!single_succ_p (sinkbb)
! 	      || single_succ (sinkbb)->index != EXIT_BLOCK))
! 	return false;
  
!       *togsi = gsi_after_labels (sinkbb);
! 
!       return true;
      }
  
    sinkbb = find_bb_for_arg (as_a <gphi *> (use), DEF_FROM_PTR (def_p));
diff -Nrcpad gcc-16-20250720/gcc/tree-ssa-structalias.cc gcc-16-20250727/gcc/tree-ssa-structalias.cc
*** gcc-16-20250720/gcc/tree-ssa-structalias.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-ssa-structalias.cc	Sun Jul 27 22:32:17 2025
*************** find_func_aliases (struct function *fn,
*** 3068,3074 ****
  	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
  	  oconstraints[i] = constraint;
  	  parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 				   &allows_reg, &is_inout);
  
  	  /* A memory constraint makes the address of the operand escape.  */
  	  if (!allows_reg && allows_mem)
--- 3068,3074 ----
  	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
  	  oconstraints[i] = constraint;
  	  parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 				   &allows_reg, &is_inout, nullptr);
  
  	  /* A memory constraint makes the address of the operand escape.  */
  	  if (!allows_reg && allows_mem)
*************** find_func_aliases (struct function *fn,
*** 3101,3107 ****
  	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
  
  	  parse_input_constraint (&constraint, 0, 0, noutputs, 0, oconstraints,
! 				  &allows_mem, &allows_reg);
  
  	  /* A memory constraint makes the address of the operand escape.  */
  	  if (!allows_reg && allows_mem)
--- 3101,3107 ----
  	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
  
  	  parse_input_constraint (&constraint, 0, 0, noutputs, 0, oconstraints,
! 				  &allows_mem, &allows_reg, nullptr);
  
  	  /* A memory constraint makes the address of the operand escape.  */
  	  if (!allows_reg && allows_mem)
diff -Nrcpad gcc-16-20250720/gcc/tree-vect-data-refs.cc gcc-16-20250727/gcc/tree-vect-data-refs.cc
*** gcc-16-20250720/gcc/tree-vect-data-refs.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-vect-data-refs.cc	Sun Jul 27 22:32:17 2025
*************** vect_vfa_access_size (vec_info *vinfo, d
*** 3956,3963 ****
      }
    tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
    int misalignment;
!   if (STMT_VINFO_VEC_STMTS (stmt_vinfo).exists ()
!       && ((misalignment = dr_misalignment (dr_info, vectype)), true)
        && (vect_supportable_dr_alignment (vinfo, dr_info, vectype, misalignment)
  	  == dr_explicit_realign_optimized))
      {
--- 3956,3962 ----
      }
    tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
    int misalignment;
!   if (((misalignment = dr_misalignment (dr_info, vectype)), true)
        && (vect_supportable_dr_alignment (vinfo, dr_info, vectype, misalignment)
  	  == dr_explicit_realign_optimized))
      {
*************** vect_describe_gather_scatter_call (stmt_
*** 4539,4548 ****
    info->ifn = gimple_call_internal_fn (call);
    info->decl = NULL_TREE;
    info->base = gimple_call_arg (call, 0);
!   info->offset = gimple_call_arg (call, 1);
    info->offset_dt = vect_unknown_def_type;
    info->offset_vectype = NULL_TREE;
!   info->scale = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
    info->element_type = TREE_TYPE (vectype);
    info->memory_type = TREE_TYPE (DR_REF (dr));
  }
--- 4538,4551 ----
    info->ifn = gimple_call_internal_fn (call);
    info->decl = NULL_TREE;
    info->base = gimple_call_arg (call, 0);
!   info->alias_ptr = gimple_call_arg
! 		     (call, internal_fn_alias_ptr_index (info->ifn));
!   info->offset = gimple_call_arg
! 		  (call, internal_fn_offset_index (info->ifn));
    info->offset_dt = vect_unknown_def_type;
    info->offset_vectype = NULL_TREE;
!   info->scale = TREE_INT_CST_LOW (gimple_call_arg
! 				  (call, internal_fn_scale_index (info->ifn)));
    info->element_type = TREE_TYPE (vectype);
    info->memory_type = TREE_TYPE (DR_REF (dr));
  }
*************** vect_check_gather_scatter (stmt_vec_info
*** 4667,4692 ****
    if (off == NULL_TREE)
      off = size_zero_node;
  
!   /* If base is not loop invariant, either off is 0, then we start with just
!      the constant offset in the loop invariant BASE and continue with base
!      as OFF, otherwise give up.
!      We could handle that case by gimplifying the addition of base + off
!      into some SSA_NAME and use that as off, but for now punt.  */
    if (!expr_invariant_in_loop_p (loop, base))
      {
!       if (!integer_zerop (off))
  	return false;
!       off = base;
!       base = size_int (pbytepos);
!     }
!   /* Otherwise put base + constant offset into the loop invariant BASE
!      and continue with OFF.  */
!   else
!     {
!       base = fold_convert (sizetype, base);
!       base = size_binop (PLUS_EXPR, base, size_int (pbytepos));
      }
  
    /* OFF at this point may be either a SSA_NAME or some tree expression
       from get_inner_reference.  Try to peel off loop invariants from it
       into BASE as long as possible.  */
--- 4670,4688 ----
    if (off == NULL_TREE)
      off = size_zero_node;
  
!   /* BASE must be loop invariant.  If it is not invariant, but OFF is, then we
!    * can fix that by swapping BASE and OFF.  */
    if (!expr_invariant_in_loop_p (loop, base))
      {
!       if (!expr_invariant_in_loop_p (loop, off))
  	return false;
! 
!       std::swap (base, off);
      }
  
+   base = fold_convert (sizetype, base);
+   base = size_binop (PLUS_EXPR, base, size_int (pbytepos));
+ 
    /* OFF at this point may be either a SSA_NAME or some tree expression
       from get_inner_reference.  Try to peel off loop invariants from it
       into BASE as long as possible.  */
*************** vect_check_gather_scatter (stmt_vec_info
*** 4864,4872 ****
--- 4860,4876 ----
        offset_vectype = NULL_TREE;
      }
  
+   gcc_checking_assert (expr_invariant_in_loop_p (loop, base));
+   gcc_checking_assert (!expr_invariant_in_loop_p (loop, off));
+ 
    info->ifn = ifn;
    info->decl = decl;
    info->base = base;
+ 
+   info->alias_ptr = build_int_cst
+     (reference_alias_ptr_type (DR_REF (dr)),
+      get_object_alignment (DR_REF (dr)));
+ 
    info->offset = off;
    info->offset_dt = vect_unknown_def_type;
    info->offset_vectype = offset_vectype;
*************** vect_find_stmt_data_reference (loop_p lo
*** 5056,5062 ****
  */
  
  opt_result
! vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf, bool *fatal)
  {
    class loop *loop = NULL;
    unsigned int i;
--- 5060,5066 ----
  */
  
  opt_result
! vect_analyze_data_refs (vec_info *vinfo, bool *fatal)
  {
    class loop *loop = NULL;
    unsigned int i;
*************** vect_analyze_data_refs (vec_info *vinfo,
*** 5075,5081 ****
    FOR_EACH_VEC_ELT (datarefs, i, dr)
      {
        enum { SG_NONE, GATHER, SCATTER } gatherscatter = SG_NONE;
-       poly_uint64 vf;
  
        gcc_assert (DR_REF (dr));
        stmt_vec_info stmt_info = vinfo->lookup_stmt (DR_STMT (dr));
--- 5079,5084 ----
*************** vect_analyze_data_refs (vec_info *vinfo,
*** 5267,5277 ****
  			     stmt_info->stmt, vectype);
  	}
  
-       /* Adjust the minimal vectorization factor according to the
- 	 vector type.  */
-       vf = TYPE_VECTOR_SUBPARTS (vectype);
-       *min_vf = upper_bound (*min_vf, vf);
- 
        /* Leave the BB vectorizer to pick the vector type later, based on
  	 the final dataref group size and SLP node size.  */
        if (is_a <loop_vec_info> (vinfo))
--- 5270,5275 ----
*************** vect_create_data_ref_ptr (vec_info *vinf
*** 5728,5735 ****
        standard_iv_increment_position (loop, &incr_gsi, &insert_after);
  
        create_iv (aggr_ptr_init, PLUS_EXPR,
! 		 fold_convert (aggr_ptr_type, iv_step),
! 		 aggr_ptr, loop, &incr_gsi, insert_after,
  		 &indx_before_incr, &indx_after_incr);
        incr = gsi_stmt (incr_gsi);
  
--- 5726,5732 ----
        standard_iv_increment_position (loop, &incr_gsi, &insert_after);
  
        create_iv (aggr_ptr_init, PLUS_EXPR,
! 		 iv_step, aggr_ptr, loop, &incr_gsi, insert_after,
  		 &indx_before_incr, &indx_after_incr);
        incr = gsi_stmt (incr_gsi);
  
*************** vect_create_data_ref_ptr (vec_info *vinf
*** 5757,5763 ****
      {
        standard_iv_increment_position (containing_loop, &incr_gsi,
  				      &insert_after);
!       create_iv (aptr, PLUS_EXPR, fold_convert (aggr_ptr_type, DR_STEP (dr)),
  		 aggr_ptr, containing_loop, &incr_gsi, insert_after,
  		 &indx_before_incr, &indx_after_incr);
        incr = gsi_stmt (incr_gsi);
--- 5754,5760 ----
      {
        standard_iv_increment_position (containing_loop, &incr_gsi,
  				      &insert_after);
!       create_iv (aptr, PLUS_EXPR, DR_STEP (dr),
  		 aggr_ptr, containing_loop, &incr_gsi, insert_after,
  		 &indx_before_incr, &indx_after_incr);
        incr = gsi_stmt (incr_gsi);
*************** vect_store_lanes_supported (tree vectype
*** 6080,6283 ****
  }
  
  
- /* Function vect_permute_store_chain.
- 
-    Given a chain of interleaved stores in DR_CHAIN of LENGTH that must be
-    a power of 2 or equal to 3, generate interleave_high/low stmts to reorder
-    the data correctly for the stores.  Return the final references for stores
-    in RESULT_CHAIN.
- 
-    E.g., LENGTH is 4 and the scalar type is short, i.e., VF is 8.
-    The input is 4 vectors each containing 8 elements.  We assign a number to
-    each element, the input sequence is:
- 
-    1st vec:   0  1  2  3  4  5  6  7
-    2nd vec:   8  9 10 11 12 13 14 15
-    3rd vec:  16 17 18 19 20 21 22 23
-    4th vec:  24 25 26 27 28 29 30 31
- 
-    The output sequence should be:
- 
-    1st vec:  0  8 16 24  1  9 17 25
-    2nd vec:  2 10 18 26  3 11 19 27
-    3rd vec:  4 12 20 28  5 13 21 30
-    4th vec:  6 14 22 30  7 15 23 31
- 
-    i.e., we interleave the contents of the four vectors in their order.
- 
-    We use interleave_high/low instructions to create such output.  The input of
-    each interleave_high/low operation is two vectors:
-    1st vec    2nd vec
-    0 1 2 3    4 5 6 7
-    the even elements of the result vector are obtained left-to-right from the
-    high/low elements of the first vector.  The odd elements of the result are
-    obtained left-to-right from the high/low elements of the second vector.
-    The output of interleave_high will be:   0 4 1 5
-    and of interleave_low:                   2 6 3 7
- 
- 
-    The permutation is done in log LENGTH stages.  In each stage interleave_high
-    and interleave_low stmts are created for each pair of vectors in DR_CHAIN,
-    where the first argument is taken from the first half of DR_CHAIN and the
-    second argument from it's second half.
-    In our example,
- 
-    I1: interleave_high (1st vec, 3rd vec)
-    I2: interleave_low (1st vec, 3rd vec)
-    I3: interleave_high (2nd vec, 4th vec)
-    I4: interleave_low (2nd vec, 4th vec)
- 
-    The output for the first stage is:
- 
-    I1:  0 16  1 17  2 18  3 19
-    I2:  4 20  5 21  6 22  7 23
-    I3:  8 24  9 25 10 26 11 27
-    I4: 12 28 13 29 14 30 15 31
- 
-    The output of the second stage, i.e. the final result is:
- 
-    I1:  0  8 16 24  1  9 17 25
-    I2:  2 10 18 26  3 11 19 27
-    I3:  4 12 20 28  5 13 21 30
-    I4:  6 14 22 30  7 15 23 31.  */
- 
- void
- vect_permute_store_chain (vec_info *vinfo, vec<tree> &dr_chain,
- 			  unsigned int length,
- 			  stmt_vec_info stmt_info,
- 			  gimple_stmt_iterator *gsi,
- 			  vec<tree> *result_chain)
- {
-   tree vect1, vect2, high, low;
-   gimple *perm_stmt;
-   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
-   tree perm_mask_low, perm_mask_high;
-   tree data_ref;
-   tree perm3_mask_low, perm3_mask_high;
-   unsigned int i, j, n, log_length = exact_log2 (length);
- 
-   result_chain->quick_grow (length);
-   memcpy (result_chain->address (), dr_chain.address (),
- 	  length * sizeof (tree));
- 
-   if (length == 3)
-     {
-       /* vect_grouped_store_supported ensures that this is constant.  */
-       unsigned int nelt = TYPE_VECTOR_SUBPARTS (vectype).to_constant ();
-       unsigned int j0 = 0, j1 = 0, j2 = 0;
- 
-       vec_perm_builder sel (nelt, nelt, 1);
-       sel.quick_grow (nelt);
-       vec_perm_indices indices;
-       for (j = 0; j < 3; j++)
-         {
- 	  int nelt0 = ((3 - j) * nelt) % 3;
- 	  int nelt1 = ((3 - j) * nelt + 1) % 3;
- 	  int nelt2 = ((3 - j) * nelt + 2) % 3;
- 
- 	  for (i = 0; i < nelt; i++)
- 	    {
- 	      if (3 * i + nelt0 < nelt)
- 		sel[3 * i + nelt0] = j0++;
- 	      if (3 * i + nelt1 < nelt)
- 		sel[3 * i + nelt1] = nelt + j1++;
- 	      if (3 * i + nelt2 < nelt)
- 		sel[3 * i + nelt2] = 0;
- 	    }
- 	  indices.new_vector (sel, 2, nelt);
- 	  perm3_mask_low = vect_gen_perm_mask_checked (vectype, indices);
- 
- 	  for (i = 0; i < nelt; i++)
- 	    {
- 	      if (3 * i + nelt0 < nelt)
- 		sel[3 * i + nelt0] = 3 * i + nelt0;
- 	      if (3 * i + nelt1 < nelt)
- 		sel[3 * i + nelt1] = 3 * i + nelt1;
- 	      if (3 * i + nelt2 < nelt)
- 		sel[3 * i + nelt2] = nelt + j2++;
- 	    }
- 	  indices.new_vector (sel, 2, nelt);
- 	  perm3_mask_high = vect_gen_perm_mask_checked (vectype, indices);
- 
- 	  vect1 = dr_chain[0];
- 	  vect2 = dr_chain[1];
- 
- 	  /* Create interleaving stmt:
- 	     low = VEC_PERM_EXPR <vect1, vect2,
- 				  {j, nelt, *, j + 1, nelt + j + 1, *,
- 				   j + 2, nelt + j + 2, *, ...}>  */
- 	  data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle3_low");
- 	  perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, vect1,
- 					   vect2, perm3_mask_low);
- 	  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 
- 	  vect1 = data_ref;
- 	  vect2 = dr_chain[2];
- 	  /* Create interleaving stmt:
- 	     low = VEC_PERM_EXPR <vect1, vect2,
- 				  {0, 1, nelt + j, 3, 4, nelt + j + 1,
- 				   6, 7, nelt + j + 2, ...}>  */
- 	  data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle3_high");
- 	  perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, vect1,
- 					   vect2, perm3_mask_high);
- 	  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	  (*result_chain)[j] = data_ref;
- 	}
-     }
-   else
-     {
-       /* If length is not equal to 3 then only power of 2 is supported.  */
-       gcc_assert (pow2p_hwi (length));
- 
-       /* The encoding has 2 interleaved stepped patterns.  */
-       poly_uint64 nelt = TYPE_VECTOR_SUBPARTS (vectype);
-       vec_perm_builder sel (nelt, 2, 3);
-       sel.quick_grow (6);
-       for (i = 0; i < 3; i++)
- 	{
- 	  sel[i * 2] = i;
- 	  sel[i * 2 + 1] = i + nelt;
- 	}
- 	vec_perm_indices indices (sel, 2, nelt);
- 	perm_mask_high = vect_gen_perm_mask_checked (vectype, indices);
- 
- 	for (i = 0; i < 6; i++)
- 	  sel[i] += exact_div (nelt, 2);
- 	indices.new_vector (sel, 2, nelt);
- 	perm_mask_low = vect_gen_perm_mask_checked (vectype, indices);
- 
- 	for (i = 0, n = log_length; i < n; i++)
- 	  {
- 	    for (j = 0; j < length/2; j++)
- 	      {
- 		vect1 = dr_chain[j];
- 		vect2 = dr_chain[j+length/2];
- 
- 		/* Create interleaving stmt:
- 		   high = VEC_PERM_EXPR <vect1, vect2, {0, nelt, 1, nelt+1,
- 							...}>  */
- 		high = make_temp_ssa_name (vectype, NULL, "vect_inter_high");
- 		perm_stmt = gimple_build_assign (high, VEC_PERM_EXPR, vect1,
- 						 vect2, perm_mask_high);
- 		vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 		(*result_chain)[2*j] = high;
- 
- 		/* Create interleaving stmt:
- 		   low = VEC_PERM_EXPR <vect1, vect2,
- 					{nelt/2, nelt*3/2, nelt/2+1, nelt*3/2+1,
- 					 ...}>  */
- 		low = make_temp_ssa_name (vectype, NULL, "vect_inter_low");
- 		perm_stmt = gimple_build_assign (low, VEC_PERM_EXPR, vect1,
- 						 vect2, perm_mask_low);
- 		vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 		(*result_chain)[2*j+1] = low;
- 	      }
- 	    memcpy (dr_chain.address (), result_chain->address (),
- 		    length * sizeof (tree));
- 	  }
-     }
- }
- 
  /* Function vect_setup_realignment
  
     This function is called when vectorizing an unaligned load using
--- 6077,6082 ----
*************** vect_load_lanes_supported (tree vectype,
*** 6708,7340 ****
    return IFN_LAST;
  }
  
- /* Function vect_permute_load_chain.
- 
-    Given a chain of interleaved loads in DR_CHAIN of LENGTH that must be
-    a power of 2 or equal to 3, generate extract_even/odd stmts to reorder
-    the input data correctly.  Return the final references for loads in
-    RESULT_CHAIN.
- 
-    E.g., LENGTH is 4 and the scalar type is short, i.e., VF is 8.
-    The input is 4 vectors each containing 8 elements. We assign a number to each
-    element, the input sequence is:
- 
-    1st vec:   0  1  2  3  4  5  6  7
-    2nd vec:   8  9 10 11 12 13 14 15
-    3rd vec:  16 17 18 19 20 21 22 23
-    4th vec:  24 25 26 27 28 29 30 31
- 
-    The output sequence should be:
- 
-    1st vec:  0 4  8 12 16 20 24 28
-    2nd vec:  1 5  9 13 17 21 25 29
-    3rd vec:  2 6 10 14 18 22 26 30
-    4th vec:  3 7 11 15 19 23 27 31
- 
-    i.e., the first output vector should contain the first elements of each
-    interleaving group, etc.
- 
-    We use extract_even/odd instructions to create such output.  The input of
-    each extract_even/odd operation is two vectors
-    1st vec    2nd vec
-    0 1 2 3    4 5 6 7
- 
-    and the output is the vector of extracted even/odd elements.  The output of
-    extract_even will be:   0 2 4 6
-    and of extract_odd:     1 3 5 7
- 
- 
-    The permutation is done in log LENGTH stages.  In each stage extract_even
-    and extract_odd stmts are created for each pair of vectors in DR_CHAIN in
-    their order.  In our example,
- 
-    E1: extract_even (1st vec, 2nd vec)
-    E2: extract_odd (1st vec, 2nd vec)
-    E3: extract_even (3rd vec, 4th vec)
-    E4: extract_odd (3rd vec, 4th vec)
- 
-    The output for the first stage will be:
- 
-    E1:  0  2  4  6  8 10 12 14
-    E2:  1  3  5  7  9 11 13 15
-    E3: 16 18 20 22 24 26 28 30
-    E4: 17 19 21 23 25 27 29 31
- 
-    In order to proceed and create the correct sequence for the next stage (or
-    for the correct output, if the second stage is the last one, as in our
-    example), we first put the output of extract_even operation and then the
-    output of extract_odd in RESULT_CHAIN (which is then copied to DR_CHAIN).
-    The input for the second stage is:
- 
-    1st vec (E1):  0  2  4  6  8 10 12 14
-    2nd vec (E3): 16 18 20 22 24 26 28 30
-    3rd vec (E2):  1  3  5  7  9 11 13 15
-    4th vec (E4): 17 19 21 23 25 27 29 31
- 
-    The output of the second stage:
- 
-    E1: 0 4  8 12 16 20 24 28
-    E2: 2 6 10 14 18 22 26 30
-    E3: 1 5  9 13 17 21 25 29
-    E4: 3 7 11 15 19 23 27 31
- 
-    And RESULT_CHAIN after reordering:
- 
-    1st vec (E1):  0 4  8 12 16 20 24 28
-    2nd vec (E3):  1 5  9 13 17 21 25 29
-    3rd vec (E2):  2 6 10 14 18 22 26 30
-    4th vec (E4):  3 7 11 15 19 23 27 31.  */
- 
- static void
- vect_permute_load_chain (vec_info *vinfo, vec<tree> dr_chain,
- 			 unsigned int length,
- 			 stmt_vec_info stmt_info,
- 			 gimple_stmt_iterator *gsi,
- 			 vec<tree> *result_chain)
- {
-   tree data_ref, first_vect, second_vect;
-   tree perm_mask_even, perm_mask_odd;
-   tree perm3_mask_low, perm3_mask_high;
-   gimple *perm_stmt;
-   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
-   unsigned int i, j, log_length = exact_log2 (length);
- 
-   result_chain->quick_grow (length);
-   memcpy (result_chain->address (), dr_chain.address (),
- 	  length * sizeof (tree));
- 
-   if (length == 3)
-     {
-       /* vect_grouped_load_supported ensures that this is constant.  */
-       unsigned nelt = TYPE_VECTOR_SUBPARTS (vectype).to_constant ();
-       unsigned int k;
- 
-       vec_perm_builder sel (nelt, nelt, 1);
-       sel.quick_grow (nelt);
-       vec_perm_indices indices;
-       for (k = 0; k < 3; k++)
- 	{
- 	  for (i = 0; i < nelt; i++)
- 	    if (3 * i + k < 2 * nelt)
- 	      sel[i] = 3 * i + k;
- 	    else
- 	      sel[i] = 0;
- 	  indices.new_vector (sel, 2, nelt);
- 	  perm3_mask_low = vect_gen_perm_mask_checked (vectype, indices);
- 
- 	  for (i = 0, j = 0; i < nelt; i++)
- 	    if (3 * i + k < 2 * nelt)
- 	      sel[i] = i;
- 	    else
- 	      sel[i] = nelt + ((nelt + k) % 3) + 3 * (j++);
- 	  indices.new_vector (sel, 2, nelt);
- 	  perm3_mask_high = vect_gen_perm_mask_checked (vectype, indices);
- 
- 	  first_vect = dr_chain[0];
- 	  second_vect = dr_chain[1];
- 
- 	  /* Create interleaving stmt (low part of):
- 	     low = VEC_PERM_EXPR <first_vect, second_vect2, {k, 3 + k, 6 + k,
- 							     ...}>  */
- 	  data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle3_low");
- 	  perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, first_vect,
- 					   second_vect, perm3_mask_low);
- 	  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 
- 	  /* Create interleaving stmt (high part of):
- 	     high = VEC_PERM_EXPR <first_vect, second_vect2, {k, 3 + k, 6 + k,
- 							      ...}>  */
- 	  first_vect = data_ref;
- 	  second_vect = dr_chain[2];
- 	  data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle3_high");
- 	  perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, first_vect,
- 					   second_vect, perm3_mask_high);
- 	  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	  (*result_chain)[k] = data_ref;
- 	}
-     }
-   else
-     {
-       /* If length is not equal to 3 then only power of 2 is supported.  */
-       gcc_assert (pow2p_hwi (length));
- 
-       /* The encoding has a single stepped pattern.  */
-       poly_uint64 nelt = TYPE_VECTOR_SUBPARTS (vectype);
-       vec_perm_builder sel (nelt, 1, 3);
-       sel.quick_grow (3);
-       for (i = 0; i < 3; ++i)
- 	sel[i] = i * 2;
-       vec_perm_indices indices (sel, 2, nelt);
-       perm_mask_even = vect_gen_perm_mask_checked (vectype, indices);
- 
-       for (i = 0; i < 3; ++i)
- 	sel[i] = i * 2 + 1;
-       indices.new_vector (sel, 2, nelt);
-       perm_mask_odd = vect_gen_perm_mask_checked (vectype, indices);
- 
-       for (i = 0; i < log_length; i++)
- 	{
- 	  for (j = 0; j < length; j += 2)
- 	    {
- 	      first_vect = dr_chain[j];
- 	      second_vect = dr_chain[j+1];
- 
- 	      /* data_ref = permute_even (first_data_ref, second_data_ref);  */
- 	      data_ref = make_temp_ssa_name (vectype, NULL, "vect_perm_even");
- 	      perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
- 					       first_vect, second_vect,
- 					       perm_mask_even);
- 	      vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	      (*result_chain)[j/2] = data_ref;
- 
- 	      /* data_ref = permute_odd (first_data_ref, second_data_ref);  */
- 	      data_ref = make_temp_ssa_name (vectype, NULL, "vect_perm_odd");
- 	      perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
- 					       first_vect, second_vect,
- 					       perm_mask_odd);
- 	      vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	      (*result_chain)[j/2+length/2] = data_ref;
- 	    }
- 	  memcpy (dr_chain.address (), result_chain->address (),
- 		  length * sizeof (tree));
- 	}
-     }
- }
- 
- /* Function vect_shift_permute_load_chain.
- 
-    Given a chain of loads in DR_CHAIN of LENGTH 2 or 3, generate
-    sequence of stmts to reorder the input data accordingly.
-    Return the final references for loads in RESULT_CHAIN.
-    Return true if successed, false otherwise.
- 
-    E.g., LENGTH is 3 and the scalar type is short, i.e., VF is 8.
-    The input is 3 vectors each containing 8 elements.  We assign a
-    number to each element, the input sequence is:
- 
-    1st vec:   0  1  2  3  4  5  6  7
-    2nd vec:   8  9 10 11 12 13 14 15
-    3rd vec:  16 17 18 19 20 21 22 23
- 
-    The output sequence should be:
- 
-    1st vec:  0 3 6  9 12 15 18 21
-    2nd vec:  1 4 7 10 13 16 19 22
-    3rd vec:  2 5 8 11 14 17 20 23
- 
-    We use 3 shuffle instructions and 3 * 3 - 1 shifts to create such output.
- 
-    First we shuffle all 3 vectors to get correct elements order:
- 
-    1st vec:  ( 0  3  6) ( 1  4  7) ( 2  5)
-    2nd vec:  ( 8 11 14) ( 9 12 15) (10 13)
-    3rd vec:  (16 19 22) (17 20 23) (18 21)
- 
-    Next we unite and shift vector 3 times:
- 
-    1st step:
-      shift right by 6 the concatenation of:
-      "1st vec" and  "2nd vec"
-        ( 0  3  6) ( 1  4  7) |( 2  5) _ ( 8 11 14) ( 9 12 15)| (10 13)
-      "2nd vec" and  "3rd vec"
-        ( 8 11 14) ( 9 12 15) |(10 13) _ (16 19 22) (17 20 23)| (18 21)
-      "3rd vec" and  "1st vec"
-        (16 19 22) (17 20 23) |(18 21) _ ( 0  3  6) ( 1  4  7)| ( 2  5)
- 			     | New vectors                   |
- 
-      So that now new vectors are:
- 
-      1st vec:  ( 2  5) ( 8 11 14) ( 9 12 15)
-      2nd vec:  (10 13) (16 19 22) (17 20 23)
-      3rd vec:  (18 21) ( 0  3  6) ( 1  4  7)
- 
-    2nd step:
-      shift right by 5 the concatenation of:
-      "1st vec" and  "3rd vec"
-        ( 2  5) ( 8 11 14) |( 9 12 15) _ (18 21) ( 0  3  6)| ( 1  4  7)
-      "2nd vec" and  "1st vec"
-        (10 13) (16 19 22) |(17 20 23) _ ( 2  5) ( 8 11 14)| ( 9 12 15)
-      "3rd vec" and  "2nd vec"
-        (18 21) ( 0  3  6) |( 1  4  7) _ (10 13) (16 19 22)| (17 20 23)
- 			  | New vectors                   |
- 
-      So that now new vectors are:
- 
-      1st vec:  ( 9 12 15) (18 21) ( 0  3  6)
-      2nd vec:  (17 20 23) ( 2  5) ( 8 11 14)
-      3rd vec:  ( 1  4  7) (10 13) (16 19 22) READY
- 
-    3rd step:
-      shift right by 5 the concatenation of:
-      "1st vec" and  "1st vec"
-        ( 9 12 15) (18 21) |( 0  3  6) _ ( 9 12 15) (18 21)| ( 0  3  6)
-      shift right by 3 the concatenation of:
-      "2nd vec" and  "2nd vec"
-                (17 20 23) |( 2  5) ( 8 11 14) _ (17 20 23)| ( 2  5) ( 8 11 14)
- 			  | New vectors                   |
- 
-      So that now all vectors are READY:
-      1st vec:  ( 0  3  6) ( 9 12 15) (18 21)
-      2nd vec:  ( 2  5) ( 8 11 14) (17 20 23)
-      3rd vec:  ( 1  4  7) (10 13) (16 19 22)
- 
-    This algorithm is faster than one in vect_permute_load_chain if:
-      1.  "shift of a concatination" is faster than general permutation.
- 	 This is usually so.
-      2.  The TARGET machine can't execute vector instructions in parallel.
- 	 This is because each step of the algorithm depends on previous.
- 	 The algorithm in vect_permute_load_chain is much more parallel.
- 
-    The algorithm is applicable only for LOAD CHAIN LENGTH less than VF.
- */
- 
- static bool
- vect_shift_permute_load_chain (vec_info *vinfo, vec<tree> dr_chain,
- 			       unsigned int length,
- 			       stmt_vec_info stmt_info,
- 			       gimple_stmt_iterator *gsi,
- 			       vec<tree> *result_chain)
- {
-   tree vect[3], vect_shift[3], data_ref, first_vect, second_vect;
-   tree perm2_mask1, perm2_mask2, perm3_mask;
-   tree select_mask, shift1_mask, shift2_mask, shift3_mask, shift4_mask;
-   gimple *perm_stmt;
- 
-   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
-   machine_mode vmode = TYPE_MODE (vectype);
-   unsigned int i;
-   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
- 
-   unsigned HOST_WIDE_INT nelt, vf;
-   if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nelt)
-       || !LOOP_VINFO_VECT_FACTOR (loop_vinfo).is_constant (&vf))
-     /* Not supported for variable-length vectors.  */
-     return false;
- 
-   vec_perm_builder sel (nelt, nelt, 1);
-   sel.quick_grow (nelt);
- 
-   result_chain->quick_grow (length);
-   memcpy (result_chain->address (), dr_chain.address (),
- 	  length * sizeof (tree));
- 
-   if (pow2p_hwi (length) && vf > 4)
-     {
-       unsigned int j, log_length = exact_log2 (length);
-       for (i = 0; i < nelt / 2; ++i)
- 	sel[i] = i * 2;
-       for (i = 0; i < nelt / 2; ++i)
- 	sel[nelt / 2 + i] = i * 2 + 1;
-       vec_perm_indices indices (sel, 2, nelt);
-       if (!can_vec_perm_const_p (vmode, vmode, indices))
- 	{
- 	  if (dump_enabled_p ())
- 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			     "shuffle of 2 fields structure is not \
- 			      supported by target\n");
- 	  return false;
- 	}
-       perm2_mask1 = vect_gen_perm_mask_checked (vectype, indices);
- 
-       for (i = 0; i < nelt / 2; ++i)
- 	sel[i] = i * 2 + 1;
-       for (i = 0; i < nelt / 2; ++i)
- 	sel[nelt / 2 + i] = i * 2;
-       indices.new_vector (sel, 2, nelt);
-       if (!can_vec_perm_const_p (vmode, vmode, indices))
- 	{
- 	  if (dump_enabled_p ())
- 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			     "shuffle of 2 fields structure is not \
- 			      supported by target\n");
- 	  return false;
- 	}
-       perm2_mask2 = vect_gen_perm_mask_checked (vectype, indices);
- 
-       /* Generating permutation constant to shift all elements.
- 	 For vector length 8 it is {4 5 6 7 8 9 10 11}.  */
-       for (i = 0; i < nelt; i++)
- 	sel[i] = nelt / 2 + i;
-       indices.new_vector (sel, 2, nelt);
-       if (!can_vec_perm_const_p (vmode, vmode, indices))
- 	{
- 	  if (dump_enabled_p ())
- 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			     "shift permutation is not supported by target\n");
- 	  return false;
- 	}
-       shift1_mask = vect_gen_perm_mask_checked (vectype, indices);
- 
-       /* Generating permutation constant to select vector from 2.
- 	 For vector length 8 it is {0 1 2 3 12 13 14 15}.  */
-       for (i = 0; i < nelt / 2; i++)
- 	sel[i] = i;
-       for (i = nelt / 2; i < nelt; i++)
- 	sel[i] = nelt + i;
-       indices.new_vector (sel, 2, nelt);
-       if (!can_vec_perm_const_p (vmode, vmode, indices))
- 	{
- 	  if (dump_enabled_p ())
- 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			     "select is not supported by target\n");
- 	  return false;
- 	}
-       select_mask = vect_gen_perm_mask_checked (vectype, indices);
- 
-       for (i = 0; i < log_length; i++)
- 	{
- 	  for (j = 0; j < length; j += 2)
- 	    {
- 	      first_vect = dr_chain[j];
- 	      second_vect = dr_chain[j + 1];
- 
- 	      data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle2");
- 	      perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
- 					       first_vect, first_vect,
- 					       perm2_mask1);
- 	      vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	      vect[0] = data_ref;
- 
- 	      data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle2");
- 	      perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
- 					       second_vect, second_vect,
- 					       perm2_mask2);
- 	      vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	      vect[1] = data_ref;
- 
- 	      data_ref = make_temp_ssa_name (vectype, NULL, "vect_shift");
- 	      perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
- 					       vect[0], vect[1], shift1_mask);
- 	      vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	      (*result_chain)[j/2 + length/2] = data_ref;
- 
- 	      data_ref = make_temp_ssa_name (vectype, NULL, "vect_select");
- 	      perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
- 					       vect[0], vect[1], select_mask);
- 	      vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	      (*result_chain)[j/2] = data_ref;
- 	    }
- 	  memcpy (dr_chain.address (), result_chain->address (),
- 		  length * sizeof (tree));
- 	}
-       return true;
-     }
-   if (length == 3 && vf > 2)
-     {
-       unsigned int k = 0, l = 0;
- 
-       /* Generating permutation constant to get all elements in rigth order.
- 	 For vector length 8 it is {0 3 6 1 4 7 2 5}.  */
-       for (i = 0; i < nelt; i++)
- 	{
- 	  if (3 * k + (l % 3) >= nelt)
- 	    {
- 	      k = 0;
- 	      l += (3 - (nelt % 3));
- 	    }
- 	  sel[i] = 3 * k + (l % 3);
- 	  k++;
- 	}
-       vec_perm_indices indices (sel, 2, nelt);
-       if (!can_vec_perm_const_p (vmode, vmode, indices))
- 	{
- 	  if (dump_enabled_p ())
- 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			     "shuffle of 3 fields structure is not \
- 			      supported by target\n");
- 	  return false;
- 	}
-       perm3_mask = vect_gen_perm_mask_checked (vectype, indices);
- 
-       /* Generating permutation constant to shift all elements.
- 	 For vector length 8 it is {6 7 8 9 10 11 12 13}.  */
-       for (i = 0; i < nelt; i++)
- 	sel[i] = 2 * (nelt / 3) + (nelt % 3) + i;
-       indices.new_vector (sel, 2, nelt);
-       if (!can_vec_perm_const_p (vmode, vmode, indices))
- 	{
- 	  if (dump_enabled_p ())
- 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			     "shift permutation is not supported by target\n");
- 	  return false;
- 	}
-       shift1_mask = vect_gen_perm_mask_checked (vectype, indices);
- 
-       /* Generating permutation constant to shift all elements.
- 	 For vector length 8 it is {5 6 7 8 9 10 11 12}.  */
-       for (i = 0; i < nelt; i++)
- 	sel[i] = 2 * (nelt / 3) + 1 + i;
-       indices.new_vector (sel, 2, nelt);
-       if (!can_vec_perm_const_p (vmode, vmode, indices))
- 	{
- 	  if (dump_enabled_p ())
- 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			     "shift permutation is not supported by target\n");
- 	  return false;
- 	}
-       shift2_mask = vect_gen_perm_mask_checked (vectype, indices);
- 
-       /* Generating permutation constant to shift all elements.
- 	 For vector length 8 it is {3 4 5 6 7 8 9 10}.  */
-       for (i = 0; i < nelt; i++)
- 	sel[i] = (nelt / 3) + (nelt % 3) / 2 + i;
-       indices.new_vector (sel, 2, nelt);
-       if (!can_vec_perm_const_p (vmode, vmode, indices))
- 	{
- 	  if (dump_enabled_p ())
- 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			     "shift permutation is not supported by target\n");
- 	  return false;
- 	}
-       shift3_mask = vect_gen_perm_mask_checked (vectype, indices);
- 
-       /* Generating permutation constant to shift all elements.
- 	 For vector length 8 it is {5 6 7 8 9 10 11 12}.  */
-       for (i = 0; i < nelt; i++)
- 	sel[i] = 2 * (nelt / 3) + (nelt % 3) / 2 + i;
-       indices.new_vector (sel, 2, nelt);
-       if (!can_vec_perm_const_p (vmode, vmode, indices))
- 	{
- 	  if (dump_enabled_p ())
- 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			     "shift permutation is not supported by target\n");
- 	  return false;
- 	}
-       shift4_mask = vect_gen_perm_mask_checked (vectype, indices);
- 
-       for (k = 0; k < 3; k++)
- 	{
- 	  data_ref = make_temp_ssa_name (vectype, NULL, "vect_shuffle3");
- 	  perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
- 					   dr_chain[k], dr_chain[k],
- 					   perm3_mask);
- 	  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	  vect[k] = data_ref;
- 	}
- 
-       for (k = 0; k < 3; k++)
- 	{
- 	  data_ref = make_temp_ssa_name (vectype, NULL, "vect_shift1");
- 	  perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
- 					   vect[k % 3], vect[(k + 1) % 3],
- 					   shift1_mask);
- 	  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	  vect_shift[k] = data_ref;
- 	}
- 
-       for (k = 0; k < 3; k++)
- 	{
- 	  data_ref = make_temp_ssa_name (vectype, NULL, "vect_shift2");
- 	  perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR,
- 					   vect_shift[(4 - k) % 3],
- 					   vect_shift[(3 - k) % 3],
- 					   shift2_mask);
- 	  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
- 	  vect[k] = data_ref;
- 	}
- 
-       (*result_chain)[3 - (nelt % 3)] = vect[2];
- 
-       data_ref = make_temp_ssa_name (vectype, NULL, "vect_shift3");
-       perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, vect[0],
- 				       vect[0], shift3_mask);
-       vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
-       (*result_chain)[nelt % 3] = data_ref;
- 
-       data_ref = make_temp_ssa_name (vectype, NULL, "vect_shift4");
-       perm_stmt = gimple_build_assign (data_ref, VEC_PERM_EXPR, vect[1],
- 				       vect[1], shift4_mask);
-       vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
-       (*result_chain)[0] = data_ref;
-       return true;
-     }
-   return false;
- }
- 
- /* Function vect_transform_grouped_load.
- 
-    Given a chain of input interleaved data-refs (in DR_CHAIN), build statements
-    to perform their permutation and ascribe the result vectorized statements to
-    the scalar statements.
- */
- 
- void
- vect_transform_grouped_load (vec_info *vinfo, stmt_vec_info stmt_info,
- 			     vec<tree> dr_chain,
- 			     int size, gimple_stmt_iterator *gsi)
- {
-   machine_mode mode;
-   vec<tree> result_chain = vNULL;
- 
-   /* DR_CHAIN contains input data-refs that are a part of the interleaving.
-      RESULT_CHAIN is the output of vect_permute_load_chain, it contains permuted
-      vectors, that are ready for vector computation.  */
-   result_chain.create (size);
- 
-   /* If reassociation width for vector type is 2 or greater target machine can
-      execute 2 or more vector instructions in parallel.  Otherwise try to
-      get chain for loads group using vect_shift_permute_load_chain.  */
-   mode = TYPE_MODE (STMT_VINFO_VECTYPE (stmt_info));
-   if (targetm.sched.reassociation_width (VEC_PERM_EXPR, mode) > 1
-       || pow2p_hwi (size)
-       || !vect_shift_permute_load_chain (vinfo, dr_chain, size, stmt_info,
- 					 gsi, &result_chain))
-     vect_permute_load_chain (vinfo, dr_chain,
- 			     size, stmt_info, gsi, &result_chain);
-   vect_record_grouped_load_vectors (vinfo, stmt_info, result_chain);
-   result_chain.release ();
- }
- 
- /* RESULT_CHAIN contains the output of a group of grouped loads that were
-    generated as part of the vectorization of STMT_INFO.  Assign the statement
-    for each vector to the associated scalar statement.  */
- 
- void
- vect_record_grouped_load_vectors (vec_info *, stmt_vec_info stmt_info,
- 				  vec<tree> result_chain)
- {
-   stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
-   unsigned int i, gap_count;
-   tree tmp_data_ref;
- 
-   /* Put a permuted data-ref in the VECTORIZED_STMT field.
-      Since we scan the chain starting from it's first node, their order
-      corresponds the order of data-refs in RESULT_CHAIN.  */
-   stmt_vec_info next_stmt_info = first_stmt_info;
-   gap_count = 1;
-   FOR_EACH_VEC_ELT (result_chain, i, tmp_data_ref)
-     {
-       if (!next_stmt_info)
- 	break;
- 
-       /* Skip the gaps.  Loads created for the gaps will be removed by dead
-        code elimination pass later.  No need to check for the first stmt in
-        the group, since it always exists.
-        DR_GROUP_GAP is the number of steps in elements from the previous
-        access (if there is no gap DR_GROUP_GAP is 1).  We skip loads that
-        correspond to the gaps.  */
-       if (next_stmt_info != first_stmt_info
- 	  && gap_count < DR_GROUP_GAP (next_stmt_info))
- 	{
- 	  gap_count++;
- 	  continue;
- 	}
- 
-       /* ???  The following needs cleanup after the removal of
-          DR_GROUP_SAME_DR_STMT.  */
-       if (next_stmt_info)
-         {
- 	  gimple *new_stmt = SSA_NAME_DEF_STMT (tmp_data_ref);
- 	  /* We assume that if VEC_STMT is not NULL, this is a case of multiple
- 	     copies, and we put the new vector statement last.  */
- 	  STMT_VINFO_VEC_STMTS (next_stmt_info).safe_push (new_stmt);
- 
- 	  next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
- 	  gap_count = 1;
-         }
-     }
- }
- 
  /* Function vect_force_dr_alignment_p.
  
     Returns whether the alignment of a DECL can be forced to be aligned
--- 6507,6512 ----
*************** vect_can_force_dr_alignment_p (const_tre
*** 7362,7374 ****
     alignment.
     If CHECK_ALIGNED_ACCESSES is TRUE, check if the access is supported even
     it is aligned, i.e., check if it is possible to vectorize it with different
!    alignment.  */
  
  enum dr_alignment_support
  vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
! 			       tree vectype, int misalignment)
  {
!   data_reference *dr = dr_info->dr;
    stmt_vec_info stmt_info = dr_info->stmt;
    machine_mode mode = TYPE_MODE (vectype);
    loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
--- 6534,6547 ----
     alignment.
     If CHECK_ALIGNED_ACCESSES is TRUE, check if the access is supported even
     it is aligned, i.e., check if it is possible to vectorize it with different
!    alignment.  If GS_INFO is passed we are dealing with a gather/scatter.  */
  
  enum dr_alignment_support
  vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
! 			       tree vectype, int misalignment,
! 			       gather_scatter_info *gs_info)
  {
!   data_reference *dr = dr_info ? dr_info->dr : nullptr;
    stmt_vec_info stmt_info = dr_info->stmt;
    machine_mode mode = TYPE_MODE (vectype);
    loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
*************** vect_supportable_dr_alignment (vec_info
*** 7380,7393 ****
    else if (dr_safe_speculative_read_required (stmt_info))
      return dr_unaligned_unsupported;
  
-   /* For now assume all conditional loads/stores support unaligned
-      access without any special code.  */
-   if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
-     if (gimple_call_internal_p (stmt)
- 	&& (gimple_call_internal_fn (stmt) == IFN_MASK_LOAD
- 	    || gimple_call_internal_fn (stmt) == IFN_MASK_STORE))
-       return dr_unaligned_supported;
- 
    if (loop_vinfo)
      {
        vect_loop = LOOP_VINFO_LOOP (loop_vinfo);
--- 6553,6558 ----
*************** vect_supportable_dr_alignment (vec_info
*** 7457,7463 ****
          }
      } */
  
!   if (DR_IS_READ (dr))
      {
        if (can_implement_p (vec_realign_load_optab, mode)
  	  && (!targetm.vectorize.builtin_mask_for_load
--- 6622,6628 ----
          }
      } */
  
!   if (dr && DR_IS_READ (dr))
      {
        if (can_implement_p (vec_realign_load_optab, mode)
  	  && (!targetm.vectorize.builtin_mask_for_load
*************** vect_supportable_dr_alignment (vec_info
*** 7485,7494 ****
  
    bool is_packed = false;
    tree type = TREE_TYPE (DR_REF (dr));
    if (misalignment == DR_MISALIGNMENT_UNKNOWN)
!     is_packed = not_size_aligned (DR_REF (dr));
    if (targetm.vectorize.support_vector_misalignment (mode, type, misalignment,
! 						     is_packed))
      return dr_unaligned_supported;
  
    /* Unsupported.  */
--- 6650,6692 ----
  
    bool is_packed = false;
    tree type = TREE_TYPE (DR_REF (dr));
+   bool is_gather_scatter = gs_info != nullptr;
    if (misalignment == DR_MISALIGNMENT_UNKNOWN)
!     {
!       if (!is_gather_scatter || dr != nullptr)
! 	is_packed = not_size_aligned (DR_REF (dr));
!       else
! 	{
! 	  /* Gather-scatter accesses normally perform only component accesses
! 	     so alignment is irrelevant for them.  Targets like riscv do care
! 	     about scalar alignment in vector accesses, though, so check scalar
! 	     alignment here.  We determined the alias pointer as well as the
! 	     base alignment during pattern recognition and can re-use it here.
! 
! 	     As we do not have an analyzed dataref we only know the alignment
! 	     of the reference itself and nothing about init, steps, etc.
! 	     For now don't try harder to determine misalignment and
! 	     just assume it is unknown.  We consider the type packed if its
! 	     scalar alignment is lower than the natural alignment of a vector
! 	     element's type.  */
! 
! 	  gcc_assert (!GATHER_SCATTER_LEGACY_P (*gs_info));
! 	  gcc_assert (dr == nullptr);
! 
! 	  tree inner_vectype = TREE_TYPE (vectype);
! 
! 	  unsigned HOST_WIDE_INT scalar_align
! 	    = tree_to_uhwi (gs_info->alias_ptr);
! 	  unsigned HOST_WIDE_INT inner_vectype_sz
! 	    = tree_to_uhwi (TYPE_SIZE (inner_vectype));
! 
! 	  bool is_misaligned = scalar_align < inner_vectype_sz;
! 	  is_packed = scalar_align > 1 && is_misaligned;
! 	}
!     }
    if (targetm.vectorize.support_vector_misalignment (mode, type, misalignment,
! 						     is_packed,
! 						     is_gather_scatter))
      return dr_unaligned_supported;
  
    /* Unsupported.  */
diff -Nrcpad gcc-16-20250720/gcc/tree-vect-loop.cc gcc-16-20250727/gcc/tree-vect-loop.cc
*** gcc-16-20250720/gcc/tree-vect-loop.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-vect-loop.cc	Sun Jul 27 22:32:17 2025
*************** vect_analyze_loop_2 (loop_vec_info loop_
*** 2373,2379 ****
    opt_result ok = opt_result::success ();
    int res;
    unsigned int max_vf = MAX_VECTORIZATION_FACTOR;
-   poly_uint64 min_vf = 2;
    loop_vec_info orig_loop_vinfo = NULL;
  
    /* If we are dealing with an epilogue then orig_loop_vinfo points to the
--- 2373,2378 ----
*************** vect_analyze_loop_2 (loop_vec_info loop_
*** 2420,2426 ****
    /* Analyze the data references and also adjust the minimal
       vectorization factor according to the loads and stores.  */
  
!   ok = vect_analyze_data_refs (loop_vinfo, &min_vf, &fatal);
    if (!ok)
      {
        if (dump_enabled_p ())
--- 2419,2425 ----
    /* Analyze the data references and also adjust the minimal
       vectorization factor according to the loads and stores.  */
  
!   ok = vect_analyze_data_refs (loop_vinfo, &fatal);
    if (!ok)
      {
        if (dump_enabled_p ())
*************** vect_analyze_loop_2 (loop_vec_info loop_
*** 2485,2493 ****
  			 "bad data dependence.\n");
        return ok;
      }
-   if (max_vf != MAX_VECTORIZATION_FACTOR
-       && maybe_lt (max_vf, min_vf))
-     return opt_result::failure_at (vect_location, "bad data dependence.\n");
    LOOP_VINFO_MAX_VECT_FACTOR (loop_vinfo) = max_vf;
  
    ok = vect_set_stmts_vectype (loop_vinfo);
--- 2484,2489 ----
*************** again:
*** 2887,2893 ****
  	continue;
        vinfo = DR_GROUP_FIRST_ELEMENT (vinfo);
        unsigned int size = DR_GROUP_SIZE (vinfo);
!       tree vectype = STMT_VINFO_VECTYPE (vinfo);
        if (vect_store_lanes_supported (vectype, size, false) == IFN_LAST
  	 && ! known_eq (TYPE_VECTOR_SUBPARTS (vectype), 1U)
  	 && ! vect_grouped_store_supported (vectype, size))
--- 2883,2889 ----
  	continue;
        vinfo = DR_GROUP_FIRST_ELEMENT (vinfo);
        unsigned int size = DR_GROUP_SIZE (vinfo);
!       tree vectype = SLP_TREE_VECTYPE (SLP_INSTANCE_TREE (instance));
        if (vect_store_lanes_supported (vectype, size, false) == IFN_LAST
  	 && ! known_eq (TYPE_VECTOR_SUBPARTS (vectype), 1U)
  	 && ! vect_grouped_store_supported (vectype, size))
*************** again:
*** 2901,2907 ****
  	      vinfo = DR_GROUP_FIRST_ELEMENT (vinfo);
  	      bool single_element_p = !DR_GROUP_NEXT_ELEMENT (vinfo);
  	      size = DR_GROUP_SIZE (vinfo);
! 	      vectype = STMT_VINFO_VECTYPE (vinfo);
  	      if (vect_load_lanes_supported (vectype, size, false) == IFN_LAST
  		  && ! vect_grouped_load_supported (vectype, single_element_p,
  						    size))
--- 2897,2903 ----
  	      vinfo = DR_GROUP_FIRST_ELEMENT (vinfo);
  	      bool single_element_p = !DR_GROUP_NEXT_ELEMENT (vinfo);
  	      size = DR_GROUP_SIZE (vinfo);
! 	      vectype = SLP_TREE_VECTYPE (node);
  	      if (vect_load_lanes_supported (vectype, size, false) == IFN_LAST
  		  && ! vect_grouped_load_supported (vectype, single_element_p,
  						    size))
*************** vectorize_fold_left_reduction (loop_vec_
*** 6693,6699 ****
  			       vec_loop_lens *lens)
  {
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
!   tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
    internal_fn mask_reduc_fn = get_masked_reduction_fn (reduc_fn, vectype_in);
  
    gcc_assert (!nested_in_vect_loop_p (loop, stmt_info));
--- 6689,6695 ----
  			       vec_loop_lens *lens)
  {
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
!   tree vectype_out = SLP_TREE_VECTYPE (slp_node);
    internal_fn mask_reduc_fn = get_masked_reduction_fn (reduc_fn, vectype_in);
  
    gcc_assert (!nested_in_vect_loop_p (loop, stmt_info));
*************** vectorizable_lane_reducing (loop_vec_inf
*** 7080,7093 ****
  
    for (int i = 0; i < (int) gimple_num_ops (stmt) - 1; i++)
      {
-       stmt_vec_info def_stmt_info;
        slp_tree slp_op;
        tree op;
        tree vectype;
        enum vect_def_type dt;
  
!       if (!vect_is_simple_use (loop_vinfo, stmt_info, slp_node, i, &op,
! 			       &slp_op, &dt, &vectype, &def_stmt_info))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 7076,7088 ----
  
    for (int i = 0; i < (int) gimple_num_ops (stmt) - 1; i++)
      {
        slp_tree slp_op;
        tree op;
        tree vectype;
        enum vect_def_type dt;
  
!       if (!vect_is_simple_use (loop_vinfo, slp_node, i, &op,
! 			       &slp_op, &dt, &vectype))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vectorizable_reduction (loop_vec_info lo
*** 7514,7520 ****
  
        stmt_vec_info def_stmt_info;
        enum vect_def_type dt;
!       if (!vect_is_simple_use (loop_vinfo, stmt_info, slp_for_stmt_info,
  			       i + opno_adjust, &op.ops[i], &slp_op[i], &dt,
  			       &vectype_op[i], &def_stmt_info))
  	{
--- 7509,7515 ----
  
        stmt_vec_info def_stmt_info;
        enum vect_def_type dt;
!       if (!vect_is_simple_use (loop_vinfo, slp_for_stmt_info,
  			       i + opno_adjust, &op.ops[i], &slp_op[i], &dt,
  			       &vectype_op[i], &def_stmt_info))
  	{
*************** vect_transform_reduction (loop_vec_info
*** 8185,8191 ****
  			  stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
  			  slp_tree slp_node)
  {
!   tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
    unsigned vec_num;
  
--- 8180,8186 ----
  			  stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
  			  slp_tree slp_node)
  {
!   tree vectype_out = SLP_TREE_VECTYPE (slp_node);
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
    unsigned vec_num;
  
*************** vect_transform_reduction (loop_vec_info
*** 8212,8218 ****
    tree vectype_in = STMT_VINFO_REDUC_VECTYPE_IN (stmt_info);
  
    if (!vectype_in)
!     vectype_in = STMT_VINFO_VECTYPE (stmt_info);
  
    vec_num = vect_get_num_copies (loop_vinfo, slp_node, vectype_in);
  
--- 8207,8213 ----
    tree vectype_in = STMT_VINFO_REDUC_VECTYPE_IN (stmt_info);
  
    if (!vectype_in)
!     vectype_in = SLP_TREE_VECTYPE (slp_node);
  
    vec_num = vect_get_num_copies (loop_vinfo, slp_node, vectype_in);
  
*************** vect_transform_reduction (loop_vec_info
*** 8277,8283 ****
    if (!cond_fn_p)
      {
        gcc_assert (reduc_index >= 0 && reduc_index <= 2);
!       vect_get_vec_defs (loop_vinfo, stmt_info, slp_node, 1,
  			 single_defuse_cycle && reduc_index == 0
  			 ? NULL_TREE : op.ops[0], &vec_oprnds[0],
  			 single_defuse_cycle && reduc_index == 1
--- 8272,8278 ----
    if (!cond_fn_p)
      {
        gcc_assert (reduc_index >= 0 && reduc_index <= 2);
!       vect_get_vec_defs (loop_vinfo, slp_node,
  			 single_defuse_cycle && reduc_index == 0
  			 ? NULL_TREE : op.ops[0], &vec_oprnds[0],
  			 single_defuse_cycle && reduc_index == 1
*************** vect_transform_reduction (loop_vec_info
*** 8292,8310 ****
  	 vectype.  */
        gcc_assert (single_defuse_cycle
  		  && (reduc_index == 1 || reduc_index == 2));
!       vect_get_vec_defs (loop_vinfo, stmt_info, slp_node, 1, op.ops[0],
! 			 truth_type_for (vectype_in), &vec_oprnds[0],
  			 reduc_index == 1 ? NULL_TREE : op.ops[1],
! 			 NULL_TREE, &vec_oprnds[1],
  			 reduc_index == 2 ? NULL_TREE : op.ops[2],
! 			 NULL_TREE, &vec_oprnds[2]);
      }
  
    /* For single def-use cycles get one copy of the vectorized reduction
       definition.  */
    if (single_defuse_cycle)
      {
!       vect_get_vec_defs (loop_vinfo, stmt_info, slp_node, 1,
  			 reduc_index == 0 ? op.ops[0] : NULL_TREE,
  			 &vec_oprnds[0],
  			 reduc_index == 1 ? op.ops[1] : NULL_TREE,
--- 8287,8305 ----
  	 vectype.  */
        gcc_assert (single_defuse_cycle
  		  && (reduc_index == 1 || reduc_index == 2));
!       vect_get_vec_defs (loop_vinfo, slp_node, op.ops[0],
! 			 &vec_oprnds[0],
  			 reduc_index == 1 ? NULL_TREE : op.ops[1],
! 			 &vec_oprnds[1],
  			 reduc_index == 2 ? NULL_TREE : op.ops[2],
! 			 &vec_oprnds[2]);
      }
  
    /* For single def-use cycles get one copy of the vectorized reduction
       definition.  */
    if (single_defuse_cycle)
      {
!       vect_get_vec_defs (loop_vinfo, slp_node,
  			 reduc_index == 0 ? op.ops[0] : NULL_TREE,
  			 &vec_oprnds[0],
  			 reduc_index == 1 ? op.ops[1] : NULL_TREE,
*************** vect_transform_cycle_phi (loop_vec_info
*** 8532,8538 ****
  			  stmt_vec_info stmt_info,
  			  slp_tree slp_node, slp_instance slp_node_instance)
  {
!   tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
    int i;
    bool nested_cycle = false;
--- 8527,8533 ----
  			  stmt_vec_info stmt_info,
  			  slp_tree slp_node, slp_instance slp_node_instance)
  {
!   tree vectype_out = SLP_TREE_VECTYPE (slp_node);
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
    int i;
    bool nested_cycle = false;
*************** vectorizable_lc_phi (loop_vec_info loop_
*** 8763,8768 ****
--- 8758,8775 ----
  			 "incompatible vector types for invariants\n");
        return false;
      }
+ 
+   /* ???  This can happen with data vs. mask uses of boolean.  */
+   if (!useless_type_conversion_p (SLP_TREE_VECTYPE (slp_node),
+ 				  SLP_TREE_VECTYPE
+ 				    (SLP_TREE_CHILDREN (slp_node)[0])))
+     {
+       if (dump_enabled_p ())
+ 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ 			 "missed mask promotion\n");
+       return false;
+     }
+ 
    STMT_VINFO_TYPE (stmt_info) = lc_phi_info_type;
    return true;
  }
*************** vect_transform_lc_phi (loop_vec_info loo
*** 8773,8785 ****
  		       slp_tree slp_node)
  {
  
!   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    tree scalar_dest = gimple_phi_result (stmt_info->stmt);
    basic_block bb = gimple_bb (stmt_info->stmt);
    edge e = single_pred_edge (bb);
    tree vec_dest = vect_create_destination_var (scalar_dest, vectype);
    auto_vec<tree> vec_oprnds;
!   vect_get_vec_defs (loop_vinfo, stmt_info, slp_node, 1,
  		     gimple_phi_arg_def (stmt_info->stmt, 0), &vec_oprnds);
    for (unsigned i = 0; i < vec_oprnds.length (); i++)
      {
--- 8780,8792 ----
  		       slp_tree slp_node)
  {
  
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
    tree scalar_dest = gimple_phi_result (stmt_info->stmt);
    basic_block bb = gimple_bb (stmt_info->stmt);
    edge e = single_pred_edge (bb);
    tree vec_dest = vect_create_destination_var (scalar_dest, vectype);
    auto_vec<tree> vec_oprnds;
!   vect_get_vec_defs (loop_vinfo, slp_node,
  		     gimple_phi_arg_def (stmt_info->stmt, 0), &vec_oprnds);
    for (unsigned i = 0; i < vec_oprnds.length (); i++)
      {
*************** vect_transform_lc_phi (loop_vec_info loo
*** 8796,8802 ****
  
  bool
  vectorizable_phi (vec_info *,
! 		  stmt_vec_info stmt_info, gimple **vec_stmt,
  		  slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    if (!is_a <gphi *> (stmt_info->stmt) || !slp_node)
--- 8803,8809 ----
  
  bool
  vectorizable_phi (vec_info *,
! 		  stmt_vec_info stmt_info,
  		  slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    if (!is_a <gphi *> (stmt_info->stmt) || !slp_node)
*************** vectorizable_phi (vec_info *,
*** 8807,8813 ****
  
    tree vectype = SLP_TREE_VECTYPE (slp_node);
  
!   if (!vec_stmt) /* transformation not required.  */
      {
        slp_tree child;
        unsigned i;
--- 8814,8820 ----
  
    tree vectype = SLP_TREE_VECTYPE (slp_node);
  
!   if (cost_vec) /* transformation not required.  */
      {
        slp_tree child;
        unsigned i;
*************** vectorizable_phi (vec_info *,
*** 8938,8945 ****
  
  bool
  vectorizable_recurr (loop_vec_info loop_vinfo, stmt_vec_info stmt_info,
! 		     gimple **vec_stmt, slp_tree slp_node,
! 		     stmt_vector_for_cost *cost_vec)
  {
    if (!loop_vinfo || !is_a<gphi *> (stmt_info->stmt))
      return false;
--- 8945,8951 ----
  
  bool
  vectorizable_recurr (loop_vec_info loop_vinfo, stmt_vec_info stmt_info,
! 		     slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    if (!loop_vinfo || !is_a<gphi *> (stmt_info->stmt))
      return false;
*************** vectorizable_recurr (loop_vec_info loop_
*** 8950,8963 ****
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_first_order_recurrence)
      return false;
  
!   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
!   unsigned ncopies;
!   if (slp_node)
!     ncopies = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
!   else
!     ncopies = vect_get_num_copies (loop_vinfo, vectype);
    poly_int64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
!   unsigned dist = slp_node ? SLP_TREE_LANES (slp_node) : 1;
    /* We need to be able to make progress with a single vector.  */
    if (maybe_gt (dist * 2, nunits))
      {
--- 8956,8965 ----
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_first_order_recurrence)
      return false;
  
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
!   unsigned ncopies = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
    poly_int64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
!   unsigned dist = SLP_TREE_LANES (slp_node);
    /* We need to be able to make progress with a single vector.  */
    if (maybe_gt (dist * 2, nunits))
      {
*************** vectorizable_recurr (loop_vec_info loop_
*** 8975,9022 ****
      sel.quick_push (nunits - dist + i);
    vec_perm_indices indices (sel, 2, nunits);
  
!   if (!vec_stmt) /* transformation not required.  */
      {
        if (!can_vec_perm_const_p (TYPE_MODE (vectype), TYPE_MODE (vectype),
  				 indices))
  	return false;
  
!       if (slp_node)
! 	{
! 	  /* We eventually need to set a vector type on invariant
! 	     arguments.  */
! 	  unsigned j;
! 	  slp_tree child;
! 	  FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (slp_node), j, child)
! 	    if (!vect_maybe_update_slp_op_vectype
! 		  (child, SLP_TREE_VECTYPE (slp_node)))
! 	      {
! 		if (dump_enabled_p ())
! 		  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
! 				   "incompatible vector types for "
! 				   "invariants\n");
! 		return false;
! 	      }
! 	}
  
        /* Verify we have set up compatible types.  */
        edge le = loop_latch_edge (LOOP_VINFO_LOOP (loop_vinfo));
!       tree latch_vectype = NULL_TREE;
!       if (slp_node)
! 	{
! 	  slp_tree latch_def = SLP_TREE_CHILDREN (slp_node)[le->dest_idx];
! 	  latch_vectype = SLP_TREE_VECTYPE (latch_def);
! 	}
!       else
! 	{
! 	  tree latch_def = PHI_ARG_DEF_FROM_EDGE (phi, le);
! 	  if (TREE_CODE (latch_def) == SSA_NAME)
! 	    {
! 	      stmt_vec_info latch_def_info = loop_vinfo->lookup_def (latch_def);
! 	      latch_def_info = vect_stmt_to_vectorize (latch_def_info);
! 	      latch_vectype = STMT_VINFO_VECTYPE (latch_def_info);
! 	    }
! 	}
        if (!types_compatible_p (latch_vectype, vectype))
  	return false;
  
--- 8977,9006 ----
      sel.quick_push (nunits - dist + i);
    vec_perm_indices indices (sel, 2, nunits);
  
!   if (cost_vec) /* transformation not required.  */
      {
        if (!can_vec_perm_const_p (TYPE_MODE (vectype), TYPE_MODE (vectype),
  				 indices))
  	return false;
  
!       /* We eventually need to set a vector type on invariant
! 	 arguments.  */
!       unsigned j;
!       slp_tree child;
!       FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (slp_node), j, child)
! 	if (!vect_maybe_update_slp_op_vectype (child, vectype))
! 	  {
! 	    if (dump_enabled_p ())
! 	      dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
! 			       "incompatible vector types for "
! 			       "invariants\n");
! 	    return false;
! 	  }
  
        /* Verify we have set up compatible types.  */
        edge le = loop_latch_edge (LOOP_VINFO_LOOP (loop_vinfo));
!       slp_tree latch_def = SLP_TREE_CHILDREN (slp_node)[le->dest_idx];
!       tree latch_vectype = SLP_TREE_VECTYPE (latch_def);
        if (!types_compatible_p (latch_vectype, vectype))
  	return false;
  
*************** vectorizable_recurr (loop_vec_info loop_
*** 9024,9032 ****
  	 for each copy.  With SLP the prologue value is explicitly
  	 represented and costed separately.  */
        unsigned prologue_cost = 0;
-       if (!slp_node)
- 	prologue_cost = record_stmt_cost (cost_vec, 1, scalar_to_vec,
- 					  stmt_info, 0, vect_prologue);
        unsigned inside_cost = record_stmt_cost (cost_vec, ncopies, vector_stmt,
  					       stmt_info, 0, vect_body);
        if (dump_enabled_p ())
--- 9008,9013 ----
*************** vectorizable_recurr (loop_vec_info loop_
*** 9078,9091 ****
  				 NULL, perm);
        vect_finish_stmt_generation (loop_vinfo, stmt_info, vperm, &gsi2);
  
!       if (slp_node)
! 	slp_node->push_vec_def (vperm);
!       else
! 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (vperm);
      }
  
-   if (!slp_node)
-     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
    return true;
  }
  
--- 9059,9067 ----
  				 NULL, perm);
        vect_finish_stmt_generation (loop_vinfo, stmt_info, vperm, &gsi2);
  
!       slp_node->push_vec_def (vperm);
      }
  
    return true;
  }
  
*************** vect_update_nonlinear_iv (gimple_seq* st
*** 9397,9403 ****
  static bool
  vectorizable_nonlinear_induction (loop_vec_info loop_vinfo,
  				  stmt_vec_info stmt_info,
! 				  gimple **vec_stmt, slp_tree slp_node,
  				  stmt_vector_for_cost *cost_vec)
  {
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
--- 9373,9379 ----
  static bool
  vectorizable_nonlinear_induction (loop_vec_info loop_vinfo,
  				  stmt_vec_info stmt_info,
! 				  slp_tree slp_node,
  				  stmt_vector_for_cost *cost_vec)
  {
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
*************** vectorizable_nonlinear_induction (loop_v
*** 9553,9559 ****
        gcc_unreachable ();
      }
  
!   if (!vec_stmt) /* transformation not required.  */
      {
        unsigned inside_cost = 0, prologue_cost = 0;
        /* loop cost for vec_loop. Neg induction doesn't have any
--- 9529,9535 ----
        gcc_unreachable ();
      }
  
!   if (cost_vec) /* transformation not required.  */
      {
        unsigned inside_cost = 0, prologue_cost = 0;
        /* loop cost for vec_loop. Neg induction doesn't have any
*************** vectorizable_nonlinear_induction (loop_v
*** 9708,9715 ****
  bool
  vectorizable_induction (loop_vec_info loop_vinfo,
  			stmt_vec_info stmt_info,
! 			gimple **vec_stmt, slp_tree slp_node,
! 			stmt_vector_for_cost *cost_vec)
  {
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
    bool nested_in_vect_loop = false;
--- 9684,9690 ----
  bool
  vectorizable_induction (loop_vec_info loop_vinfo,
  			stmt_vec_info stmt_info,
! 			slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
    bool nested_in_vect_loop = false;
*************** vectorizable_induction (loop_vec_info lo
*** 9743,9749 ****
    /* Handle nonlinear induction in a separate place.  */
    if (induction_type != vect_step_op_add)
      return vectorizable_nonlinear_induction (loop_vinfo, stmt_info,
! 					     vec_stmt, slp_node, cost_vec);
  
    tree vectype = SLP_TREE_VECTYPE (slp_node);
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
--- 9718,9724 ----
    /* Handle nonlinear induction in a separate place.  */
    if (induction_type != vect_step_op_add)
      return vectorizable_nonlinear_induction (loop_vinfo, stmt_info,
! 					     slp_node, cost_vec);
  
    tree vectype = SLP_TREE_VECTYPE (slp_node);
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
*************** vectorizable_induction (loop_vec_info lo
*** 9847,9853 ****
  	}
      }
  
!   if (!vec_stmt) /* transformation not required.  */
      {
        unsigned inside_cost = 0, prologue_cost = 0;
        /* We eventually need to set a vector type on invariant
--- 9822,9828 ----
  	}
      }
  
!   if (cost_vec) /* transformation not required.  */
      {
        unsigned inside_cost = 0, prologue_cost = 0;
        /* We eventually need to set a vector type on invariant
diff -Nrcpad gcc-16-20250720/gcc/tree-vect-patterns.cc gcc-16-20250727/gcc/tree-vect-patterns.cc
*** gcc-16-20250720/gcc/tree-vect-patterns.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-vect-patterns.cc	Sun Jul 27 22:32:17 2025
*************** vect_recog_gather_scatter_pattern (vec_i
*** 6042,6053 ****
  
  	  tree vec_els
  	    = vect_get_mask_load_else (elsval, TREE_TYPE (gs_vectype));
! 	  pattern_stmt = gimple_build_call_internal (gs_info.ifn, 6, base,
  						     offset, scale, zero, mask,
  						     vec_els);
  	}
        else
! 	pattern_stmt = gimple_build_call_internal (gs_info.ifn, 4, base,
  						   offset, scale, zero);
        tree lhs = gimple_get_lhs (stmt_info->stmt);
        tree load_lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
--- 6042,6055 ----
  
  	  tree vec_els
  	    = vect_get_mask_load_else (elsval, TREE_TYPE (gs_vectype));
! 	  pattern_stmt = gimple_build_call_internal (gs_info.ifn, 7, base,
! 						     gs_info.alias_ptr,
  						     offset, scale, zero, mask,
  						     vec_els);
  	}
        else
! 	pattern_stmt = gimple_build_call_internal (gs_info.ifn, 5, base,
! 						   gs_info.alias_ptr,
  						   offset, scale, zero);
        tree lhs = gimple_get_lhs (stmt_info->stmt);
        tree load_lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
*************** vect_recog_gather_scatter_pattern (vec_i
*** 6057,6068 ****
      {
        tree rhs = vect_get_store_rhs (stmt_info);
        if (mask != NULL)
! 	pattern_stmt = gimple_build_call_internal (gs_info.ifn, 5,
! 						   base, offset, scale, rhs,
! 						   mask);
        else
! 	pattern_stmt = gimple_build_call_internal (gs_info.ifn, 4,
! 						   base, offset, scale, rhs);
      }
    gimple_call_set_nothrow (pattern_stmt, true);
  
--- 6059,6071 ----
      {
        tree rhs = vect_get_store_rhs (stmt_info);
        if (mask != NULL)
! 	pattern_stmt = gimple_build_call_internal (gs_info.ifn, 6,
! 						   base, gs_info.alias_ptr,
! 						   offset, scale, rhs, mask);
        else
! 	pattern_stmt = gimple_build_call_internal (gs_info.ifn, 5,
! 						   base, gs_info.alias_ptr,
! 						   offset, scale, rhs);
      }
    gimple_call_set_nothrow (pattern_stmt, true);
  
diff -Nrcpad gcc-16-20250720/gcc/tree-vect-slp.cc gcc-16-20250727/gcc/tree-vect-slp.cc
*** gcc-16-20250720/gcc/tree-vect-slp.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-vect-slp.cc	Sun Jul 27 22:32:17 2025
*************** vect_def_types_match (enum vect_def_type
*** 507,525 ****
  	      && (dtb == vect_external_def || dtb == vect_constant_def)));
  }
  
  static const int no_arg_map[] = { 0 };
  static const int arg0_map[] = { 1, 0 };
! static const int arg1_map[] = { 1, 1 };
  static const int arg2_arg3_map[] = { 2, 2, 3 };
! static const int arg1_arg3_map[] = { 2, 1, 3 };
! static const int arg1_arg4_arg5_map[] = { 3, 1, 4, 5 };
! static const int arg1_arg3_arg4_map[] = { 3, 1, 3, 4 };
  static const int arg3_arg2_map[] = { 2, 3, 2 };
  static const int op1_op0_map[] = { 2, 1, 0 };
! static const int off_map[] = { 1, -3 };
! static const int off_op0_map[] = { 2, -3, 0 };
! static const int off_arg2_arg3_map[] = { 3, -3, 2, 3 };
! static const int off_arg3_arg2_map[] = { 3, -3, 3, 2 };
  static const int mask_call_maps[6][7] = {
    { 1, 1, },
    { 2, 1, 2, },
--- 507,527 ----
  	      && (dtb == vect_external_def || dtb == vect_constant_def)));
  }
  
+ #define GATHER_SCATTER_OFFSET (-3)
+ 
  static const int no_arg_map[] = { 0 };
  static const int arg0_map[] = { 1, 0 };
! static const int arg2_map[] = { 1, 2 };
  static const int arg2_arg3_map[] = { 2, 2, 3 };
! static const int arg2_arg4_map[] = { 2, 2, 4 };
! static const int arg2_arg5_arg6_map[] = { 3, 2, 5, 6 };
! static const int arg2_arg4_arg5_map[] = { 3, 2, 4, 5 };
  static const int arg3_arg2_map[] = { 2, 3, 2 };
  static const int op1_op0_map[] = { 2, 1, 0 };
! static const int off_map[] = { 1, GATHER_SCATTER_OFFSET };
! static const int off_op0_map[] = { 2, GATHER_SCATTER_OFFSET, 0 };
! static const int off_arg2_arg3_map[] = { 3, GATHER_SCATTER_OFFSET, 2, 3 };
! static const int off_arg3_arg2_map[] = { 3, GATHER_SCATTER_OFFSET, 3, 2 };
  static const int mask_call_maps[6][7] = {
    { 1, 1, },
    { 2, 1, 2, },
*************** vect_get_operand_map (const gimple *stmt
*** 568,585 ****
  	    return gather_scatter_p ? off_arg2_arg3_map : arg2_arg3_map;
  
  	  case IFN_GATHER_LOAD:
! 	    return arg1_map;
  
  	  case IFN_MASK_GATHER_LOAD:
  	  case IFN_MASK_LEN_GATHER_LOAD:
! 	    return arg1_arg4_arg5_map;
  
  	  case IFN_SCATTER_STORE:
! 	    return arg1_arg3_map;
  
  	  case IFN_MASK_SCATTER_STORE:
  	  case IFN_MASK_LEN_SCATTER_STORE:
! 	    return arg1_arg3_arg4_map;
  
  	  case IFN_MASK_STORE:
  	    return gather_scatter_p ? off_arg3_arg2_map : arg3_arg2_map;
--- 570,587 ----
  	    return gather_scatter_p ? off_arg2_arg3_map : arg2_arg3_map;
  
  	  case IFN_GATHER_LOAD:
! 	    return arg2_map;
  
  	  case IFN_MASK_GATHER_LOAD:
  	  case IFN_MASK_LEN_GATHER_LOAD:
! 	    return arg2_arg5_arg6_map;
  
  	  case IFN_SCATTER_STORE:
! 	    return arg2_arg4_map;
  
  	  case IFN_MASK_SCATTER_STORE:
  	  case IFN_MASK_LEN_SCATTER_STORE:
! 	    return arg2_arg4_arg5_map;
  
  	  case IFN_MASK_STORE:
  	    return gather_scatter_p ? off_arg3_arg2_map : arg3_arg2_map;
*************** vect_get_and_check_slp_defs (vec_info *v
*** 691,697 ****
      {
        oprnd_info = (*oprnds_info)[i];
        int opno = map ? map[i] : int (i);
!       if (opno == -3)
  	{
  	  gcc_assert (STMT_VINFO_GATHER_SCATTER_P (stmt_info));
  	  if (!is_a <loop_vec_info> (vinfo)
--- 693,699 ----
      {
        oprnd_info = (*oprnds_info)[i];
        int opno = map ? map[i] : int (i);
!       if (opno == GATHER_SCATTER_OFFSET)
  	{
  	  gcc_assert (STMT_VINFO_GATHER_SCATTER_P (stmt_info));
  	  if (!is_a <loop_vec_info> (vinfo)
*************** vect_analyze_slp (vec_info *vinfo, unsig
*** 5239,5245 ****
  		    if (STMT_VINFO_STRIDED_P (stmt_vinfo)
  			|| compare_step_with_zero (vinfo, stmt_vinfo) <= 0
  			|| vect_load_lanes_supported
! 			     (STMT_VINFO_VECTYPE (stmt_vinfo),
  			      DR_GROUP_SIZE (stmt_vinfo), masked) == IFN_LAST
  			/* ???  During SLP re-discovery with a single lane
  			   a masked grouped load will appear permuted and
--- 5241,5247 ----
  		    if (STMT_VINFO_STRIDED_P (stmt_vinfo)
  			|| compare_step_with_zero (vinfo, stmt_vinfo) <= 0
  			|| vect_load_lanes_supported
! 			     (SLP_TREE_VECTYPE (load_node),
  			      DR_GROUP_SIZE (stmt_vinfo), masked) == IFN_LAST
  			/* ???  During SLP re-discovery with a single lane
  			   a masked grouped load will appear permuted and
*************** vect_analyze_slp (vec_info *vinfo, unsig
*** 5260,5266 ****
  			 || SLP_TREE_LANES (load_node) == group_size
  			 || (vect_slp_prefer_store_lanes_p
  			     (vinfo, stmt_vinfo,
! 			      STMT_VINFO_VECTYPE (stmt_vinfo), masked,
  			      group_size, SLP_TREE_LANES (load_node))));
  		  }
  
--- 5262,5268 ----
  			 || SLP_TREE_LANES (load_node) == group_size
  			 || (vect_slp_prefer_store_lanes_p
  			     (vinfo, stmt_vinfo,
! 			      SLP_TREE_VECTYPE (load_node), masked,
  			      group_size, SLP_TREE_LANES (load_node))));
  		  }
  
*************** vect_slp_analyze_operations (vec_info *v
*** 8648,8654 ****
  	  || (SLP_INSTANCE_KIND (instance) == slp_inst_kind_gcond
  	      && !vectorizable_early_exit (vinfo,
  					   SLP_INSTANCE_ROOT_STMTS (instance)[0],
! 					   NULL, NULL,
  					   SLP_INSTANCE_TREE (instance),
  					   &cost_vec)))
          {
--- 8650,8656 ----
  	  || (SLP_INSTANCE_KIND (instance) == slp_inst_kind_gcond
  	      && !vectorizable_early_exit (vinfo,
  					   SLP_INSTANCE_ROOT_STMTS (instance)[0],
! 					   NULL,
  					   SLP_INSTANCE_TREE (instance),
  					   &cost_vec)))
          {
*************** vect_slp_analyze_bb_1 (bb_vec_info bb_vi
*** 9570,9583 ****
  
    slp_instance instance;
    int i;
-   poly_uint64 min_vf = 2;
  
    /* The first group of checks is independent of the vector size.  */
    fatal = true;
  
    /* Analyze the data references.  */
  
!   if (!vect_analyze_data_refs (bb_vinfo, &min_vf, NULL))
      {
        if (dump_enabled_p ())
          dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 9572,9584 ----
  
    slp_instance instance;
    int i;
  
    /* The first group of checks is independent of the vector size.  */
    fatal = true;
  
    /* Analyze the data references.  */
  
!   if (!vect_analyze_data_refs (bb_vinfo, NULL))
      {
        if (dump_enabled_p ())
          dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vect_schedule_slp_node (vec_info *vinfo,
*** 11371,11377 ****
  		  && !SSA_NAME_IS_DEFAULT_DEF (def))
  		{
  		  gimple *stmt = SSA_NAME_DEF_STMT (def);
! 		  if (!last_stmt)
  		    last_stmt = stmt;
  		  else if (vect_stmt_dominates_stmt_p (last_stmt, stmt))
  		    last_stmt = stmt;
--- 11372,11382 ----
  		  && !SSA_NAME_IS_DEFAULT_DEF (def))
  		{
  		  gimple *stmt = SSA_NAME_DEF_STMT (def);
! 		  if (gimple_uid (stmt) == -1u)
! 		    /* If the stmt is not inside the region do not
! 		       use it as possible insertion point.  */
! 		    ;
! 		  else if (!last_stmt)
  		    last_stmt = stmt;
  		  else if (vect_stmt_dominates_stmt_p (last_stmt, stmt))
  		    last_stmt = stmt;
*************** vectorize_slp_instance_root_stmt (vec_in
*** 11676,11685 ****
        auto root_stmt_info = instance->root_stmts[0];
        auto last_stmt = STMT_VINFO_STMT (vect_orig_stmt (root_stmt_info));
        gimple_stmt_iterator rgsi = gsi_for_stmt (last_stmt);
-       gimple *vec_stmt = NULL;
        gcc_assert (!SLP_TREE_VEC_DEFS (node).is_empty ());
        bool res = vectorizable_early_exit (vinfo, root_stmt_info, &rgsi,
! 					  &vec_stmt, node, NULL);
        gcc_assert (res);
        return;
      }
--- 11681,11689 ----
        auto root_stmt_info = instance->root_stmts[0];
        auto last_stmt = STMT_VINFO_STMT (vect_orig_stmt (root_stmt_info));
        gimple_stmt_iterator rgsi = gsi_for_stmt (last_stmt);
        gcc_assert (!SLP_TREE_VEC_DEFS (node).is_empty ());
        bool res = vectorizable_early_exit (vinfo, root_stmt_info, &rgsi,
! 					  node, NULL);
        gcc_assert (res);
        return;
      }
diff -Nrcpad gcc-16-20250720/gcc/tree-vect-stmts.cc gcc-16-20250727/gcc/tree-vect-stmts.cc
*** gcc-16-20250720/gcc/tree-vect-stmts.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-vect-stmts.cc	Sun Jul 27 22:32:17 2025
*************** along with GCC; see the file COPYING3.
*** 62,75 ****
  /* For lang_hooks.types.type_for_mode.  */
  #include "langhooks.h"
  
- /* Return the vectorized type for the given statement.  */
- 
- tree
- stmt_vectype (class _stmt_vec_info *stmt_info)
- {
-   return STMT_VINFO_VECTYPE (stmt_info);
- }
- 
  /* Return TRUE iff the given statement is in an inner loop relative to
     the loop being vectorized.  */
  bool
--- 62,67 ----
*************** vect_mark_stmts_to_be_vectorized (loop_v
*** 901,913 ****
  
  /* Function vect_model_simple_cost.
  
!    Models cost for simple operations, i.e. those that only emit ncopies of a
!    single op.  Right now, this does not account for multiple insns that could
!    be generated for the single vector op.  We will handle that shortly.  */
  
  static void
! vect_model_simple_cost (vec_info *, int ncopies, enum vect_def_type *dt,
! 			int ndts, slp_tree node,
  			stmt_vector_for_cost *cost_vec,
  			vect_cost_for_stmt kind = vector_stmt)
  {
--- 893,903 ----
  
  /* Function vect_model_simple_cost.
  
!    Models cost for simple operations, i.e. those that only emit N operations
!    of the same KIND.  */
  
  static void
! vect_model_simple_cost (vec_info *, int n, slp_tree node,
  			stmt_vector_for_cost *cost_vec,
  			vect_cost_for_stmt kind = vector_stmt)
  {
*************** vect_model_simple_cost (vec_info *, int
*** 915,936 ****
  
    gcc_assert (cost_vec != NULL);
  
!   /* ???  Somehow we need to fix this at the callers.  */
!   if (node)
!     ncopies = SLP_TREE_NUMBER_OF_VEC_STMTS (node);
! 
!   if (!node)
!     /* Cost the "broadcast" of a scalar operand in to a vector operand.
!        Use scalar_to_vec to cost the broadcast, as elsewhere in the vector
!        cost model.  */
!     for (int i = 0; i < ndts; i++)
!       if (dt[i] == vect_constant_def || dt[i] == vect_external_def)
! 	prologue_cost += record_stmt_cost (cost_vec, 1, scalar_to_vec,
! 					   node, 0, vect_prologue);
  
    /* Pass the inside-of-loop statements to the target-specific cost model.  */
!   inside_cost += record_stmt_cost (cost_vec, ncopies, kind,
! 				   node, 0, vect_body);
  
    if (dump_enabled_p ())
      dump_printf_loc (MSG_NOTE, vect_location,
--- 905,914 ----
  
    gcc_assert (cost_vec != NULL);
  
!   n *= SLP_TREE_NUMBER_OF_VEC_STMTS (node);
  
    /* Pass the inside-of-loop statements to the target-specific cost model.  */
!   inside_cost += record_stmt_cost (cost_vec, n, kind, node, 0, vect_body);
  
    if (dump_enabled_p ())
      dump_printf_loc (MSG_NOTE, vect_location,
*************** vect_init_vector (vec_info *vinfo, stmt_
*** 1269,1398 ****
  }
  
  
- /* Function vect_get_vec_defs_for_operand.
- 
-    OP is an operand in STMT_VINFO.  This function returns a vector of
-    NCOPIES defs that will be used in the vectorized stmts for STMT_VINFO.
- 
-    In the case that OP is an SSA_NAME which is defined in the loop, then
-    STMT_VINFO_VEC_STMTS of the defining stmt holds the relevant defs.
- 
-    In case OP is an invariant or constant, a new stmt that creates a vector def
-    needs to be introduced.  VECTYPE may be used to specify a required type for
-    vector invariant.  */
- 
- void
- vect_get_vec_defs_for_operand (vec_info *vinfo, stmt_vec_info stmt_vinfo,
- 			       unsigned ncopies,
- 			       tree op, vec<tree> *vec_oprnds, tree vectype)
- {
-   gimple *def_stmt;
-   enum vect_def_type dt;
-   bool is_simple_use;
-   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
- 
-   if (dump_enabled_p ())
-     dump_printf_loc (MSG_NOTE, vect_location,
- 		     "vect_get_vec_defs_for_operand: %T\n", op);
- 
-   stmt_vec_info def_stmt_info;
-   is_simple_use = vect_is_simple_use (op, loop_vinfo, &dt,
- 				      &def_stmt_info, &def_stmt);
-   gcc_assert (is_simple_use);
-   if (def_stmt && dump_enabled_p ())
-     dump_printf_loc (MSG_NOTE, vect_location, "  def_stmt =  %G", def_stmt);
- 
-   vec_oprnds->create (ncopies);
-   if (dt == vect_constant_def || dt == vect_external_def)
-     {
-       tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
-       tree vector_type;
- 
-       if (vectype)
- 	vector_type = vectype;
-       else if (VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (op))
- 	       && VECTOR_BOOLEAN_TYPE_P (stmt_vectype))
- 	vector_type = truth_type_for (stmt_vectype);
-       else
- 	vector_type = get_vectype_for_scalar_type (loop_vinfo, TREE_TYPE (op));
- 
-       gcc_assert (vector_type);
-       /* A masked load can have a default SSA definition as else operand.
- 	 We should "vectorize" this instead of creating a duplicate from the
- 	 scalar default.  */
-       tree vop;
-       if (TREE_CODE (op) == SSA_NAME
- 	  && SSA_NAME_IS_DEFAULT_DEF (op)
- 	  && VAR_P (SSA_NAME_VAR (op)))
- 	vop = get_or_create_ssa_default_def (cfun,
- 					     create_tmp_var (vector_type));
-       else
- 	vop = vect_init_vector (vinfo, stmt_vinfo, op, vector_type, NULL);
-       while (ncopies--)
- 	vec_oprnds->quick_push (vop);
-     }
-   else
-     {
-       def_stmt_info = vect_stmt_to_vectorize (def_stmt_info);
-       gcc_assert (STMT_VINFO_VEC_STMTS (def_stmt_info).length () == ncopies);
-       for (unsigned i = 0; i < ncopies; ++i)
- 	vec_oprnds->quick_push (gimple_get_lhs
- 				  (STMT_VINFO_VEC_STMTS (def_stmt_info)[i]));
-     }
- }
- 
- 
  /* Get vectorized definitions for OP0 and OP1.  */
  
  void
! vect_get_vec_defs (vec_info *vinfo, stmt_vec_info stmt_info, slp_tree slp_node,
! 		   unsigned ncopies,
! 		   tree op0, tree vectype0, vec<tree> *vec_oprnds0,
! 		   tree op1, tree vectype1, vec<tree> *vec_oprnds1,
! 		   tree op2, tree vectype2, vec<tree> *vec_oprnds2,
! 		   tree op3, tree vectype3, vec<tree> *vec_oprnds3)
! {
!   if (slp_node)
!     {
!       if (op0)
! 	vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[0], vec_oprnds0);
!       if (op1)
! 	vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[1], vec_oprnds1);
!       if (op2)
! 	vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[2], vec_oprnds2);
!       if (op3)
! 	vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[3], vec_oprnds3);
!     }
!   else
!     {
!       if (op0)
! 	vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
! 				       op0, vec_oprnds0, vectype0);
!       if (op1)
! 	vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
! 				       op1, vec_oprnds1, vectype1);
!       if (op2)
! 	vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
! 				       op2, vec_oprnds2, vectype2);
!       if (op3)
! 	vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
! 				       op3, vec_oprnds3, vectype3);
!     }
! }
! 
! void
! vect_get_vec_defs (vec_info *vinfo, stmt_vec_info stmt_info, slp_tree slp_node,
! 		   unsigned ncopies,
  		   tree op0, vec<tree> *vec_oprnds0,
  		   tree op1, vec<tree> *vec_oprnds1,
  		   tree op2, vec<tree> *vec_oprnds2,
  		   tree op3, vec<tree> *vec_oprnds3)
  {
!   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
! 		     op0, NULL_TREE, vec_oprnds0,
! 		     op1, NULL_TREE, vec_oprnds1,
! 		     op2, NULL_TREE, vec_oprnds2,
! 		     op3, NULL_TREE, vec_oprnds3);
  }
  
  /* Helper function called by vect_finish_replace_stmt and
--- 1247,1269 ----
  }
  
  
  /* Get vectorized definitions for OP0 and OP1.  */
  
  void
! vect_get_vec_defs (vec_info *, slp_tree slp_node,
  		   tree op0, vec<tree> *vec_oprnds0,
  		   tree op1, vec<tree> *vec_oprnds1,
  		   tree op2, vec<tree> *vec_oprnds2,
  		   tree op3, vec<tree> *vec_oprnds3)
  {
!   if (op0)
!     vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[0], vec_oprnds0);
!   if (op1)
!     vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[1], vec_oprnds1);
!   if (op2)
!     vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[2], vec_oprnds2);
!   if (op3)
!     vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[3], vec_oprnds3);
  }
  
  /* Helper function called by vect_finish_replace_stmt and
*************** check_load_store_for_partial_vectors (lo
*** 1566,1573 ****
    bool is_load = (vls_type == VLS_LOAD);
    if (memory_access_type == VMAT_LOAD_STORE_LANES)
      {
!       if (slp_node)
! 	nvectors /= group_size;
        internal_fn ifn
  	= (is_load ? vect_load_lanes_supported (vectype, group_size, true,
  						elsvals)
--- 1437,1443 ----
    bool is_load = (vls_type == VLS_LOAD);
    if (memory_access_type == VMAT_LOAD_STORE_LANES)
      {
!       nvectors /= group_size;
        internal_fn ifn
  	= (is_load ? vect_load_lanes_supported (vectype, group_size, true,
  						elsvals)
*************** check_load_store_for_partial_vectors (lo
*** 1622,1629 ****
        return;
      }
  
!   if (memory_access_type != VMAT_CONTIGUOUS
!       && memory_access_type != VMAT_CONTIGUOUS_PERMUTE)
      {
        /* Element X of the data must come from iteration i * VF + X of the
  	 scalar loop.  We need more work to support other mappings.  */
--- 1492,1498 ----
        return;
      }
  
!   if (memory_access_type != VMAT_CONTIGUOUS)
      {
        /* Element X of the data must come from iteration i * VF + X of the
  	 scalar loop.  We need more work to support other mappings.  */
*************** prepare_vec_mask (loop_vec_info loop_vin
*** 1734,1740 ****
     else values will be stored in the vector ELSVALS points to.  */
  
  static bool
! vect_truncate_gather_scatter_offset (stmt_vec_info stmt_info,
  				     loop_vec_info loop_vinfo, bool masked_p,
  				     gather_scatter_info *gs_info,
  				     vec<int> *elsvals)
--- 1603,1609 ----
     else values will be stored in the vector ELSVALS points to.  */
  
  static bool
! vect_truncate_gather_scatter_offset (stmt_vec_info stmt_info, tree vectype,
  				     loop_vec_info loop_vinfo, bool masked_p,
  				     gather_scatter_info *gs_info,
  				     vec<int> *elsvals)
*************** vect_truncate_gather_scatter_offset (stm
*** 1752,1758 ****
      }
  
    /* Get the number of bits in an element.  */
-   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    scalar_mode element_mode = SCALAR_TYPE_MODE (TREE_TYPE (vectype));
    unsigned int element_bits = GET_MODE_BITSIZE (element_mode);
  
--- 1621,1626 ----
*************** vect_truncate_gather_scatter_offset (stm
*** 1803,1808 ****
--- 1671,1679 ----
        /* Logically the sum of DR_BASE_ADDRESS, DR_INIT and DR_OFFSET,
  	 but we don't need to store that here.  */
        gs_info->base = NULL_TREE;
+       gs_info->alias_ptr = build_int_cst
+ 	(reference_alias_ptr_type (DR_REF (dr)),
+ 	 get_object_alignment (DR_REF (dr)));
        gs_info->element_type = TREE_TYPE (vectype);
        gs_info->offset = fold_convert (offset_type, step);
        gs_info->offset_dt = vect_constant_def;
*************** vect_truncate_gather_scatter_offset (stm
*** 1829,1842 ****
     else values will be stored in the vector ELSVALS points to.  */
  
  static bool
! vect_use_strided_gather_scatters_p (stmt_vec_info stmt_info,
  				    loop_vec_info loop_vinfo, bool masked_p,
  				    gather_scatter_info *gs_info,
  				    vec<int> *elsvals)
  {
    if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info, elsvals)
        || gs_info->ifn == IFN_LAST)
!     return vect_truncate_gather_scatter_offset (stmt_info, loop_vinfo,
  						masked_p, gs_info, elsvals);
  
    tree old_offset_type = TREE_TYPE (gs_info->offset);
--- 1700,1713 ----
     else values will be stored in the vector ELSVALS points to.  */
  
  static bool
! vect_use_strided_gather_scatters_p (stmt_vec_info stmt_info, tree vectype,
  				    loop_vec_info loop_vinfo, bool masked_p,
  				    gather_scatter_info *gs_info,
  				    vec<int> *elsvals)
  {
    if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info, elsvals)
        || gs_info->ifn == IFN_LAST)
!     return vect_truncate_gather_scatter_offset (stmt_info, vectype, loop_vinfo,
  						masked_p, gs_info, elsvals);
  
    tree old_offset_type = TREE_TYPE (gs_info->offset);
*************** get_group_load_store_type (vec_info *vin
*** 2106,2112 ****
         separated by the stride, until we have a complete vector.
         Fall back to scalar accesses if that isn't possible.  */
      *memory_access_type = VMAT_STRIDED_SLP;
!   else
      {
        int cmp = compare_step_with_zero (vinfo, stmt_info);
        if (cmp < 0)
--- 1977,1983 ----
         separated by the stride, until we have a complete vector.
         Fall back to scalar accesses if that isn't possible.  */
      *memory_access_type = VMAT_STRIDED_SLP;
!   else if (!STMT_VINFO_GATHER_SCATTER_P (stmt_info))
      {
        int cmp = compare_step_with_zero (vinfo, stmt_info);
        if (cmp < 0)
*************** get_group_load_store_type (vec_info *vin
*** 2349,2367 ****
       allows us to use contiguous accesses.  */
    if ((*memory_access_type == VMAT_ELEMENTWISE
         || *memory_access_type == VMAT_STRIDED_SLP)
        && single_element_p
        && SLP_TREE_LANES (slp_node) == 1
        && loop_vinfo
!       && vect_use_strided_gather_scatters_p (stmt_info, loop_vinfo,
  					     masked_p, gs_info, elsvals))
      *memory_access_type = VMAT_GATHER_SCATTER;
  
    if (*memory_access_type == VMAT_CONTIGUOUS_DOWN
        || *memory_access_type == VMAT_CONTIGUOUS_REVERSE)
      *poffset = neg_ldst_offset;
  
!   if (*memory_access_type == VMAT_GATHER_SCATTER
!       || *memory_access_type == VMAT_ELEMENTWISE
        || *memory_access_type == VMAT_STRIDED_SLP
        || *memory_access_type == VMAT_INVARIANT)
      {
--- 2220,2292 ----
       allows us to use contiguous accesses.  */
    if ((*memory_access_type == VMAT_ELEMENTWISE
         || *memory_access_type == VMAT_STRIDED_SLP)
+       && !STMT_VINFO_GATHER_SCATTER_P (stmt_info)
        && single_element_p
        && SLP_TREE_LANES (slp_node) == 1
        && loop_vinfo
!       && vect_use_strided_gather_scatters_p (stmt_info, vectype, loop_vinfo,
  					     masked_p, gs_info, elsvals))
      *memory_access_type = VMAT_GATHER_SCATTER;
+   else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
+     {
+       tree offset;
+       slp_tree offset_node;
+       *memory_access_type = VMAT_GATHER_SCATTER;
+       if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info,
+ 				      elsvals))
+ 	gcc_unreachable ();
+       /* When using internal functions, we rely on pattern recognition
+ 	 to convert the type of the offset to the type that the target
+ 	 requires, with the result being a call to an internal function.
+ 	 If that failed for some reason (e.g. because another pattern
+ 	 took priority), just handle cases in which the offset already
+ 	 has the right type.  */
+       else if (GATHER_SCATTER_IFN_P (*gs_info)
+ 	       && !is_gimple_call (stmt_info->stmt)
+ 	       && !tree_nop_conversion_p (TREE_TYPE (gs_info->offset),
+ 					  TREE_TYPE (gs_info->offset_vectype)))
+ 	{
+ 	  if (dump_enabled_p ())
+ 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ 			     "%s offset requires a conversion\n",
+ 			     vls_type == VLS_LOAD ? "gather" : "scatter");
+ 	  return false;
+ 	}
+       else if (!vect_is_simple_use (vinfo, slp_node, 0, &offset, &offset_node,
+ 				    &gs_info->offset_dt,
+ 				    &gs_info->offset_vectype))
+ 	{
+ 	  if (dump_enabled_p ())
+ 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ 			     "%s index use not simple.\n",
+ 			     vls_type == VLS_LOAD ? "gather" : "scatter");
+ 	  return false;
+ 	}
+       else if (GATHER_SCATTER_EMULATED_P (*gs_info))
+ 	{
+ 	  if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant ()
+ 	      || !TYPE_VECTOR_SUBPARTS (gs_info->offset_vectype).is_constant ()
+ 	      || VECTOR_BOOLEAN_TYPE_P (gs_info->offset_vectype)
+ 	      || !constant_multiple_p (TYPE_VECTOR_SUBPARTS
+ 					 (gs_info->offset_vectype),
+ 				       TYPE_VECTOR_SUBPARTS (vectype)))
+ 	    {
+ 	      if (dump_enabled_p ())
+ 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ 				 "unsupported vector types for emulated "
+ 				 "gather.\n");
+ 	      return false;
+ 	    }
+ 	}
+     }
  
    if (*memory_access_type == VMAT_CONTIGUOUS_DOWN
        || *memory_access_type == VMAT_CONTIGUOUS_REVERSE)
      *poffset = neg_ldst_offset;
  
!   if (*memory_access_type == VMAT_ELEMENTWISE
!       || (*memory_access_type == VMAT_GATHER_SCATTER
! 	  && GATHER_SCATTER_LEGACY_P (*gs_info))
        || *memory_access_type == VMAT_STRIDED_SLP
        || *memory_access_type == VMAT_INVARIANT)
      {
*************** get_group_load_store_type (vec_info *vin
*** 2370,2379 ****
      }
    else
      {
!       *misalignment = dr_misalignment (first_dr_info, vectype, *poffset);
        *alignment_support_scheme
! 	= vect_supportable_dr_alignment (vinfo, first_dr_info, vectype,
! 					 *misalignment);
      }
  
    if (vls_type != VLS_LOAD && first_stmt_info == stmt_info)
--- 2295,2309 ----
      }
    else
      {
!       if (*memory_access_type == VMAT_GATHER_SCATTER
! 	  && !first_dr_info)
! 	*misalignment = DR_MISALIGNMENT_UNKNOWN;
!       else
! 	*misalignment = dr_misalignment (first_dr_info, vectype, *poffset);
        *alignment_support_scheme
! 	= vect_supportable_dr_alignment
! 	   (vinfo, first_dr_info, vectype, *misalignment,
! 	    *memory_access_type == VMAT_GATHER_SCATTER ? gs_info : nullptr);
      }
  
    if (vls_type != VLS_LOAD && first_stmt_info == stmt_info)
*************** get_load_store_type (vec_info  *vinfo, s
*** 2443,2500 ****
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
    *misalignment = DR_MISALIGNMENT_UNKNOWN;
    *poffset = 0;
!   if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
!     {
!       *memory_access_type = VMAT_GATHER_SCATTER;
!       if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info,
! 				      elsvals))
! 	gcc_unreachable ();
!       /* When using internal functions, we rely on pattern recognition
! 	 to convert the type of the offset to the type that the target
! 	 requires, with the result being a call to an internal function.
! 	 If that failed for some reason (e.g. because another pattern
! 	 took priority), just handle cases in which the offset already
! 	 has the right type.  */
!       else if (gs_info->ifn != IFN_LAST
! 	       && !is_gimple_call (stmt_info->stmt)
! 	       && !tree_nop_conversion_p (TREE_TYPE (gs_info->offset),
! 					  TREE_TYPE (gs_info->offset_vectype)))
! 	{
! 	  if (dump_enabled_p ())
! 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
! 			     "%s offset requires a conversion\n",
! 			     vls_type == VLS_LOAD ? "gather" : "scatter");
! 	  return false;
! 	}
!       slp_tree offset_node = SLP_TREE_CHILDREN (slp_node)[0];
!       gs_info->offset_dt = SLP_TREE_DEF_TYPE (offset_node);
!       gs_info->offset_vectype = SLP_TREE_VECTYPE (offset_node);
!       if (gs_info->ifn == IFN_LAST && !gs_info->decl)
! 	{
! 	  if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant ()
! 	      || !TYPE_VECTOR_SUBPARTS (gs_info->offset_vectype).is_constant ()
! 	      || VECTOR_BOOLEAN_TYPE_P (gs_info->offset_vectype)
! 	      || !constant_multiple_p (TYPE_VECTOR_SUBPARTS
! 					 (gs_info->offset_vectype),
! 				       TYPE_VECTOR_SUBPARTS (vectype)))
! 	    {
! 	      if (dump_enabled_p ())
! 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
! 				 "unsupported vector types for emulated "
! 				 "gather.\n");
! 	      return false;
! 	    }
! 	}
!       /* Gather-scatter accesses perform only component accesses, alignment
! 	 is irrelevant for them.  */
!       *alignment_support_scheme = dr_unaligned_supported;
!     }
!   else if (!get_group_load_store_type (vinfo, stmt_info, vectype, slp_node,
! 				       masked_p,
! 				       vls_type, memory_access_type, poffset,
! 				       alignment_support_scheme,
! 				       misalignment, gs_info, lanes_ifn,
! 				       elsvals))
      return false;
  
    if ((*memory_access_type == VMAT_ELEMENTWISE
--- 2373,2384 ----
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
    *misalignment = DR_MISALIGNMENT_UNKNOWN;
    *poffset = 0;
!   if (!get_group_load_store_type (vinfo, stmt_info, vectype, slp_node,
! 				  masked_p,
! 				  vls_type, memory_access_type, poffset,
! 				  alignment_support_scheme,
! 				  misalignment, gs_info, lanes_ifn,
! 				  elsvals))
      return false;
  
    if ((*memory_access_type == VMAT_ELEMENTWISE
*************** get_load_store_type (vec_info  *vinfo, s
*** 2528,2544 ****
  			   "alignment. With non-contiguous memory vectorization"
  			   " could read out of bounds at %G ",
  			   STMT_VINFO_STMT (stmt_info));
! 	if (inbounds)
! 	  LOOP_VINFO_MUST_USE_PARTIAL_VECTORS_P (loop_vinfo) = true;
! 	else
! 	  return false;
      }
  
    /* If this DR needs alignment for correctness, we must ensure the target
       alignment is a constant power-of-two multiple of the amount read per
       vector iteration or force masking.  */
    if (dr_safe_speculative_read_required (stmt_info)
!       && *alignment_support_scheme == dr_aligned)
      {
        /* We can only peel for loops, of course.  */
        gcc_checking_assert (loop_vinfo);
--- 2412,2429 ----
  			   "alignment. With non-contiguous memory vectorization"
  			   " could read out of bounds at %G ",
  			   STMT_VINFO_STMT (stmt_info));
!       if (inbounds)
! 	LOOP_VINFO_MUST_USE_PARTIAL_VECTORS_P (loop_vinfo) = true;
!       else
! 	return false;
      }
  
    /* If this DR needs alignment for correctness, we must ensure the target
       alignment is a constant power-of-two multiple of the amount read per
       vector iteration or force masking.  */
    if (dr_safe_speculative_read_required (stmt_info)
!       && (*alignment_support_scheme == dr_aligned
! 	  && *memory_access_type != VMAT_GATHER_SCATTER))
      {
        /* We can only peel for loops, of course.  */
        gcc_checking_assert (loop_vinfo);
*************** get_load_store_type (vec_info  *vinfo, s
*** 2665,2671 ****
     to the mask in *MASK_NODE if MASK_NODE is not NULL.  */
  
  static bool
! vect_check_scalar_mask (vec_info *vinfo, stmt_vec_info stmt_info,
  			slp_tree slp_node, unsigned mask_index,
  			tree *mask, slp_tree *mask_node,
  			vect_def_type *mask_dt_out, tree *mask_vectype_out)
--- 2550,2556 ----
     to the mask in *MASK_NODE if MASK_NODE is not NULL.  */
  
  static bool
! vect_check_scalar_mask (vec_info *vinfo,
  			slp_tree slp_node, unsigned mask_index,
  			tree *mask, slp_tree *mask_node,
  			vect_def_type *mask_dt_out, tree *mask_vectype_out)
*************** vect_check_scalar_mask (vec_info *vinfo,
*** 2673,2679 ****
    enum vect_def_type mask_dt;
    tree mask_vectype;
    slp_tree mask_node_1;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, mask_index,
  			   mask, &mask_node_1, &mask_dt, &mask_vectype))
      {
        if (dump_enabled_p ())
--- 2558,2564 ----
    enum vect_def_type mask_dt;
    tree mask_vectype;
    slp_tree mask_node_1;
!   if (!vect_is_simple_use (vinfo, slp_node, mask_index,
  			   mask, &mask_node_1, &mask_dt, &mask_vectype))
      {
        if (dump_enabled_p ())
*************** vect_check_scalar_mask (vec_info *vinfo,
*** 2693,2700 ****
  
    /* If the caller is not prepared for adjusting an external/constant
       SLP mask vector type fail.  */
!   if (slp_node
!       && !mask_node
        && SLP_TREE_DEF_TYPE (mask_node_1) != vect_internal_def)
      {
        if (dump_enabled_p ())
--- 2578,2584 ----
  
    /* If the caller is not prepared for adjusting an external/constant
       SLP mask vector type fail.  */
!   if (!mask_node
        && SLP_TREE_DEF_TYPE (mask_node_1) != vect_internal_def)
      {
        if (dump_enabled_p ())
*************** vect_check_scalar_mask (vec_info *vinfo,
*** 2703,2709 ****
        return false;
      }
  
!   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    if (!mask_vectype)
      mask_vectype = get_mask_type_for_scalar_type (vinfo, TREE_TYPE (vectype),
  						  mask_node_1);
--- 2587,2593 ----
        return false;
      }
  
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
    if (!mask_vectype)
      mask_vectype = get_mask_type_for_scalar_type (vinfo, TREE_TYPE (vectype),
  						  mask_node_1);
*************** vect_check_store_rhs (vec_info *vinfo, s
*** 2754,2766 ****
  	  && internal_store_fn_p (gimple_call_internal_fn (call)))
  	op_no = internal_fn_stored_value_index (gimple_call_internal_fn (call));
      }
!   if (slp_node)
!     op_no = vect_slp_child_index_for_operand
! 	      (stmt_info->stmt, op_no, STMT_VINFO_GATHER_SCATTER_P (stmt_info));
  
    enum vect_def_type rhs_dt;
    tree rhs_vectype;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, op_no,
  			   rhs, rhs_node, &rhs_dt, &rhs_vectype))
      {
        if (dump_enabled_p ())
--- 2638,2649 ----
  	  && internal_store_fn_p (gimple_call_internal_fn (call)))
  	op_no = internal_fn_stored_value_index (gimple_call_internal_fn (call));
      }
!   op_no = vect_slp_child_index_for_operand
! 	    (stmt_info->stmt, op_no, STMT_VINFO_GATHER_SCATTER_P (stmt_info));
  
    enum vect_def_type rhs_dt;
    tree rhs_vectype;
!   if (!vect_is_simple_use (vinfo, slp_node, op_no,
  			   rhs, rhs_node, &rhs_dt, &rhs_vectype))
      {
        if (dump_enabled_p ())
*************** vect_check_store_rhs (vec_info *vinfo, s
*** 2780,2786 ****
        return false;
      }
  
!   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    if (rhs_vectype && !useless_type_conversion_p (vectype, rhs_vectype))
      {
        if (dump_enabled_p ())
--- 2663,2669 ----
        return false;
      }
  
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
    if (rhs_vectype && !useless_type_conversion_p (vectype, rhs_vectype))
      {
        if (dump_enabled_p ())
*************** vect_get_mask_load_else (int elsval, tre
*** 2886,2896 ****
  
  static gimple *
  vect_build_one_gather_load_call (vec_info *vinfo, stmt_vec_info stmt_info,
  				 gimple_stmt_iterator *gsi,
  				 gather_scatter_info *gs_info,
  				 tree ptr, tree offset, tree mask)
  {
-   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gs_info->decl));
    tree rettype = TREE_TYPE (TREE_TYPE (gs_info->decl));
    tree srctype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
--- 2769,2779 ----
  
  static gimple *
  vect_build_one_gather_load_call (vec_info *vinfo, stmt_vec_info stmt_info,
+ 				 tree vectype,
  				 gimple_stmt_iterator *gsi,
  				 gather_scatter_info *gs_info,
  				 tree ptr, tree offset, tree mask)
  {
    tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gs_info->decl));
    tree rettype = TREE_TYPE (TREE_TYPE (gs_info->decl));
    tree srctype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
*************** vect_build_one_scatter_store_call (vec_i
*** 3067,3074 ****
     containing loop.  */
  
  static void
! vect_get_gather_scatter_ops (loop_vec_info loop_vinfo,
! 			     class loop *loop, stmt_vec_info stmt_info,
  			     slp_tree slp_node, gather_scatter_info *gs_info,
  			     tree *dataref_ptr, vec<tree> *vec_offset)
  {
--- 2950,2956 ----
     containing loop.  */
  
  static void
! vect_get_gather_scatter_ops (class loop *loop,
  			     slp_tree slp_node, gather_scatter_info *gs_info,
  			     tree *dataref_ptr, vec<tree> *vec_offset)
  {
*************** vect_get_gather_scatter_ops (loop_vec_in
*** 3081,3096 ****
        new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
        gcc_assert (!new_bb);
      }
!   if (slp_node)
!     vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[0], vec_offset);
!   else
!     {
!       unsigned ncopies
! 	= vect_get_num_copies (loop_vinfo, gs_info->offset_vectype);
!       vect_get_vec_defs_for_operand (loop_vinfo, stmt_info, ncopies,
! 				     gs_info->offset, vec_offset,
! 				     gs_info->offset_vectype);
!     }
  }
  
  /* Prepare to implement a grouped or strided load or store using
--- 2963,2969 ----
        new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
        gcc_assert (!new_bb);
      }
!   vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[0], vec_offset);
  }
  
  /* Prepare to implement a grouped or strided load or store using
*************** vect_get_gather_scatter_ops (loop_vec_in
*** 3103,3109 ****
     I * DR_STEP / SCALE.  */
  
  static void
! vect_get_strided_load_store_ops (stmt_vec_info stmt_info,
  				 loop_vec_info loop_vinfo,
  				 gimple_stmt_iterator *gsi,
  				 gather_scatter_info *gs_info,
--- 2976,2982 ----
     I * DR_STEP / SCALE.  */
  
  static void
! vect_get_strided_load_store_ops (stmt_vec_info stmt_info, tree vectype,
  				 loop_vec_info loop_vinfo,
  				 gimple_stmt_iterator *gsi,
  				 gather_scatter_info *gs_info,
*************** vect_get_strided_load_store_ops (stmt_ve
*** 3111,3117 ****
  				 vec_loop_lens *loop_lens)
  {
    struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
-   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
  
    if (LOOP_VINFO_USING_SELECT_VL_P (loop_vinfo))
      {
--- 2984,2989 ----
*************** vect_get_data_ptr_increment (vec_info *v
*** 3236,3264 ****
  static bool
  vectorizable_bswap (vec_info *vinfo,
  		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		    gimple **vec_stmt, slp_tree slp_node,
  		    slp_tree *slp_op,
  		    tree vectype_in, stmt_vector_for_cost *cost_vec)
  {
    tree op, vectype;
    gcall *stmt = as_a <gcall *> (stmt_info->stmt);
-   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
-   unsigned ncopies;
  
    op = gimple_call_arg (stmt, 0);
!   vectype = STMT_VINFO_VECTYPE (stmt_info);
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
  
-   /* Multiple types in SLP are handled by creating the appropriate number of
-      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
-      case of SLP.  */
-   if (slp_node)
-     ncopies = 1;
-   else
-     ncopies = vect_get_num_copies (loop_vinfo, vectype);
- 
-   gcc_assert (ncopies >= 1);
- 
    if (TYPE_SIZE (vectype_in) != TYPE_SIZE (vectype))
      {
        if (dump_enabled_p ())
--- 3108,3124 ----
  static bool
  vectorizable_bswap (vec_info *vinfo,
  		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		    slp_tree slp_node,
  		    slp_tree *slp_op,
  		    tree vectype_in, stmt_vector_for_cost *cost_vec)
  {
    tree op, vectype;
    gcall *stmt = as_a <gcall *> (stmt_info->stmt);
  
    op = gimple_call_arg (stmt, 0);
!   vectype = SLP_TREE_VECTYPE (slp_node);
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
  
    if (TYPE_SIZE (vectype_in) != TYPE_SIZE (vectype))
      {
        if (dump_enabled_p ())
*************** vectorizable_bswap (vec_info *vinfo,
*** 3288,3297 ****
    if (!can_vec_perm_const_p (vmode, vmode, indices))
      return false;
  
!   if (! vec_stmt)
      {
!       if (slp_node
! 	  && !vect_maybe_update_slp_op_vectype (slp_op[0], vectype_in))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 3148,3156 ----
    if (!can_vec_perm_const_p (vmode, vmode, indices))
      return false;
  
!   if (cost_vec)
      {
!       if (!vect_maybe_update_slp_op_vectype (slp_op[0], vectype_in))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vectorizable_bswap (vec_info *vinfo,
*** 3304,3311 ****
        record_stmt_cost (cost_vec,
  			1, vector_stmt, stmt_info, 0, vect_prologue);
        record_stmt_cost (cost_vec,
! 			slp_node
! 			? SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) : ncopies,
  			vec_perm, stmt_info, 0, vect_body);
        return true;
      }
--- 3163,3169 ----
        record_stmt_cost (cost_vec,
  			1, vector_stmt, stmt_info, 0, vect_prologue);
        record_stmt_cost (cost_vec,
! 			SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node),
  			vec_perm, stmt_info, 0, vect_body);
        return true;
      }
*************** vectorizable_bswap (vec_info *vinfo,
*** 3314,3321 ****
  
    /* Transform.  */
    vec<tree> vec_oprnds = vNULL;
!   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
! 		     op, &vec_oprnds);
    /* Arguments are ready. create the new vector stmt.  */
    unsigned i;
    tree vop;
--- 3172,3178 ----
  
    /* Transform.  */
    vec<tree> vec_oprnds = vNULL;
!   vect_get_vec_defs (vinfo, slp_node, op, &vec_oprnds);
    /* Arguments are ready. create the new vector stmt.  */
    unsigned i;
    tree vop;
*************** vectorizable_bswap (vec_info *vinfo,
*** 3334,3348 ****
        new_stmt = gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
  						   vectype, tem2));
        vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
!       if (slp_node)
! 	slp_node->push_vec_def (new_stmt);
!       else
! 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
      }
  
-   if (!slp_node)
-     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
- 
    vec_oprnds.release ();
    return true;
  }
--- 3191,3199 ----
        new_stmt = gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
  						   vectype, tem2));
        vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
!       slp_node->push_vec_def (new_stmt);
      }
  
    vec_oprnds.release ();
    return true;
  }
*************** simple_integer_narrowing (tree vectype_o
*** 3382,3395 ****
  static bool
  vectorizable_call (vec_info *vinfo,
  		   stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		   gimple **vec_stmt, slp_tree slp_node,
  		   stmt_vector_for_cost *cost_vec)
  {
    gcall *stmt;
    tree vec_dest;
    tree scalar_dest;
    tree op;
!   tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
    tree vectype_out, vectype_in;
    poly_uint64 nunits_in;
    poly_uint64 nunits_out;
--- 3233,3246 ----
  static bool
  vectorizable_call (vec_info *vinfo,
  		   stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		   slp_tree slp_node,
  		   stmt_vector_for_cost *cost_vec)
  {
    gcall *stmt;
    tree vec_dest;
    tree scalar_dest;
    tree op;
!   tree vec_oprnd0 = NULL_TREE;
    tree vectype_out, vectype_in;
    poly_uint64 nunits_in;
    poly_uint64 nunits_out;
*************** vectorizable_call (vec_info *vinfo,
*** 3401,3419 ****
  	vect_unknown_def_type };
    tree vectypes[ARRAY_SIZE (dt)] = {};
    slp_tree slp_op[ARRAY_SIZE (dt)] = {};
-   int ndts = ARRAY_SIZE (dt);
-   int ncopies, j;
    auto_vec<tree, 8> vargs;
    enum { NARROW, NONE, WIDEN } modifier;
    size_t i, nargs;
-   tree lhs;
    tree clz_ctz_arg1 = NULL_TREE;
  
    if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && ! vec_stmt)
      return false;
  
    /* Is STMT_INFO a vectorizable call?   */
--- 3252,3267 ----
  	vect_unknown_def_type };
    tree vectypes[ARRAY_SIZE (dt)] = {};
    slp_tree slp_op[ARRAY_SIZE (dt)] = {};
    auto_vec<tree, 8> vargs;
    enum { NARROW, NONE, WIDEN } modifier;
    size_t i, nargs;
    tree clz_ctz_arg1 = NULL_TREE;
  
    if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && cost_vec)
      return false;
  
    /* Is STMT_INFO a vectorizable call?   */
*************** vectorizable_call (vec_info *vinfo,
*** 3433,3439 ****
  
    gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
  
!   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
  
    /* Process function arguments.  */
    rhs_type = NULL_TREE;
--- 3281,3287 ----
  
    gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
  
!   vectype_out = SLP_TREE_VECTYPE (slp_node);
  
    /* Process function arguments.  */
    rhs_type = NULL_TREE;
*************** vectorizable_call (vec_info *vinfo,
*** 3470,3482 ****
      {
        if ((int) i == mask_opno)
  	{
! 	  if (!vect_check_scalar_mask (vinfo, stmt_info, slp_node, mask_opno,
  				       &op, &slp_op[i], &dt[i], &vectypes[i]))
  	    return false;
  	  continue;
  	}
  
!       if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
  			       i, &op, &slp_op[i], &dt[i], &vectypes[i]))
  	{
  	  if (dump_enabled_p ())
--- 3318,3330 ----
      {
        if ((int) i == mask_opno)
  	{
! 	  if (!vect_check_scalar_mask (vinfo, slp_node, mask_opno,
  				       &op, &slp_op[i], &dt[i], &vectypes[i]))
  	    return false;
  	  continue;
  	}
  
!       if (!vect_is_simple_use (vinfo, slp_node,
  			       i, &op, &slp_op[i], &dt[i], &vectypes[i]))
  	{
  	  if (dump_enabled_p ())
*************** vectorizable_call (vec_info *vinfo,
*** 3512,3518 ****
       from the scalar type.  */
    if (!vectype_in)
      vectype_in = get_vectype_for_scalar_type (vinfo, rhs_type, slp_node);
!   if (vec_stmt)
      gcc_assert (vectype_in);
    if (!vectype_in)
      {
--- 3360,3366 ----
       from the scalar type.  */
    if (!vectype_in)
      vectype_in = get_vectype_for_scalar_type (vinfo, rhs_type, slp_node);
!   if (!cost_vec)
      gcc_assert (vectype_in);
    if (!vectype_in)
      {
*************** vectorizable_call (vec_info *vinfo,
*** 3532,3544 ****
        return false;
      }
  
!   if (vect_emulated_vector_p (vectype_in) || vect_emulated_vector_p (vectype_out))
!   {
        if (dump_enabled_p ())
  	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
  			 "use emulated vector type for call\n");
        return false;
!   }
  
    /* FORNOW */
    nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
--- 3380,3393 ----
        return false;
      }
  
!   if (vect_emulated_vector_p (vectype_in)
!       || vect_emulated_vector_p (vectype_out))
!     {
        if (dump_enabled_p ())
  	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
  			 "use emulated vector type for call\n");
        return false;
!     }
  
    /* FORNOW */
    nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
*************** vectorizable_call (vec_info *vinfo,
*** 3593,3599 ****
    if (ifn == IFN_LAST && !fndecl)
      {
        if (cfn == CFN_GOMP_SIMD_LANE
! 	  && (!slp_node || SLP_TREE_LANES (slp_node) == 1)
  	  && loop_vinfo
  	  && LOOP_VINFO_LOOP (loop_vinfo)->simduid
  	  && TREE_CODE (gimple_call_arg (stmt, 0)) == SSA_NAME
--- 3442,3448 ----
    if (ifn == IFN_LAST && !fndecl)
      {
        if (cfn == CFN_GOMP_SIMD_LANE
! 	  && SLP_TREE_LANES (slp_node) == 1
  	  && loop_vinfo
  	  && LOOP_VINFO_LOOP (loop_vinfo)->simduid
  	  && TREE_CODE (gimple_call_arg (stmt, 0)) == SSA_NAME
*************** vectorizable_call (vec_info *vinfo,
*** 3609,3615 ****
  		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP32)
  		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP64)
  		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP128)))
! 	return vectorizable_bswap (vinfo, stmt_info, gsi, vec_stmt, slp_node,
  				   slp_op, vectype_in, cost_vec);
        else
  	{
--- 3458,3464 ----
  		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP32)
  		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP64)
  		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP128)))
! 	return vectorizable_bswap (vinfo, stmt_info, gsi, slp_node,
  				   slp_op, vectype_in, cost_vec);
        else
  	{
*************** vectorizable_call (vec_info *vinfo,
*** 3620,3661 ****
  	}
      }
  
-   if (slp_node)
-     ncopies = 1;
-   else if (modifier == NARROW && ifn == IFN_LAST)
-     ncopies = vect_get_num_copies (loop_vinfo, vectype_out);
-   else
-     ncopies = vect_get_num_copies (loop_vinfo, vectype_in);
- 
-   /* Sanity check: make sure that at least one copy of the vectorized stmt
-      needs to be generated.  */
-   gcc_assert (ncopies >= 1);
- 
    int reduc_idx = STMT_VINFO_REDUC_IDX (stmt_info);
    internal_fn cond_fn = get_conditional_internal_fn (ifn);
    internal_fn cond_len_fn = get_len_internal_fn (ifn);
    int len_opno = internal_fn_len_index (cond_len_fn);
    vec_loop_masks *masks = (loop_vinfo ? &LOOP_VINFO_MASKS (loop_vinfo) : NULL);
    vec_loop_lens *lens = (loop_vinfo ? &LOOP_VINFO_LENS (loop_vinfo) : NULL);
!   if (!vec_stmt) /* transformation not required.  */
      {
!       if (slp_node)
! 	for (i = 0; i < nargs; ++i)
! 	  if (!vect_maybe_update_slp_op_vectype (slp_op[i],
! 						 vectypes[i]
! 						 ? vectypes[i] : vectype_in))
! 	    {
! 	      if (dump_enabled_p ())
! 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
! 				 "incompatible vector types for invariants\n");
! 	      return false;
! 	    }
        STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_call");
!       vect_model_simple_cost (vinfo, ncopies, dt, ndts, slp_node, cost_vec);
!       if (ifn != IFN_LAST && modifier == NARROW && !slp_node)
! 	record_stmt_cost (cost_vec, ncopies / 2,
! 			  vec_promote_demote, stmt_info, 0, vect_body);
  
        if (loop_vinfo
  	  && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)
--- 3469,3495 ----
  	}
      }
  
    int reduc_idx = STMT_VINFO_REDUC_IDX (stmt_info);
    internal_fn cond_fn = get_conditional_internal_fn (ifn);
    internal_fn cond_len_fn = get_len_internal_fn (ifn);
    int len_opno = internal_fn_len_index (cond_len_fn);
    vec_loop_masks *masks = (loop_vinfo ? &LOOP_VINFO_MASKS (loop_vinfo) : NULL);
    vec_loop_lens *lens = (loop_vinfo ? &LOOP_VINFO_LENS (loop_vinfo) : NULL);
!   if (cost_vec) /* transformation not required.  */
      {
!       for (i = 0; i < nargs; ++i)
! 	if (!vect_maybe_update_slp_op_vectype (slp_op[i],
! 					       vectypes[i]
! 					       ? vectypes[i] : vectype_in))
! 	  {
! 	    if (dump_enabled_p ())
! 	      dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
! 			       "incompatible vector types for invariants\n");
! 	    return false;
! 	  }
        STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_call");
!       vect_model_simple_cost (vinfo, 1, slp_node, cost_vec);
  
        if (loop_vinfo
  	  && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)
*************** vectorizable_call (vec_info *vinfo,
*** 3677,3686 ****
  	    }
  	  else
  	    {
! 	      unsigned int nvectors
! 		= (slp_node
! 		   ? SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node)
! 		   : ncopies);
  	      tree scalar_mask = NULL_TREE;
  	      if (mask_opno >= 0)
  		scalar_mask = gimple_call_arg (stmt_info->stmt, mask_opno);
--- 3511,3517 ----
  	    }
  	  else
  	    {
! 	      unsigned int nvectors = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
  	      tree scalar_mask = NULL_TREE;
  	      if (mask_opno >= 0)
  		scalar_mask = gimple_call_arg (stmt_info->stmt, mask_opno);
*************** vectorizable_call (vec_info *vinfo,
*** 3733,3952 ****
        tree prev_res = NULL_TREE;
        vargs.safe_grow (vect_nargs, true);
        auto_vec<vec<tree> > vec_defs (nargs);
!       for (j = 0; j < ncopies; ++j)
  	{
! 	  /* Build argument list for the vectorized call.  */
! 	  if (slp_node)
  	    {
! 	      if (cfn == CFN_GOMP_SIMD_LANE)
  		{
! 		  for (i = 0; i < SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); ++i)
  		    {
! 		      /* ???  For multi-lane SLP we'd need to build
! 			 { 0, 0, .., 1, 1, ... }.  */
! 		      tree cst = build_index_vector (vectype_out,
! 						     i * nunits_out, 1);
! 		      tree new_var
! 			  = vect_get_new_ssa_name (vectype_out, vect_simple_var,
! 						   "cst_");
! 		      gimple *init_stmt = gimple_build_assign (new_var, cst);
! 		      vect_init_vector_1 (vinfo, stmt_info, init_stmt, NULL);
! 		      new_temp = make_ssa_name (vec_dest);
! 		      gimple *new_stmt
! 			= gimple_build_assign (new_temp, new_var);
! 		      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt,
! 						   gsi);
! 		      slp_node->push_vec_def (new_stmt);
  		    }
! 		  continue;
  		}
! 
! 	      vec<tree> vec_oprnds0;
! 	      vect_get_slp_defs (vinfo, slp_node, &vec_defs);
! 	      vec_oprnds0 = vec_defs[0];
! 
! 	      /* Arguments are ready.  Create the new vector stmt.  */
! 	      FOR_EACH_VEC_ELT (vec_oprnds0, i, vec_oprnd0)
  		{
! 		  int varg = 0;
! 		  if (masked_loop_p && reduc_idx >= 0)
  		    {
  		      unsigned int vec_num = vec_oprnds0.length ();
! 		      /* Always true for SLP.  */
! 		      gcc_assert (ncopies == 1);
! 		      vargs[varg++] = vect_get_loop_mask (loop_vinfo,
! 							  gsi, masks, vec_num,
! 							  vectype_out, i);
  		    }
! 		  size_t k;
! 		  for (k = 0; k < nargs; k++)
  		    {
! 		      vec<tree> vec_oprndsk = vec_defs[k];
! 		      vargs[varg++] = vec_oprndsk[i];
  		    }
- 		  if (masked_loop_p && reduc_idx >= 0)
- 		    vargs[varg++] = vargs[reduc_idx + 1];
- 		  if (clz_ctz_arg1)
- 		    vargs[varg++] = clz_ctz_arg1;
  
! 		  gimple *new_stmt;
! 		  if (modifier == NARROW)
! 		    {
! 		      /* We don't define any narrowing conditional functions
! 			 at present.  */
! 		      gcc_assert (mask_opno < 0);
! 		      tree half_res = make_ssa_name (vectype_in);
! 		      gcall *call
! 			= gimple_build_call_internal_vec (ifn, vargs);
! 		      gimple_call_set_lhs (call, half_res);
! 		      gimple_call_set_nothrow (call, true);
! 		      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
! 		      if ((i & 1) == 0)
! 			{
! 			  prev_res = half_res;
! 			  continue;
! 			}
! 		      new_temp = make_ssa_name (vec_dest);
! 		      new_stmt = vect_gimple_build (new_temp, convert_code,
! 						    prev_res, half_res);
! 		      vect_finish_stmt_generation (vinfo, stmt_info,
! 						   new_stmt, gsi);
! 		    }
  		  else
! 		    {
! 		      if (len_opno >= 0 && len_loop_p)
! 			{
! 			  unsigned int vec_num = vec_oprnds0.length ();
! 			  /* Always true for SLP.  */
! 			  gcc_assert (ncopies == 1);
! 			  tree len
! 			    = vect_get_loop_len (loop_vinfo, gsi, lens, vec_num,
! 						 vectype_out, i, 1);
! 			  signed char biasval
! 			    = LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS (loop_vinfo);
! 			  tree bias = build_int_cst (intQI_type_node, biasval);
! 			  vargs[len_opno] = len;
! 			  vargs[len_opno + 1] = bias;
! 			}
! 		      else if (mask_opno >= 0 && masked_loop_p)
! 			{
! 			  unsigned int vec_num = vec_oprnds0.length ();
! 			  /* Always true for SLP.  */
! 			  gcc_assert (ncopies == 1);
! 			  tree mask = vect_get_loop_mask (loop_vinfo,
! 							  gsi, masks, vec_num,
! 							  vectype_out, i);
! 			  vargs[mask_opno] = prepare_vec_mask
! 			    (loop_vinfo, TREE_TYPE (mask), mask,
! 			     vargs[mask_opno], gsi);
! 			}
! 
! 		      gcall *call;
! 		      if (ifn != IFN_LAST)
! 			call = gimple_build_call_internal_vec (ifn, vargs);
! 		      else
! 			call = gimple_build_call_vec (fndecl, vargs);
! 		      new_temp = make_ssa_name (vec_dest, call);
! 		      gimple_call_set_lhs (call, new_temp);
! 		      gimple_call_set_nothrow (call, true);
! 		      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
! 		      new_stmt = call;
! 		    }
! 		  slp_node->push_vec_def (new_stmt);
! 		}
! 	      continue;
! 	    }
! 
! 	  int varg = 0;
! 	  if (masked_loop_p && reduc_idx >= 0)
! 	    vargs[varg++] = vect_get_loop_mask (loop_vinfo, gsi, masks, ncopies,
! 						vectype_out, j);
! 	  for (i = 0; i < nargs; i++)
! 	    {
! 	      op = gimple_call_arg (stmt, i);
! 	      if (j == 0)
! 		{
! 		  vec_defs.quick_push (vNULL);
! 		  vect_get_vec_defs_for_operand (vinfo, stmt_info, ncopies,
! 						 op, &vec_defs[i],
! 						 vectypes[i]);
! 		}
! 	      vargs[varg++] = vec_defs[i][j];
! 	    }
! 	  if (masked_loop_p && reduc_idx >= 0)
! 	    vargs[varg++] = vargs[reduc_idx + 1];
! 	  if (clz_ctz_arg1)
! 	    vargs[varg++] = clz_ctz_arg1;
! 
! 	  if (len_opno >= 0 && len_loop_p)
! 	    {
! 	      tree len = vect_get_loop_len (loop_vinfo, gsi, lens, ncopies,
! 					    vectype_out, j, 1);
! 	      signed char biasval
! 		= LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS (loop_vinfo);
! 	      tree bias = build_int_cst (intQI_type_node, biasval);
! 	      vargs[len_opno] = len;
! 	      vargs[len_opno + 1] = bias;
! 	    }
! 	  else if (mask_opno >= 0 && masked_loop_p)
! 	    {
! 	      tree mask = vect_get_loop_mask (loop_vinfo, gsi, masks, ncopies,
! 					      vectype_out, j);
! 	      vargs[mask_opno]
! 		= prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
! 				    vargs[mask_opno], gsi);
! 	    }
! 
! 	  gimple *new_stmt;
! 	  if (cfn == CFN_GOMP_SIMD_LANE)
! 	    {
! 	      tree cst = build_index_vector (vectype_out, j * nunits_out, 1);
! 	      tree new_var
! 		= vect_get_new_ssa_name (vectype_out, vect_simple_var, "cst_");
! 	      gimple *init_stmt = gimple_build_assign (new_var, cst);
! 	      vect_init_vector_1 (vinfo, stmt_info, init_stmt, NULL);
! 	      new_temp = make_ssa_name (vec_dest);
! 	      new_stmt = gimple_build_assign (new_temp, new_var);
! 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
! 	    }
! 	  else if (modifier == NARROW)
! 	    {
! 	      /* We don't define any narrowing conditional functions at
! 		 present.  */
! 	      gcc_assert (mask_opno < 0);
! 	      tree half_res = make_ssa_name (vectype_in);
! 	      gcall *call = gimple_build_call_internal_vec (ifn, vargs);
! 	      gimple_call_set_lhs (call, half_res);
! 	      gimple_call_set_nothrow (call, true);
! 	      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
! 	      if ((j & 1) == 0)
! 		{
! 		  prev_res = half_res;
! 		  continue;
  		}
! 	      new_temp = make_ssa_name (vec_dest);
! 	      new_stmt = vect_gimple_build (new_temp, convert_code, prev_res,
! 					    half_res);
! 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
! 	    }
! 	  else
! 	    {
! 	      gcall *call;
! 	      if (ifn != IFN_LAST)
! 		call = gimple_build_call_internal_vec (ifn, vargs);
! 	      else
! 		call = gimple_build_call_vec (fndecl, vargs);
! 	      new_temp = make_ssa_name (vec_dest, call);
! 	      gimple_call_set_lhs (call, new_temp);
! 	      gimple_call_set_nothrow (call, true);
! 	      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
! 	      new_stmt = call;
  	    }
- 
- 	  if (j == (modifier == NARROW ? 1 : 0))
- 	    *vec_stmt = new_stmt;
- 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
  	}
        for (i = 0; i < nargs; i++)
  	{
  	  vec<tree> vec_oprndsi = vec_defs[i];
--- 3564,3675 ----
        tree prev_res = NULL_TREE;
        vargs.safe_grow (vect_nargs, true);
        auto_vec<vec<tree> > vec_defs (nargs);
! 
!       /* Build argument list for the vectorized call.  */
!       if (cfn == CFN_GOMP_SIMD_LANE)
  	{
! 	  for (i = 0; i < SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); ++i)
  	    {
! 	      /* ???  For multi-lane SLP we'd need to build
! 		 { 0, 0, .., 1, 1, ... }.  */
! 	      tree cst = build_index_vector (vectype_out,
! 					     i * nunits_out, 1);
! 	      tree new_var
! 		= vect_get_new_ssa_name (vectype_out, vect_simple_var, "cst_");
! 	      gimple *init_stmt = gimple_build_assign (new_var, cst);
! 	      vect_init_vector_1 (vinfo, stmt_info, init_stmt, NULL);
! 	      new_temp = make_ssa_name (vec_dest);
! 	      gimple *new_stmt = gimple_build_assign (new_temp, new_var);
! 	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
! 	      slp_node->push_vec_def (new_stmt);
! 	    }
! 	}
!       else
! 	{
! 	  vec<tree> vec_oprnds0;
! 	  vect_get_slp_defs (vinfo, slp_node, &vec_defs);
! 	  vec_oprnds0 = vec_defs[0];
! 
! 	  /* Arguments are ready.  Create the new vector stmt.  */
! 	  FOR_EACH_VEC_ELT (vec_oprnds0, i, vec_oprnd0)
! 	    {
! 	      int varg = 0;
! 	      if (masked_loop_p && reduc_idx >= 0)
  		{
! 		  unsigned int vec_num = vec_oprnds0.length ();
! 		  vargs[varg++] = vect_get_loop_mask (loop_vinfo, gsi, masks,
! 						      vec_num, vectype_out, i);
! 		}
! 	      size_t k;
! 	      for (k = 0; k < nargs; k++)
! 		{
! 		  vec<tree> vec_oprndsk = vec_defs[k];
! 		  vargs[varg++] = vec_oprndsk[i];
! 		}
! 	      if (masked_loop_p && reduc_idx >= 0)
! 		vargs[varg++] = vargs[reduc_idx + 1];
! 	      if (clz_ctz_arg1)
! 		vargs[varg++] = clz_ctz_arg1;
! 
! 	      gimple *new_stmt;
! 	      if (modifier == NARROW)
! 		{
! 		  /* We don't define any narrowing conditional functions
! 		     at present.  */
! 		  gcc_assert (mask_opno < 0);
! 		  tree half_res = make_ssa_name (vectype_in);
! 		  gcall *call = gimple_build_call_internal_vec (ifn, vargs);
! 		  gimple_call_set_lhs (call, half_res);
! 		  gimple_call_set_nothrow (call, true);
! 		  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
! 		  if ((i & 1) == 0)
  		    {
! 		      prev_res = half_res;
! 		      continue;
  		    }
! 		  new_temp = make_ssa_name (vec_dest);
! 		  new_stmt = vect_gimple_build (new_temp, convert_code,
! 						prev_res, half_res);
! 		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
  		}
! 	      else
  		{
! 		  if (len_opno >= 0 && len_loop_p)
  		    {
  		      unsigned int vec_num = vec_oprnds0.length ();
! 		      tree len = vect_get_loop_len (loop_vinfo, gsi, lens,
! 						    vec_num, vectype_out, i, 1);
! 		      signed char biasval
! 			= LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS (loop_vinfo);
! 		      tree bias = build_int_cst (intQI_type_node, biasval);
! 		      vargs[len_opno] = len;
! 		      vargs[len_opno + 1] = bias;
  		    }
! 		  else if (mask_opno >= 0 && masked_loop_p)
  		    {
! 		      unsigned int vec_num = vec_oprnds0.length ();
! 		      tree mask = vect_get_loop_mask (loop_vinfo, gsi, masks,
! 						      vec_num, vectype_out, i);
! 		      vargs[mask_opno]
! 			= prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
! 					    vargs[mask_opno], gsi);
  		    }
  
! 		  gcall *call;
! 		  if (ifn != IFN_LAST)
! 		    call = gimple_build_call_internal_vec (ifn, vargs);
  		  else
! 		    call = gimple_build_call_vec (fndecl, vargs);
! 		  new_temp = make_ssa_name (vec_dest, call);
! 		  gimple_call_set_lhs (call, new_temp);
! 		  gimple_call_set_nothrow (call, true);
! 		  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
! 		  new_stmt = call;
  		}
! 	      slp_node->push_vec_def (new_stmt);
  	    }
  	}
+ 
        for (i = 0; i < nargs; i++)
  	{
  	  vec<tree> vec_oprndsi = vec_defs[i];
*************** vectorizable_call (vec_info *vinfo,
*** 3958,4030 ****
        auto_vec<vec<tree> > vec_defs (nargs);
        /* We don't define any narrowing conditional functions at present.  */
        gcc_assert (mask_opno < 0);
-       for (j = 0; j < ncopies; ++j)
- 	{
- 	  /* Build argument list for the vectorized call.  */
- 	  if (j == 0)
- 	    vargs.create (nargs * 2);
- 	  else
- 	    vargs.truncate (0);
  
! 	  if (slp_node)
! 	    {
! 	      vec<tree> vec_oprnds0;
! 
! 	      vect_get_slp_defs (vinfo, slp_node, &vec_defs);
! 	      vec_oprnds0 = vec_defs[0];
  
! 	      /* Arguments are ready.  Create the new vector stmt.  */
! 	      for (i = 0; vec_oprnds0.iterate (i, &vec_oprnd0); i += 2)
! 		{
! 		  size_t k;
! 		  vargs.truncate (0);
! 		  for (k = 0; k < nargs; k++)
! 		    {
! 		      vec<tree> vec_oprndsk = vec_defs[k];
! 		      vargs.quick_push (vec_oprndsk[i]);
! 		      vargs.quick_push (vec_oprndsk[i + 1]);
! 		    }
! 		  gcall *call;
! 		  if (ifn != IFN_LAST)
! 		    call = gimple_build_call_internal_vec (ifn, vargs);
! 		  else
! 		    call = gimple_build_call_vec (fndecl, vargs);
! 		  new_temp = make_ssa_name (vec_dest, call);
! 		  gimple_call_set_lhs (call, new_temp);
! 		  gimple_call_set_nothrow (call, true);
! 		  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
! 		  slp_node->push_vec_def (call);
! 		}
! 	      continue;
! 	    }
  
! 	  for (i = 0; i < nargs; i++)
  	    {
! 	      op = gimple_call_arg (stmt, i);
! 	      if (j == 0)
! 		{
! 		  vec_defs.quick_push (vNULL);
! 		  vect_get_vec_defs_for_operand (vinfo, stmt_info, 2 * ncopies,
! 						 op, &vec_defs[i], vectypes[i]);
! 		}
! 	      vec_oprnd0 = vec_defs[i][2*j];
! 	      vec_oprnd1 = vec_defs[i][2*j+1];
! 
! 	      vargs.quick_push (vec_oprnd0);
! 	      vargs.quick_push (vec_oprnd1);
  	    }
! 
! 	  gcall *new_stmt = gimple_build_call_vec (fndecl, vargs);
! 	  new_temp = make_ssa_name (vec_dest, new_stmt);
! 	  gimple_call_set_lhs (new_stmt, new_temp);
! 	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
! 
! 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
  	}
  
-       if (!slp_node)
- 	*vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
- 
        for (i = 0; i < nargs; i++)
  	{
  	  vec<tree> vec_oprndsi = vec_defs[i];
--- 3681,3716 ----
        auto_vec<vec<tree> > vec_defs (nargs);
        /* We don't define any narrowing conditional functions at present.  */
        gcc_assert (mask_opno < 0);
  
!       /* Build argument list for the vectorized call.  */
!       vargs.create (nargs * 2);
  
!       vect_get_slp_defs (vinfo, slp_node, &vec_defs);
!       vec<tree> vec_oprnds0 = vec_defs[0];
  
!       /* Arguments are ready.  Create the new vector stmt.  */
!       for (i = 0; vec_oprnds0.iterate (i, &vec_oprnd0); i += 2)
! 	{
! 	  size_t k;
! 	  vargs.truncate (0);
! 	  for (k = 0; k < nargs; k++)
  	    {
! 	      vec<tree> vec_oprndsk = vec_defs[k];
! 	      vargs.quick_push (vec_oprndsk[i]);
! 	      vargs.quick_push (vec_oprndsk[i + 1]);
  	    }
! 	  gcall *call;
! 	  if (ifn != IFN_LAST)
! 	    call = gimple_build_call_internal_vec (ifn, vargs);
! 	  else
! 	    call = gimple_build_call_vec (fndecl, vargs);
! 	  new_temp = make_ssa_name (vec_dest, call);
! 	  gimple_call_set_lhs (call, new_temp);
! 	  gimple_call_set_nothrow (call, true);
! 	  vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
! 	  slp_node->push_vec_def (call);
  	}
  
        for (i = 0; i < nargs; i++)
  	{
  	  vec<tree> vec_oprndsi = vec_defs[i];
*************** vectorizable_call (vec_info *vinfo,
*** 4037,4057 ****
  
    vargs.release ();
  
-   /* The call in STMT might prevent it from being removed in dce.
-      We however cannot remove it here, due to the way the ssa name
-      it defines is mapped to the new definition.  So just replace
-      rhs of the statement with something harmless.  */
- 
-   if (slp_node)
-     return true;
- 
-   stmt_info = vect_orig_stmt (stmt_info);
-   lhs = gimple_get_lhs (stmt_info->stmt);
- 
-   gassign *new_stmt
-     = gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
-   vinfo->replace_stmt (gsi, stmt_info, new_stmt);
- 
    return true;
  }
  
--- 3723,3728 ----
*************** vect_simd_lane_linear (tree op, class lo
*** 4145,4156 ****
  static bool
  vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
  			      gimple_stmt_iterator *gsi,
! 			      gimple **vec_stmt, slp_tree slp_node,
! 			      stmt_vector_for_cost *)
  {
    tree vec_dest;
    tree scalar_dest;
!   tree op, type;
    tree vec_oprnd0 = NULL_TREE;
    tree vectype;
    poly_uint64 nunits;
--- 3816,3827 ----
  static bool
  vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
  			      gimple_stmt_iterator *gsi,
! 			      slp_tree slp_node,
! 			      stmt_vector_for_cost *cost_vec)
  {
    tree vec_dest;
    tree scalar_dest;
!   tree op;
    tree vec_oprnd0 = NULL_TREE;
    tree vectype;
    poly_uint64 nunits;
*************** vectorizable_simd_clone_call (vec_info *
*** 4162,4168 ****
    auto_vec<simd_call_arg_info> arginfo;
    vec<tree> vargs = vNULL;
    size_t i, nargs;
!   tree lhs, rtype, ratype;
    vec<constructor_elt, va_gc> *ret_ctor_elts = NULL;
    int masked_call_offset = 0;
  
--- 3833,3839 ----
    auto_vec<simd_call_arg_info> arginfo;
    vec<tree> vargs = vNULL;
    size_t i, nargs;
!   tree rtype, ratype;
    vec<constructor_elt, va_gc> *ret_ctor_elts = NULL;
    int masked_call_offset = 0;
  
*************** vectorizable_simd_clone_call (vec_info *
*** 4192,4198 ****
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && ! vec_stmt)
      return false;
  
    if (gimple_call_lhs (stmt)
--- 3863,3869 ----
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && cost_vec)
      return false;
  
    if (gimple_call_lhs (stmt)
*************** vectorizable_simd_clone_call (vec_info *
*** 4201,4207 ****
  
    gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
  
!   vectype = STMT_VINFO_VECTYPE (stmt_info);
  
    if (loop_vinfo && nested_in_vect_loop_p (loop, stmt_info))
      return false;
--- 3872,3878 ----
  
    gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
  
!   vectype = SLP_TREE_VECTYPE (slp_node);
  
    if (loop_vinfo && nested_in_vect_loop_p (loop, stmt_info))
      return false;
*************** vectorizable_simd_clone_call (vec_info *
*** 4213,4221 ****
    if (nargs == 0)
      return false;
  
!   vec<tree>& simd_clone_info = (slp_node ? SLP_TREE_SIMD_CLONE_INFO (slp_node)
! 				: STMT_VINFO_SIMD_CLONE_INFO (stmt_info));
!   if (!vec_stmt)
      simd_clone_info.truncate (0);
    arginfo.reserve (nargs, true);
    auto_vec<slp_tree> slp_op;
--- 3884,3891 ----
    if (nargs == 0)
      return false;
  
!   vec<tree>& simd_clone_info = SLP_TREE_SIMD_CLONE_INFO (slp_node);
!   if (cost_vec)
      simd_clone_info.truncate (0);
    arginfo.reserve (nargs, true);
    auto_vec<slp_tree> slp_op;
*************** vectorizable_simd_clone_call (vec_info *
*** 4231,4240 ****
        thisarginfo.op = NULL_TREE;
        thisarginfo.simd_lane_linear = false;
  
!       int op_no = i + masked_call_offset;
!       if (slp_node)
! 	op_no = vect_slp_child_index_for_operand (stmt, op_no, false);
!       if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
  			       op_no, &op, &slp_op[i],
  			       &thisarginfo.dt, &thisarginfo.vectype)
  	  || thisarginfo.dt == vect_uninitialized_def)
--- 3901,3910 ----
        thisarginfo.op = NULL_TREE;
        thisarginfo.simd_lane_linear = false;
  
!       int op_no = vect_slp_child_index_for_operand (stmt,
! 						    i + masked_call_offset,
! 						    false);
!       if (!vect_is_simple_use (vinfo, slp_node,
  			       op_no, &op, &slp_op[i],
  			       &thisarginfo.dt, &thisarginfo.vectype)
  	  || thisarginfo.dt == vect_uninitialized_def)
*************** vectorizable_simd_clone_call (vec_info *
*** 4252,4261 ****
  	     at analysis time, handling conflicts via
  	     vect_maybe_update_slp_op_vectype.  At transform time
  	     we have a vector type recorded for SLP.  */
! 	  gcc_assert (!vec_stmt
! 		      || !slp_node
  		      || thisarginfo.vectype != NULL_TREE);
! 	  if (!vec_stmt)
  	    thisarginfo.vectype = get_vectype_for_scalar_type (vinfo,
  							       TREE_TYPE (op),
  							       slp_node);
--- 3922,3930 ----
  	     at analysis time, handling conflicts via
  	     vect_maybe_update_slp_op_vectype.  At transform time
  	     we have a vector type recorded for SLP.  */
! 	  gcc_assert (cost_vec
  		      || thisarginfo.vectype != NULL_TREE);
! 	  if (cost_vec)
  	    thisarginfo.vectype = get_vectype_for_scalar_type (vinfo,
  							       TREE_TYPE (op),
  							       slp_node);
*************** vectorizable_simd_clone_call (vec_info *
*** 4265,4271 ****
  
        /* For linear arguments, the analyze phase should have saved
  	 the base and step in {STMT_VINFO,SLP_TREE}_SIMD_CLONE_INFO.  */
!       if (vec_stmt
  	  && i * 3 + 4 <= simd_clone_info.length ()
  	  && simd_clone_info[i * 3 + 2])
  	{
--- 3934,3940 ----
  
        /* For linear arguments, the analyze phase should have saved
  	 the base and step in {STMT_VINFO,SLP_TREE}_SIMD_CLONE_INFO.  */
!       if (!cost_vec
  	  && i * 3 + 4 <= simd_clone_info.length ()
  	  && simd_clone_info[i * 3 + 2])
  	{
*************** vectorizable_simd_clone_call (vec_info *
*** 4289,4295 ****
  			       thisarginfo.op, bias);
  	    }
  	}
!       else if (!vec_stmt
  	       && thisarginfo.dt != vect_constant_def
  	       && thisarginfo.dt != vect_external_def
  	       && loop_vinfo
--- 3958,3964 ----
  			       thisarginfo.op, bias);
  	    }
  	}
!       else if (cost_vec
  	       && thisarginfo.dt != vect_constant_def
  	       && thisarginfo.dt != vect_external_def
  	       && loop_vinfo
*************** vectorizable_simd_clone_call (vec_info *
*** 4309,4315 ****
  	 linear too.  */
        if (POINTER_TYPE_P (TREE_TYPE (op))
  	  && !thisarginfo.linear_step
! 	  && !vec_stmt
  	  && thisarginfo.dt != vect_constant_def
  	  && thisarginfo.dt != vect_external_def
  	  && loop_vinfo
--- 3978,3984 ----
  	 linear too.  */
        if (POINTER_TYPE_P (TREE_TYPE (op))
  	  && !thisarginfo.linear_step
! 	  && cost_vec
  	  && thisarginfo.dt != vect_constant_def
  	  && thisarginfo.dt != vect_external_def
  	  && loop_vinfo
*************** vectorizable_simd_clone_call (vec_info *
*** 4320,4329 ****
      }
  
    poly_uint64 vf = loop_vinfo ? LOOP_VINFO_VECT_FACTOR (loop_vinfo) : 1;
!   unsigned group_size = slp_node ? SLP_TREE_LANES (slp_node) : 1;
    unsigned int badness = 0;
    struct cgraph_node *bestn = NULL;
!   if (vec_stmt)
      bestn = cgraph_node::get (simd_clone_info[0]);
    else
      for (struct cgraph_node *n = node->simd_clones; n != NULL;
--- 3989,3998 ----
      }
  
    poly_uint64 vf = loop_vinfo ? LOOP_VINFO_VECT_FACTOR (loop_vinfo) : 1;
!   unsigned group_size = SLP_TREE_LANES (slp_node);
    unsigned int badness = 0;
    struct cgraph_node *bestn = NULL;
!   if (!cost_vec)
      bestn = cgraph_node::get (simd_clone_info[0]);
    else
      for (struct cgraph_node *n = node->simd_clones; n != NULL;
*************** vectorizable_simd_clone_call (vec_info *
*** 4350,4356 ****
  	if (n->simdclone->inbranch)
  	  this_badness += 8192;
  
! 	/* If STMT_VINFO_VECTYPE has not been set yet pass the general vector
  	   mode,  which for targets that use it will determine what ISA we can
  	   vectorize this code with.  */
  	machine_mode vector_mode = vinfo->vector_mode;
--- 4019,4025 ----
  	if (n->simdclone->inbranch)
  	  this_badness += 8192;
  
! 	/* If SLP_TREE_VECTYPE has not been set yet pass the general vector
  	   mode,  which for targets that use it will determine what ISA we can
  	   vectorize this code with.  */
  	machine_mode vector_mode = vinfo->vector_mode;
*************** vectorizable_simd_clone_call (vec_info *
*** 4535,4544 ****
  
    fndecl = bestn->decl;
    nunits = bestn->simdclone->simdlen;
!   if (slp_node)
!     ncopies = vector_unroll_factor (vf * group_size, nunits);
!   else
!     ncopies = vector_unroll_factor (vf, nunits);
  
    /* If the function isn't const, only allow it in simd loops where user
       has asserted that at least nunits consecutive iterations can be
--- 4204,4210 ----
  
    fndecl = bestn->decl;
    nunits = bestn->simdclone->simdlen;
!   ncopies = vector_unroll_factor (vf * group_size, nunits);
  
    /* If the function isn't const, only allow it in simd loops where user
       has asserted that at least nunits consecutive iterations can be
*************** vectorizable_simd_clone_call (vec_info *
*** 4551,4567 ****
       needs to be generated.  */
    gcc_assert (ncopies >= 1);
  
!   if (!vec_stmt) /* transformation not required.  */
      {
!       if (slp_node)
! 	for (unsigned i = 0; i < nargs; ++i)
! 	  if (!vect_maybe_update_slp_op_vectype (slp_op[i], arginfo[i].vectype))
! 	    {
! 	      if (dump_enabled_p ())
! 		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
! 				 "incompatible vector types for invariants\n");
! 	      return false;
! 	    }
        /* When the original call is pure or const but the SIMD ABI dictates
  	 an aggregate return we will have to use a virtual definition and
  	 in a loop eventually even need to add a virtual PHI.  That's
--- 4217,4232 ----
       needs to be generated.  */
    gcc_assert (ncopies >= 1);
  
!   if (cost_vec) /* transformation not required.  */
      {
!       for (unsigned i = 0; i < nargs; ++i)
! 	if (!vect_maybe_update_slp_op_vectype (slp_op[i], arginfo[i].vectype))
! 	  {
! 	    if (dump_enabled_p ())
! 	      dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
! 			       "incompatible vector types for invariants\n");
! 	    return false;
! 	  }
        /* When the original call is pure or const but the SIMD ABI dictates
  	 an aggregate return we will have to use a virtual definition and
  	 in a loop eventually even need to add a virtual PHI.  That's
*************** vectorizable_simd_clone_call (vec_info *
*** 4573,4579 ****
        /* ???  For SLP code-gen we end up inserting after the last
  	 vector argument def rather than at the original call position
  	 so automagic virtual operand updating doesn't work.  */
!       if (gimple_vuse (stmt) && slp_node)
  	vinfo->any_known_not_updated_vssa = true;
        simd_clone_info.safe_push (bestn->decl);
        for (i = 0; i < bestn->simdclone->nargs; i++)
--- 4238,4244 ----
        /* ???  For SLP code-gen we end up inserting after the last
  	 vector argument def rather than at the original call position
  	 so automagic virtual operand updating doesn't work.  */
!       if (gimple_vuse (stmt))
  	vinfo->any_known_not_updated_vssa = true;
        simd_clone_info.safe_push (bestn->decl);
        for (i = 0; i < bestn->simdclone->nargs; i++)
*************** vectorizable_simd_clone_call (vec_info *
*** 4619,4625 ****
  
        STMT_VINFO_TYPE (stmt_info) = call_simd_clone_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_simd_clone_call");
! /*      vect_model_simple_cost (vinfo, ncopies, dt, slp_node, cost_vec); */
        return true;
      }
  
--- 4284,4290 ----
  
        STMT_VINFO_TYPE (stmt_info) = call_simd_clone_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_simd_clone_call");
! /*      vect_model_simple_cost (vinfo, 1, slp_node, cost_vec); */
        return true;
      }
  
*************** vectorizable_simd_clone_call (vec_info *
*** 4647,4659 ****
    auto_vec<vec<tree> > vec_oprnds;
    auto_vec<unsigned> vec_oprnds_i;
    vec_oprnds_i.safe_grow_cleared (nargs, true);
!   if (slp_node)
!     {
!       vec_oprnds.reserve_exact (nargs);
!       vect_get_slp_defs (vinfo, slp_node, &vec_oprnds);
!     }
!   else
!     vec_oprnds.safe_grow_cleared (nargs, true);
    for (j = 0; j < ncopies; ++j)
      {
        poly_uint64 callee_nelements;
--- 4312,4319 ----
    auto_vec<vec<tree> > vec_oprnds;
    auto_vec<unsigned> vec_oprnds_i;
    vec_oprnds_i.safe_grow_cleared (nargs, true);
!   vec_oprnds.reserve_exact (nargs);
!   vect_get_slp_defs (vinfo, slp_node, &vec_oprnds);
    for (j = 0; j < ncopies; ++j)
      {
        poly_uint64 callee_nelements;
*************** vectorizable_simd_clone_call (vec_info *
*** 4688,4697 ****
  		      gcc_assert ((k & (k - 1)) == 0);
  		      if (m == 0)
  			{
- 			  if (!slp_node)
- 			    vect_get_vec_defs_for_operand (vinfo, stmt_info,
- 							   ncopies * o / k, op,
- 							   &vec_oprnds[i]);
  			  vec_oprnds_i[i] = 0;
  			  vec_oprnd0 = vec_oprnds[i][vec_oprnds_i[i]++];
  			}
--- 4348,4353 ----
*************** vectorizable_simd_clone_call (vec_info *
*** 4728,4738 ****
  			{
  			  if (m == 0 && l == 0)
  			    {
- 			      if (!slp_node)
- 				vect_get_vec_defs_for_operand (vinfo, stmt_info,
- 							       k * o * ncopies,
- 							       op,
- 							       &vec_oprnds[i]);
  			      vec_oprnds_i[i] = 0;
  			      vec_oprnd0 = vec_oprnds[i][vec_oprnds_i[i]++];
  			    }
--- 4384,4389 ----
*************** vectorizable_simd_clone_call (vec_info *
*** 4796,4809 ****
  			  /* The SIMD clone function has the same number of
  			     elements as the current function.  */
  			  if (m == 0)
! 			    {
! 			      if (!slp_node)
! 				vect_get_vec_defs_for_operand (vinfo, stmt_info,
! 							       o * ncopies,
! 							       op,
! 							       &vec_oprnds[i]);
! 			      vec_oprnds_i[i] = 0;
! 			    }
  			  vec_oprnd0 = vec_oprnds[i][vec_oprnds_i[i]++];
  			  if (loop_vinfo
  			      && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo))
--- 4447,4453 ----
  			  /* The SIMD clone function has the same number of
  			     elements as the current function.  */
  			  if (m == 0)
! 			    vec_oprnds_i[i] = 0;
  			  vec_oprnd0 = vec_oprnds[i][vec_oprnds_i[i]++];
  			  if (loop_vinfo
  			      && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo))
*************** vectorizable_simd_clone_call (vec_info *
*** 4854,4867 ****
  		  for (m = j * o; m < (j + 1) * o; m++)
  		    {
  		      if (m == 0)
! 			{
! 			  if (!slp_node)
! 			    vect_get_vec_defs_for_operand (vinfo, stmt_info,
! 							   o * ncopies,
! 							   op,
! 							   &vec_oprnds[i]);
! 			  vec_oprnds_i[i] = 0;
! 			}
  		      if (maybe_lt (atype_subparts,
  				    TYPE_VECTOR_SUBPARTS (arginfo[i].vectype)))
  			{
--- 4498,4504 ----
  		  for (m = j * o; m < (j + 1) * o; m++)
  		    {
  		      if (m == 0)
! 			vec_oprnds_i[i] = 0;
  		      if (maybe_lt (atype_subparts,
  				    TYPE_VECTOR_SUBPARTS (arginfo[i].vectype)))
  			{
*************** vectorizable_simd_clone_call (vec_info *
*** 5096,5108 ****
  		  new_stmt = gimple_build_assign (make_ssa_name (vectype), t);
  		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
  
! 		  if (j == 0 && l == 0)
! 		    *vec_stmt = new_stmt;
! 		  if (slp_node)
! 		    SLP_TREE_VEC_DEFS (slp_node)
! 		      .quick_push (gimple_assign_lhs (new_stmt));
! 		  else
! 		    STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
  		}
  
  	      if (ratype)
--- 4733,4740 ----
  		  new_stmt = gimple_build_assign (make_ssa_name (vectype), t);
  		  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
  
! 		  SLP_TREE_VEC_DEFS (slp_node)
! 		    .quick_push (gimple_assign_lhs (new_stmt));
  		}
  
  	      if (ratype)
*************** vectorizable_simd_clone_call (vec_info *
*** 5145,5157 ****
  		= gimple_build_assign (make_ssa_name (vec_dest), vec_oprnd0);
  	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
  
! 	      if ((unsigned) j == k - 1)
! 		*vec_stmt = new_stmt;
! 	      if (slp_node)
! 		SLP_TREE_VEC_DEFS (slp_node)
! 		  .quick_push (gimple_assign_lhs (new_stmt));
! 	      else
! 		STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
  	      continue;
  	    }
  	  else if (ratype)
--- 4777,4784 ----
  		= gimple_build_assign (make_ssa_name (vec_dest), vec_oprnd0);
  	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
  
! 	      SLP_TREE_VEC_DEFS (slp_node)
! 		.quick_push (gimple_assign_lhs (new_stmt));
  	      continue;
  	    }
  	  else if (ratype)
*************** vectorizable_simd_clone_call (vec_info *
*** 5172,5183 ****
  	    }
  	}
  
!       if (j == 0)
! 	*vec_stmt = new_stmt;
!       if (slp_node)
! 	SLP_TREE_VEC_DEFS (slp_node).quick_push (gimple_get_lhs (new_stmt));
!       else
! 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
      }
  
    for (i = 0; i < nargs; ++i)
--- 4799,4805 ----
  	    }
  	}
  
!       SLP_TREE_VEC_DEFS (slp_node).quick_push (gimple_get_lhs (new_stmt));
      }
  
    for (i = 0; i < nargs; ++i)
*************** vectorizable_simd_clone_call (vec_info *
*** 5190,5215 ****
    /* Mark the clone as no longer being a candidate for GC.  */
    bestn->gc_candidate = false;
  
-   /* The call in STMT might prevent it from being removed in dce.
-      We however cannot remove it here, due to the way the ssa name
-      it defines is mapped to the new definition.  So just replace
-      rhs of the statement with something harmless.  */
- 
-   if (slp_node)
-     return true;
- 
-   gimple *new_stmt;
-   if (scalar_dest)
-     {
-       type = TREE_TYPE (scalar_dest);
-       lhs = gimple_call_lhs (vect_orig_stmt (stmt_info)->stmt);
-       new_stmt = gimple_build_assign (lhs, build_zero_cst (type));
-     }
-   else
-     new_stmt = gimple_build_nop ();
-   vinfo->replace_stmt (gsi, vect_orig_stmt (stmt_info), new_stmt);
-   unlink_stmt_vdef (stmt);
- 
    return true;
  }
  
--- 4812,4817 ----
*************** vect_create_vectorized_demotion_stmts (v
*** 5280,5291 ****
        else
  	{
  	  /* This is the last step of the conversion sequence. Store the
! 	     vectors in SLP_NODE or in vector info of the scalar statement
! 	     (or in STMT_VINFO_RELATED_STMT chain).  */
! 	  if (slp_node)
! 	    slp_node->push_vec_def (new_stmt);
! 	  else
! 	    STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
  	}
      }
  
--- 4882,4889 ----
        else
  	{
  	  /* This is the last step of the conversion sequence. Store the
! 	     vectors in SLP_NODE.  */
! 	  slp_node->push_vec_def (new_stmt);
  	}
      }
  
*************** vect_create_half_widening_stmts (vec_inf
*** 5430,5436 ****
  static bool
  vectorizable_conversion (vec_info *vinfo,
  			 stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 			 gimple **vec_stmt, slp_tree slp_node,
  			 stmt_vector_for_cost *cost_vec)
  {
    tree vec_dest, cvt_op = NULL_TREE;
--- 5028,5034 ----
  static bool
  vectorizable_conversion (vec_info *vinfo,
  			 stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 			 slp_tree slp_node,
  			 stmt_vector_for_cost *cost_vec)
  {
    tree vec_dest, cvt_op = NULL_TREE;
*************** vectorizable_conversion (vec_info *vinfo
*** 5441,5447 ****
    code_helper codecvt1 = ERROR_MARK, codecvt2 = ERROR_MARK;
    tree new_temp;
    enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
-   int ndts = 2;
    poly_uint64 nunits_in;
    poly_uint64 nunits_out;
    tree vectype_out, vectype_in;
--- 5039,5044 ----
*************** vectorizable_conversion (vec_info *vinfo
*** 5473,5479 ****
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && ! vec_stmt)
      return false;
  
    gimple* stmt = stmt_info->stmt;
--- 5070,5076 ----
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && cost_vec)
      return false;
  
    gimple* stmt = stmt_info->stmt;
*************** vectorizable_conversion (vec_info *vinfo
*** 5517,5523 ****
  
    /* Check the operands of the operation.  */
    slp_tree slp_op0, slp_op1 = NULL;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
  			   0, &op0, &slp_op0, &dt[0], &vectype_in))
      {
        if (dump_enabled_p ())
--- 5114,5120 ----
  
    /* Check the operands of the operation.  */
    slp_tree slp_op0, slp_op1 = NULL;
!   if (!vect_is_simple_use (vinfo, slp_node,
  			   0, &op0, &slp_op0, &dt[0], &vectype_in))
      {
        if (dump_enabled_p ())
*************** vectorizable_conversion (vec_info *vinfo
*** 5556,5562 ****
        op1 = is_gimple_assign (stmt) ? gimple_assign_rhs2 (stmt) :
  				     gimple_call_arg (stmt, 0);
        tree vectype1_in;
!       if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 1,
  			       &op1, &slp_op1, &dt[1], &vectype1_in))
  	{
            if (dump_enabled_p ())
--- 5153,5159 ----
        op1 = is_gimple_assign (stmt) ? gimple_assign_rhs2 (stmt) :
  				     gimple_call_arg (stmt, 0);
        tree vectype1_in;
!       if (!vect_is_simple_use (vinfo, slp_node, 1,
  			       &op1, &slp_op1, &dt[1], &vectype1_in))
  	{
            if (dump_enabled_p ())
*************** vectorizable_conversion (vec_info *vinfo
*** 5574,5580 ****
       from the scalar type.  */
    if (!vectype_in)
      vectype_in = get_vectype_for_scalar_type (vinfo, rhs_type, slp_node);
!   if (vec_stmt)
      gcc_assert (vectype_in);
    if (!vectype_in)
      {
--- 5171,5177 ----
       from the scalar type.  */
    if (!vectype_in)
      vectype_in = get_vectype_for_scalar_type (vinfo, rhs_type, slp_node);
!   if (!cost_vec)
      gcc_assert (vectype_in);
    if (!vectype_in)
      {
*************** vectorizable_conversion (vec_info *vinfo
*** 5817,5823 ****
        LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
      }
  
!   if (!vec_stmt)		/* transformation not required.  */
      {
        if (!vect_maybe_update_slp_op_vectype (slp_op0, vectype_in)
  	  || !vect_maybe_update_slp_op_vectype (slp_op1, vectype_in))
--- 5414,5420 ----
        LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
      }
  
!   if (cost_vec)		/* transformation not required.  */
      {
        if (!vect_maybe_update_slp_op_vectype (slp_op0, vectype_in)
  	  || !vect_maybe_update_slp_op_vectype (slp_op1, vectype_in))
*************** vectorizable_conversion (vec_info *vinfo
*** 5832,5838 ****
          {
  	  STMT_VINFO_TYPE (stmt_info) = type_conversion_vec_info_type;
  	  vect_model_simple_cost (vinfo, (1 + multi_step_cvt),
! 				  dt, ndts, slp_node, cost_vec);
  	}
        else if (modifier == NARROW_SRC || modifier == NARROW_DST)
  	{
--- 5429,5435 ----
          {
  	  STMT_VINFO_TYPE (stmt_info) = type_conversion_vec_info_type;
  	  vect_model_simple_cost (vinfo, (1 + multi_step_cvt),
! 				  slp_node, cost_vec);
  	}
        else if (modifier == NARROW_SRC || modifier == NARROW_DST)
  	{
*************** vectorizable_conversion (vec_info *vinfo
*** 5903,5910 ****
    switch (modifier)
      {
      case NONE:
!       vect_get_vec_defs (vinfo, stmt_info, slp_node, 1,
! 			 op0, vectype_in, &vec_oprnds0);
        /* vec_dest is intermediate type operand when multi_step_cvt.  */
        if (multi_step_cvt)
  	{
--- 5500,5506 ----
    switch (modifier)
      {
      case NONE:
!       vect_get_vec_defs (vinfo, slp_node, op0, &vec_oprnds0);
        /* vec_dest is intermediate type operand when multi_step_cvt.  */
        if (multi_step_cvt)
  	{
*************** vectorizable_conversion (vec_info *vinfo
*** 5939,5948 ****
  	 of elements that we can fit in a vectype (nunits), we have to
  	 generate more than one vector stmt - i.e - we need to "unroll"
  	 the vector stmt by a factor VF/nunits.  */
!       vect_get_vec_defs (vinfo, stmt_info, slp_node, 1,
! 			 op0, vectype_in, &vec_oprnds0,
  			 code == WIDEN_LSHIFT_EXPR ? NULL_TREE : op1,
! 			 vectype_in, &vec_oprnds1);
        if (code == WIDEN_LSHIFT_EXPR)
  	{
  	  int oprnds_size = vec_oprnds0.length ();
--- 5535,5543 ----
  	 of elements that we can fit in a vectype (nunits), we have to
  	 generate more than one vector stmt - i.e - we need to "unroll"
  	 the vector stmt by a factor VF/nunits.  */
!       vect_get_vec_defs (vinfo, slp_node, op0, &vec_oprnds0,
  			 code == WIDEN_LSHIFT_EXPR ? NULL_TREE : op1,
! 			 &vec_oprnds1);
        if (code == WIDEN_LSHIFT_EXPR)
  	{
  	  int oprnds_size = vec_oprnds0.length ();
*************** vectorizable_conversion (vec_info *vinfo
*** 5993,6000 ****
  	 of elements that we can fit in a vectype (nunits), we have to
  	 generate more than one vector stmt - i.e - we need to "unroll"
  	 the vector stmt by a factor VF/nunits.  */
!       vect_get_vec_defs (vinfo, stmt_info, slp_node, 1,
! 			 op0, vectype_in, &vec_oprnds0);
        /* Arguments are ready.  Create the new vector stmts.  */
        if (cvt_type && modifier == NARROW_DST)
  	FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
--- 5588,5594 ----
  	 of elements that we can fit in a vectype (nunits), we have to
  	 generate more than one vector stmt - i.e - we need to "unroll"
  	 the vector stmt by a factor VF/nunits.  */
!       vect_get_vec_defs (vinfo, slp_node, op0, &vec_oprnds0);
        /* Arguments are ready.  Create the new vector stmts.  */
        if (cvt_type && modifier == NARROW_DST)
  	FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
*************** vect_nop_conversion_p (stmt_vec_info stm
*** 6073,6089 ****
  static bool
  vectorizable_assignment (vec_info *vinfo,
  			 stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 			 gimple **vec_stmt, slp_tree slp_node,
  			 stmt_vector_for_cost *cost_vec)
  {
    tree vec_dest;
    tree scalar_dest;
    tree op;
-   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
    tree new_temp;
    enum vect_def_type dt[1] = {vect_unknown_def_type};
-   int ndts = 1;
-   int ncopies;
    int i;
    vec<tree> vec_oprnds = vNULL;
    tree vop;
--- 5667,5680 ----
  static bool
  vectorizable_assignment (vec_info *vinfo,
  			 stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 			 slp_tree slp_node,
  			 stmt_vector_for_cost *cost_vec)
  {
    tree vec_dest;
    tree scalar_dest;
    tree op;
    tree new_temp;
    enum vect_def_type dt[1] = {vect_unknown_def_type};
    int i;
    vec<tree> vec_oprnds = vNULL;
    tree vop;
*************** vectorizable_assignment (vec_info *vinfo
*** 6095,6101 ****
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && ! vec_stmt)
      return false;
  
    /* Is vectorizable assignment?  */
--- 5686,5692 ----
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && cost_vec)
      return false;
  
    /* Is vectorizable assignment?  */
*************** vectorizable_assignment (vec_info *vinfo
*** 6116,6136 ****
  	|| CONVERT_EXPR_CODE_P (code)))
      return false;
  
!   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
  
-   /* Multiple types in SLP are handled by creating the appropriate number of
-      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
-      case of SLP.  */
-   if (slp_node)
-     ncopies = 1;
-   else
-     ncopies = vect_get_num_copies (loop_vinfo, vectype);
- 
-   gcc_assert (ncopies >= 1);
- 
    slp_tree slp_op;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 0, &op, &slp_op,
  			   &dt[0], &vectype_in))
      {
        if (dump_enabled_p ())
--- 5707,5717 ----
  	|| CONVERT_EXPR_CODE_P (code)))
      return false;
  
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
  
    slp_tree slp_op;
!   if (!vect_is_simple_use (vinfo, slp_node, 0, &op, &slp_op,
  			   &dt[0], &vectype_in))
      {
        if (dump_enabled_p ())
*************** vectorizable_assignment (vec_info *vinfo
*** 6187,6196 ****
        return false;
      }
  
!   if (!vec_stmt) /* transformation not required.  */
      {
!       if (slp_node
! 	  && !vect_maybe_update_slp_op_vectype (slp_op, vectype_in))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 5768,5776 ----
        return false;
      }
  
!   if (cost_vec) /* transformation not required.  */
      {
!       if (!vect_maybe_update_slp_op_vectype (slp_op, vectype_in))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vectorizable_assignment (vec_info *vinfo
*** 6200,6206 ****
        STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_assignment");
        if (!vect_nop_conversion_p (stmt_info))
! 	vect_model_simple_cost (vinfo, ncopies, dt, ndts, slp_node, cost_vec);
        return true;
      }
  
--- 5780,5786 ----
        STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_assignment");
        if (!vect_nop_conversion_p (stmt_info))
! 	vect_model_simple_cost (vinfo, 1, slp_node, cost_vec);
        return true;
      }
  
*************** vectorizable_assignment (vec_info *vinfo
*** 6212,6218 ****
    vec_dest = vect_create_destination_var (scalar_dest, vectype);
  
    /* Handle use.  */
!   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies, op, &vec_oprnds);
  
    /* Arguments are ready. create the new vector stmt.  */
    FOR_EACH_VEC_ELT (vec_oprnds, i, vop)
--- 5792,5798 ----
    vec_dest = vect_create_destination_var (scalar_dest, vectype);
  
    /* Handle use.  */
!   vect_get_vec_defs (vinfo, slp_node, op, &vec_oprnds);
  
    /* Arguments are ready. create the new vector stmt.  */
    FOR_EACH_VEC_ELT (vec_oprnds, i, vop)
*************** vectorizable_assignment (vec_info *vinfo
*** 6224,6236 ****
        new_temp = make_ssa_name (vec_dest, new_stmt);
        gimple_assign_set_lhs (new_stmt, new_temp);
        vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
!       if (slp_node)
! 	slp_node->push_vec_def (new_stmt);
!       else
! 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
      }
-   if (!slp_node)
-     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
  
    vec_oprnds.release ();
    return true;
--- 5804,5811 ----
        new_temp = make_ssa_name (vec_dest, new_stmt);
        gimple_assign_set_lhs (new_stmt, new_temp);
        vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
!       slp_node->push_vec_def (new_stmt);
      }
  
    vec_oprnds.release ();
    return true;
*************** vect_supportable_shift (vec_info *vinfo,
*** 6272,6278 ****
  static bool
  vectorizable_shift (vec_info *vinfo,
  		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		    gimple **vec_stmt, slp_tree slp_node,
  		    stmt_vector_for_cost *cost_vec)
  {
    tree vec_dest;
--- 5847,5853 ----
  static bool
  vectorizable_shift (vec_info *vinfo,
  		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		    slp_tree slp_node,
  		    stmt_vector_for_cost *cost_vec)
  {
    tree vec_dest;
*************** vectorizable_shift (vec_info *vinfo,
*** 6280,6286 ****
    tree op0, op1 = NULL;
    tree vec_oprnd1 = NULL_TREE;
    tree vectype;
-   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
    enum tree_code code;
    machine_mode vec_mode;
    tree new_temp;
--- 5855,5860 ----
*************** vectorizable_shift (vec_info *vinfo,
*** 6288,6299 ****
    int icode;
    machine_mode optab_op2_mode;
    enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
-   int ndts = 2;
    poly_uint64 nunits_in;
    poly_uint64 nunits_out;
    tree vectype_out;
    tree op1_vectype;
-   int ncopies;
    int i;
    vec<tree> vec_oprnds0 = vNULL;
    vec<tree> vec_oprnds1 = vNULL;
--- 5862,5871 ----
*************** vectorizable_shift (vec_info *vinfo,
*** 6308,6314 ****
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
        && STMT_VINFO_DEF_TYPE (stmt_info) != vect_nested_cycle
!       && ! vec_stmt)
      return false;
  
    /* Is STMT a vectorizable binary/unary operation?   */
--- 5880,5886 ----
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
        && STMT_VINFO_DEF_TYPE (stmt_info) != vect_nested_cycle
!       && cost_vec)
      return false;
  
    /* Is STMT a vectorizable binary/unary operation?   */
*************** vectorizable_shift (vec_info *vinfo,
*** 6326,6332 ****
      return false;
  
    scalar_dest = gimple_assign_lhs (stmt);
!   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
    if (!type_has_mode_precision_p (TREE_TYPE (scalar_dest)))
      {
        if (dump_enabled_p ())
--- 5898,5904 ----
      return false;
  
    scalar_dest = gimple_assign_lhs (stmt);
!   vectype_out = SLP_TREE_VECTYPE (slp_node);
    if (!type_has_mode_precision_p (TREE_TYPE (scalar_dest)))
      {
        if (dump_enabled_p ())
*************** vectorizable_shift (vec_info *vinfo,
*** 6336,6342 ****
      }
  
    slp_tree slp_op0;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
  			   0, &op0, &slp_op0, &dt[0], &vectype))
      {
        if (dump_enabled_p ())
--- 5908,5914 ----
      }
  
    slp_tree slp_op0;
!   if (!vect_is_simple_use (vinfo, slp_node,
  			   0, &op0, &slp_op0, &dt[0], &vectype))
      {
        if (dump_enabled_p ())
*************** vectorizable_shift (vec_info *vinfo,
*** 6348,6354 ****
       from the scalar type.  */
    if (!vectype)
      vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op0), slp_node);
!   if (vec_stmt)
      gcc_assert (vectype);
    if (!vectype)
      {
--- 5920,5926 ----
       from the scalar type.  */
    if (!vectype)
      vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op0), slp_node);
!   if (!cost_vec)
      gcc_assert (vectype);
    if (!vectype)
      {
*************** vectorizable_shift (vec_info *vinfo,
*** 6365,6371 ****
  
    stmt_vec_info op1_def_stmt_info;
    slp_tree slp_op1;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 1, &op1, &slp_op1,
  			   &dt[1], &op1_vectype, &op1_def_stmt_info))
      {
        if (dump_enabled_p ())
--- 5937,5943 ----
  
    stmt_vec_info op1_def_stmt_info;
    slp_tree slp_op1;
!   if (!vect_is_simple_use (vinfo, slp_node, 1, &op1, &slp_op1,
  			   &dt[1], &op1_vectype, &op1_def_stmt_info))
      {
        if (dump_enabled_p ())
*************** vectorizable_shift (vec_info *vinfo,
*** 6374,6396 ****
        return false;
      }
  
-   /* Multiple types in SLP are handled by creating the appropriate number of
-      vectorized stmts for each SLP node.  Hence, NCOPIES is always 1 in
-      case of SLP.  */
-   if (slp_node)
-     ncopies = 1;
-   else
-     ncopies = vect_get_num_copies (loop_vinfo, vectype);
- 
-   gcc_assert (ncopies >= 1);
- 
    /* Determine whether the shift amount is a vector, or scalar.  If the
       shift/rotate amount is a vector, use the vector/vector shift optabs.  */
  
    if ((dt[1] == vect_internal_def
         || dt[1] == vect_induction_def
         || dt[1] == vect_nested_cycle)
!       && (!slp_node || SLP_TREE_LANES (slp_node) == 1))
      scalar_shift_arg = false;
    else if (dt[1] == vect_constant_def
  	   || dt[1] == vect_external_def
--- 5946,5958 ----
        return false;
      }
  
    /* Determine whether the shift amount is a vector, or scalar.  If the
       shift/rotate amount is a vector, use the vector/vector shift optabs.  */
  
    if ((dt[1] == vect_internal_def
         || dt[1] == vect_induction_def
         || dt[1] == vect_nested_cycle)
!       && SLP_TREE_LANES (slp_node) == 1)
      scalar_shift_arg = false;
    else if (dt[1] == vect_constant_def
  	   || dt[1] == vect_external_def
*************** vectorizable_shift (vec_info *vinfo,
*** 6399,6427 ****
        /* In SLP, need to check whether the shift count is the same,
  	 in loops if it is a constant or invariant, it is always
  	 a scalar shift.  */
!       if (slp_node)
! 	{
! 	  vec<stmt_vec_info> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
! 	  stmt_vec_info slpstmt_info;
  
! 	  FOR_EACH_VEC_ELT (stmts, k, slpstmt_info)
! 	    if (slpstmt_info)
! 	      {
! 		gassign *slpstmt = as_a <gassign *> (slpstmt_info->stmt);
! 		if (!operand_equal_p (gimple_assign_rhs2 (slpstmt), op1, 0))
! 		  scalar_shift_arg = false;
! 	      }
  
! 	  /* For internal SLP defs we have to make sure we see scalar stmts
! 	     for all vector elements.
! 	     ???  For different vectors we could resort to a different
! 	     scalar shift operand but code-generation below simply always
! 	     takes the first.  */
! 	  if (dt[1] == vect_internal_def
! 	      && maybe_ne (nunits_out * SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node),
! 			   stmts.length ()))
! 	    scalar_shift_arg = false;
! 	}
  
        /* If the shift amount is computed by a pattern stmt we cannot
           use the scalar amount directly thus give up and use a vector
--- 5961,5986 ----
        /* In SLP, need to check whether the shift count is the same,
  	 in loops if it is a constant or invariant, it is always
  	 a scalar shift.  */
!       vec<stmt_vec_info> stmts = SLP_TREE_SCALAR_STMTS (slp_node);
!       stmt_vec_info slpstmt_info;
  
!       FOR_EACH_VEC_ELT (stmts, k, slpstmt_info)
! 	if (slpstmt_info)
! 	  {
! 	    gassign *slpstmt = as_a <gassign *> (slpstmt_info->stmt);
! 	    if (!operand_equal_p (gimple_assign_rhs2 (slpstmt), op1, 0))
! 	      scalar_shift_arg = false;
! 	  }
  
!       /* For internal SLP defs we have to make sure we see scalar stmts
! 	 for all vector elements.
! 	 ???  For different vectors we could resort to a different
! 	 scalar shift operand but code-generation below simply always
! 	 takes the first.  */
!       if (dt[1] == vect_internal_def
! 	  && maybe_ne (nunits_out * SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node),
! 		       stmts.length ()))
! 	scalar_shift_arg = false;
  
        /* If the shift amount is computed by a pattern stmt we cannot
           use the scalar amount directly thus give up and use a vector
*************** vectorizable_shift (vec_info *vinfo,
*** 6455,6462 ****
  			TYPE_VECTOR_SUBPARTS (vectype))
  	   || TYPE_MODE (op1_vectype) != TYPE_MODE (vectype));
        if (incompatible_op1_vectype_p
! 	  && (!slp_node
! 	      || SLP_TREE_DEF_TYPE (slp_op1) != vect_constant_def
  	      || slp_op1->refcnt != 1))
  	{
  	  if (dump_enabled_p ())
--- 6014,6020 ----
  			TYPE_VECTOR_SUBPARTS (vectype))
  	   || TYPE_MODE (op1_vectype) != TYPE_MODE (vectype));
        if (incompatible_op1_vectype_p
! 	  && (SLP_TREE_DEF_TYPE (slp_op1) != vect_constant_def
  	      || slp_op1->refcnt != 1))
  	{
  	  if (dump_enabled_p ())
*************** vectorizable_shift (vec_info *vinfo,
*** 6537,6552 ****
    if (vect_emulated_vector_p (vectype))
      return false;
  
!   if (!vec_stmt) /* transformation not required.  */
      {
!       if (slp_node
! 	  && (!vect_maybe_update_slp_op_vectype (slp_op0, vectype)
! 	      || ((!scalar_shift_arg || dt[1] == vect_internal_def)
! 		  && (!incompatible_op1_vectype_p
! 		      || dt[1] == vect_constant_def)
! 		  && !vect_maybe_update_slp_op_vectype
! 			(slp_op1,
! 			 incompatible_op1_vectype_p ? vectype : op1_vectype))))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 6095,6109 ----
    if (vect_emulated_vector_p (vectype))
      return false;
  
!   if (cost_vec) /* transformation not required.  */
      {
!       if (!vect_maybe_update_slp_op_vectype (slp_op0, vectype)
! 	  || ((!scalar_shift_arg || dt[1] == vect_internal_def)
! 	      && (!incompatible_op1_vectype_p
! 		  || dt[1] == vect_constant_def)
! 	      && !vect_maybe_update_slp_op_vectype
! 			 (slp_op1,
! 			  incompatible_op1_vectype_p ? vectype : op1_vectype)))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vectorizable_shift (vec_info *vinfo,
*** 6554,6577 ****
  	  return false;
  	}
        /* Now adjust the constant shift amount in place.  */
!       if (slp_node
! 	  && incompatible_op1_vectype_p
  	  && dt[1] == vect_constant_def)
! 	{
! 	  for (unsigned i = 0;
! 	       i < SLP_TREE_SCALAR_OPS (slp_op1).length (); ++i)
! 	    {
! 	      SLP_TREE_SCALAR_OPS (slp_op1)[i]
! 		= fold_convert (TREE_TYPE (vectype),
! 				SLP_TREE_SCALAR_OPS (slp_op1)[i]);
! 	      gcc_assert ((TREE_CODE (SLP_TREE_SCALAR_OPS (slp_op1)[i])
! 			   == INTEGER_CST));
! 	    }
! 	}
        STMT_VINFO_TYPE (stmt_info) = shift_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_shift");
!       vect_model_simple_cost (vinfo, ncopies, dt,
! 			      scalar_shift_arg ? 1 : ndts, slp_node, cost_vec);
        return true;
      }
  
--- 6111,6130 ----
  	  return false;
  	}
        /* Now adjust the constant shift amount in place.  */
!       if (incompatible_op1_vectype_p
  	  && dt[1] == vect_constant_def)
! 	for (unsigned i = 0;
! 	     i < SLP_TREE_SCALAR_OPS (slp_op1).length (); ++i)
! 	  {
! 	    SLP_TREE_SCALAR_OPS (slp_op1)[i]
! 	      = fold_convert (TREE_TYPE (vectype),
! 			      SLP_TREE_SCALAR_OPS (slp_op1)[i]);
! 	    gcc_assert ((TREE_CODE (SLP_TREE_SCALAR_OPS (slp_op1)[i])
! 			 == INTEGER_CST));
! 	  }
        STMT_VINFO_TYPE (stmt_info) = shift_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_shift");
!       vect_model_simple_cost (vinfo, 1, slp_node, cost_vec);
        return true;
      }
  
*************** vectorizable_shift (vec_info *vinfo,
*** 6581,6595 ****
      dump_printf_loc (MSG_NOTE, vect_location,
                       "transform binary/unary operation.\n");
  
-   if (incompatible_op1_vectype_p && !slp_node)
-     {
-       gcc_assert (!scalar_shift_arg && was_scalar_shift_arg);
-       op1 = fold_convert (TREE_TYPE (vectype), op1);
-       if (dt[1] != vect_constant_def)
- 	op1 = vect_init_vector (vinfo, stmt_info, op1,
- 				TREE_TYPE (vectype), NULL);
-     }
- 
    /* Handle def.  */
    vec_dest = vect_create_destination_var (scalar_dest, vectype);
  
--- 6134,6139 ----
*************** vectorizable_shift (vec_info *vinfo,
*** 6606,6612 ****
  	    dump_printf_loc (MSG_NOTE, vect_location,
  			     "operand 1 using scalar mode.\n");
  	  vec_oprnd1 = op1;
! 	  vec_oprnds1.create (slp_node ? slp_node->vec_stmts_size : ncopies);
  	  vec_oprnds1.quick_push (vec_oprnd1);
  	      /* Store vec_oprnd1 for every vector stmt to be created.
  		 We check during the analysis that all the shift arguments
--- 6150,6156 ----
  	    dump_printf_loc (MSG_NOTE, vect_location,
  			     "operand 1 using scalar mode.\n");
  	  vec_oprnd1 = op1;
! 	  vec_oprnds1.create (SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node));
  	  vec_oprnds1.quick_push (vec_oprnd1);
  	      /* Store vec_oprnd1 for every vector stmt to be created.
  		 We check during the analysis that all the shift arguments
*************** vectorizable_shift (vec_info *vinfo,
*** 6614,6624 ****
  		 TODO: Allow different constants for different vector
  		 stmts generated for an SLP instance.  */
  	  for (k = 0;
! 	       k < (slp_node ? slp_node->vec_stmts_size - 1 : ncopies - 1); k++)
  	    vec_oprnds1.quick_push (vec_oprnd1);
  	}
      }
!   else if (!scalar_shift_arg && slp_node && incompatible_op1_vectype_p)
      {
        if (was_scalar_shift_arg)
  	{
--- 6158,6168 ----
  		 TODO: Allow different constants for different vector
  		 stmts generated for an SLP instance.  */
  	  for (k = 0;
! 	       k < SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) - 1; k++)
  	    vec_oprnds1.quick_push (vec_oprnd1);
  	}
      }
!   else if (!scalar_shift_arg && incompatible_op1_vectype_p)
      {
        if (was_scalar_shift_arg)
  	{
*************** vectorizable_shift (vec_info *vinfo,
*** 6646,6652 ****
    /* vec_oprnd1 is available if operand 1 should be of a scalar-type
       (a special case for certain kind of vector shifts); otherwise,
       operand 1 should be of a vector type (the usual case).  */
!   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
  		     op0, &vec_oprnds0,
  		     vec_oprnd1 ? NULL_TREE : op1, &vec_oprnds1);
  
--- 6190,6196 ----
    /* vec_oprnd1 is available if operand 1 should be of a scalar-type
       (a special case for certain kind of vector shifts); otherwise,
       operand 1 should be of a vector type (the usual case).  */
!   vect_get_vec_defs (vinfo, slp_node,
  		     op0, &vec_oprnds0,
  		     vec_oprnd1 ? NULL_TREE : op1, &vec_oprnds1);
  
*************** vectorizable_shift (vec_info *vinfo,
*** 6674,6688 ****
        new_temp = make_ssa_name (vec_dest, new_stmt);
        gimple_assign_set_lhs (new_stmt, new_temp);
        vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
!       if (slp_node)
! 	slp_node->push_vec_def (new_stmt);
!       else
! 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
      }
  
-   if (!slp_node)
-     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
- 
    vec_oprnds0.release ();
    vec_oprnds1.release ();
  
--- 6218,6226 ----
        new_temp = make_ssa_name (vec_dest, new_stmt);
        gimple_assign_set_lhs (new_stmt, new_temp);
        vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
!       slp_node->push_vec_def (new_stmt);
      }
  
    vec_oprnds0.release ();
    vec_oprnds1.release ();
  
*************** vectorizable_shift (vec_info *vinfo,
*** 6700,6706 ****
  static bool
  vectorizable_operation (vec_info *vinfo,
  			stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 			gimple **vec_stmt, slp_tree slp_node,
  			stmt_vector_for_cost *cost_vec)
  {
    tree vec_dest;
--- 6238,6244 ----
  static bool
  vectorizable_operation (vec_info *vinfo,
  			stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 			slp_tree slp_node,
  			stmt_vector_for_cost *cost_vec)
  {
    tree vec_dest;
*************** vectorizable_operation (vec_info *vinfo,
*** 6716,6722 ****
    bool target_support_p;
    enum vect_def_type dt[3]
      = {vect_unknown_def_type, vect_unknown_def_type, vect_unknown_def_type};
-   int ndts = 3;
    poly_uint64 nunits_in;
    poly_uint64 nunits_out;
    tree vectype_out;
--- 6254,6259 ----
*************** vectorizable_operation (vec_info *vinfo,
*** 6731,6737 ****
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && ! vec_stmt)
      return false;
  
    /* Is STMT a vectorizable binary/unary operation?   */
--- 6268,6274 ----
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && cost_vec)
      return false;
  
    /* Is STMT a vectorizable binary/unary operation?   */
*************** vectorizable_operation (vec_info *vinfo,
*** 6798,6804 ****
      }
  
    slp_tree slp_op0;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
  			   0, &op0, &slp_op0, &dt[0], &vectype))
      {
        if (dump_enabled_p ())
--- 6335,6341 ----
      }
  
    slp_tree slp_op0;
!   if (!vect_is_simple_use (vinfo, slp_node,
  			   0, &op0, &slp_op0, &dt[0], &vectype))
      {
        if (dump_enabled_p ())
*************** vectorizable_operation (vec_info *vinfo,
*** 6832,6838 ****
  	vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op0),
  					       slp_node);
      }
!   if (vec_stmt)
      gcc_assert (vectype);
    if (!vectype)
      {
--- 6369,6375 ----
  	vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op0),
  					       slp_node);
      }
!   if (!cost_vec)
      gcc_assert (vectype);
    if (!vectype)
      {
*************** vectorizable_operation (vec_info *vinfo,
*** 6854,6860 ****
    slp_tree slp_op1 = NULL, slp_op2 = NULL;
    if (op_type == binary_op || op_type == ternary_op)
      {
!       if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
  			       1, &op1, &slp_op1, &dt[1], &vectype2))
  	{
  	  if (dump_enabled_p ())
--- 6391,6397 ----
    slp_tree slp_op1 = NULL, slp_op2 = NULL;
    if (op_type == binary_op || op_type == ternary_op)
      {
!       if (!vect_is_simple_use (vinfo, slp_node,
  			       1, &op1, &slp_op1, &dt[1], &vectype2))
  	{
  	  if (dump_enabled_p ())
*************** vectorizable_operation (vec_info *vinfo,
*** 6872,6878 ****
      }
    if (op_type == ternary_op)
      {
!       if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
  			       2, &op2, &slp_op2, &dt[2], &vectype3))
  	{
  	  if (dump_enabled_p ())
--- 6409,6415 ----
      }
    if (op_type == ternary_op)
      {
!       if (!vect_is_simple_use (vinfo, slp_node,
  			       2, &op2, &slp_op2, &dt[2], &vectype3))
  	{
  	  if (dump_enabled_p ())
*************** vectorizable_operation (vec_info *vinfo,
*** 6938,6944 ****
  	       || !target_support_p)
  	      && maybe_ne (GET_MODE_SIZE (vec_mode), UNITS_PER_WORD))
  	  /* Check only during analysis.  */
! 	  || (!vec_stmt && !vect_can_vectorize_without_simd_p (code)))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf (MSG_NOTE, "using word mode not possible.\n");
--- 6475,6481 ----
  	       || !target_support_p)
  	      && maybe_ne (GET_MODE_SIZE (vec_mode), UNITS_PER_WORD))
  	  /* Check only during analysis.  */
! 	  || (cost_vec && !vect_can_vectorize_without_simd_p (code)))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf (MSG_NOTE, "using word mode not possible.\n");
*************** vectorizable_operation (vec_info *vinfo,
*** 6967,6973 ****
    bool mask_out_inactive = ((!is_invariant && gimple_could_trap_p (stmt))
  			    || reduc_idx >= 0);
  
!   if (!vec_stmt) /* transformation not required.  */
      {
        if (loop_vinfo
  	  && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)
--- 6504,6510 ----
    bool mask_out_inactive = ((!is_invariant && gimple_could_trap_p (stmt))
  			    || reduc_idx >= 0);
  
!   if (cost_vec) /* transformation not required.  */
      {
        if (loop_vinfo
  	  && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)
*************** vectorizable_operation (vec_info *vinfo,
*** 7006,7012 ****
  
        STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_operation");
!       vect_model_simple_cost (vinfo, 1, dt, ndts, slp_node, cost_vec);
        if (using_emulated_vectors_p)
  	{
  	  /* The above vect_model_simple_cost call handles constants
--- 6543,6549 ----
  
        STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
        DUMP_VECT_SCOPE ("vectorizable_operation");
!       vect_model_simple_cost (vinfo, 1, slp_node, cost_vec);
        if (using_emulated_vectors_p)
  	{
  	  /* The above vect_model_simple_cost call handles constants
*************** vectorizable_operation (vec_info *vinfo,
*** 7066,7072 ****
    else
      vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
  
!   vect_get_vec_defs (vinfo, stmt_info, slp_node, 1,
  		     op0, &vec_oprnds0, op1, &vec_oprnds1, op2, &vec_oprnds2);
    /* Arguments are ready.  Create the new vector stmt.  */
    FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
--- 6603,6609 ----
    else
      vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
  
!   vect_get_vec_defs (vinfo, slp_node,
  		     op0, &vec_oprnds0, op1, &vec_oprnds1, op2, &vec_oprnds2);
    /* Arguments are ready.  Create the new vector stmt.  */
    FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
*************** check_scan_store (vec_info *vinfo, stmt_
*** 7949,7965 ****
  
  static bool
  vectorizable_scan_store (vec_info *vinfo, stmt_vec_info stmt_info,
! 			 slp_tree slp_node, gimple_stmt_iterator *gsi,
! 			 gimple **vec_stmt, int ncopies)
  {
    loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
    dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
    tree ref_type = reference_alias_ptr_type (DR_REF (dr_info->dr));
!   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
  
    if (dump_enabled_p ())
      dump_printf_loc (MSG_NOTE, vect_location,
! 		     "transform scan store. ncopies = %d\n", ncopies);
  
    gimple *stmt = STMT_VINFO_STMT (stmt_info);
    tree rhs = gimple_assign_rhs1 (stmt);
--- 7486,7501 ----
  
  static bool
  vectorizable_scan_store (vec_info *vinfo, stmt_vec_info stmt_info,
! 			 slp_tree slp_node, gimple_stmt_iterator *gsi)
  {
    loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
    dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
    tree ref_type = reference_alias_ptr_type (DR_REF (dr_info->dr));
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
  
    if (dump_enabled_p ())
      dump_printf_loc (MSG_NOTE, vect_location,
! 		     "transform scan store.\n");
  
    gimple *stmt = STMT_VINFO_STMT (stmt_info);
    tree rhs = gimple_assign_rhs1 (stmt);
*************** vectorizable_scan_store (vec_info *vinfo
*** 8070,8077 ****
        /* We want to lookup the vector operands of the reduction, not those
  	 of the store - for SLP we have to use the proper SLP node for the
  	 lookup, which should be the single child of the scan store.  */
!       vect_get_vec_defs (vinfo, stmt_info, SLP_TREE_CHILDREN (slp_node)[0],
! 			 ncopies, rhs1, &vec_oprnds2, rhs2, &vec_oprnds3);
        /* ???  For SLP we do not key the def on 'rhs1' or 'rhs2' but get
  	 them in SLP child order.  So we have to swap here with logic
  	 similar to above.  */
--- 7606,7613 ----
        /* We want to lookup the vector operands of the reduction, not those
  	 of the store - for SLP we have to use the proper SLP node for the
  	 lookup, which should be the single child of the scan store.  */
!       vect_get_vec_defs (vinfo, SLP_TREE_CHILDREN (slp_node)[0],
! 			 rhs1, &vec_oprnds2, rhs2, &vec_oprnds3);
        /* ???  For SLP we do not key the def on 'rhs1' or 'rhs2' but get
  	 them in SLP child order.  So we have to swap here with logic
  	 similar to above.  */
*************** vectorizable_scan_store (vec_info *vinfo
*** 8085,8091 ****
  	  std::swap (vec_oprnds2[i], vec_oprnds3[i]);;
      }
    else
!     vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
  		       rhs2, &vec_oprnds3);
    for (unsigned j = 0; j < vec_oprnds3.length (); j++)
      {
--- 7621,7627 ----
  	  std::swap (vec_oprnds2[i], vec_oprnds3[i]);;
      }
    else
!     vect_get_vec_defs (vinfo, slp_node,
  		       rhs2, &vec_oprnds3);
    for (unsigned j = 0; j < vec_oprnds3.length (); j++)
      {
*************** vectorizable_scan_store (vec_info *vinfo
*** 8106,8116 ****
  	  vect_copy_ref_info (data_ref, DR_REF (load1_dr_info->dr));
  	  gimple *g = gimple_build_assign (vec_oprnd2, data_ref);
  	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
- 	  if (! slp_node)
- 	    {
- 	      STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
- 	      *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
- 	    }
  	}
  
        tree v = vec_oprnd2;
--- 7642,7647 ----
*************** vectorizable_scan_store (vec_info *vinfo
*** 8124,8134 ****
  					   ? zero_vec : vec_oprnd1, v,
  					   perms[i]);
  	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
- 	  if (! slp_node)
- 	    {
- 	      STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
- 	      *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
- 	    }
  
  	  if (zero_vec && use_whole_vector[i] == scan_store_kind_lshift_cond)
  	    {
--- 7655,7660 ----
*************** vectorizable_scan_store (vec_info *vinfo
*** 8145,8152 ****
  				       new_temp, vec_oprnd1);
  	      vect_finish_stmt_generation (vinfo, stmt_info,
  							   g, gsi);
- 	      if (! slp_node)
- 		STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
  	      new_temp = new_temp2;
  	    }
  
--- 7671,7676 ----
*************** vectorizable_scan_store (vec_info *vinfo
*** 8164,8171 ****
  	  tree new_temp2 = make_ssa_name (vectype);
  	  g = gimple_build_assign (new_temp2, code, v, new_temp);
  	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
- 	  if (! slp_node)
- 	    STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
  
  	  v = new_temp2;
  	}
--- 7688,7693 ----
*************** vectorizable_scan_store (vec_info *vinfo
*** 8173,8180 ****
        tree new_temp = make_ssa_name (vectype);
        gimple *g = gimple_build_assign (new_temp, code, orig, v);
        vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
-       if (! slp_node)
- 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
  
        tree last_perm_arg = new_temp;
        /* For exclusive scan, new_temp computed above is the exclusive scan
--- 7695,7700 ----
*************** vectorizable_scan_store (vec_info *vinfo
*** 8185,8200 ****
  	  last_perm_arg = make_ssa_name (vectype);
  	  g = gimple_build_assign (last_perm_arg, code, new_temp, vec_oprnd2);
  	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
- 	  if (! slp_node)
- 	    STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
  	}
  
        orig = make_ssa_name (vectype);
        g = gimple_build_assign (orig, VEC_PERM_EXPR, last_perm_arg,
  			       last_perm_arg, perms[units_log2]);
        vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
-       if (! slp_node)
- 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
  
        if (!inscan_var_store)
  	{
--- 7705,7716 ----
*************** vectorizable_scan_store (vec_info *vinfo
*** 8204,8211 ****
  	  vect_copy_ref_info (data_ref, DR_REF (dr_info->dr));
  	  g = gimple_build_assign (data_ref, new_temp);
  	  vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
- 	  if (! slp_node)
- 	    STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
  	}
      }
  
--- 7720,7725 ----
*************** vectorizable_scan_store (vec_info *vinfo
*** 8221,8228 ****
  	vect_copy_ref_info (data_ref, DR_REF (dr_info->dr));
  	gimple *g = gimple_build_assign (data_ref, orig);
  	vect_finish_stmt_generation (vinfo, stmt_info, g, gsi);
- 	if (! slp_node)
- 	  STMT_VINFO_VEC_STMTS (stmt_info).safe_push (g);
        }
    return true;
  }
--- 7735,7740 ----
*************** vectorizable_scan_store (vec_info *vinfo
*** 8239,8245 ****
  static bool
  vectorizable_store (vec_info *vinfo,
  		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		    gimple **vec_stmt, slp_tree slp_node,
  		    stmt_vector_for_cost *cost_vec)
  {
    tree data_ref;
--- 7751,7757 ----
  static bool
  vectorizable_store (vec_info *vinfo,
  		    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		    slp_tree slp_node,
  		    stmt_vector_for_cost *cost_vec)
  {
    tree data_ref;
*************** vectorizable_store (vec_info *vinfo,
*** 8270,8276 ****
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && ! vec_stmt)
      return false;
  
    /* Is vectorizable store? */
--- 7782,7788 ----
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && cost_vec)
      return false;
  
    /* Is vectorizable store? */
*************** vectorizable_store (vec_info *vinfo,
*** 8307,8313 ****
  	mask_index = vect_slp_child_index_for_operand
  		    (call, mask_index, STMT_VINFO_GATHER_SCATTER_P (stmt_info));
        if (mask_index >= 0
! 	  && !vect_check_scalar_mask (vinfo, stmt_info, slp_node, mask_index,
  				      &mask, &mask_node, &mask_dt,
  				      &mask_vectype))
  	return false;
--- 7819,7825 ----
  	mask_index = vect_slp_child_index_for_operand
  		    (call, mask_index, STMT_VINFO_GATHER_SCATTER_P (stmt_info));
        if (mask_index >= 0
! 	  && !vect_check_scalar_mask (vinfo, slp_node, mask_index,
  				      &mask, &mask_node, &mask_dt,
  				      &mask_vectype))
  	return false;
*************** vectorizable_store (vec_info *vinfo,
*** 8382,8388 ****
  	}
        else if (memory_access_type != VMAT_LOAD_STORE_LANES
  	       && (memory_access_type != VMAT_GATHER_SCATTER
! 		   || (gs_info.decl && !VECTOR_BOOLEAN_TYPE_P (mask_vectype))))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 7894,7901 ----
  	}
        else if (memory_access_type != VMAT_LOAD_STORE_LANES
  	       && (memory_access_type != VMAT_GATHER_SCATTER
! 		   || (GATHER_SCATTER_LEGACY_P (gs_info)
! 		       && !VECTOR_BOOLEAN_TYPE_P (mask_vectype))))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vectorizable_store (vec_info *vinfo,
*** 8390,8397 ****
  	  return false;
  	}
        else if (memory_access_type == VMAT_GATHER_SCATTER
! 	       && gs_info.ifn == IFN_LAST
! 	       && !gs_info.decl)
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 7903,7909 ----
  	  return false;
  	}
        else if (memory_access_type == VMAT_GATHER_SCATTER
! 	       && GATHER_SCATTER_EMULATED_P (gs_info))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vectorizable_store (vec_info *vinfo,
*** 8423,8436 ****
        group_size = vec_num = 1;
      }
  
!   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) > 1 && !vec_stmt)
      {
        if (!check_scan_store (vinfo, stmt_info, vectype, rhs_dt, slp_node, mask,
  			     memory_access_type))
  	return false;
      }
  
!   bool costing_p = !vec_stmt;
    if (costing_p) /* transformation not required.  */
      {
        STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) = memory_access_type;
--- 7935,7948 ----
        group_size = vec_num = 1;
      }
  
!   if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) > 1 && cost_vec)
      {
        if (!check_scan_store (vinfo, stmt_info, vectype, rhs_dt, slp_node, mask,
  			     memory_access_type))
  	return false;
      }
  
!   bool costing_p = cost_vec;
    if (costing_p) /* transformation not required.  */
      {
        STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) = memory_access_type;
*************** vectorizable_store (vec_info *vinfo,
*** 8456,8462 ****
  
        if (dump_enabled_p ()
  	  && memory_access_type != VMAT_ELEMENTWISE
- 	  && memory_access_type != VMAT_GATHER_SCATTER
  	  && memory_access_type != VMAT_STRIDED_SLP
  	  && memory_access_type != VMAT_INVARIANT
  	  && alignment_support_scheme != dr_aligned)
--- 7968,7973 ----
*************** vectorizable_store (vec_info *vinfo,
*** 8493,8500 ****
  
  	  return true;
  	}
!       return vectorizable_scan_store (vinfo, stmt_info, slp_node,
! 				      gsi, vec_stmt, 1);
      }
  
    /* FORNOW */
--- 8004,8010 ----
  
  	  return true;
  	}
!       return vectorizable_scan_store (vinfo, stmt_info, slp_node, gsi);
      }
  
    /* FORNOW */
*************** vectorizable_store (vec_info *vinfo,
*** 8690,8704 ****
  	}
  
        alias_off = build_int_cst (ref_type, 0);
-       stmt_vec_info next_stmt_info = first_stmt_info;
        auto_vec<tree> vec_oprnds;
        /* For costing some adjacent vector stores, we'd like to cost with
  	 the total number of them once instead of cost each one by one. */
        unsigned int n_adjacent_stores = 0;
        running_off = offvar;
        if (!costing_p)
! 	vect_get_vec_defs (vinfo, next_stmt_info, slp_node, ncopies, op,
! 			   &vec_oprnds);
        unsigned int group_el = 0;
        unsigned HOST_WIDE_INT elsz
  	= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
--- 8200,8212 ----
  	}
  
        alias_off = build_int_cst (ref_type, 0);
        auto_vec<tree> vec_oprnds;
        /* For costing some adjacent vector stores, we'd like to cost with
  	 the total number of them once instead of cost each one by one. */
        unsigned int n_adjacent_stores = 0;
        running_off = offvar;
        if (!costing_p)
! 	vect_get_vec_defs (vinfo, slp_node, op, &vec_oprnds);
        unsigned int group_el = 0;
        unsigned HOST_WIDE_INT elsz
  	= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
*************** vectorizable_store (vec_info *vinfo,
*** 8833,8839 ****
      {
        aggr_type = elem_type;
        if (!costing_p)
! 	vect_get_strided_load_store_ops (stmt_info, loop_vinfo, gsi, &gs_info,
  					 &bump, &vec_offset, loop_lens);
      }
    else
--- 8341,8348 ----
      {
        aggr_type = elem_type;
        if (!costing_p)
! 	vect_get_strided_load_store_ops (stmt_info, vectype, loop_vinfo,
! 					 gsi, &gs_info,
  					 &bump, &vec_offset, loop_lens);
      }
    else
*************** vectorizable_store (vec_info *vinfo,
*** 8855,8893 ****
       more than one vector stmt - i.e - we need to "unroll" the
       vector stmt by a factor VF/nunits.  */
  
-   /* In case of interleaving (non-unit grouped access):
- 
-         S1:  &base + 2 = x2
-         S2:  &base = x0
-         S3:  &base + 1 = x1
-         S4:  &base + 3 = x3
- 
-      We create vectorized stores starting from base address (the access of the
-      first stmt in the chain (S2 in the above example), when the last store stmt
-      of the chain (S4) is reached:
- 
-         VS1: &base = vx2
- 	VS2: &base + vec_size*1 = vx0
- 	VS3: &base + vec_size*2 = vx1
- 	VS4: &base + vec_size*3 = vx3
- 
-      Then permutation statements are generated:
- 
- 	VS5: vx5 = VEC_PERM_EXPR < vx0, vx3, {0, 8, 1, 9, 2, 10, 3, 11} >
- 	VS6: vx6 = VEC_PERM_EXPR < vx0, vx3, {4, 12, 5, 13, 6, 14, 7, 15} >
- 	...
- 
-      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
-      (the order of the data-refs in the output of vect_permute_store_chain
-      corresponds to the order of scalar stmts in the interleaving chain - see
-      the documentation of vect_permute_store_chain()).
- 
-      In case of both multiple types and interleaving, above vector stores and
-      permutation stmts are created for every copy.  The result vector stmts are
-      put in STMT_VINFO_VEC_STMT for the first copy and in the corresponding
-      STMT_VINFO_RELATED_STMT for the next copies.
-   */
- 
    auto_vec<tree> dr_chain (group_size);
    auto_vec<tree> vec_masks;
    tree vec_mask = NULL;
--- 8364,8369 ----
*************** vectorizable_store (vec_info *vinfo,
*** 9073,9080 ****
  		    vect_get_slp_defs (mask_node, &vec_masks);
  
  		  if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
! 		    vect_get_gather_scatter_ops (loop_vinfo, loop, stmt_info,
! 						 slp_node, &gs_info,
  						 &dataref_ptr, &vec_offsets);
  		  else
  		    dataref_ptr
--- 8549,8555 ----
  		    vect_get_slp_defs (mask_node, &vec_masks);
  
  		  if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
! 		    vect_get_gather_scatter_ops (loop, slp_node, &gs_info,
  						 &dataref_ptr, &vec_offsets);
  		  else
  		    dataref_ptr
*************** vectorizable_store (vec_info *vinfo,
*** 9117,9123 ****
  					       final_mask, vec_mask, gsi);
  	    }
  
! 	  if (gs_info.ifn != IFN_LAST)
  	    {
  	      if (costing_p)
  		{
--- 8592,8598 ----
  					       final_mask, vec_mask, gsi);
  	    }
  
! 	  if (GATHER_SCATTER_IFN_P (gs_info))
  	    {
  	      if (costing_p)
  		{
*************** vectorizable_store (vec_info *vinfo,
*** 9157,9186 ****
  		{
  		  if (VECTOR_TYPE_P (TREE_TYPE (vec_offset)))
  		    call = gimple_build_call_internal (
! 			    IFN_MASK_LEN_SCATTER_STORE, 7, dataref_ptr,
  			    vec_offset, scale, vec_oprnd, final_mask, final_len,
  			    bias);
  		  else
  		    /* Non-vector offset indicates that prefer to take
  		       MASK_LEN_STRIDED_STORE instead of the
! 		       IFN_MASK_SCATTER_STORE with direct stride arg.  */
  		    call = gimple_build_call_internal (
  			    IFN_MASK_LEN_STRIDED_STORE, 6, dataref_ptr,
  			    vec_offset, vec_oprnd, final_mask, final_len, bias);
  		}
  	      else if (final_mask)
  		call = gimple_build_call_internal
! 			     (IFN_MASK_SCATTER_STORE, 5, dataref_ptr,
  			      vec_offset, scale, vec_oprnd, final_mask);
  	      else
! 		call = gimple_build_call_internal (IFN_SCATTER_STORE, 4,
! 						   dataref_ptr, vec_offset,
  						   scale, vec_oprnd);
  	      gimple_call_set_nothrow (call, true);
  	      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
  	      new_stmt = call;
  	    }
! 	   else if (gs_info.decl)
  	    {
  	      /* The builtin decls path for scatter is legacy, x86 only.  */
  	      gcc_assert (nunits.is_constant ()
--- 8632,8668 ----
  		{
  		  if (VECTOR_TYPE_P (TREE_TYPE (vec_offset)))
  		    call = gimple_build_call_internal (
! 			    IFN_MASK_LEN_SCATTER_STORE, 8, dataref_ptr,
! 			    gs_info.alias_ptr,
  			    vec_offset, scale, vec_oprnd, final_mask, final_len,
  			    bias);
  		  else
  		    /* Non-vector offset indicates that prefer to take
  		       MASK_LEN_STRIDED_STORE instead of the
! 		       IFN_MASK_SCATTER_STORE with direct stride arg.
! 		       Similar to the gather case we have checked the
! 		       alignment for a scatter already and assume
! 		       that the strided store has the same requirements.  */
  		    call = gimple_build_call_internal (
  			    IFN_MASK_LEN_STRIDED_STORE, 6, dataref_ptr,
  			    vec_offset, vec_oprnd, final_mask, final_len, bias);
  		}
  	      else if (final_mask)
  		call = gimple_build_call_internal
! 			     (IFN_MASK_SCATTER_STORE, 6, dataref_ptr,
! 			      gs_info.alias_ptr,
  			      vec_offset, scale, vec_oprnd, final_mask);
  	      else
! 		call = gimple_build_call_internal (IFN_SCATTER_STORE, 5,
! 						   dataref_ptr,
! 						   gs_info.alias_ptr,
! 						   vec_offset,
  						   scale, vec_oprnd);
  	      gimple_call_set_nothrow (call, true);
  	      vect_finish_stmt_generation (vinfo, stmt_info, call, gsi);
  	      new_stmt = call;
  	    }
! 	  else if (GATHER_SCATTER_LEGACY_P (gs_info))
  	    {
  	      /* The builtin decls path for scatter is legacy, x86 only.  */
  	      gcc_assert (nunits.is_constant ()
*************** vectorizable_store (vec_info *vinfo,
*** 9377,9383 ****
  
    gcc_assert (memory_access_type == VMAT_CONTIGUOUS
  	      || memory_access_type == VMAT_CONTIGUOUS_DOWN
- 	      || memory_access_type == VMAT_CONTIGUOUS_PERMUTE
  	      || memory_access_type == VMAT_CONTIGUOUS_REVERSE);
  
    unsigned inside_cost = 0, prologue_cost = 0;
--- 8859,8864 ----
*************** vectorizable_store (vec_info *vinfo,
*** 9390,9434 ****
    if (!costing_p)
      {
        /* Get vectorized arguments for SLP_NODE.  */
!       vect_get_vec_defs (vinfo, stmt_info, slp_node, 1, op,
! 			 &vec_oprnds, mask, &vec_masks);
        vec_oprnd = vec_oprnds[0];
        if (mask)
  	vec_mask = vec_masks[0];
      }
-   else
-     {
-       /* For interleaved stores we collect vectorized defs for all the
- 	 stores in the group in DR_CHAIN. DR_CHAIN is then used as an
- 	 input to vect_permute_store_chain().
- 
- 	 If the store is not grouped, DR_GROUP_SIZE is 1, and DR_CHAIN
- 	 is of size 1.  */
-       stmt_vec_info next_stmt_info = first_stmt_info;
-       for (i = 0; i < group_size; i++)
- 	{
- 	  /* Since gaps are not supported for interleaved stores,
- 	     DR_GROUP_SIZE is the exact number of stmts in the chain.
- 	     Therefore, NEXT_STMT_INFO can't be NULL_TREE.  In case
- 	     that there is no interleaving, DR_GROUP_SIZE is 1,
- 	     and only one iteration of the loop will be executed.  */
- 	  op = vect_get_store_rhs (next_stmt_info);
- 	  if (!costing_p)
- 	    {
- 	      vect_get_vec_defs_for_operand (vinfo, next_stmt_info,
- 					     1, op, gvec_oprnds[i]);
- 	      vec_oprnd = (*gvec_oprnds[i])[0];
- 	      dr_chain.quick_push (vec_oprnd);
- 	    }
- 	  next_stmt_info = DR_GROUP_NEXT_ELEMENT (next_stmt_info);
- 	}
-       if (mask && !costing_p)
- 	{
- 	  vect_get_vec_defs_for_operand (vinfo, stmt_info, 1,
- 					 mask, &vec_masks, mask_vectype);
- 	  vec_mask = vec_masks[0];
- 	}
-     }
  
    /* We should have catched mismatched types earlier.  */
    gcc_assert (costing_p
--- 8871,8881 ----
    if (!costing_p)
      {
        /* Get vectorized arguments for SLP_NODE.  */
!       vect_get_vec_defs (vinfo, slp_node, op, &vec_oprnds, mask, &vec_masks);
        vec_oprnd = vec_oprnds[0];
        if (mask)
  	vec_mask = vec_masks[0];
      }
  
    /* We should have catched mismatched types earlier.  */
    gcc_assert (costing_p
*************** vectorizable_store (vec_info *vinfo,
*** 9455,9479 ****
  					    simd_lane_access_p, bump);
  
    new_stmt = NULL;
!   if (grouped_store)
!     {
!       /* Permute.  */
!       gcc_assert (memory_access_type == VMAT_CONTIGUOUS_PERMUTE);
!       if (costing_p)
! 	{
! 	  int group_size = DR_GROUP_SIZE (first_stmt_info);
! 	  int nstmts = ceil_log2 (group_size) * group_size;
! 	  inside_cost += record_stmt_cost (cost_vec, nstmts, vec_perm,
! 					   slp_node, 0, vect_body);
! 	  if (dump_enabled_p ())
! 	    dump_printf_loc (MSG_NOTE, vect_location, "vect_model_store_cost: "
! 			     "strided group_size = %d .\n", group_size);
! 	}
!       else
! 	vect_permute_store_chain (vinfo, dr_chain, group_size, stmt_info,
! 				  gsi, &result_chain);
!     }
! 
    for (i = 0; i < vec_num; i++)
      {
        if (!costing_p)
--- 8902,8908 ----
  					    simd_lane_access_p, bump);
  
    new_stmt = NULL;
!   gcc_assert (!grouped_store);
    for (i = 0; i < vec_num; i++)
      {
        if (!costing_p)
*************** hoist_defs_of_uses (gimple *stmt, class
*** 9826,9832 ****
  static bool
  vectorizable_load (vec_info *vinfo,
  		   stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		   gimple **vec_stmt, slp_tree slp_node,
  		   stmt_vector_for_cost *cost_vec)
  {
    tree scalar_dest;
--- 9255,9261 ----
  static bool
  vectorizable_load (vec_info *vinfo,
  		   stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
! 		   slp_tree slp_node,
  		   stmt_vector_for_cost *cost_vec)
  {
    tree scalar_dest;
*************** vectorizable_load (vec_info *vinfo,
*** 9870,9876 ****
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && ! vec_stmt)
      return false;
  
    if (!STMT_VINFO_DATA_REF (stmt_info))
--- 9299,9305 ----
      return false;
  
    if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
!       && cost_vec)
      return false;
  
    if (!STMT_VINFO_DATA_REF (stmt_info))
*************** vectorizable_load (vec_info *vinfo,
*** 9919,9925 ****
  	mask_index = vect_slp_child_index_for_operand
  		    (call, mask_index, STMT_VINFO_GATHER_SCATTER_P (stmt_info));
        if (mask_index >= 0
! 	  && !vect_check_scalar_mask (vinfo, stmt_info, slp_node, mask_index,
  				      &mask, &slp_op, &mask_dt, &mask_vectype))
  	return false;
  
--- 9348,9354 ----
  	mask_index = vect_slp_child_index_for_operand
  		    (call, mask_index, STMT_VINFO_GATHER_SCATTER_P (stmt_info));
        if (mask_index >= 0
! 	  && !vect_check_scalar_mask (vinfo, slp_node, mask_index,
  				      &mask, &slp_op, &mask_dt, &mask_vectype))
  	return false;
  
*************** vectorizable_load (vec_info *vinfo,
*** 9928,9939 ****
  	els_index = vect_slp_child_index_for_operand
  	  (call, els_index, STMT_VINFO_GATHER_SCATTER_P (stmt_info));
        if (els_index >= 0
! 	  && !vect_is_simple_use (vinfo, stmt_info, slp_node, els_index,
  				  &els, &els_op, &els_dt, &els_vectype))
  	return false;
      }
  
!   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
  
    if (loop_vinfo)
--- 9357,9368 ----
  	els_index = vect_slp_child_index_for_operand
  	  (call, els_index, STMT_VINFO_GATHER_SCATTER_P (stmt_info));
        if (els_index >= 0
! 	  && !vect_is_simple_use (vinfo, slp_node, els_index,
  				  &els, &els_op, &els_dt, &els_vectype))
  	return false;
      }
  
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
    poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
  
    if (loop_vinfo)
*************** vectorizable_load (vec_info *vinfo,
*** 10091,10098 ****
  	  return false;
  	}
        else if (memory_access_type == VMAT_GATHER_SCATTER
! 	       && gs_info.ifn == IFN_LAST
! 	       && !gs_info.decl)
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 9520,9526 ----
  	  return false;
  	}
        else if (memory_access_type == VMAT_GATHER_SCATTER
! 	       && GATHER_SCATTER_EMULATED_P (gs_info))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vectorizable_load (vec_info *vinfo,
*** 10109,10115 ****
  	}
      }
  
!   bool costing_p = !vec_stmt;
  
    if (costing_p) /* transformation not required.  */
      {
--- 9537,9543 ----
  	}
      }
  
!   bool costing_p = cost_vec;
  
    if (costing_p) /* transformation not required.  */
      {
*************** vectorizable_load (vec_info *vinfo,
*** 10642,10648 ****
        vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
      }
  
-   gcc_assert (alignment_support_scheme);
    vec_loop_masks *loop_masks
      = (loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
         ? &LOOP_VINFO_MASKS (loop_vinfo)
--- 10070,10075 ----
*************** vectorizable_load (vec_info *vinfo,
*** 10662,10671 ****
  
    /* Targets with store-lane instructions must not require explicit
       realignment.  vect_supportable_dr_alignment always returns either
!      dr_aligned or dr_unaligned_supported for masked operations.  */
    gcc_assert ((memory_access_type != VMAT_LOAD_STORE_LANES
  	       && !mask
  	       && !loop_masks)
  	      || alignment_support_scheme == dr_aligned
  	      || alignment_support_scheme == dr_unaligned_supported);
  
--- 10089,10100 ----
  
    /* Targets with store-lane instructions must not require explicit
       realignment.  vect_supportable_dr_alignment always returns either
!      dr_aligned or dr_unaligned_supported for (non-length) masked
!      operations.  */
    gcc_assert ((memory_access_type != VMAT_LOAD_STORE_LANES
  	       && !mask
  	       && !loop_masks)
+ 	      || memory_access_type == VMAT_GATHER_SCATTER
  	      || alignment_support_scheme == dr_aligned
  	      || alignment_support_scheme == dr_unaligned_supported);
  
*************** vectorizable_load (vec_info *vinfo,
*** 10701,10739 ****
          S2:     z = x + 1       -               -
    */
  
-   /* In case of interleaving (non-unit grouped access):
- 
-      S1:  x2 = &base + 2
-      S2:  x0 = &base
-      S3:  x1 = &base + 1
-      S4:  x3 = &base + 3
- 
-      Vectorized loads are created in the order of memory accesses
-      starting from the access of the first stmt of the chain:
- 
-      VS1: vx0 = &base
-      VS2: vx1 = &base + vec_size*1
-      VS3: vx3 = &base + vec_size*2
-      VS4: vx4 = &base + vec_size*3
- 
-      Then permutation statements are generated:
- 
-      VS5: vx5 = VEC_PERM_EXPR < vx0, vx1, { 0, 2, ..., i*2 } >
-      VS6: vx6 = VEC_PERM_EXPR < vx0, vx1, { 1, 3, ..., i*2+1 } >
-        ...
- 
-      And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
-      (the order of the data-refs in the output of vect_permute_load_chain
-      corresponds to the order of scalar stmts in the interleaving chain - see
-      the documentation of vect_permute_load_chain()).
-      The generation of permutation stmts and recording them in
-      STMT_VINFO_VEC_STMT is done in vect_transform_grouped_load().
- 
-      In case of both multiple types and interleaving, the vector loads and
-      permutation stmts above are created for every copy.  The result vector
-      stmts are put in STMT_VINFO_VEC_STMT for the first copy and in the
-      corresponding STMT_VINFO_RELATED_STMT for the next copies.  */
- 
    /* If the data reference is aligned (dr_aligned) or potentially unaligned
       on a target that supports unaligned accesses (dr_unaligned_supported)
       we generate the following code:
--- 10130,10135 ----
*************** vectorizable_load (vec_info *vinfo,
*** 10824,10830 ****
      {
        aggr_type = elem_type;
        if (!costing_p)
! 	vect_get_strided_load_store_ops (stmt_info, loop_vinfo, gsi, &gs_info,
  					 &bump, &vec_offset, loop_lens);
      }
    else
--- 10220,10227 ----
      {
        aggr_type = elem_type;
        if (!costing_p)
! 	vect_get_strided_load_store_ops (stmt_info, vectype, loop_vinfo,
! 					 gsi, &gs_info,
  					 &bump, &vec_offset, loop_lens);
      }
    else
*************** vectorizable_load (vec_info *vinfo,
*** 11010,11017 ****
  
    if (memory_access_type == VMAT_GATHER_SCATTER)
      {
-       gcc_assert (alignment_support_scheme == dr_aligned
- 		  || alignment_support_scheme == dr_unaligned_supported);
        gcc_assert (!grouped_load && !slp_perm);
  
        unsigned int inside_cost = 0, prologue_cost = 0;
--- 10407,10412 ----
*************** vectorizable_load (vec_info *vinfo,
*** 11020,11027 ****
        if (!costing_p)
  	{
  	  if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
! 	    vect_get_gather_scatter_ops (loop_vinfo, loop, stmt_info,
! 					 slp_node, &gs_info, &dataref_ptr,
  					 &vec_offsets);
  	  else
  	    dataref_ptr
--- 10415,10421 ----
        if (!costing_p)
  	{
  	  if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
! 	    vect_get_gather_scatter_ops (loop, slp_node, &gs_info, &dataref_ptr,
  					 &vec_offsets);
  	  else
  	    dataref_ptr
*************** vectorizable_load (vec_info *vinfo,
*** 11054,11060 ****
  
  	  /* 2. Create the vector-load in the loop.  */
  	  unsigned HOST_WIDE_INT align;
! 	  if (gs_info.ifn != IFN_LAST)
  	    {
  	      if (costing_p)
  		{
--- 10448,10454 ----
  
  	  /* 2. Create the vector-load in the loop.  */
  	  unsigned HOST_WIDE_INT align;
! 	  if (GATHER_SCATTER_IFN_P (gs_info))
  	    {
  	      if (costing_p)
  		{
*************** vectorizable_load (vec_info *vinfo,
*** 11100,11106 ****
  		{
  		  if (VECTOR_TYPE_P (TREE_TYPE (vec_offset)))
  		    call = gimple_build_call_internal (IFN_MASK_LEN_GATHER_LOAD,
! 						       8, dataref_ptr,
  						       vec_offset, scale, zero,
  						       final_mask, vec_els,
  						       final_len, bias);
--- 10494,10501 ----
  		{
  		  if (VECTOR_TYPE_P (TREE_TYPE (vec_offset)))
  		    call = gimple_build_call_internal (IFN_MASK_LEN_GATHER_LOAD,
! 						       9, dataref_ptr,
! 						       gs_info.alias_ptr,
  						       vec_offset, scale, zero,
  						       final_mask, vec_els,
  						       final_len, bias);
*************** vectorizable_load (vec_info *vinfo,
*** 11115,11132 ****
  		}
  	      else if (final_mask)
  		call = gimple_build_call_internal (IFN_MASK_GATHER_LOAD,
! 						   6, dataref_ptr,
  						   vec_offset, scale,
  						   zero, final_mask, vec_els);
  	      else
! 		call = gimple_build_call_internal (IFN_GATHER_LOAD, 4,
! 						   dataref_ptr, vec_offset,
! 						   scale, zero);
  	      gimple_call_set_nothrow (call, true);
  	      new_stmt = call;
  	      data_ref = NULL_TREE;
  	    }
! 	  else if (gs_info.decl)
  	    {
  	      /* The builtin decls path for gather is legacy, x86 only.  */
  	      gcc_assert (!final_len && nunits.is_constant ());
--- 10510,10529 ----
  		}
  	      else if (final_mask)
  		call = gimple_build_call_internal (IFN_MASK_GATHER_LOAD,
! 						   7, dataref_ptr,
! 						   gs_info.alias_ptr,
  						   vec_offset, scale,
  						   zero, final_mask, vec_els);
  	      else
! 		call = gimple_build_call_internal (IFN_GATHER_LOAD, 5,
! 						   dataref_ptr,
! 						   gs_info.alias_ptr,
! 						   vec_offset, scale, zero);
  	      gimple_call_set_nothrow (call, true);
  	      new_stmt = call;
  	      data_ref = NULL_TREE;
  	    }
! 	  else if (GATHER_SCATTER_LEGACY_P (gs_info))
  	    {
  	      /* The builtin decls path for gather is legacy, x86 only.  */
  	      gcc_assert (!final_len && nunits.is_constant ());
*************** vectorizable_load (vec_info *vinfo,
*** 11143,11149 ****
  	      if (known_eq (nunits, offset_nunits))
  		{
  		  new_stmt = vect_build_one_gather_load_call
! 			       (vinfo, stmt_info, gsi, &gs_info,
  				dataref_ptr, vec_offsets[i], final_mask);
  		  data_ref = NULL_TREE;
  		}
--- 10540,10546 ----
  	      if (known_eq (nunits, offset_nunits))
  		{
  		  new_stmt = vect_build_one_gather_load_call
! 			       (vinfo, stmt_info, vectype, gsi, &gs_info,
  				dataref_ptr, vec_offsets[i], final_mask);
  		  data_ref = NULL_TREE;
  		}
*************** vectorizable_load (vec_info *vinfo,
*** 11153,11159 ****
  		     lanes but the builtins will produce full vectype
  		     data with just the lower lanes filled.  */
  		  new_stmt = vect_build_one_gather_load_call
! 			       (vinfo, stmt_info, gsi, &gs_info,
  				dataref_ptr, vec_offsets[2 * i], final_mask);
  		  tree low = make_ssa_name (vectype);
  		  gimple_set_lhs (new_stmt, low);
--- 10550,10556 ----
  		     lanes but the builtins will produce full vectype
  		     data with just the lower lanes filled.  */
  		  new_stmt = vect_build_one_gather_load_call
! 			       (vinfo, stmt_info, vectype, gsi, &gs_info,
  				dataref_ptr, vec_offsets[2 * i], final_mask);
  		  tree low = make_ssa_name (vectype);
  		  gimple_set_lhs (new_stmt, low);
*************** vectorizable_load (vec_info *vinfo,
*** 11192,11198 ****
  		    }
  
  		  new_stmt = vect_build_one_gather_load_call
! 			       (vinfo, stmt_info, gsi, &gs_info, dataref_ptr,
  				vec_offsets[2 * i + 1], final_mask);
  		  tree high = make_ssa_name (vectype);
  		  gimple_set_lhs (new_stmt, high);
--- 10589,10596 ----
  		    }
  
  		  new_stmt = vect_build_one_gather_load_call
! 			       (vinfo, stmt_info, vectype, gsi, &gs_info,
! 				dataref_ptr,
  				vec_offsets[2 * i + 1], final_mask);
  		  tree high = make_ssa_name (vectype);
  		  gimple_set_lhs (new_stmt, high);
*************** vectorizable_load (vec_info *vinfo,
*** 11235,11241 ****
  						   new_stmt, gsi);
  		    }
  		  new_stmt = vect_build_one_gather_load_call
! 			       (vinfo, stmt_info, gsi, &gs_info,
  				dataref_ptr, vec_offset, final_mask);
  		  data_ref = NULL_TREE;
  		}
--- 10633,10639 ----
  						   new_stmt, gsi);
  		    }
  		  new_stmt = vect_build_one_gather_load_call
! 			       (vinfo, stmt_info, vectype, gsi, &gs_info,
  				dataref_ptr, vec_offset, final_mask);
  		  data_ref = NULL_TREE;
  		}
*************** vectorizable_load (vec_info *vinfo,
*** 11816,11833 ****
  	 alignment support schemes.  */
        if (costing_p)
  	{
! 	  /* For VMAT_CONTIGUOUS_PERMUTE if it's grouped load, we
! 	     only need to take care of the first stmt, whose
! 	     stmt_info is first_stmt_info, vec_num iterating on it
! 	     will cover the cost for the remaining, it's consistent
! 	     with transforming.  For the prologue cost for realign,
  	     we only need to count it once for the whole group.  */
  	  bool first_stmt_info_p = first_stmt_info == stmt_info;
  	  bool add_realign_cost = first_stmt_info_p && i == 0;
  	  if (memory_access_type == VMAT_CONTIGUOUS
! 	      || memory_access_type == VMAT_CONTIGUOUS_REVERSE
! 	      || (memory_access_type == VMAT_CONTIGUOUS_PERMUTE
! 		  && (!grouped_load || first_stmt_info_p)))
  	    {
  	      /* Leave realign cases alone to keep them simple.  */
  	      if (alignment_support_scheme == dr_explicit_realign_optimized
--- 11214,11225 ----
  	 alignment support schemes.  */
        if (costing_p)
  	{
! 	  /* For the prologue cost for realign,
  	     we only need to count it once for the whole group.  */
  	  bool first_stmt_info_p = first_stmt_info == stmt_info;
  	  bool add_realign_cost = first_stmt_info_p && i == 0;
  	  if (memory_access_type == VMAT_CONTIGUOUS
! 	      || memory_access_type == VMAT_CONTIGUOUS_REVERSE)
  	    {
  	      /* Leave realign cases alone to keep them simple.  */
  	      if (alignment_support_scheme == dr_explicit_realign_optimized
*************** vectorizable_load (vec_info *vinfo,
*** 11915,11921 ****
  	}
  
        /* Collect vector loads and later create their permutation in
! 	 vect_transform_grouped_load ().  */
        if (!costing_p && (grouped_load || slp_perm))
  	dr_chain.quick_push (new_temp);
  
--- 11307,11313 ----
  	}
  
        /* Collect vector loads and later create their permutation in
! 	 vect_transform_slp_perm_load.  */
        if (!costing_p && (grouped_load || slp_perm))
  	dr_chain.quick_push (new_temp);
  
*************** vectorizable_load (vec_info *vinfo,
*** 11984,11991 ****
    if (costing_p)
      {
        gcc_assert (memory_access_type == VMAT_CONTIGUOUS
! 		  || memory_access_type == VMAT_CONTIGUOUS_REVERSE
! 		  || memory_access_type == VMAT_CONTIGUOUS_PERMUTE);
        if (n_adjacent_loads > 0)
  	vect_get_load_cost (vinfo, stmt_info, slp_node, n_adjacent_loads,
  			    alignment_support_scheme, misalignment, false,
--- 11376,11382 ----
    if (costing_p)
      {
        gcc_assert (memory_access_type == VMAT_CONTIGUOUS
! 		  || memory_access_type == VMAT_CONTIGUOUS_REVERSE);
        if (n_adjacent_loads > 0)
  	vect_get_load_cost (vinfo, stmt_info, slp_node, n_adjacent_loads,
  			    alignment_support_scheme, misalignment, false,
*************** vectorizable_load (vec_info *vinfo,
*** 12015,12021 ****
     condition operands are supportable using vec_is_simple_use.  */
  
  static bool
! vect_is_simple_cond (tree cond, vec_info *vinfo, stmt_vec_info stmt_info,
  		     slp_tree slp_node, tree *comp_vectype,
  		     enum vect_def_type *dts, tree vectype)
  {
--- 11406,11412 ----
     condition operands are supportable using vec_is_simple_use.  */
  
  static bool
! vect_is_simple_cond (tree cond, vec_info *vinfo,
  		     slp_tree slp_node, tree *comp_vectype,
  		     enum vect_def_type *dts, tree vectype)
  {
*************** vect_is_simple_cond (tree cond, vec_info
*** 12027,12033 ****
    if (TREE_CODE (cond) == SSA_NAME
        && VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (cond)))
      {
!       if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 0, &cond,
  			       &slp_op, &dts[0], comp_vectype)
  	  || !*comp_vectype
  	  || !VECTOR_BOOLEAN_TYPE_P (*comp_vectype))
--- 11418,11424 ----
    if (TREE_CODE (cond) == SSA_NAME
        && VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (cond)))
      {
!       if (!vect_is_simple_use (vinfo, slp_node, 0, &cond,
  			       &slp_op, &dts[0], comp_vectype)
  	  || !*comp_vectype
  	  || !VECTOR_BOOLEAN_TYPE_P (*comp_vectype))
*************** vect_is_simple_cond (tree cond, vec_info
*** 12043,12049 ****
  
    if (TREE_CODE (lhs) == SSA_NAME)
      {
!       if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 0,
  			       &lhs, &slp_op, &dts[0], &vectype1))
  	return false;
      }
--- 11434,11440 ----
  
    if (TREE_CODE (lhs) == SSA_NAME)
      {
!       if (!vect_is_simple_use (vinfo, slp_node, 0,
  			       &lhs, &slp_op, &dts[0], &vectype1))
  	return false;
      }
*************** vect_is_simple_cond (tree cond, vec_info
*** 12055,12061 ****
  
    if (TREE_CODE (rhs) == SSA_NAME)
      {
!       if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 1,
  			       &rhs, &slp_op, &dts[1], &vectype2))
  	return false;
      }
--- 11446,11452 ----
  
    if (TREE_CODE (rhs) == SSA_NAME)
      {
!       if (!vect_is_simple_use (vinfo, slp_node, 1,
  			       &rhs, &slp_op, &dts[1], &vectype2))
  	return false;
      }
*************** vect_is_simple_cond (tree cond, vec_info
*** 12108,12114 ****
  static bool
  vectorizable_condition (vec_info *vinfo,
  			stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
- 			gimple **vec_stmt,
  			slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    tree scalar_dest = NULL_TREE;
--- 11499,11504 ----
*************** vectorizable_condition (vec_info *vinfo,
*** 12124,12132 ****
    enum vect_def_type dts[4]
      = {vect_unknown_def_type, vect_unknown_def_type,
         vect_unknown_def_type, vect_unknown_def_type};
-   int ndts = 4;
-   int ncopies;
-   int vec_num;
    enum tree_code code, cond_code, bitop1 = NOP_EXPR, bitop2 = NOP_EXPR;
    int i;
    bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
--- 11514,11519 ----
*************** vectorizable_condition (vec_info *vinfo,
*** 12156,12162 ****
      = STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info)) != NULL;
    if (for_reduction)
      {
!       if (slp_node && SLP_TREE_LANES (slp_node) > 1)
  	return false;
        reduc_info = info_for_reduction (vinfo, stmt_info);
        reduction_type = STMT_VINFO_REDUC_TYPE (reduc_info);
--- 11543,11549 ----
      = STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info)) != NULL;
    if (for_reduction)
      {
!       if (SLP_TREE_LANES (slp_node) > 1)
  	return false;
        reduc_info = info_for_reduction (vinfo, stmt_info);
        reduction_type = STMT_VINFO_REDUC_TYPE (reduc_info);
*************** vectorizable_condition (vec_info *vinfo,
*** 12170,12207 ****
  	return false;
      }
  
!   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
  
!   if (slp_node)
!     {
!       ncopies = 1;
!       vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
!     }
!   else
!     {
!       ncopies = vect_get_num_copies (loop_vinfo, vectype);
!       vec_num = 1;
!     }
! 
!   gcc_assert (ncopies >= 1);
!   if (for_reduction && ncopies > 1)
!     return false; /* FORNOW */
  
    cond_expr = gimple_assign_rhs1 (stmt);
    gcc_assert (! COMPARISON_CLASS_P (cond_expr));
  
!   if (!vect_is_simple_cond (cond_expr, vinfo, stmt_info, slp_node,
  			    &comp_vectype, &dts[0], vectype)
        || !comp_vectype)
      return false;
  
    unsigned op_adjust = COMPARISON_CLASS_P (cond_expr) ? 1 : 0;
    slp_tree then_slp_node, else_slp_node;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 1 + op_adjust,
  			   &then_clause, &then_slp_node, &dts[2], &vectype1))
      return false;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node, 2 + op_adjust,
  			   &else_clause, &else_slp_node, &dts[3], &vectype2))
      return false;
  
--- 11557,11581 ----
  	return false;
      }
  
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
    tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
  
!   int vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
  
    cond_expr = gimple_assign_rhs1 (stmt);
    gcc_assert (! COMPARISON_CLASS_P (cond_expr));
  
!   if (!vect_is_simple_cond (cond_expr, vinfo, slp_node,
  			    &comp_vectype, &dts[0], vectype)
        || !comp_vectype)
      return false;
  
    unsigned op_adjust = COMPARISON_CLASS_P (cond_expr) ? 1 : 0;
    slp_tree then_slp_node, else_slp_node;
!   if (!vect_is_simple_use (vinfo, slp_node, 1 + op_adjust,
  			   &then_clause, &then_slp_node, &dts[2], &vectype1))
      return false;
!   if (!vect_is_simple_use (vinfo, slp_node, 2 + op_adjust,
  			   &else_clause, &else_slp_node, &dts[3], &vectype2))
      return false;
  
*************** vectorizable_condition (vec_info *vinfo,
*** 12249,12257 ****
  	}
        /* ???  The vectorized operand query below doesn't allow swapping
  	 this way for SLP.  */
!       if (slp_node)
! 	return false;
!       std::swap (then_clause, else_clause);
      }
  
    if (!masked && VECTOR_BOOLEAN_TYPE_P (comp_vectype))
--- 11623,11630 ----
  	}
        /* ???  The vectorized operand query below doesn't allow swapping
  	 this way for SLP.  */
!       return false;
!       /* std::swap (then_clause, else_clause); */
      }
  
    if (!masked && VECTOR_BOOLEAN_TYPE_P (comp_vectype))
*************** vectorizable_condition (vec_info *vinfo,
*** 12305,12311 ****
        return false;
      }
  
!   if (!vec_stmt)
      {
        if (bitop1 != NOP_EXPR)
  	{
--- 11678,11684 ----
        return false;
      }
  
!   if (cost_vec)
      {
        if (bitop1 != NOP_EXPR)
  	{
*************** vectorizable_condition (vec_info *vinfo,
*** 12336,12349 ****
  		       || !expand_vec_cond_expr_p (vectype, vec_cmp_type))))
  	return false;
  
!       if (slp_node
! 	  && (!vect_maybe_update_slp_op_vectype
! 		 (SLP_TREE_CHILDREN (slp_node)[0], comp_vectype)
! 	      || (op_adjust == 1
! 		  && !vect_maybe_update_slp_op_vectype
! 			(SLP_TREE_CHILDREN (slp_node)[1], comp_vectype))
! 	      || !vect_maybe_update_slp_op_vectype (then_slp_node, vectype)
! 	      || !vect_maybe_update_slp_op_vectype (else_slp_node, vectype)))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 11709,11721 ----
  		       || !expand_vec_cond_expr_p (vectype, vec_cmp_type))))
  	return false;
  
!       if (!vect_maybe_update_slp_op_vectype (SLP_TREE_CHILDREN (slp_node)[0],
! 					     comp_vectype)
! 	  || (op_adjust == 1
! 	      && !vect_maybe_update_slp_op_vectype
! 			      (SLP_TREE_CHILDREN (slp_node)[1], comp_vectype))
! 	  || !vect_maybe_update_slp_op_vectype (then_slp_node, vectype)
! 	  || !vect_maybe_update_slp_op_vectype (else_slp_node, vectype))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vectorizable_condition (vec_info *vinfo,
*** 12360,12370 ****
  						  vectype, OPTIMIZE_FOR_SPEED))
  		vect_record_loop_len (loop_vinfo,
  				      &LOOP_VINFO_LENS (loop_vinfo),
! 				      ncopies * vec_num, vectype, 1);
  	      else
  		vect_record_loop_mask (loop_vinfo,
  				       &LOOP_VINFO_MASKS (loop_vinfo),
! 				       ncopies * vec_num, vectype, NULL);
  	    }
  	  /* Extra inactive lanes should be safe for vect_nested_cycle.  */
  	  else if (STMT_VINFO_DEF_TYPE (reduc_info) != vect_nested_cycle)
--- 11732,11742 ----
  						  vectype, OPTIMIZE_FOR_SPEED))
  		vect_record_loop_len (loop_vinfo,
  				      &LOOP_VINFO_LENS (loop_vinfo),
! 				      vec_num, vectype, 1);
  	      else
  		vect_record_loop_mask (loop_vinfo,
  				       &LOOP_VINFO_MASKS (loop_vinfo),
! 				       vec_num, vectype, NULL);
  	    }
  	  /* Extra inactive lanes should be safe for vect_nested_cycle.  */
  	  else if (STMT_VINFO_DEF_TYPE (reduc_info) != vect_nested_cycle)
*************** vectorizable_condition (vec_info *vinfo,
*** 12378,12385 ****
  	}
  
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       vect_model_simple_cost (vinfo, ncopies, dts, ndts, slp_node,
! 			      cost_vec, kind);
        return true;
      }
  
--- 11750,11756 ----
  	}
  
        STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
!       vect_model_simple_cost (vinfo, 1, slp_node, cost_vec, kind);
        return true;
      }
  
*************** vectorizable_condition (vec_info *vinfo,
*** 12408,12414 ****
  	masks = &LOOP_VINFO_MASKS (loop_vinfo);
        else
  	{
! 	  scalar_cond_masked_key cond (cond_expr, ncopies);
  	  if (loop_vinfo->scalar_cond_masked_set.contains (cond))
  	    masks = &LOOP_VINFO_MASKS (loop_vinfo);
  	  else
--- 11779,11785 ----
  	masks = &LOOP_VINFO_MASKS (loop_vinfo);
        else
  	{
! 	  scalar_cond_masked_key cond (cond_expr, 1);
  	  if (loop_vinfo->scalar_cond_masked_set.contains (cond))
  	    masks = &LOOP_VINFO_MASKS (loop_vinfo);
  	  else
*************** vectorizable_condition (vec_info *vinfo,
*** 12443,12460 ****
  
    /* Handle cond expr.  */
    if (masked)
!     vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
! 		       cond_expr, comp_vectype, &vec_oprnds0,
! 		       then_clause, vectype, &vec_oprnds2,
  		       reduction_type != EXTRACT_LAST_REDUCTION
! 		       ? else_clause : NULL, vectype, &vec_oprnds3);
    else
!     vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
! 		       cond_expr0, comp_vectype, &vec_oprnds0,
! 		       cond_expr1, comp_vectype, &vec_oprnds1,
! 		       then_clause, vectype, &vec_oprnds2,
  		       reduction_type != EXTRACT_LAST_REDUCTION
! 		       ? else_clause : NULL, vectype, &vec_oprnds3);
  
    if (reduction_type == EXTRACT_LAST_REDUCTION)
      vec_else_clause = else_clause;
--- 11814,11831 ----
  
    /* Handle cond expr.  */
    if (masked)
!     vect_get_vec_defs (vinfo, slp_node,
! 		       cond_expr, &vec_oprnds0,
! 		       then_clause, &vec_oprnds2,
  		       reduction_type != EXTRACT_LAST_REDUCTION
! 		       ? else_clause : NULL, &vec_oprnds3);
    else
!     vect_get_vec_defs (vinfo, slp_node,
! 		       cond_expr0, &vec_oprnds0,
! 		       cond_expr1, &vec_oprnds1,
! 		       then_clause, &vec_oprnds2,
  		       reduction_type != EXTRACT_LAST_REDUCTION
! 		       ? else_clause : NULL, &vec_oprnds3);
  
    if (reduction_type == EXTRACT_LAST_REDUCTION)
      vec_else_clause = else_clause;
*************** vectorizable_condition (vec_info *vinfo,
*** 12571,12577 ****
  	      if (lens)
  		{
  		  len = vect_get_loop_len (loop_vinfo, gsi, lens,
! 					   vec_num * ncopies, vectype, i, 1);
  		  signed char biasval
  		    = LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS (loop_vinfo);
  		  bias = build_int_cst (intQI_type_node, biasval);
--- 11942,11948 ----
  	      if (lens)
  		{
  		  len = vect_get_loop_len (loop_vinfo, gsi, lens,
! 					   vec_num, vectype, i, 1);
  		  signed char biasval
  		    = LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS (loop_vinfo);
  		  bias = build_int_cst (intQI_type_node, biasval);
*************** vectorizable_condition (vec_info *vinfo,
*** 12585,12591 ****
  	  if (masks)
  	    {
  	      tree loop_mask
! 		= vect_get_loop_mask (loop_vinfo, gsi, masks, vec_num * ncopies,
  				      vectype, i);
  	      tree tmp2 = make_ssa_name (vec_cmp_type);
  	      gassign *g
--- 11956,11962 ----
  	  if (masks)
  	    {
  	      tree loop_mask
! 		= vect_get_loop_mask (loop_vinfo, gsi, masks, vec_num,
  				      vectype, i);
  	      tree tmp2 = make_ssa_name (vec_cmp_type);
  	      gassign *g
*************** vectorizable_condition (vec_info *vinfo,
*** 12637,12651 ****
  					  vec_then_clause, vec_else_clause);
  	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
  	}
!       if (slp_node)
! 	slp_node->push_vec_def (new_stmt);
!       else
! 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
      }
  
-   if (!slp_node)
-     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
- 
    vec_oprnds0.release ();
    vec_oprnds1.release ();
    vec_oprnds2.release ();
--- 12008,12016 ----
  					  vec_then_clause, vec_else_clause);
  	  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
  	}
!       slp_node->push_vec_def (new_stmt);
      }
  
    vec_oprnds0.release ();
    vec_oprnds1.release ();
    vec_oprnds2.release ();
*************** vectorizable_condition (vec_info *vinfo,
*** 12665,12682 ****
  static bool
  vectorizable_comparison_1 (vec_info *vinfo, tree vectype,
  			   stmt_vec_info stmt_info, tree_code code,
! 			   gimple_stmt_iterator *gsi, gimple **vec_stmt,
  			   slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    tree lhs, rhs1, rhs2;
    tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
    tree vec_rhs1 = NULL_TREE, vec_rhs2 = NULL_TREE;
    tree new_temp;
-   loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
    enum vect_def_type dts[2] = {vect_unknown_def_type, vect_unknown_def_type};
-   int ndts = 2;
    poly_uint64 nunits;
-   int ncopies;
    enum tree_code bitop1 = NOP_EXPR, bitop2 = NOP_EXPR;
    int i;
    bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
--- 12030,12044 ----
  static bool
  vectorizable_comparison_1 (vec_info *vinfo, tree vectype,
  			   stmt_vec_info stmt_info, tree_code code,
! 			   gimple_stmt_iterator *gsi,
  			   slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    tree lhs, rhs1, rhs2;
    tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
    tree vec_rhs1 = NULL_TREE, vec_rhs2 = NULL_TREE;
    tree new_temp;
    enum vect_def_type dts[2] = {vect_unknown_def_type, vect_unknown_def_type};
    poly_uint64 nunits;
    enum tree_code bitop1 = NOP_EXPR, bitop2 = NOP_EXPR;
    int i;
    bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
*************** vectorizable_comparison_1 (vec_info *vin
*** 12694,12715 ****
    mask_type = vectype;
    nunits = TYPE_VECTOR_SUBPARTS (vectype);
  
-   if (slp_node)
-     ncopies = 1;
-   else
-     ncopies = vect_get_num_copies (loop_vinfo, vectype);
- 
-   gcc_assert (ncopies >= 1);
- 
    if (TREE_CODE_CLASS (code) != tcc_comparison)
      return false;
  
    slp_tree slp_rhs1, slp_rhs2;
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
  			   0, &rhs1, &slp_rhs1, &dts[0], &vectype1))
      return false;
  
!   if (!vect_is_simple_use (vinfo, stmt_info, slp_node,
  			   1, &rhs2, &slp_rhs2, &dts[1], &vectype2))
      return false;
  
--- 12056,12070 ----
    mask_type = vectype;
    nunits = TYPE_VECTOR_SUBPARTS (vectype);
  
    if (TREE_CODE_CLASS (code) != tcc_comparison)
      return false;
  
    slp_tree slp_rhs1, slp_rhs2;
!   if (!vect_is_simple_use (vinfo, slp_node,
  			   0, &rhs1, &slp_rhs1, &dts[0], &vectype1))
      return false;
  
!   if (!vect_is_simple_use (vinfo, slp_node,
  			   1, &rhs2, &slp_rhs2, &dts[1], &vectype2))
      return false;
  
*************** vectorizable_comparison_1 (vec_info *vin
*** 12775,12781 ****
  	}
      }
  
!   if (!vec_stmt)
      {
        if (bitop1 == NOP_EXPR)
  	{
--- 12130,12136 ----
  	}
      }
  
!   if (cost_vec)
      {
        if (bitop1 == NOP_EXPR)
  	{
*************** vectorizable_comparison_1 (vec_info *vin
*** 12800,12808 ****
  	}
  
        /* Put types on constant and invariant SLP children.  */
!       if (slp_node
! 	  && (!vect_maybe_update_slp_op_vectype (slp_rhs1, vectype)
! 	      || !vect_maybe_update_slp_op_vectype (slp_rhs2, vectype)))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 12155,12162 ----
  	}
  
        /* Put types on constant and invariant SLP children.  */
!       if (!vect_maybe_update_slp_op_vectype (slp_rhs1, vectype)
! 	  || !vect_maybe_update_slp_op_vectype (slp_rhs2, vectype))
  	{
  	  if (dump_enabled_p ())
  	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vectorizable_comparison_1 (vec_info *vin
*** 12810,12817 ****
  	  return false;
  	}
  
!       vect_model_simple_cost (vinfo, ncopies * (1 + (bitop2 != NOP_EXPR)),
! 			      dts, ndts, slp_node, cost_vec);
        return true;
      }
  
--- 12164,12171 ----
  	  return false;
  	}
  
!       vect_model_simple_cost (vinfo, 1 + (bitop2 != NOP_EXPR),
! 			      slp_node, cost_vec);
        return true;
      }
  
*************** vectorizable_comparison_1 (vec_info *vin
*** 12822,12830 ****
    if (lhs)
      mask = vect_create_destination_var (lhs, mask_type);
  
!   vect_get_vec_defs (vinfo, stmt_info, slp_node, ncopies,
! 		     rhs1, vectype, &vec_oprnds0,
! 		     rhs2, vectype, &vec_oprnds1);
    if (swap_p)
      std::swap (vec_oprnds0, vec_oprnds1);
  
--- 12176,12182 ----
    if (lhs)
      mask = vect_create_destination_var (lhs, mask_type);
  
!   vect_get_vec_defs (vinfo, slp_node, rhs1, &vec_oprnds0, rhs2, &vec_oprnds1);
    if (swap_p)
      std::swap (vec_oprnds0, vec_oprnds1);
  
*************** vectorizable_comparison_1 (vec_info *vin
*** 12863,12877 ****
  	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
  	    }
  	}
!       if (slp_node)
! 	slp_node->push_vec_def (new_stmt);
!       else
! 	STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt);
      }
  
-   if (!slp_node)
-     *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0];
- 
    vec_oprnds0.release ();
    vec_oprnds1.release ();
  
--- 12215,12223 ----
  	      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
  	    }
  	}
!       slp_node->push_vec_def (new_stmt);
      }
  
    vec_oprnds0.release ();
    vec_oprnds1.release ();
  
*************** vectorizable_comparison_1 (vec_info *vin
*** 12889,12895 ****
  static bool
  vectorizable_comparison (vec_info *vinfo,
  			 stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
- 			 gimple **vec_stmt,
  			 slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
--- 12235,12240 ----
*************** vectorizable_comparison (vec_info *vinfo
*** 12905,12916 ****
      return false;
  
    enum tree_code code = gimple_assign_rhs_code (stmt);
!   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    if (!vectorizable_comparison_1 (vinfo, vectype, stmt_info, code, gsi,
! 				  vec_stmt, slp_node, cost_vec))
      return false;
  
!   if (!vec_stmt)
      STMT_VINFO_TYPE (stmt_info) = comparison_vec_info_type;
  
    return true;
--- 12250,12261 ----
      return false;
  
    enum tree_code code = gimple_assign_rhs_code (stmt);
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
    if (!vectorizable_comparison_1 (vinfo, vectype, stmt_info, code, gsi,
! 				  slp_node, cost_vec))
      return false;
  
!   if (cost_vec)
      STMT_VINFO_TYPE (stmt_info) = comparison_vec_info_type;
  
    return true;
*************** vectorizable_comparison (vec_info *vinfo
*** 12921,12927 ****
  
  bool
  vectorizable_early_exit (vec_info *vinfo, stmt_vec_info stmt_info,
! 			 gimple_stmt_iterator *gsi, gimple **vec_stmt,
  			 slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
--- 12266,12272 ----
  
  bool
  vectorizable_early_exit (vec_info *vinfo, stmt_vec_info stmt_info,
! 			 gimple_stmt_iterator *gsi,
  			 slp_tree slp_node, stmt_vector_for_cost *cost_vec)
  {
    loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
*************** vectorizable_early_exit (vec_info *vinfo
*** 12939,12986 ****
  
    auto code = gimple_cond_code (STMT_VINFO_STMT (stmt_info));
  
-   tree vectype = NULL_TREE;
-   slp_tree slp_op0;
-   tree op0;
-   enum vect_def_type dt0;
- 
-   /* Early break gcond kind SLP trees can be root only and have no children,
-      for instance in the case where the argument is an external.  If that's
-      the case there is no operand to analyse use of.  */
-   if ((!slp_node || !SLP_TREE_CHILDREN (slp_node).is_empty ())
-       && !vect_is_simple_use (vinfo, stmt_info, slp_node, 0, &op0, &slp_op0, &dt0,
- 			      &vectype))
-     {
-       if (dump_enabled_p ())
- 	  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			   "use not simple.\n");
- 	return false;
-     }
- 
    /* For SLP we don't want to use the type of the operands of the SLP node, when
       vectorizing using SLP slp_node will be the children of the gcond and we
       want to use the type of the direct children which since the gcond is root
       will be the current node, rather than a child node as vect_is_simple_use
       assumes.  */
!   if (slp_node)
!     vectype = SLP_TREE_VECTYPE (slp_node);
! 
    if (!vectype)
      return false;
  
    machine_mode mode = TYPE_MODE (vectype);
!   int ncopies, vec_num;
! 
!   if (slp_node)
!     {
!       ncopies = 1;
!       vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
!     }
!   else
!     {
!       ncopies = vect_get_num_copies (loop_vinfo, vectype);
!       vec_num = 1;
!     }
  
    vec_loop_masks *masks = &LOOP_VINFO_MASKS (loop_vinfo);
    vec_loop_lens *lens = &LOOP_VINFO_LENS (loop_vinfo);
--- 12284,12300 ----
  
    auto code = gimple_cond_code (STMT_VINFO_STMT (stmt_info));
  
    /* For SLP we don't want to use the type of the operands of the SLP node, when
       vectorizing using SLP slp_node will be the children of the gcond and we
       want to use the type of the direct children which since the gcond is root
       will be the current node, rather than a child node as vect_is_simple_use
       assumes.  */
!   tree vectype = SLP_TREE_VECTYPE (slp_node);
    if (!vectype)
      return false;
  
    machine_mode mode = TYPE_MODE (vectype);
!   int vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
  
    vec_loop_masks *masks = &LOOP_VINFO_MASKS (loop_vinfo);
    vec_loop_lens *lens = &LOOP_VINFO_LENS (loop_vinfo);
*************** vectorizable_early_exit (vec_info *vinfo
*** 13010,13016 ****
  					exit_true_edge->dest);
  
    /* Analyze only.  */
!   if (!vec_stmt)
      {
        if (direct_optab_handler (cbranch_optab, mode) == CODE_FOR_nothing)
  	{
--- 12324,12330 ----
  					exit_true_edge->dest);
  
    /* Analyze only.  */
!   if (cost_vec)
      {
        if (direct_optab_handler (cbranch_optab, mode) == CODE_FOR_nothing)
  	{
*************** vectorizable_early_exit (vec_info *vinfo
*** 13022,13052 ****
  	  return false;
  	}
  
-       if (ncopies > 1
- 	  && direct_optab_handler (ior_optab, mode) == CODE_FOR_nothing)
- 	{
- 	  if (dump_enabled_p ())
- 	      dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- 			       "can't vectorize early exit because the "
- 			       "target does not support boolean vector IOR "
- 			       "for type %T.\n",
- 			       vectype);
- 	  return false;
- 	}
- 
        if (!vectorizable_comparison_1 (vinfo, vectype, stmt_info, code, gsi,
! 				      vec_stmt, slp_node, cost_vec))
  	return false;
  
        if (LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo))
  	{
  	  if (direct_internal_fn_supported_p (IFN_VCOND_MASK_LEN, vectype,
  					      OPTIMIZE_FOR_SPEED))
! 	    vect_record_loop_len (loop_vinfo, lens, ncopies * vec_num,
! 				  vectype, 1);
  	  else
! 	    vect_record_loop_mask (loop_vinfo, masks, ncopies * vec_num,
! 				   vectype, NULL);
  	}
  
        return true;
--- 12336,12352 ----
  	  return false;
  	}
  
        if (!vectorizable_comparison_1 (vinfo, vectype, stmt_info, code, gsi,
! 				      slp_node, cost_vec))
  	return false;
  
        if (LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo))
  	{
  	  if (direct_internal_fn_supported_p (IFN_VCOND_MASK_LEN, vectype,
  					      OPTIMIZE_FOR_SPEED))
! 	    vect_record_loop_len (loop_vinfo, lens, vec_num, vectype, 1);
  	  else
! 	    vect_record_loop_mask (loop_vinfo, masks, vec_num, vectype, NULL);
  	}
  
        return true;
*************** vectorizable_early_exit (vec_info *vinfo
*** 13066,13093 ****
       vectorized.  It's not very clean to do this here, But the masking code below is
       complex and this keeps it all in one place to ease fixes and backports.  Once we
       drop the non-SLP loop vect or split vectorizable_* this can be simplified.  */
-   if (!slp_node)
-     {
-       if (!vectorizable_comparison_1 (vinfo, vectype, stmt_info, code, gsi,
- 				      vec_stmt, slp_node, cost_vec))
- 	gcc_unreachable ();
-     }
  
    gimple *stmt = STMT_VINFO_STMT (stmt_info);
    basic_block cond_bb = gimple_bb (stmt);
    gimple_stmt_iterator  cond_gsi = gsi_last_bb (cond_bb);
  
    auto_vec<tree> stmts;
! 
!   if (slp_node)
!     stmts.safe_splice (SLP_TREE_VEC_DEFS (slp_node));
!   else
!     {
!       auto vec_stmts = STMT_VINFO_VEC_STMTS (stmt_info);
!       stmts.reserve_exact (vec_stmts.length ());
!       for (auto stmt : vec_stmts)
! 	stmts.quick_push (gimple_assign_lhs (stmt));
!     }
  
    /* If we're comparing against a previous forall we need to negate the resullts
       before we do the final comparison or reduction.  */
--- 12366,12378 ----
       vectorized.  It's not very clean to do this here, But the masking code below is
       complex and this keeps it all in one place to ease fixes and backports.  Once we
       drop the non-SLP loop vect or split vectorizable_* this can be simplified.  */
  
    gimple *stmt = STMT_VINFO_STMT (stmt_info);
    basic_block cond_bb = gimple_bb (stmt);
    gimple_stmt_iterator  cond_gsi = gsi_last_bb (cond_bb);
  
    auto_vec<tree> stmts;
!   stmts.safe_splice (SLP_TREE_VEC_DEFS (slp_node));
  
    /* If we're comparing against a previous forall we need to negate the resullts
       before we do the final comparison or reduction.  */
*************** vectorizable_early_exit (vec_info *vinfo
*** 13126,13132 ****
  	for (unsigned i = 0; i < stmts.length (); i++)
  	  {
  	    tree stmt_mask
! 	      = vect_get_loop_mask (loop_vinfo, gsi, masks, ncopies * vec_num,
  				    vectype, i);
  	    stmt_mask
  	      = prepare_vec_mask (loop_vinfo, TREE_TYPE (stmt_mask), stmt_mask,
--- 12411,12417 ----
  	for (unsigned i = 0; i < stmts.length (); i++)
  	  {
  	    tree stmt_mask
! 	      = vect_get_loop_mask (loop_vinfo, gsi, masks, vec_num,
  				    vectype, i);
  	    stmt_mask
  	      = prepare_vec_mask (loop_vinfo, TREE_TYPE (stmt_mask), stmt_mask,
*************** vectorizable_early_exit (vec_info *vinfo
*** 13137,13143 ****
  	for (unsigned i = 0; i < stmts.length (); i++)
  	  {
  	    tree len_mask = vect_gen_loop_len_mask (loop_vinfo, gsi, &cond_gsi,
! 						    lens, ncopies * vec_num,
  						    vectype, stmts[i], i, 1);
  
  	    workset.quick_push (len_mask);
--- 12422,12428 ----
  	for (unsigned i = 0; i < stmts.length (); i++)
  	  {
  	    tree len_mask = vect_gen_loop_len_mask (loop_vinfo, gsi, &cond_gsi,
! 						    lens, vec_num,
  						    vectype, stmts[i], i, 1);
  
  	    workset.quick_push (len_mask);
*************** vectorizable_early_exit (vec_info *vinfo
*** 13162,13174 ****
        if (masked_loop_p)
  	{
  	  tree mask
! 	    = vect_get_loop_mask (loop_vinfo, gsi, masks, ncopies, vectype, 0);
  	  new_temp = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
  				       new_temp, &cond_gsi);
  	}
        else if (len_loop_p)
  	new_temp = vect_gen_loop_len_mask (loop_vinfo, gsi, &cond_gsi, lens,
! 					   ncopies, vectype, new_temp, 0, 1);
      }
  
    gcc_assert (new_temp);
--- 12447,12459 ----
        if (masked_loop_p)
  	{
  	  tree mask
! 	    = vect_get_loop_mask (loop_vinfo, gsi, masks, 1, vectype, 0);
  	  new_temp = prepare_vec_mask (loop_vinfo, TREE_TYPE (mask), mask,
  				       new_temp, &cond_gsi);
  	}
        else if (len_loop_p)
  	new_temp = vect_gen_loop_len_mask (loop_vinfo, gsi, &cond_gsi, lens,
! 					   1, vectype, new_temp, 0, 1);
      }
  
    gcc_assert (new_temp);
*************** vectorizable_early_exit (vec_info *vinfo
*** 13176,13188 ****
    gimple_cond_set_condition (cond_stmt, NE_EXPR, new_temp, cst);
    update_stmt (orig_stmt);
  
!   if (slp_node)
!     SLP_TREE_VEC_DEFS (slp_node).truncate (0);
!    else
!     STMT_VINFO_VEC_STMTS (stmt_info).truncate (0);
! 
!   if (!slp_node)
!     *vec_stmt = orig_stmt;
  
    return true;
  }
--- 12461,12468 ----
    gimple_cond_set_condition (cond_stmt, NE_EXPR, new_temp, cst);
    update_stmt (orig_stmt);
  
!   /* ??? */
!   SLP_TREE_VEC_DEFS (slp_node).truncate (0);
  
    return true;
  }
*************** vect_analyze_stmt (vec_info *vinfo,
*** 13310,13367 ****
      /* Prefer vectorizable_call over vectorizable_simd_clone_call so
         -mveclibabi= takes preference over library functions with
         the simd attribute.  */
!     ok = (vectorizable_call (vinfo, stmt_info, NULL, NULL, node, cost_vec)
! 	  || vectorizable_simd_clone_call (vinfo, stmt_info, NULL, NULL, node,
  					   cost_vec)
  	  || vectorizable_conversion (vinfo, stmt_info,
! 				      NULL, NULL, node, cost_vec)
  	  || vectorizable_operation (vinfo, stmt_info,
! 				     NULL, NULL, node, cost_vec)
  	  || vectorizable_assignment (vinfo, stmt_info,
! 				      NULL, NULL, node, cost_vec)
! 	  || vectorizable_load (vinfo, stmt_info, NULL, NULL, node, cost_vec)
! 	  || vectorizable_store (vinfo, stmt_info, NULL, NULL, node, cost_vec)
  	  || vectorizable_lane_reducing (as_a <loop_vec_info> (vinfo),
  					 stmt_info, node, cost_vec)
  	  || vectorizable_reduction (as_a <loop_vec_info> (vinfo), stmt_info,
  				     node, node_instance, cost_vec)
  	  || vectorizable_induction (as_a <loop_vec_info> (vinfo), stmt_info,
! 				     NULL, node, cost_vec)
! 	  || vectorizable_shift (vinfo, stmt_info, NULL, NULL, node, cost_vec)
  	  || vectorizable_condition (vinfo, stmt_info,
! 				     NULL, NULL, node, cost_vec)
! 	  || vectorizable_comparison (vinfo, stmt_info, NULL, NULL, node,
  				      cost_vec)
  	  || vectorizable_lc_phi (as_a <loop_vec_info> (vinfo),
  				  stmt_info, node)
  	  || vectorizable_recurr (as_a <loop_vec_info> (vinfo),
! 				   stmt_info, NULL, node, cost_vec)
! 	  || vectorizable_early_exit (vinfo, stmt_info, NULL, NULL, node,
  				      cost_vec));
    else
      {
        if (bb_vinfo)
! 	ok = (vectorizable_call (vinfo, stmt_info, NULL, NULL, node, cost_vec)
  	      || vectorizable_simd_clone_call (vinfo, stmt_info,
! 					       NULL, NULL, node, cost_vec)
! 	      || vectorizable_conversion (vinfo, stmt_info, NULL, NULL, node,
  					  cost_vec)
  	      || vectorizable_shift (vinfo, stmt_info,
! 				     NULL, NULL, node, cost_vec)
  	      || vectorizable_operation (vinfo, stmt_info,
! 					 NULL, NULL, node, cost_vec)
! 	      || vectorizable_assignment (vinfo, stmt_info, NULL, NULL, node,
  					  cost_vec)
  	      || vectorizable_load (vinfo, stmt_info,
! 				    NULL, NULL, node, cost_vec)
  	      || vectorizable_store (vinfo, stmt_info,
! 				     NULL, NULL, node, cost_vec)
  	      || vectorizable_condition (vinfo, stmt_info,
! 					 NULL, NULL, node, cost_vec)
! 	      || vectorizable_comparison (vinfo, stmt_info, NULL, NULL, node,
  					  cost_vec)
! 	      || vectorizable_phi (vinfo, stmt_info, NULL, node, cost_vec)
! 	      || vectorizable_early_exit (vinfo, stmt_info, NULL, NULL, node,
  					  cost_vec));
  
      }
--- 12590,12647 ----
      /* Prefer vectorizable_call over vectorizable_simd_clone_call so
         -mveclibabi= takes preference over library functions with
         the simd attribute.  */
!     ok = (vectorizable_call (vinfo, stmt_info, NULL, node, cost_vec)
! 	  || vectorizable_simd_clone_call (vinfo, stmt_info, NULL, node,
  					   cost_vec)
  	  || vectorizable_conversion (vinfo, stmt_info,
! 				      NULL, node, cost_vec)
  	  || vectorizable_operation (vinfo, stmt_info,
! 				     NULL, node, cost_vec)
  	  || vectorizable_assignment (vinfo, stmt_info,
! 				      NULL, node, cost_vec)
! 	  || vectorizable_load (vinfo, stmt_info, NULL, node, cost_vec)
! 	  || vectorizable_store (vinfo, stmt_info, NULL, node, cost_vec)
  	  || vectorizable_lane_reducing (as_a <loop_vec_info> (vinfo),
  					 stmt_info, node, cost_vec)
  	  || vectorizable_reduction (as_a <loop_vec_info> (vinfo), stmt_info,
  				     node, node_instance, cost_vec)
  	  || vectorizable_induction (as_a <loop_vec_info> (vinfo), stmt_info,
! 				     node, cost_vec)
! 	  || vectorizable_shift (vinfo, stmt_info, NULL, node, cost_vec)
  	  || vectorizable_condition (vinfo, stmt_info,
! 				     NULL, node, cost_vec)
! 	  || vectorizable_comparison (vinfo, stmt_info, NULL, node,
  				      cost_vec)
  	  || vectorizable_lc_phi (as_a <loop_vec_info> (vinfo),
  				  stmt_info, node)
  	  || vectorizable_recurr (as_a <loop_vec_info> (vinfo),
! 				   stmt_info, node, cost_vec)
! 	  || vectorizable_early_exit (vinfo, stmt_info, NULL, node,
  				      cost_vec));
    else
      {
        if (bb_vinfo)
! 	ok = (vectorizable_call (vinfo, stmt_info, NULL, node, cost_vec)
  	      || vectorizable_simd_clone_call (vinfo, stmt_info,
! 					       NULL, node, cost_vec)
! 	      || vectorizable_conversion (vinfo, stmt_info, NULL, node,
  					  cost_vec)
  	      || vectorizable_shift (vinfo, stmt_info,
! 				     NULL, node, cost_vec)
  	      || vectorizable_operation (vinfo, stmt_info,
! 					 NULL, node, cost_vec)
! 	      || vectorizable_assignment (vinfo, stmt_info, NULL, node,
  					  cost_vec)
  	      || vectorizable_load (vinfo, stmt_info,
! 				    NULL, node, cost_vec)
  	      || vectorizable_store (vinfo, stmt_info,
! 				     NULL, node, cost_vec)
  	      || vectorizable_condition (vinfo, stmt_info,
! 					 NULL, node, cost_vec)
! 	      || vectorizable_comparison (vinfo, stmt_info, NULL, node,
  					  cost_vec)
! 	      || vectorizable_phi (vinfo, stmt_info, node, cost_vec)
! 	      || vectorizable_early_exit (vinfo, stmt_info, NULL, node,
  					  cost_vec));
  
      }
*************** vect_transform_stmt (vec_info *vinfo,
*** 13403,13459 ****
  		     slp_tree slp_node, slp_instance slp_node_instance)
  {
    bool is_store = false;
-   gimple *vec_stmt = NULL;
    bool done;
  
!   gcc_assert (slp_node || !PURE_SLP_STMT (stmt_info));
  
    if (dump_enabled_p ())
      dump_printf_loc (MSG_NOTE, vect_location,
  		     "------>vectorizing statement: %G", stmt_info->stmt);
  
    tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info);
!   if (slp_node)
!     STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (slp_node);
  
    switch (STMT_VINFO_TYPE (stmt_info))
      {
      case type_demotion_vec_info_type:
      case type_promotion_vec_info_type:
      case type_conversion_vec_info_type:
!       done = vectorizable_conversion (vinfo, stmt_info,
! 				      gsi, &vec_stmt, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case induc_vec_info_type:
        done = vectorizable_induction (as_a <loop_vec_info> (vinfo),
! 				     stmt_info, &vec_stmt, slp_node,
! 				     NULL);
        gcc_assert (done);
        break;
  
      case shift_vec_info_type:
!       done = vectorizable_shift (vinfo, stmt_info,
! 				 gsi, &vec_stmt, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case op_vec_info_type:
!       done = vectorizable_operation (vinfo, stmt_info, gsi, &vec_stmt, slp_node,
! 				     NULL);
        gcc_assert (done);
        break;
  
      case assignment_vec_info_type:
!       done = vectorizable_assignment (vinfo, stmt_info,
! 				      gsi, &vec_stmt, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case load_vec_info_type:
!       done = vectorizable_load (vinfo, stmt_info, gsi, &vec_stmt, slp_node,
! 				NULL);
        gcc_assert (done);
        break;
  
--- 12683,12731 ----
  		     slp_tree slp_node, slp_instance slp_node_instance)
  {
    bool is_store = false;
    bool done;
  
!   gcc_assert (slp_node);
  
    if (dump_enabled_p ())
      dump_printf_loc (MSG_NOTE, vect_location,
  		     "------>vectorizing statement: %G", stmt_info->stmt);
  
    tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info);
!   STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (slp_node);
  
    switch (STMT_VINFO_TYPE (stmt_info))
      {
      case type_demotion_vec_info_type:
      case type_promotion_vec_info_type:
      case type_conversion_vec_info_type:
!       done = vectorizable_conversion (vinfo, stmt_info, gsi, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case induc_vec_info_type:
        done = vectorizable_induction (as_a <loop_vec_info> (vinfo),
! 				     stmt_info, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case shift_vec_info_type:
!       done = vectorizable_shift (vinfo, stmt_info, gsi, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case op_vec_info_type:
!       done = vectorizable_operation (vinfo, stmt_info, gsi, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case assignment_vec_info_type:
!       done = vectorizable_assignment (vinfo, stmt_info, gsi, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case load_vec_info_type:
!       done = vectorizable_load (vinfo, stmt_info, gsi, slp_node, NULL);
        gcc_assert (done);
        break;
  
*************** vect_transform_stmt (vec_info *vinfo,
*** 13469,13500 ****
  	;
        else
  	{
! 	  done = vectorizable_store (vinfo, stmt_info,
! 				     gsi, &vec_stmt, slp_node, NULL);
  	  gcc_assert (done);
  	  is_store = true;
  	}
        break;
  
      case condition_vec_info_type:
!       done = vectorizable_condition (vinfo, stmt_info,
! 				     gsi, &vec_stmt, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case comparison_vec_info_type:
!       done = vectorizable_comparison (vinfo, stmt_info, gsi, &vec_stmt,
! 				      slp_node, NULL);
        gcc_assert (done);
        break;
  
      case call_vec_info_type:
!       done = vectorizable_call (vinfo, stmt_info,
! 				gsi, &vec_stmt, slp_node, NULL);
        break;
  
      case call_simd_clone_vec_info_type:
!       done = vectorizable_simd_clone_call (vinfo, stmt_info, gsi, &vec_stmt,
  					   slp_node, NULL);
        break;
  
--- 12741,12768 ----
  	;
        else
  	{
! 	  done = vectorizable_store (vinfo, stmt_info, gsi, slp_node, NULL);
  	  gcc_assert (done);
  	  is_store = true;
  	}
        break;
  
      case condition_vec_info_type:
!       done = vectorizable_condition (vinfo, stmt_info, gsi, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case comparison_vec_info_type:
!       done = vectorizable_comparison (vinfo, stmt_info, gsi, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case call_vec_info_type:
!       done = vectorizable_call (vinfo, stmt_info, gsi, slp_node, NULL);
        break;
  
      case call_simd_clone_vec_info_type:
!       done = vectorizable_simd_clone_call (vinfo, stmt_info, gsi,
  					   slp_node, NULL);
        break;
  
*************** vect_transform_stmt (vec_info *vinfo,
*** 13518,13535 ****
  
      case recurr_info_type:
        done = vectorizable_recurr (as_a <loop_vec_info> (vinfo),
! 				  stmt_info, &vec_stmt, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case phi_info_type:
!       done = vectorizable_phi (vinfo, stmt_info, &vec_stmt, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case loop_exit_ctrl_vec_info_type:
!       done = vectorizable_early_exit (vinfo, stmt_info, gsi, &vec_stmt,
! 				      slp_node, NULL);
        gcc_assert (done);
        break;
  
--- 12786,12802 ----
  
      case recurr_info_type:
        done = vectorizable_recurr (as_a <loop_vec_info> (vinfo),
! 				  stmt_info, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case phi_info_type:
!       done = vectorizable_phi (vinfo, stmt_info, slp_node, NULL);
        gcc_assert (done);
        break;
  
      case loop_exit_ctrl_vec_info_type:
!       done = vectorizable_early_exit (vinfo, stmt_info, gsi, slp_node, NULL);
        gcc_assert (done);
        break;
  
*************** vect_transform_stmt (vec_info *vinfo,
*** 13544,13555 ****
        done = true;
      }
  
-   if (!slp_node && vec_stmt)
-     gcc_assert (STMT_VINFO_VEC_STMTS (stmt_info).exists ());
- 
    if (STMT_VINFO_TYPE (stmt_info) != store_vec_info_type
!       && (!slp_node
! 	  || !slp_node->ldst_lanes
  	  || SLP_TREE_CODE (slp_node) == VEC_PERM_EXPR))
      {
        /* Handle stmts whose DEF is used outside the loop-nest that is
--- 12811,12818 ----
        done = true;
      }
  
    if (STMT_VINFO_TYPE (stmt_info) != store_vec_info_type
!       && (!slp_node->ldst_lanes
  	  || SLP_TREE_CODE (slp_node) == VEC_PERM_EXPR))
      {
        /* Handle stmts whose DEF is used outside the loop-nest that is
*************** vect_transform_stmt (vec_info *vinfo,
*** 13559,13566 ****
        gcc_assert (done);
      }
  
!   if (slp_node)
!     STMT_VINFO_VECTYPE (stmt_info) = saved_vectype;
  
    return is_store;
  }
--- 12822,12828 ----
        gcc_assert (done);
      }
  
!   STMT_VINFO_VECTYPE (stmt_info) = saved_vectype;
  
    return is_store;
  }
*************** vect_is_simple_use (tree operand, vec_in
*** 13995,14117 ****
  
  /* Function vect_is_simple_use.
  
-    Same as vect_is_simple_use but also determines the vector operand
-    type of OPERAND and stores it to *VECTYPE.  If the definition of
-    OPERAND is vect_uninitialized_def, vect_constant_def or
-    vect_external_def *VECTYPE will be set to NULL_TREE and the caller
-    is responsible to compute the best suited vector type for the
-    scalar operand.  */
- 
- bool
- vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
- 		    tree *vectype, stmt_vec_info *def_stmt_info_out,
- 		    gimple **def_stmt_out)
- {
-   stmt_vec_info def_stmt_info;
-   gimple *def_stmt;
-   if (!vect_is_simple_use (operand, vinfo, dt, &def_stmt_info, &def_stmt))
-     return false;
- 
-   if (def_stmt_out)
-     *def_stmt_out = def_stmt;
-   if (def_stmt_info_out)
-     *def_stmt_info_out = def_stmt_info;
- 
-   /* Now get a vector type if the def is internal, otherwise supply
-      NULL_TREE and leave it up to the caller to figure out a proper
-      type for the use stmt.  */
-   if (*dt == vect_internal_def
-       || *dt == vect_induction_def
-       || *dt == vect_reduction_def
-       || *dt == vect_double_reduction_def
-       || *dt == vect_nested_cycle
-       || *dt == vect_first_order_recurrence)
-     {
-       *vectype = STMT_VINFO_VECTYPE (def_stmt_info);
-       gcc_assert (*vectype != NULL_TREE);
-       if (dump_enabled_p ())
- 	dump_printf_loc (MSG_NOTE, vect_location,
- 			 "vect_is_simple_use: vectype %T\n", *vectype);
-     }
-   else if (*dt == vect_uninitialized_def
- 	   || *dt == vect_constant_def
- 	   || *dt == vect_external_def)
-     *vectype = NULL_TREE;
-   else
-     gcc_unreachable ();
- 
-   return true;
- }
- 
- /* Function vect_is_simple_use.
- 
     Same as vect_is_simple_use but determines the operand by operand
     position OPERAND from either STMT or SLP_NODE, filling in *OP
     and *SLP_DEF (when SLP_NODE is not NULL).  */
  
  bool
! vect_is_simple_use (vec_info *vinfo, stmt_vec_info stmt, slp_tree slp_node,
  		    unsigned operand, tree *op, slp_tree *slp_def,
  		    enum vect_def_type *dt,
  		    tree *vectype, stmt_vec_info *def_stmt_info_out)
  {
!   if (slp_node)
      {
!       slp_tree child = SLP_TREE_CHILDREN (slp_node)[operand];
!       *slp_def = child;
!       *vectype = SLP_TREE_VECTYPE (child);
!       if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
  	{
! 	  /* ???  VEC_PERM nodes might be intermediate and their lane value
! 	     have no representative (nor do we build a VEC_PERM stmt for
! 	     the actual operation).  Note for two-operator nodes we set
! 	     a representative but leave scalar stmts empty as we'd only
! 	     have one for a subset of lanes.  Ideally no caller would
! 	     require *op for internal defs.  */
! 	  if (SLP_TREE_REPRESENTATIVE (child))
! 	    {
! 	      *op = gimple_get_lhs (SLP_TREE_REPRESENTATIVE (child)->stmt);
! 	      return vect_is_simple_use (*op, vinfo, dt, def_stmt_info_out);
! 	    }
! 	  else
! 	    {
! 	      gcc_assert (SLP_TREE_CODE (child) == VEC_PERM_EXPR);
! 	      *op = error_mark_node;
! 	      *dt = vect_internal_def;
! 	      if (def_stmt_info_out)
! 		*def_stmt_info_out = NULL;
! 	      return true;
! 	    }
  	}
        else
  	{
  	  if (def_stmt_info_out)
  	    *def_stmt_info_out = NULL;
- 	  *op = SLP_TREE_SCALAR_OPS (child)[0];
- 	  *dt = SLP_TREE_DEF_TYPE (child);
  	  return true;
  	}
      }
    else
      {
!       *slp_def = NULL;
!       if (gassign *ass = dyn_cast <gassign *> (stmt->stmt))
! 	{
! 	  if (gimple_assign_rhs_code (ass) == COND_EXPR
! 	      && COMPARISON_CLASS_P (gimple_assign_rhs1 (ass)))
! 	    gcc_unreachable ();
! 	  else if (gimple_assign_rhs_code (ass) == VIEW_CONVERT_EXPR)
! 	    *op = TREE_OPERAND (gimple_assign_rhs1 (ass), 0);
! 	  else
! 	    *op = gimple_op (ass, operand + 1);
! 	}
!       else if (gcond *cond = dyn_cast <gcond *> (stmt->stmt))
! 	*op = gimple_op (cond, operand);
!       else if (gcall *call = dyn_cast <gcall *> (stmt->stmt))
! 	*op = gimple_call_arg (call, operand);
!       else
! 	gcc_unreachable ();
!       return vect_is_simple_use (*op, vinfo, dt, vectype, def_stmt_info_out);
      }
  }
  
--- 13257,13305 ----
  
  /* Function vect_is_simple_use.
  
     Same as vect_is_simple_use but determines the operand by operand
     position OPERAND from either STMT or SLP_NODE, filling in *OP
     and *SLP_DEF (when SLP_NODE is not NULL).  */
  
  bool
! vect_is_simple_use (vec_info *vinfo, slp_tree slp_node,
  		    unsigned operand, tree *op, slp_tree *slp_def,
  		    enum vect_def_type *dt,
  		    tree *vectype, stmt_vec_info *def_stmt_info_out)
  {
!   slp_tree child = SLP_TREE_CHILDREN (slp_node)[operand];
!   *slp_def = child;
!   *vectype = SLP_TREE_VECTYPE (child);
!   if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
      {
!       /* ???  VEC_PERM nodes might be intermediate and their lane value
! 	 have no representative (nor do we build a VEC_PERM stmt for
! 	 the actual operation).  Note for two-operator nodes we set
! 	 a representative but leave scalar stmts empty as we'd only
! 	 have one for a subset of lanes.  Ideally no caller would
! 	 require *op for internal defs.  */
!       if (SLP_TREE_REPRESENTATIVE (child))
  	{
! 	  *op = gimple_get_lhs (SLP_TREE_REPRESENTATIVE (child)->stmt);
! 	  return vect_is_simple_use (*op, vinfo, dt, def_stmt_info_out);
  	}
        else
  	{
+ 	  gcc_assert (SLP_TREE_CODE (child) == VEC_PERM_EXPR);
+ 	  *op = error_mark_node;
+ 	  *dt = vect_internal_def;
  	  if (def_stmt_info_out)
  	    *def_stmt_info_out = NULL;
  	  return true;
  	}
      }
    else
      {
!       if (def_stmt_info_out)
! 	*def_stmt_info_out = NULL;
!       *op = SLP_TREE_SCALAR_OPS (child)[0];
!       *dt = SLP_TREE_DEF_TYPE (child);
!       return true;
      }
  }
  
diff -Nrcpad gcc-16-20250720/gcc/tree-vectorizer.cc gcc-16-20250727/gcc/tree-vectorizer.cc
*** gcc-16-20250720/gcc/tree-vectorizer.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-vectorizer.cc	Sun Jul 27 22:32:17 2025
*************** vec_info::new_stmt_vec_info (gimple *stm
*** 724,730 ****
    STMT_VINFO_REDUC_IDX (res) = -1;
    STMT_VINFO_SLP_VECT_ONLY (res) = false;
    STMT_VINFO_SLP_VECT_ONLY_PATTERN (res) = false;
-   STMT_VINFO_VEC_STMTS (res) = vNULL;
    res->reduc_initial_values = vNULL;
    res->reduc_scalar_results = vNULL;
  
--- 724,729 ----
*************** vec_info::free_stmt_vec_info (stmt_vec_i
*** 790,797 ****
  
    stmt_info->reduc_initial_values.release ();
    stmt_info->reduc_scalar_results.release ();
-   STMT_VINFO_SIMD_CLONE_INFO (stmt_info).release ();
-   STMT_VINFO_VEC_STMTS (stmt_info).release ();
    free (stmt_info);
  }
  
--- 789,794 ----
diff -Nrcpad gcc-16-20250720/gcc/tree-vectorizer.h gcc-16-20250727/gcc/tree-vectorizer.h
*** gcc-16-20250720/gcc/tree-vectorizer.h	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/tree-vectorizer.h	Sun Jul 27 22:32:17 2025
*************** enum vect_memory_access_type {
*** 184,194 ****
       of invariants.  */
    VMAT_CONTIGUOUS_DOWN,
  
-   /* A simple contiguous access in which the elements need to be permuted
-      after loading or before storing.  Only used for loop vectorization;
-      SLP uses separate permutes.  */
-   VMAT_CONTIGUOUS_PERMUTE,
- 
    /* A simple contiguous access in which the elements need to be reversed
       after loading or before storing.  */
    VMAT_CONTIGUOUS_REVERSE,
--- 184,189 ----
*************** public:
*** 1359,1367 ****
    /* The vector type to be used for the LHS of this statement.  */
    tree vectype;
  
-   /* The vectorized stmts.  */
-   vec<gimple *> vec_stmts;
- 
    /* The following is relevant only for stmts that contain a non-scalar
       data-ref (array/pointer/struct access). A GIMPLE stmt is expected to have
       at most one such data-ref.  */
--- 1354,1359 ----
*************** public:
*** 1398,1408 ****
       pattern statement.  */
    gimple_seq pattern_def_seq;
  
-   /* Selected SIMD clone's function info.  First vector element
-      is SIMD clone's function decl, followed by a pair of trees (base + step)
-      for linear arguments (pair of NULLs for other arguments).  */
-   vec<tree> simd_clone_info;
- 
    /* Classify the def of this stmt.  */
    enum vect_def_type def_type;
  
--- 1390,1395 ----
*************** struct gather_scatter_info {
*** 1557,1562 ****
--- 1544,1553 ----
    /* The loop-invariant base value.  */
    tree base;
  
+   /* The TBBA alias pointer the value of which determines the alignment
+      of the scalar accesses.  */
+   tree alias_ptr;
+ 
    /* The original scalar offset, which is a non-loop-invariant SSA_NAME.  */
    tree offset;
  
*************** struct gather_scatter_info {
*** 1583,1589 ****
  #define STMT_VINFO_RELEVANT(S)             (S)->relevant
  #define STMT_VINFO_LIVE_P(S)               (S)->live
  #define STMT_VINFO_VECTYPE(S)              (S)->vectype
- #define STMT_VINFO_VEC_STMTS(S)            (S)->vec_stmts
  #define STMT_VINFO_VECTORIZABLE(S)         (S)->vectorizable
  #define STMT_VINFO_DATA_REF(S)             ((S)->dr_aux.dr + 0)
  #define STMT_VINFO_GATHER_SCATTER_P(S)	   (S)->gather_scatter_p
--- 1574,1579 ----
*************** struct gather_scatter_info {
*** 1614,1620 ****
  #define STMT_VINFO_IN_PATTERN_P(S)         (S)->in_pattern_p
  #define STMT_VINFO_RELATED_STMT(S)         (S)->related_stmt
  #define STMT_VINFO_PATTERN_DEF_SEQ(S)      (S)->pattern_def_seq
- #define STMT_VINFO_SIMD_CLONE_INFO(S)	   (S)->simd_clone_info
  #define STMT_VINFO_DEF_TYPE(S)             (S)->def_type
  #define STMT_VINFO_GROUPED_ACCESS(S) \
    ((S)->dr_aux.dr && DR_GROUP_FIRST_ELEMENT(S))
--- 1604,1609 ----
*************** struct gather_scatter_info {
*** 1655,1660 ****
--- 1644,1657 ----
  #define PURE_SLP_STMT(S)                  ((S)->slp_type == pure_slp)
  #define STMT_SLP_TYPE(S)                   (S)->slp_type
  
+ #define GATHER_SCATTER_LEGACY_P(info) ((info).decl != NULL_TREE \
+ 				       && (info).ifn == IFN_LAST)
+ #define GATHER_SCATTER_IFN_P(info) ((info).decl == NULL_TREE \
+ 				    && (info).ifn != IFN_LAST)
+ #define GATHER_SCATTER_EMULATED_P(info) ((info).decl == NULL_TREE \
+ 					 && (info).ifn == IFN_LAST)
+ 
+ 
  /* Contains the scalar or vector costs for a vec_info.  */
  class vector_costs
  {
*************** extern bool vect_chooses_same_modes_p (m
*** 2422,2431 ****
  extern bool vect_get_loop_mask_type (loop_vec_info);
  extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *,
  				stmt_vec_info * = NULL, gimple ** = NULL);
! extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *,
! 				tree *, stmt_vec_info * = NULL,
! 				gimple ** = NULL);
! extern bool vect_is_simple_use (vec_info *, stmt_vec_info, slp_tree,
  				unsigned, tree *, slp_tree *,
  				enum vect_def_type *,
  				tree *, stmt_vec_info * = NULL);
--- 2419,2425 ----
  extern bool vect_get_loop_mask_type (loop_vec_info);
  extern bool vect_is_simple_use (tree, vec_info *, enum vect_def_type *,
  				stmt_vec_info * = NULL, gimple ** = NULL);
! extern bool vect_is_simple_use (vec_info *, slp_tree,
  				unsigned, tree *, slp_tree *,
  				enum vect_def_type *,
  				tree *, stmt_vec_info * = NULL);
*************** extern void vect_finish_stmt_generation
*** 2486,2503 ****
  					 gimple_stmt_iterator *);
  extern opt_result vect_mark_stmts_to_be_vectorized (loop_vec_info, bool *);
  extern tree vect_get_store_rhs (stmt_vec_info);
! void vect_get_vec_defs_for_operand (vec_info *vinfo, stmt_vec_info, unsigned,
! 				    tree op, vec<tree> *, tree = NULL);
! void vect_get_vec_defs (vec_info *, stmt_vec_info, slp_tree, unsigned,
  			tree, vec<tree> *,
  			tree = NULL, vec<tree> * = NULL,
  			tree = NULL, vec<tree> * = NULL,
  			tree = NULL, vec<tree> * = NULL);
- void vect_get_vec_defs (vec_info *, stmt_vec_info, slp_tree, unsigned,
- 			tree, tree, vec<tree> *,
- 			tree = NULL, tree = NULL, vec<tree> * = NULL,
- 			tree = NULL, tree = NULL, vec<tree> * = NULL,
- 			tree = NULL, tree = NULL, vec<tree> * = NULL);
  extern tree vect_init_vector (vec_info *, stmt_vec_info, tree, tree,
                                gimple_stmt_iterator *);
  extern tree vect_get_slp_vect_def (slp_tree, unsigned);
--- 2480,2490 ----
  					 gimple_stmt_iterator *);
  extern opt_result vect_mark_stmts_to_be_vectorized (loop_vec_info, bool *);
  extern tree vect_get_store_rhs (stmt_vec_info);
! void vect_get_vec_defs (vec_info *, slp_tree,
  			tree, vec<tree> *,
  			tree = NULL, vec<tree> * = NULL,
  			tree = NULL, vec<tree> * = NULL,
  			tree = NULL, vec<tree> * = NULL);
  extern tree vect_init_vector (vec_info *, stmt_vec_info, tree, tree,
                                gimple_stmt_iterator *);
  extern tree vect_get_slp_vect_def (slp_tree, unsigned);
*************** extern bool ref_within_array_bound (gimp
*** 2534,2540 ****
  /* In tree-vect-data-refs.cc.  */
  extern bool vect_can_force_dr_alignment_p (const_tree, poly_uint64);
  extern enum dr_alignment_support vect_supportable_dr_alignment
! 				   (vec_info *, dr_vec_info *, tree, int);
  extern tree vect_get_smallest_scalar_type (stmt_vec_info, tree);
  extern opt_result vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *);
  extern bool vect_slp_analyze_instance_dependence (vec_info *, slp_instance);
--- 2521,2528 ----
  /* In tree-vect-data-refs.cc.  */
  extern bool vect_can_force_dr_alignment_p (const_tree, poly_uint64);
  extern enum dr_alignment_support vect_supportable_dr_alignment
! 				   (vec_info *, dr_vec_info *, tree, int,
! 				     gather_scatter_info * = nullptr);
  extern tree vect_get_smallest_scalar_type (stmt_vec_info, tree);
  extern opt_result vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *);
  extern bool vect_slp_analyze_instance_dependence (vec_info *, slp_instance);
*************** extern bool vect_check_gather_scatter (s
*** 2552,2558 ****
  extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
  						 vec<data_reference_p> *,
  						 vec<int> *, int);
! extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *);
  extern void vect_record_base_alignments (vec_info *);
  extern tree vect_create_data_ref_ptr (vec_info *,
  				      stmt_vec_info, tree, class loop *, tree,
--- 2540,2546 ----
  extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
  						 vec<data_reference_p> *,
  						 vec<int> *, int);
! extern opt_result vect_analyze_data_refs (vec_info *, bool *);
  extern void vect_record_base_alignments (vec_info *);
  extern tree vect_create_data_ref_ptr (vec_info *,
  				      stmt_vec_info, tree, class loop *, tree,
*************** extern internal_fn vect_store_lanes_supp
*** 2568,2584 ****
  extern bool vect_grouped_load_supported (tree, bool, unsigned HOST_WIDE_INT);
  extern internal_fn vect_load_lanes_supported (tree, unsigned HOST_WIDE_INT,
  					      bool, vec<int> * = nullptr);
- extern void vect_permute_store_chain (vec_info *, vec<tree> &,
- 				      unsigned int, stmt_vec_info,
- 				      gimple_stmt_iterator *, vec<tree> *);
  extern tree vect_setup_realignment (vec_info *,
  				    stmt_vec_info, gimple_stmt_iterator *,
  				    tree *, enum dr_alignment_support, tree,
  	                            class loop **);
- extern void vect_transform_grouped_load (vec_info *, stmt_vec_info, vec<tree>,
- 					 int, gimple_stmt_iterator *);
- extern void vect_record_grouped_load_vectors (vec_info *,
- 					      stmt_vec_info, vec<tree>);
  extern tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
  extern tree vect_get_new_ssa_name (tree, enum vect_var_kind,
  				   const char * = NULL);
--- 2556,2565 ----
*************** extern bool vectorizable_reduction (loop
*** 2647,2654 ****
  				    slp_tree, slp_instance,
  				    stmt_vector_for_cost *);
  extern bool vectorizable_induction (loop_vec_info, stmt_vec_info,
! 				    gimple **, slp_tree,
! 				    stmt_vector_for_cost *);
  extern bool vect_transform_reduction (loop_vec_info, stmt_vec_info,
  				      gimple_stmt_iterator *,
  				      slp_tree);
--- 2628,2634 ----
  				    slp_tree, slp_instance,
  				    stmt_vector_for_cost *);
  extern bool vectorizable_induction (loop_vec_info, stmt_vec_info,
! 				    slp_tree, stmt_vector_for_cost *);
  extern bool vect_transform_reduction (loop_vec_info, stmt_vec_info,
  				      gimple_stmt_iterator *,
  				      slp_tree);
*************** extern bool vect_transform_cycle_phi (lo
*** 2656,2667 ****
  				      slp_tree, slp_instance);
  extern bool vectorizable_lc_phi (loop_vec_info, stmt_vec_info, slp_tree);
  extern bool vect_transform_lc_phi (loop_vec_info, stmt_vec_info, slp_tree);
! extern bool vectorizable_phi (vec_info *, stmt_vec_info, gimple **, slp_tree,
  			      stmt_vector_for_cost *);
  extern bool vectorizable_recurr (loop_vec_info, stmt_vec_info,
! 				  gimple **, slp_tree, stmt_vector_for_cost *);
  extern bool vectorizable_early_exit (vec_info *, stmt_vec_info,
! 				     gimple_stmt_iterator *, gimple **,
  				     slp_tree, stmt_vector_for_cost *);
  extern bool vect_emulated_vector_p (tree);
  extern bool vect_can_vectorize_without_simd_p (tree_code);
--- 2636,2647 ----
  				      slp_tree, slp_instance);
  extern bool vectorizable_lc_phi (loop_vec_info, stmt_vec_info, slp_tree);
  extern bool vect_transform_lc_phi (loop_vec_info, stmt_vec_info, slp_tree);
! extern bool vectorizable_phi (vec_info *, stmt_vec_info, slp_tree,
  			      stmt_vector_for_cost *);
  extern bool vectorizable_recurr (loop_vec_info, stmt_vec_info,
! 				  slp_tree, stmt_vector_for_cost *);
  extern bool vectorizable_early_exit (vec_info *, stmt_vec_info,
! 				     gimple_stmt_iterator *,
  				     slp_tree, stmt_vector_for_cost *);
  extern bool vect_emulated_vector_p (tree);
  extern bool vect_can_vectorize_without_simd_p (tree_code);
diff -Nrcpad gcc-16-20250720/gcc/varasm.cc gcc-16-20250727/gcc/varasm.cc
*** gcc-16-20250720/gcc/varasm.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/varasm.cc	Sun Jul 27 22:32:17 2025
*************** assemble_asm (tree asm_str)
*** 1734,1740 ****
  	  constraints[i]
  	    = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
  	  if (!parse_output_constraint (&constraints[i], i, ninputs, noutputs,
! 					&allows_mem, &allows_reg, &is_inout))
  	    goto done;
  	  if (is_inout)
  	    {
--- 1734,1741 ----
  	  constraints[i]
  	    = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
  	  if (!parse_output_constraint (&constraints[i], i, ninputs, noutputs,
! 					&allows_mem, &allows_reg, &is_inout,
! 					nullptr))
  	    goto done;
  	  if (is_inout)
  	    {
*************** assemble_asm (tree asm_str)
*** 1776,1782 ****
  	    = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
  	  if (!parse_input_constraint (&constraints[i + noutputs], i,
  				       ninputs, noutputs, 0, constraints,
! 				       &allows_mem, &allows_reg))
  	    goto done;
  	  if (strchr (constraints[i], '%'))
  	    {
--- 1777,1783 ----
  	    = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
  	  if (!parse_input_constraint (&constraints[i + noutputs], i,
  				       ninputs, noutputs, 0, constraints,
! 				       &allows_mem, &allows_reg, nullptr))
  	    goto done;
  	  if (strchr (constraints[i], '%'))
  	    {
*************** assemble_name_resolve (const char *name)
*** 2907,2913 ****
        ultimate_transparent_alias_target (&id);
        if (id != id_orig)
  	name = IDENTIFIER_POINTER (id);
!       gcc_assert (! TREE_CHAIN (id));
      }
  
    return name;
--- 2908,2914 ----
        ultimate_transparent_alias_target (&id);
        if (id != id_orig)
  	name = IDENTIFIER_POINTER (id);
!       gcc_assert (!IDENTIFIER_TRANSPARENT_ALIAS (id));
      }
  
    return name;
diff -Nrcpad gcc-16-20250720/gcc/warning-control.cc gcc-16-20250727/gcc/warning-control.cc
*** gcc-16-20250720/gcc/warning-control.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/gcc/warning-control.cc	Sun Jul 27 22:32:17 2025
***************
*** 28,34 ****
  #include "gimple.h"
  #include "cgraph.h"
  #include "hash-map.h"
! #include "diagnostic-spec.h"
  
  /* Return the no-warning bit for EXPR.  */
  
--- 28,34 ----
  #include "gimple.h"
  #include "cgraph.h"
  #include "hash-map.h"
! #include "gcc-diagnostic-spec.h"
  
  /* Return the no-warning bit for EXPR.  */
  
diff -Nrcpad gcc-16-20250720/libcc1/ChangeLog gcc-16-20250727/libcc1/ChangeLog
*** gcc-16-20250720/libcc1/ChangeLog	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/libcc1/ChangeLog	Sun Jul 27 22:32:17 2025
***************
*** 1,3 ****
--- 1,13 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* context.cc: Update usage of "diagnostic_info" to explicitly
+ 	refer to "diagnostics::diagnostic_info".
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* context.cc: Update for move of diagnostics output formats into
+ 	namespace "diagnostics" as "sinks".
+ 
  2024-12-23  Simon Martin  <simon@nasilyan.com>
  
  	* Makefile.am: Remove reference to deleted marshall-c.h.
diff -Nrcpad gcc-16-20250720/libcc1/context.cc gcc-16-20250727/libcc1/context.cc
*** gcc-16-20250720/libcc1/context.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/libcc1/context.cc	Sun Jul 27 22:32:17 2025
*************** along with GCC; see the file COPYING3.
*** 39,45 ****
  #include "diagnostic.h"
  #include "langhooks.h"
  #include "langhooks-def.h"
! #include "diagnostic-format-text.h"
  
  #include "gcc-interface.h"
  
--- 39,45 ----
  #include "diagnostic.h"
  #include "langhooks.h"
  #include "langhooks-def.h"
! #include "diagnostics/text-sink.h"
  
  #include "gcc-interface.h"
  
*************** cc1_plugin::plugin_context *cc1_plugin::
*** 63,71 ****
  // This is put into the lang hooks when the plugin starts.
  
  static void
! plugin_print_error_function (diagnostic_text_output_format &text_output,
  			     const char *file,
! 			     const diagnostic_info *diagnostic)
  {
    if (current_function_decl != NULL_TREE
        && DECL_NAME (current_function_decl) != NULL_TREE
--- 63,71 ----
  // This is put into the lang hooks when the plugin starts.
  
  static void
! plugin_print_error_function (diagnostics::text_sink &text_output,
  			     const char *file,
! 			     const diagnostics::diagnostic_info *diagnostic)
  {
    if (current_function_decl != NULL_TREE
        && DECL_NAME (current_function_decl) != NULL_TREE
diff -Nrcpad gcc-16-20250720/libcpp/ChangeLog gcc-16-20250727/libcpp/ChangeLog
*** gcc-16-20250720/libcpp/ChangeLog	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/libcpp/ChangeLog	Sun Jul 27 22:32:17 2025
***************
*** 1,3 ****
--- 1,23 ----
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* charset.cc: Update comment for file rename.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* internal.h: Update comment for diagnostic_t becoming
+ 	enum class diagnostics::kind.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* include/cpplib.h: Update for moves to "source-printing".
+ 	* include/rich-location.h (class label_effects): Move to...
+ 	(class diagnostics::label_effects): ...here.
+ 
+ 2025-07-25  David Malcolm  <dmalcolm@redhat.com>
+ 
+ 	* include/rich-location.h: Replace diagnostic_path with
+ 	diagnostics::paths::path.
+ 
  2025-06-17  Jason Merrill  <jason@redhat.com>
  
  	* line-map.cc (linemap_location_from_module_p): Add.
diff -Nrcpad gcc-16-20250720/libcpp/charset.cc gcc-16-20250727/libcpp/charset.cc
*** gcc-16-20250720/libcpp/charset.cc	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/libcpp/charset.cc	Sun Jul 27 22:32:17 2025
*************** convert_escape (cpp_reader *pfile, const
*** 2420,2426 ****
  	{
  	  encoding_rich_location rich_loc (pfile);
  
! 	  /* diagnostic.cc does not support "%03o".  When it does, this
  	     code can use %03o directly in the diagnostic again.  */
  	  char buf[32];
  	  sprintf(buf, "%03o", (int) c);
--- 2420,2426 ----
  	{
  	  encoding_rich_location rich_loc (pfile);
  
! 	  /* pretty-print.cc does not support "%03o".  When it does, this
  	     code can use %03o directly in the diagnostic again.  */
  	  char buf[32];
  	  sprintf(buf, "%03o", (int) c);
diff -Nrcpad gcc-16-20250720/libcpp/include/cpplib.h gcc-16-20250727/libcpp/include/cpplib.h
*** gcc-16-20250720/libcpp/include/cpplib.h	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/libcpp/include/cpplib.h	Sun Jul 27 22:32:17 2025
*************** struct cpp_decoded_char
*** 1610,1616 ****
     This is a tabstop value, along with a callback for getting the
     widths of characters.  Normally this callback is cpp_wcwidth, but we
     support other schemes for escaping non-ASCII unicode as a series of
!    ASCII chars when printing the user's source code in diagnostic-show-locus.cc
  
     For example, consider:
     - the Unicode character U+03C0 "GREEK SMALL LETTER PI" (UTF-8: 0xCF 0x80)
--- 1610,1617 ----
     This is a tabstop value, along with a callback for getting the
     widths of characters.  Normally this callback is cpp_wcwidth, but we
     support other schemes for escaping non-ASCII unicode as a series of
!    ASCII chars when printing the user's source code in
!    gcc/diagnostics/source-printing.cc
  
     For example, consider:
     - the Unicode character U+03C0 "GREEK SMALL LETTER PI" (UTF-8: 0xCF 0x80)
diff -Nrcpad gcc-16-20250720/libcpp/include/rich-location.h gcc-16-20250727/libcpp/include/rich-location.h
*** gcc-16-20250720/libcpp/include/rich-location.h	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/libcpp/include/rich-location.h	Sun Jul 27 22:32:17 2025
*************** along with this program; see the file CO
*** 25,31 ****
  #include "label-text.h"
  
  class range_label;
! class label_effects;
  
  /* A hint to diagnostic_show_locus on how to print a source range within a
     rich_location.
--- 25,31 ----
  #include "label-text.h"
  
  class range_label;
! namespace diagnostics { class label_effects; }
  
  /* A hint to diagnostic_show_locus on how to print a source range within a
     rich_location.
*************** semi_embedded_vec<T, NUM_EMBEDDED>::trun
*** 213,219 ****
  }
  
  class fixit_hint;
! class diagnostic_path;
  
  /* A "rich" source code location, for use when printing diagnostics.
     A rich_location has one or more carets&ranges, where the carets
--- 213,219 ----
  }
  
  class fixit_hint;
! namespace diagnostics { namespace paths { class path; }}
  
  /* A "rich" source code location, for use when printing diagnostics.
     A rich_location has one or more carets&ranges, where the carets
*************** class rich_location
*** 520,527 ****
    }
  
    /* An optional path through the code.  */
!   const diagnostic_path *get_path () const { return m_path; }
!   void set_path (const diagnostic_path *path) { m_path = path; }
  
    /* A flag for hinting that the diagnostic involves character encoding
       issues, and thus that it will be helpful to the user if we show some
--- 520,527 ----
    }
  
    /* An optional path through the code.  */
!   const diagnostics::paths::path *get_path () const { return m_path; }
!   void set_path (const diagnostics::paths::path *path) { m_path = path; }
  
    /* A flag for hinting that the diagnostic involves character encoding
       issues, and thus that it will be helpful to the user if we show some
*************** protected:
*** 567,573 ****
    static const int MAX_STATIC_FIXIT_HINTS = 2;
    semi_embedded_vec <fixit_hint *, MAX_STATIC_FIXIT_HINTS> m_fixit_hints;
  
!   const diagnostic_path *m_path;
  };
  
  /* Abstract base class for labelling a range within a rich_location
--- 567,573 ----
    static const int MAX_STATIC_FIXIT_HINTS = 2;
    semi_embedded_vec <fixit_hint *, MAX_STATIC_FIXIT_HINTS> m_fixit_hints;
  
!   const diagnostics::paths::path *m_path;
  };
  
  /* Abstract base class for labelling a range within a rich_location
*************** class range_label
*** 596,602 ****
    virtual label_text get_text (unsigned range_idx) const = 0;
  
    /* Get any special effects for the label (e.g. links to other labels).  */
!   virtual const label_effects *get_effects (unsigned /*range_idx*/) const
    {
      return nullptr;
    }
--- 596,603 ----
    virtual label_text get_text (unsigned range_idx) const = 0;
  
    /* Get any special effects for the label (e.g. links to other labels).  */
!   virtual const diagnostics::label_effects *
!   get_effects (unsigned /*range_idx*/) const
    {
      return nullptr;
    }
diff -Nrcpad gcc-16-20250720/libcpp/internal.h gcc-16-20250727/libcpp/internal.h
*** gcc-16-20250720/libcpp/internal.h	Sun Jul 20 22:32:31 2025
--- gcc-16-20250727/libcpp/internal.h	Sun Jul 27 22:32:17 2025
*************** struct cpp_reader
*** 622,629 ****
       zero of said file.  */
    location_t main_loc;
  
!   /* If non-zero, override diagnostic locations (other than DK_NOTE
!      diagnostics) to this one.  */
    location_t diagnostic_override_loc;
  
    /* Returns true iff we should warn about UTF-8 bidirectional control
--- 622,629 ----
       zero of said file.  */
    location_t main_loc;
  
!   /* If non-zero, override diagnostic locations (other than
!      diagnostics::kind::note diagnostics) to this one.  */
    location_t diagnostic_override_loc;
  
    /* Returns true iff we should warn about UTF-8 bidirectional control
diff -Nrcpad gcc-16-20250720/libgm2/ChangeLog gcc-16-20250727/libgm2/ChangeLog
*** gcc-16-20250720/libgm2/ChangeLog	Sun Jul 20 22:32:32 2025
--- gcc-16-20250727/libgm2/ChangeLog	Sun Jul 27 22:32:17 2025
***************
*** 1,3 ****
--- 1,15 ----
+ 2025-07-23  Gaius Mulley  <gaiusmod2@gmail.com>
+ 
+ 	PR modula2/121164
+ 	* libm2iso/Makefile.am (libm2iso_la_M2FLAGS): Add -Wall.
+ 	* libm2iso/Makefile.in: Regenerate.
+ 	* libm2log/Makefile.am (libm2log_la_M2FLAGS): Add -Wall.
+ 	* libm2log/Makefile.in: Regenerate.
+ 	* libm2min/Makefile.am (libm2min_la_M2FLAGS): Add -Wall.
+ 	* libm2min/Makefile.in: Regenerate.
+ 	* libm2pim/Makefile.am (libm2pim_la_M2FLAGS): Add -Wall.
+ 	* libm2pim/Makefile.in: Regenerate.
+ 
  2025-06-29  Gaius Mulley  <gaiusmod2@gmail.com>
  
  	PR modula2/117203
diff -Nrcpad gcc-16-20250720/libgm2/libm2iso/Makefile.am gcc-16-20250727/libgm2/libm2iso/Makefile.am
*** gcc-16-20250720/libgm2/libm2iso/Makefile.am	Sun Jul 20 22:32:32 2025
--- gcc-16-20250727/libgm2/libm2iso/Makefile.am	Sun Jul 27 22:32:17 2025
*************** libm2iso_la_M2FLAGS = \
*** 206,211 ****
--- 206,212 ----
    -fm2-pathname=m2iso -I. -Ilibm2iso -I$(GM2_SRC)/gm2-libs-iso \
    -fm2-pathname=m2pim -I$(GM2_SRC)/gm2-libs \
    -fiso -fextended-opaque -fm2-g -g -Wcase-enum \
+   -Wall \
    -Wreturn-type -fcase -fm2-prefix=m2iso
  
  if TARGET_DARWIN
diff -Nrcpad gcc-16-20250720/libgm2/libm2iso/Makefile.in gcc-16-20250727/libgm2/libm2iso/Makefile.in
*** gcc-16-20250720/libgm2/libm2iso/Makefile.in	Sun Jul 20 22:32:32 2025
--- gcc-16-20250727/libgm2/libm2iso/Makefile.in	Sun Jul 27 22:32:17 2025
*************** FLAGS_TO_PASS = $(AM_MAKEFLAGS)
*** 594,599 ****
--- 594,600 ----
  @BUILD_ISOLIB_TRUE@  -fm2-pathname=m2iso -I. -Ilibm2iso -I$(GM2_SRC)/gm2-libs-iso \
  @BUILD_ISOLIB_TRUE@  -fm2-pathname=m2pim -I$(GM2_SRC)/gm2-libs \
  @BUILD_ISOLIB_TRUE@  -fiso -fextended-opaque -fm2-g -g -Wcase-enum \
+ @BUILD_ISOLIB_TRUE@  -Wall \
  @BUILD_ISOLIB_TRUE@  -Wreturn-type -fcase -fm2-prefix=m2iso
  
  @BUILD_ISOLIB_TRUE@@TARGET_DARWIN_FALSE@libm2iso_la_link_flags =  \
diff -Nrcpad gcc-16-20250720/libgm2/libm2log/Makefile.am gcc-16-20250727/libgm2/libm2log/Makefile.am
*** gcc-16-20250720/libgm2/libm2log/Makefile.am	Sun Jul 20 22:32:32 2025
--- gcc-16-20250727/libgm2/libm2log/Makefile.am	Sun Jul 27 22:32:17 2025
*************** libm2log_la_M2FLAGS = \
*** 136,141 ****
--- 136,142 ----
   -fm2-pathname=m2log -I$(GM2_SRC)/gm2-libs-log \
   -fm2-pathname=m2pim -I$(GM2_SRC)/gm2-libs \
   -fm2-pathname=m2iso -I$(GM2_SRC)/gm2-libs-iso \
+  -Wall \
   -Wcase-enum -Wreturn-type \
   -fcase -fm2-prefix=m2log
  
diff -Nrcpad gcc-16-20250720/libgm2/libm2log/Makefile.in gcc-16-20250727/libgm2/libm2log/Makefile.in
*** gcc-16-20250720/libgm2/libm2log/Makefile.in	Sun Jul 20 22:32:32 2025
--- gcc-16-20250727/libgm2/libm2log/Makefile.in	Sun Jul 27 22:32:17 2025
*************** FLAGS_TO_PASS = $(AM_MAKEFLAGS)
*** 485,490 ****
--- 485,491 ----
  @BUILD_LOGLIB_TRUE@ -fm2-pathname=m2log -I$(GM2_SRC)/gm2-libs-log \
  @BUILD_LOGLIB_TRUE@ -fm2-pathname=m2pim -I$(GM2_SRC)/gm2-libs \
  @BUILD_LOGLIB_TRUE@ -fm2-pathname=m2iso -I$(GM2_SRC)/gm2-libs-iso \
+ @BUILD_LOGLIB_TRUE@ -Wall \
  @BUILD_LOGLIB_TRUE@ -Wcase-enum -Wreturn-type \
  @BUILD_LOGLIB_TRUE@ -fcase -fm2-prefix=m2log
  
diff -Nrcpad gcc-16-20250720/libgm2/libm2min/Makefile.am gcc-16-20250727/libgm2/libm2min/Makefile.am
*** gcc-16-20250720/libgm2/libm2min/Makefile.am	Sun Jul 20 22:32:32 2025
--- gcc-16-20250727/libgm2/libm2min/Makefile.am	Sun Jul 27 22:32:17 2025
*************** libm2min_la_CFLAGS = -I. -I$(GM2_SRC)/gm
*** 107,112 ****
--- 107,113 ----
  libm2min_la_M2FLAGS = \
     -fm2-pathname=m2min -I. -I$(GM2_SRC)/gm2-libs-min \
     -fm2-pathname=m2pim -I$(GM2_SRC)/gm2-libs -fno-exceptions \
+    -Wall \
     -fno-m2-plugin -fno-scaffold-dynamic -fno-scaffold-main -fm2-prefix=m2min
  
  if TARGET_DARWIN
diff -Nrcpad gcc-16-20250720/libgm2/libm2min/Makefile.in gcc-16-20250727/libgm2/libm2min/Makefile.in
*** gcc-16-20250720/libgm2/libm2min/Makefile.in	Sun Jul 20 22:32:32 2025
--- gcc-16-20250727/libgm2/libm2min/Makefile.in	Sun Jul 27 22:32:17 2025
*************** libm2min_la_CFLAGS = -I. -I$(GM2_SRC)/gm
*** 449,454 ****
--- 449,455 ----
  libm2min_la_M2FLAGS = \
     -fm2-pathname=m2min -I. -I$(GM2_SRC)/gm2-libs-min \
     -fm2-pathname=m2pim -I$(GM2_SRC)/gm2-libs -fno-exceptions \
+    -Wall \
     -fno-m2-plugin -fno-scaffold-dynamic -fno-scaffold-main -fm2-prefix=m2min
  
  @TARGET_DARWIN_FALSE@libm2min_la_link_flags = $(am__append_1)
diff -Nrcpad gcc-16-20250720/libgm2/libm2pim/Makefile.am gcc-16-20250727/libgm2/libm2pim/Makefile.am
*** gcc-16-20250720/libgm2/libm2pim/Makefile.am	Sun Jul 20 22:32:32 2025
--- gcc-16-20250727/libgm2/libm2pim/Makefile.am	Sun Jul 27 22:32:17 2025
*************** libm2pim_la_M2FLAGS = \
*** 185,190 ****
--- 185,191 ----
    -fm2-pathname=m2pim -I. -I$(GM2_SRC)/gm2-libs \
    -fm2-pathname=m2iso -I$(GM2_SRC)/gm2-libs-iso \
    -fm2-g -g -Wcase-enum -Wreturn-type \
+   -Wall \
    -fcase -fm2-prefix=m2pim
  
  if TARGET_DARWIN
diff -Nrcpad gcc-16-20250720/libgm2/libm2pim/Makefile.in gcc-16-20250727/libgm2/libm2pim/Makefile.in
*** gcc-16-20250720/libgm2/libm2pim/Makefile.in	Sun Jul 20 22:32:32 2025
--- gcc-16-20250727/libgm2/libm2pim/Makefile.in	Sun Jul 27 22:32:17 2025
*************** FLAGS_TO_PASS = $(AM_MAKEFLAGS)
*** 564,569 ****
--- 564,570 ----
  @BUILD_PIMLIB_TRUE@  -fm2-pathname=m2pim -I. -I$(GM2_SRC)/gm2-libs \
  @BUILD_PIMLIB_TRUE@  -fm2-pathname=m2iso -I$(GM2_SRC)/gm2-libs-iso \
  @BUILD_PIMLIB_TRUE@  -fm2-g -g -Wcase-enum -Wreturn-type \
+ @BUILD_PIMLIB_TRUE@  -Wall \
  @BUILD_PIMLIB_TRUE@  -fcase -fm2-prefix=m2pim
  
  @BUILD_PIMLIB_TRUE@@TARGET_DARWIN_FALSE@libm2pim_la_link_flags =  \
diff -Nrcpad gcc-16-20250720/libgomp/ChangeLog gcc-16-20250727/libgomp/ChangeLog
*** gcc-16-20250720/libgomp/ChangeLog	Sun Jul 20 22:32:34 2025
--- gcc-16-20250727/libgomp/ChangeLog	Sun Jul 27 22:32:18 2025
***************
*** 1,3 ****
--- 1,11 ----
+ 2025-07-21  Thomas Schwinge  <tschwinge@baylibre.com>
+ 
+ 	PR target/119853
+ 	PR target/119854
+ 	* testsuite/libgomp.c++/target-cdtor-1.C: Adjust for
+ 	'targetm.cxx.use_aeabi_atexit'.
+ 	* testsuite/libgomp.c++/target-cdtor-2.C: Likewise.
+ 
  2025-07-18  Andrew Stubbs  <ams@baylibre.com>
  
  	PR target/121156
diff -Nrcpad gcc-16-20250720/libgomp/testsuite/libgomp.c++/target-cdtor-1.C gcc-16-20250727/libgomp/testsuite/libgomp.c++/target-cdtor-1.C
*** gcc-16-20250720/libgomp/testsuite/libgomp.c++/target-cdtor-1.C	Sun Jul 20 22:32:34 2025
--- gcc-16-20250727/libgomp/testsuite/libgomp.c++/target-cdtor-1.C	Sun Jul 27 22:32:18 2025
*************** int main()
*** 63,76 ****
    return 0;
  }
  
! /* Verify '__cxa_atexit' calls.
  
     For the host, there are four expected calls:
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, } 4 optimized { target cxa_atexit } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sH1, \&__dso_handle>} 1 optimized { target cxa_atexit } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sHD1, \&__dso_handle>} 1 optimized { target cxa_atexit } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZNSt6vectorI1SSaIS0_EED1Ev, \&svHD1, \&__dso_handle>} 1 optimized { target cxa_atexit } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sH2, \&__dso_handle>} 1 optimized { target cxa_atexit } } }
  
     For the device, there are two expected calls:
     { dg-final { scan-offload-tree-dump-times {gimple_call <__cxa_atexit, } 2 optimized { target cxa_atexit } } }
--- 63,81 ----
    return 0;
  }
  
! /* Verify '__cxa_atexit' calls (or '__aeabi_atexit', per 'targetm.cxx.use_aeabi_atexit').
  
     For the host, there are four expected calls:
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, } 4 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, } 4 optimized { target { cxa_atexit && arm_eabi } } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sH1, \&__dso_handle>} 1 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, NULL, \&sH1, _ZN1SD1Ev, \&__dso_handle>} 1 optimized { target { cxa_atexit && arm_eabi } } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sHD1, \&__dso_handle>} 1 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, NULL, \&sHD1, _ZN1SD1Ev, \&__dso_handle>} 1 optimized { target { cxa_atexit && arm_eabi } } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZNSt6vectorI1SSaIS0_EED1Ev, \&svHD1, \&__dso_handle>} 1 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, NULL, \&svHD1, _ZNSt6vectorI1SSaIS0_EED1Ev, \&__dso_handle>} 1 optimized { target { cxa_atexit && arm_eabi } } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sH2, \&__dso_handle>} 1 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, NULL, \&sH2, _ZN1SD1Ev, \&__dso_handle>} 1 optimized { target { cxa_atexit && arm_eabi } } } }
  
     For the device, there are two expected calls:
     { dg-final { scan-offload-tree-dump-times {gimple_call <__cxa_atexit, } 2 optimized { target cxa_atexit } } }
diff -Nrcpad gcc-16-20250720/libgomp/testsuite/libgomp.c++/target-cdtor-2.C gcc-16-20250727/libgomp/testsuite/libgomp.c++/target-cdtor-2.C
*** gcc-16-20250720/libgomp/testsuite/libgomp.c++/target-cdtor-2.C	Sun Jul 20 22:32:34 2025
--- gcc-16-20250727/libgomp/testsuite/libgomp.c++/target-cdtor-2.C	Sun Jul 27 22:32:18 2025
*************** int main()
*** 93,106 ****
    return 0;
  }
  
! /* Verify '__cxa_atexit' calls.
  
     For the host, there are four expected calls:
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, } 4 optimized { target cxa_atexit } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sH1, \&__dso_handle>} 1 optimized { target cxa_atexit } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sHD1, \&__dso_handle>} 1 optimized { target cxa_atexit } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZNSt6vectorI1SSaIS0_EED1Ev, \&svHD1, \&__dso_handle>} 1 optimized { target cxa_atexit } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sH2, \&__dso_handle>} 1 optimized { target cxa_atexit } } }
  
     For the device, there are two expected calls:
     { dg-final { scan-offload-tree-dump-times {gimple_call <__cxa_atexit, } 2 optimized { target cxa_atexit } } }
--- 93,111 ----
    return 0;
  }
  
! /* Verify '__cxa_atexit' calls (or '__aeabi_atexit', per 'targetm.cxx.use_aeabi_atexit').
  
     For the host, there are four expected calls:
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, } 4 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, } 4 optimized { target { cxa_atexit && arm_eabi } } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sH1, \&__dso_handle>} 1 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, NULL, \&sH1, _ZN1SD1Ev, \&__dso_handle>} 1 optimized { target { cxa_atexit && arm_eabi } } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sHD1, \&__dso_handle>} 1 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, NULL, \&sHD1, _ZN1SD1Ev, \&__dso_handle>} 1 optimized { target { cxa_atexit && arm_eabi } } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZNSt6vectorI1SSaIS0_EED1Ev, \&svHD1, \&__dso_handle>} 1 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, NULL, \&svHD1, _ZNSt6vectorI1SSaIS0_EED1Ev, \&__dso_handle>} 1 optimized { target { cxa_atexit && arm_eabi } } } }
!    { dg-final { scan-tree-dump-times {gimple_call <__cxa_atexit, NULL, _ZN1SD1Ev, \&sH2, \&__dso_handle>} 1 optimized { target { cxa_atexit && { ! arm_eabi } } } } }
!      { dg-final { scan-tree-dump-times {gimple_call <__aeabi_atexit, NULL, \&sH2, _ZN1SD1Ev, \&__dso_handle>} 1 optimized { target { cxa_atexit && arm_eabi } } } }
  
     For the device, there are two expected calls:
     { dg-final { scan-offload-tree-dump-times {gimple_call <__cxa_atexit, } 2 optimized { target cxa_atexit } } }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/ChangeLog gcc-16-20250727/libstdc++-v3/ChangeLog
*** gcc-16-20250720/libstdc++-v3/ChangeLog	Sun Jul 20 22:32:36 2025
--- gcc-16-20250727/libstdc++-v3/ChangeLog	Sun Jul 27 22:32:18 2025
***************
*** 1,3 ****
--- 1,143 ----
+ 2025-07-25  Tuur Martens  <tuurmartens4@gmail.com>
+ 
+ 	* include/bits/unordered_map.h: Rectify referencing of
+ 	non-existent type.
+ 
+ 2025-07-24  Nathaniel Shead  <nathanieloshead@gmail.com>
+ 
+ 	PR c++/117294
+ 	PR c++/113854
+ 	* testsuite/20_util/any/misc/any_cast_neg.cc: Adjust
+ 	diagnostics.
+ 	* testsuite/20_util/expected/illformed_neg.cc: Likewise.
+ 	* testsuite/20_util/optional/monadic/or_else_neg.cc: Likewise.
+ 	* testsuite/23_containers/array/creation/3_neg.cc: Likewise.
+ 	* testsuite/24_iterators/range_generators/lwg3900.cc: Likewise.
+ 	* testsuite/29_atomics/atomic/requirements/types_neg.cc:
+ 	Likewise.
+ 	* testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc:
+ 	Likewise.
+ 	* testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc:
+ 	Likewise.
+ 	* testsuite/std/format/arguments/args_neg.cc: Likewise.
+ 	* testsuite/std/format/string_neg.cc: Likewise.
+ 
+ 2025-07-24  Tomasz Kamiński  <tkaminsk@redhat.com>
+ 
+ 	PR libstdc++/104874
+ 	* testsuite/24_iterators/random_access/string_vector_iterators.cc:
+ 	Reworked.
+ 
+ 2025-07-24  Tomasz Kamiński  <tkaminsk@redhat.com>
+ 
+ 	* testsuite/21_strings/basic_string/cons/from_range.cc: Replace
+ 	test_constexpr with test_ranges inside static_assert.
+ 	* testsuite/21_strings/basic_string/modifiers/append/append_range.cc:
+ 	Likewise.
+ 	* testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc:
+ 	Likewise.
+ 	* testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc:
+ 	Likewise.
+ 	* testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc:
+ 	Likewise.
+ 	* testsuite/23_containers/vector/bool/cons/from_range.cc: Likewise.
+ 	* testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc:
+ 	Likewise.
+ 	* testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc:
+ 	Likewise.
+ 	* testsuite/23_containers/vector/cons/from_range.cc: Likewise.
+ 	* testsuite/23_containers/vector/modifiers/assign/assign_range.cc:
+ 	Likewise.
+ 	* testsuite/23_containers/vector/modifiers/insert/insert_range.cc:
+ 	Likewise.
+ 	* testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc:
+ 	Run full test_ranges instead of span-only in test_constexpr.
+ 	* testsuite/23_containers/vector/modifiers/append_range.cc:
+ 	Replace test_constexpr with calls to test_ranges and test_overlapping.
+ 	* testsuite/util/testsuite_allocator.h (__gnu_test::SimpleAllocator):
+ 	Declared member functions as constexpr.
+ 
+ 2025-07-23  Luc Grosheintz  <luc.grosheintz@gmail.com>
+ 
+ 	* testsuite/23_containers/mdspan/accessors/default.cc: Delete.
+ 	* testsuite/23_containers/mdspan/accessors/generic.cc: Slightly
+ 	generalize the test code previously in default.cc.
+ 
+ 2025-07-23  Luc Grosheintz  <luc.grosheintz@gmail.com>
+ 
+ 	* testsuite/23_containers/mdspan/extents/ctor_ints.cc: Remove
+ 	superfluous parens.
+ 	* testsuite/23_containers/mdspan/extents/ctor_shape.cc: Ditto.
+ 	* testsuite/23_containers/mdspan/mdspan.cc: Ditto.
+ 
+ 2025-07-23  Tomasz Kamiński  <tkaminsk@redhat.com>
+ 
+ 	PR libstdc++/119137
+ 	* testsuite/23_containers/inplace_vector/access/elem.cc: Cover
+ 	front and back methods and const calls.
+ 	* testsuite/23_containers/inplace_vector/access/elem_neg.cc:
+ 	Likewise.
+ 	* testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc:
+ 	New test.
+ 	* testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc:
+ 	New test.
+ 
+ 2025-07-22  Tomasz Kamiński  <tkaminsk@redhat.com>
+ 
+ 	PR libstdc++/119137
+ 	* testsuite/23_containers/inplace_vector/cons/from_range.cc: Run
+ 	iterators and range test at compile-time.
+ 	* testsuite/23_containers/inplace_vector/modifiers/assign.cc:
+ 	Likewise.
+ 	* testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc:
+ 	Likewise.
+ 	* testsuite/util/testsuite_iterators.h (__gnu_test::BoundsContainer)
+ 	(__gnu_test::OutputContainer, __gnu_test::WritableObject)
+ 	(__gnu_test::output_iterator_wrapper, __gnu_test::input_iterator_wrapper)
+ 	(__gnu_test::forward_iterator_wrapper)
+ 	(__gnu_test::bidirectional_iterator_wrapper)
+ 	(__gnu_test::random_access_iterator_wrapper)
+ 	(__gnu_test::test_container): Add appropriate _GLIBCXXNN_CONSTEXPR
+ 	macros to member functions.
+ 	(__gnu_test::contiguous_iterator_wrapper)
+ 	(__gnu_test::input_iterator_wrapper_rval)
+ 	(__gnu_test::test_range, __gnu_test::test_range_nocopy)
+ 	(__gnu_test::test_sized_range_sized_sent)
+ 	(__gnu_test::test_sized_range): Add constexpr specifier to member
+ 	functions.
+ 
+ 2025-07-22  Tomasz Kamiński  <tkaminsk@redhat.com>
+ 
+ 	PR libstdc++/119137
+ 	* include/std/inplace_vector (inplace_vector::assign_range):
+ 	Replace _Nm with _M_size in the assigment loop.
+ 
+ 2025-07-21  Luc Grosheintz  <luc.grosheintz@gmail.com>
+ 
+ 	* include/std/mdspan (mdspan::mdspan): Make default ctor
+ 	conditionally noexcept.
+ 	* testsuite/23_containers/mdspan/mdspan.cc: Add tests.
+ 
+ 2025-07-21  Luc Grosheintz  <luc.grosheintz@gmail.com>
+ 
+ 	* include/std/mdspan (mdspan::is_always_unique): Make
+ 	conditionally noexcept.
+ 	(mdspan::is_always_exhaustive): Ditto.
+ 	(mdspan::is_always_strided): Ditto.
+ 	(mdspan::is_unique): Ditto.
+ 	(mdspan::is_exhaustive): Ditto.
+ 	(mdspan::is_strided): Ditto.
+ 	* testsuite/23_containers/mdspan/layout_like.h: Make noexcept
+ 	configurable. Add ThrowingLayout.
+ 	* testsuite/23_containers/mdspan/mdspan.cc: Add tests for
+ 	noexcept.
+ 
+ 2025-07-20  Jakub Jelinek  <jakub@redhat.com>
+ 
+ 	PR libstdc++/121174
+ 	* src/c++23/std.cc.in (std::dextents): Export.  Add to FIXME comments
+ 	other not yet implemented nor exported <mdspan> entities.
+ 
  2025-07-18  Jonathan Wakely  <jwakely@redhat.com>
  
  	* include/bits/stl_iterator_base_types.h (__any_input_iterator):
diff -Nrcpad gcc-16-20250720/libstdc++-v3/include/bits/unordered_map.h gcc-16-20250727/libstdc++-v3/include/bits/unordered_map.h
*** gcc-16-20250720/libstdc++-v3/include/bits/unordered_map.h	Sun Jul 20 22:32:36 2025
--- gcc-16-20250727/libstdc++-v3/include/bits/unordered_map.h	Sun Jul 27 22:32:19 2025
*************** _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*** 91,99 ****
     *
     *  @tparam  _Key    Type of key objects.
     *  @tparam  _Tp     Type of mapped objects.
!    *  @tparam  _Hash   Hashing function object type, defaults to hash<_Value>.
     *  @tparam  _Pred   Predicate function object type, defaults
!    *                   to equal_to<_Value>.
     *  @tparam  _Alloc  Allocator type, defaults to
     *                   std::allocator<std::pair<const _Key, _Tp>>.
     *
--- 91,99 ----
     *
     *  @tparam  _Key    Type of key objects.
     *  @tparam  _Tp     Type of mapped objects.
!    *  @tparam  _Hash   Hashing function object type, defaults to hash<_Key>.
     *  @tparam  _Pred   Predicate function object type, defaults
!    *                   to equal_to<_Key>.
     *  @tparam  _Alloc  Allocator type, defaults to
     *                   std::allocator<std::pair<const _Key, _Tp>>.
     *
*************** _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*** 1360,1368 ****
     *
     *  @tparam  _Key    Type of key objects.
     *  @tparam  _Tp     Type of mapped objects.
!    *  @tparam  _Hash   Hashing function object type, defaults to hash<_Value>.
     *  @tparam  _Pred   Predicate function object type, defaults
!    *                   to equal_to<_Value>.
     *  @tparam  _Alloc  Allocator type, defaults to
     *                   std::allocator<std::pair<const _Key, _Tp>>.
     *
--- 1360,1368 ----
     *
     *  @tparam  _Key    Type of key objects.
     *  @tparam  _Tp     Type of mapped objects.
!    *  @tparam  _Hash   Hashing function object type, defaults to hash<_Key>.
     *  @tparam  _Pred   Predicate function object type, defaults
!    *                   to equal_to<_Key>.
     *  @tparam  _Alloc  Allocator type, defaults to
     *                   std::allocator<std::pair<const _Key, _Tp>>.
     *
diff -Nrcpad gcc-16-20250720/libstdc++-v3/include/std/inplace_vector gcc-16-20250727/libstdc++-v3/include/std/inplace_vector
*** gcc-16-20250720/libstdc++-v3/include/std/inplace_vector	Sun Jul 20 22:32:36 2025
--- gcc-16-20250727/libstdc++-v3/include/std/inplace_vector	Sun Jul 27 22:32:19 2025
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 269,275 ****
  	      auto __in = ranges::begin(__rg);
  	      auto __end = ranges::end(__rg);
  	      size_type __n = 0;
! 	      for (; __n < _Nm && __in != __end; ++__in)
  		_M_elems[__n++] = *__in;
  
  	      if (__in == __end)
--- 269,275 ----
  	      auto __in = ranges::begin(__rg);
  	      auto __end = ranges::end(__rg);
  	      size_type __n = 0;
! 	      for (; __n < _M_size && __in != __end; ++__in)
  		_M_elems[__n++] = *__in;
  
  	      if (__in == __end)
diff -Nrcpad gcc-16-20250720/libstdc++-v3/include/std/mdspan gcc-16-20250727/libstdc++-v3/include/std/mdspan
*** gcc-16-20250720/libstdc++-v3/include/std/mdspan	Sun Jul 20 22:32:36 2025
--- gcc-16-20250727/libstdc++-v3/include/std/mdspan	Sun Jul 27 22:32:19 2025
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 1114,1124 ****
        constexpr
        mdspan()
        requires (rank_dynamic() > 0)
!           && is_default_constructible_v<data_handle_type>
  	  && is_default_constructible_v<mapping_type>
! 	  && is_default_constructible_v<accessor_type>
!       : _M_accessor(), _M_mapping(), _M_handle()
!       { }
  
        constexpr
        mdspan(const mdspan& __other) = default;
--- 1114,1122 ----
        constexpr
        mdspan()
        requires (rank_dynamic() > 0)
! 	  && is_default_constructible_v<data_handle_type>
  	  && is_default_constructible_v<mapping_type>
! 	  && is_default_constructible_v<accessor_type> = default;
  
        constexpr
        mdspan(const mdspan& __other) = default;
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 1275,1305 ****
        constexpr const accessor_type&
        accessor() const noexcept { return _M_accessor; }
  
        static constexpr bool
!       is_always_unique() { return mapping_type::is_always_unique(); }
  
        static constexpr bool
!       is_always_exhaustive() { return mapping_type::is_always_exhaustive(); }
  
        static constexpr bool
!       is_always_strided() { return mapping_type::is_always_strided(); }
  
        constexpr bool
!       is_unique() const { return _M_mapping.is_unique(); }
  
        constexpr bool
!       is_exhaustive() const { return _M_mapping.is_exhaustive(); }
  
        constexpr bool
!       is_strided() const { return _M_mapping. is_strided(); }
  
        constexpr index_type
        stride(rank_type __r) const { return _M_mapping.stride(__r); }
  
      private:
!       [[no_unique_address]] accessor_type _M_accessor;
!       [[no_unique_address]] mapping_type _M_mapping;
!       [[no_unique_address]] data_handle_type _M_handle;
      };
  
    template<typename _CArray>
--- 1273,1313 ----
        constexpr const accessor_type&
        accessor() const noexcept { return _M_accessor; }
  
+       // Strengthened noexcept for all `is_*` methods.
+ 
        static constexpr bool
!       is_always_unique() noexcept(noexcept(mapping_type::is_always_unique()))
!       { return mapping_type::is_always_unique(); }
  
        static constexpr bool
!       is_always_exhaustive()
!       noexcept(noexcept(mapping_type::is_always_exhaustive()))
!       { return mapping_type::is_always_exhaustive(); }
  
        static constexpr bool
!       is_always_strided()
!       noexcept(noexcept(mapping_type::is_always_strided()))
!       { return mapping_type::is_always_strided(); }
  
        constexpr bool
!       is_unique() const noexcept(noexcept(_M_mapping.is_unique()))
!       { return _M_mapping.is_unique(); }
  
        constexpr bool
!       is_exhaustive() const noexcept(noexcept(_M_mapping.is_exhaustive()))
!       { return _M_mapping.is_exhaustive(); }
  
        constexpr bool
!       is_strided() const noexcept(noexcept(_M_mapping.is_strided()))
!       { return _M_mapping. is_strided(); }
  
        constexpr index_type
        stride(rank_type __r) const { return _M_mapping.stride(__r); }
  
      private:
!       [[no_unique_address]] accessor_type _M_accessor = accessor_type();
!       [[no_unique_address]] mapping_type _M_mapping = mapping_type();
!       [[no_unique_address]] data_handle_type _M_handle = data_handle_type();
      };
  
    template<typename _CArray>
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc	Sun Jul 20 22:32:37 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc	Sun Jul 27 22:32:19 2025
*************** void test01()
*** 27,32 ****
--- 27,33 ----
    const any y(1);
    any_cast<int&>(y); // { dg-error "here" }
    // { dg-error "Template argument must be constructible from a const value" "" { target { *-*-* } } 0 }
+   // { dg-error "binding reference of type 'int&' to 'const int' discards qualifiers" "" { target { *-*-* } } 0 }
  }
  
  void test02()
*************** void test02()
*** 34,39 ****
--- 35,41 ----
    any y(1);
    any_cast<int&&>(y); // { dg-error "here" }
    // { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 0 }
+   // { dg-error "cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'" "" { target { *-*-* } } 0 }
  }
  
  void test03()
*************** void test03()
*** 41,46 ****
--- 43,49 ----
    any y(1);
    any_cast<int&>(std::move(y)); // { dg-error "here" }
    // { dg-error "Template argument must be constructible from an rvalue" "" { target { *-*-* } } 0 }
+   // { dg-error "cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'" "" { target { *-*-* } } 0 }
  }
  
  // { dg-prune-output "invalid 'static_cast'" }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc	Sun Jul 20 22:32:37 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/20_util/expected/illformed_neg.cc	Sun Jul 27 22:32:19 2025
*************** test_unexpected()
*** 13,18 ****
--- 13,19 ----
    std::unexpected<void()> func(test_unexpected); // { dg-error "here" }
    // { dg-error "no matching function for call to" "" { target *-*-* } 0 }
    // { dg-error "invalidly declared function type" "" { target *-*-* } 0 }
+   // { dg-error "could not convert" "" { target *-*-* } 0 }
  
    // an array type,
    std::unexpected<int[2]> array(i); // { dg-error "here" }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc	Sun Jul 20 22:32:40 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/20_util/optional/monadic/or_else_neg.cc	Sun Jul 27 22:32:19 2025
*************** test02()
*** 26,29 ****
--- 26,30 ----
  
    std::optional<move_only> mo;
    mo.or_else([]{ return std::optional<move_only>{}; }); // { dg-error "no matching function" }
+   // { dg-error "use of deleted function" "" { target *-*-* } 0 }
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc	Sun Jul 20 22:32:40 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test(Alloc alloc)
*** 73,88 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range>(std::allocator<char>());
-   do_test<Range>(__gnu_test::uneq_allocator<char>(42));
    do_test<Range>(std::allocator<wchar_t>());
!   do_test<Range>(__gnu_test::uneq_allocator<wchar_t>(42));
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 73,91 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range>(std::allocator<char>());
    do_test<Range>(std::allocator<wchar_t>());
! 
!   if not consteval {
!     do_test<Range>(__gnu_test::uneq_allocator<char>(42));
!     do_test<Range>(__gnu_test::uneq_allocator<wchar_t>(42));
!   }
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 101,109 ****
  
    // Not lvalue-convertible to char
    struct C {
!     C(char v) : val(v) { }
!     operator char() && { return val; }
!     bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 104,112 ----
  
    // Not lvalue-convertible to char
    struct C {
!     constexpr C(char v) : val(v) { }
!     constexpr operator char() && { return val; }
!     constexpr bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 112,129 ****
    return true;
  }
  
- constexpr bool
- test_constexpr()
- {
- #if _GLIBCXX_USE_CXX11_ABI
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::string_view>(std::allocator<char>());
- #endif // _GLIBCXX_USE_CXX11_ABI
-   return true;
- }
- 
  int main()
  {
    test_ranges();
!   static_assert( test_constexpr() );
  }
--- 115,124 ----
    return true;
  }
  
  int main()
  {
    test_ranges();
! #if _GLIBCXX_USE_CXX11_ABI
!   static_assert( test_ranges() );
! #endif // _GLIBCXX_USE_CXX11_ABI
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc	Sun Jul 20 22:32:40 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 49,55 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<char>>();
--- 49,55 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<char>>();
*************** do_test_a()
*** 58,64 ****
    do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 58,64 ----
    do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 77,85 ****
  
    // Not lvalue-convertible to char
    struct C {
!     C(char v) : val(v) { }
!     operator char() && { return val; }
!     bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 77,85 ----
  
    // Not lvalue-convertible to char
    struct C {
!     constexpr C(char v) : val(v) { }
!     constexpr operator char() && { return val; }
!     constexpr bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_overlapping()
*** 107,125 ****
    VERIFY( c == "1234abcd1234" );
  }
  
- constexpr bool
- test_constexpr()
- {
- #if _GLIBCXX_USE_CXX11_ABI
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::string_view, std::allocator<char>>();
- #endif // _GLIBCXX_USE_CXX11_ABI
-   return true;
- }
- 
  int main()
  {
    test_ranges();
    test_overlapping();
!   static_assert( test_constexpr() );
  }
--- 107,117 ----
    VERIFY( c == "1234abcd1234" );
  }
  
  int main()
  {
    test_ranges();
    test_overlapping();
! #if _GLIBCXX_USE_CXX11_ABI
!   static_assert( test_ranges() );
! #endif // _GLIBCXX_USE_CXX11_ABI
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc	Sun Jul 20 22:32:40 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 41,47 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<char>>();
--- 41,47 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<char>>();
*************** do_test_a()
*** 50,56 ****
    do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 50,56 ----
    do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 69,77 ****
  
    // Not lvalue-convertible to char
    struct C {
!     C(char v) : val(v) { }
!     operator char() && { return val; }
!     bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 69,77 ----
  
    // Not lvalue-convertible to char
    struct C {
!     constexpr C(char v) : val(v) { }
!     constexpr operator char() && { return val; }
!     constexpr bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_overlapping()
*** 98,116 ****
    VERIFY( c == "1234" );
  }
  
- constexpr bool
- test_constexpr()
- {
- #if _GLIBCXX_USE_CXX11_ABI
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::string_view, std::allocator<char>>();
- #endif // _GLIBCXX_USE_CXX11_ABI
-   return true;
- }
- 
  int main()
  {
    test_ranges();
    test_overlapping();
!   static_assert( test_constexpr() );
  }
--- 98,108 ----
    VERIFY( c == "1234" );
  }
  
  int main()
  {
    test_ranges();
    test_overlapping();
! #if _GLIBCXX_USE_CXX11_ABI
!   static_assert( test_ranges() );
! #endif // _GLIBCXX_USE_CXX11_ABI
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc	Sun Jul 20 22:32:40 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 54,60 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<char>>();
--- 54,60 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<char>>();
*************** do_test_a()
*** 63,69 ****
    do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 63,69 ----
    do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 82,90 ****
  
    // Not lvalue-convertible to char
    struct C {
!     C(char v) : val(v) { }
!     operator char() && { return val; }
!     bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 82,90 ----
  
    // Not lvalue-convertible to char
    struct C {
!     constexpr C(char v) : val(v) { }
!     constexpr operator char() && { return val; }
!     constexpr bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_overlapping()
*** 112,130 ****
    VERIFY( c == "12123434abcd" );
  }
  
- constexpr bool
- test_constexpr()
- {
- #if _GLIBCXX_USE_CXX11_ABI
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::string_view, std::allocator<char>>();
- #endif // _GLIBCXX_USE_CXX11_ABI
-   return true;
- }
- 
  int main()
  {
    test_ranges();
    test_overlapping();
!   static_assert( test_constexpr() );
  }
--- 112,122 ----
    VERIFY( c == "12123434abcd" );
  }
  
  int main()
  {
    test_ranges();
    test_overlapping();
! #if _GLIBCXX_USE_CXX11_ABI
!   static_assert( test_ranges() );
! #endif // _GLIBCXX_USE_CXX11_ABI
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc	Sun Jul 20 22:32:40 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 54,60 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<char>>();
--- 54,60 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<char>>();
*************** do_test_a()
*** 63,69 ****
    do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 63,69 ----
    do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 82,90 ****
  
    // Not lvalue-convertible to char
    struct C {
!     C(char v) : val(v) { }
!     operator char() && { return val; }
!     bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 82,90 ----
  
    // Not lvalue-convertible to char
    struct C {
!     constexpr C(char v) : val(v) { }
!     constexpr operator char() && { return val; }
!     constexpr bool operator==(char b) const { return b == val; }
      char val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_overlapping()
*** 115,133 ****
    VERIFY( c == "12123434abcd" );
  }
  
- constexpr bool
- test_constexpr()
- {
- #if _GLIBCXX_USE_CXX11_ABI
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::string_view, std::allocator<char>>();
- #endif // _GLIBCXX_USE_CXX11_ABI
-   return true;
- }
- 
  int main()
  {
    test_ranges();
    test_overlapping();
!   static_assert( test_constexpr() );
  }
--- 115,125 ----
    VERIFY( c == "12123434abcd" );
  }
  
  int main()
  {
    test_ranges();
    test_overlapping();
! #if _GLIBCXX_USE_CXX11_ABI
!   static_assert( test_ranges() );
! #endif // _GLIBCXX_USE_CXX11_ABI
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/array/creation/3_neg.cc	Sun Jul 27 22:32:19 2025
*************** test03()
*** 54,56 ****
--- 54,58 ----
  }
  
  // { dg-prune-output "static assertion failed" }
+ // { dg-prune-output "use of deleted function" }
+ // { dg-prune-output "could not convert" }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc	Sun Jul 27 22:32:19 2025
*************** test_out_of_capacity()
*** 41,62 ****
  #endif
  }
  
! template<typename T>
  constexpr void
  test_access()
  {
!   std::inplace_vector<T, 10> v{1, 2, 3, 4, 5};
  
    auto& e3a = v[2];
!   auto& e3b = std::as_const(v).at(2);
    VERIFY( &e3a == &e3b );
    VERIFY( &e3a == &v.begin()[2] );
!   VERIFY( &e3a == std::as_const(v).data() + 2 );
    VERIFY( e3a == T(3) );
  
!   auto& e4a = as_const(v)[4];
    auto& e4b = v.at(4);
    VERIFY( &e4a == &e4b );
    VERIFY( &e4a == &v.cbegin()[4] );
    VERIFY( &e4a == v.data() + 4 );
    VERIFY( e4a == T(5) );
--- 41,82 ----
  #endif
  }
  
! 
! template<bool Const, typename T, size_t N>
! using InplaceVector = std::conditional_t<Const, 
! 					 const std::inplace_vector<T, N>,
! 					 std::inplace_vector<T, N>>;
! 
! template<bool Const, typename T>
  constexpr void
  test_access()
  {
!   InplaceVector<Const, T, 10> v{1, 2, 3, 4, 5};
! 
!   auto& e0a = v[0];
!   auto& e0b = v.at(0);
!   auto& e0c = v.front();
!   VERIFY( &e0a == &e0b );
!   VERIFY( &e0a == &e0c );
!   VERIFY( &e0a == &v.begin()[0] );
!   VERIFY( &e0a == &v.cbegin()[0] );
!   VERIFY( &e0a == v.data() );
!   VERIFY( e0a == T(1) );
  
    auto& e3a = v[2];
!   auto& e3b = v.at(2);
    VERIFY( &e3a == &e3b );
    VERIFY( &e3a == &v.begin()[2] );
!   VERIFY( &e3a == &v.cbegin()[2] );
!   VERIFY( &e3a == v.data() + 2 );
    VERIFY( e3a == T(3) );
  
!   auto& e4a = v[4];
    auto& e4b = v.at(4);
+   auto& e4c = v.back();
    VERIFY( &e4a == &e4b );
+   VERIFY( &e4a == &e4c );
+   VERIFY( &e4a == &v.begin()[4] );
    VERIFY( &e4a == &v.cbegin()[4] );
    VERIFY( &e4a == v.data() + 4 );
    VERIFY( e4a == T(5) );
*************** test_access()
*** 77,91 ****
    catch (std::out_of_range const&)
    {
    }
- 
-   try
-   {
-     (void)as_const(v).at(7);
-     VERIFY(false);
-   }
-   catch (std::out_of_range const&)
-   {
-   }
  #endif
  }
  
--- 97,102 ----
*************** int main()
*** 94,100 ****
    auto test_all = [] {
      test_out_of_capacity<0, int>();
      test_out_of_capacity<4, int>();
!     test_access<int>();
      return true;
    };
  
--- 105,112 ----
    auto test_all = [] {
      test_out_of_capacity<0, int>();
      test_out_of_capacity<4, int>();
!     test_access<true, int>();
!     test_access<false, int>();
      return true;
    };
  
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc	Sun Jul 27 22:32:19 2025
***************
*** 2,28 ****
  
  #include <inplace_vector>
  
! template<size_t N, typename T>
  constexpr bool
  test_out_of_capacity()
  {
!   std::inplace_vector<T, N> v;
    (void)v[N+2]; // { dg-error "in 'constexpr' expansion of" }
    return true;
  }
  
! template<typename T>
  constexpr bool
  test_out_of_size()
  {
!   std::inplace_vector<T, 10> v{1, 2, 3, 4, 5};
    (void)v[7]; // { dg-error "in 'constexpr' expansion of" }
    return true;
  }
  
! static_assert(test_out_of_capacity<0, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_out_of_capacity<4, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_out_of_size<int>());        // { dg-error "in 'constexpr' expansion of" }
  
  // { dg-prune-output "non-constant condition for static assertion" }
  // { dg-prune-output "is not a constant expression" }
--- 2,64 ----
  
  #include <inplace_vector>
  
! template<bool Const, typename T, size_t N>
! using InplaceVector 
!   = std::conditional_t<Const, 
! 		       const std::inplace_vector<T, N>,
! 		       std::inplace_vector<T, N>>;
! 
! template<bool Const, size_t N, typename T>
! constexpr bool
! test_front_on_empty()
! {
!   InplaceVector<Const, T, N> v;
!   (void)v.front(); // { dg-error "in 'constexpr' expansion of" }
!   return true;
! }
! 
! template<bool Const, size_t N, typename T>
! constexpr bool
! test_back_on_empty()
! {
!   InplaceVector<Const, T, N> v;
!   (void)v.back(); // { dg-error "in 'constexpr' expansion of" }
!   return true;
! }
! 
! template<bool Const, size_t N, typename T>
  constexpr bool
  test_out_of_capacity()
  {
!   InplaceVector<Const, T, N> v;
    (void)v[N+2]; // { dg-error "in 'constexpr' expansion of" }
    return true;
  }
  
! template<bool Const, typename T>
  constexpr bool
  test_out_of_size()
  {
!   InplaceVector<Const, T, 10> v{1, 2, 3, 4, 5};
    (void)v[7]; // { dg-error "in 'constexpr' expansion of" }
    return true;
  }
  
! static_assert(test_front_on_empty<false, 0, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_front_on_empty<false, 4, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_back_on_empty<false, 0, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_back_on_empty<false, 4, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_out_of_capacity<false, 0, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_out_of_capacity<false, 4, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_out_of_size<false, int>());        // { dg-error "in 'constexpr' expansion of" }
! 
! static_assert(test_front_on_empty<true, 0, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_front_on_empty<true, 4, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_back_on_empty<true, 0, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_back_on_empty<true, 4, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_out_of_capacity<true, 0, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_out_of_capacity<true, 4, int>()); // { dg-error "in 'constexpr' expansion of" }
! static_assert(test_out_of_size<true, int>());        // { dg-error "in 'constexpr' expansion of" }
  
  // { dg-prune-output "non-constant condition for static assertion" }
  // { dg-prune-output "is not a constant expression" }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test_it()
*** 70,76 ****
  #endif
  }
  
! bool
  test_iterators()
  {
    using namespace __gnu_test;
--- 70,76 ----
  #endif
  }
  
! constexpr bool
  test_iterators()
  {
    using namespace __gnu_test;
*************** do_test_r()
*** 131,137 ****
  #endif
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 131,137 ----
  #endif
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 152,160 ****
  
    // Not lvalue-convertible to int
    struct C {
!     C(int v) : val(v) { }
!     operator int() && { return val; }
!     bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 152,160 ----
  
    // Not lvalue-convertible to int
    struct C {
!     constexpr C(int v) : val(v) { }
!     constexpr operator int() && { return val; }
!     constexpr bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 163,184 ****
    return true;
  }
  
- constexpr bool
- test_constexpr()
- {
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   std::initializer_list<int> il{1, 2, 3, 4};
-   std::inplace_vector<int, 6> v(il.begin(), il.end());
-   eq<int>(v, il);
- 
-   do_test_r<std::span<short>>();
-   return true;
- }
- 
  int main()
  {
!   test_iterators();
!   test_ranges();
!   static_assert( test_constexpr() );
  }
  
--- 163,177 ----
    return true;
  }
  
  int main()
  {
!   auto test_all = [] {
!     test_iterators();
!     test_ranges();
!     return true;
!   };
! 
!   test_all();
!   static_assert( test_all() );
  }
  
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc	Sun Jul 27 22:32:19 2025
*************** template<size_t N, typename T>
*** 204,217 ****
  constexpr void
  test_assign_empty()
  {
!   // TODO make test iterators consteval
!   if !consteval
!   {
!     using namespace __gnu_test;
!     test_assign_empty_it<N, T, input_iterator_wrapper>();
!     test_assign_empty_it<N, T, forward_iterator_wrapper>();
!     test_assign_empty_it<N, T, random_access_iterator_wrapper>();
!   }
  
    test_assign_empty_other<N, T>;
  }
--- 204,213 ----
  constexpr void
  test_assign_empty()
  {
!   using namespace __gnu_test;
!   test_assign_empty_it<N, T, input_iterator_wrapper>();
!   test_assign_empty_it<N, T, forward_iterator_wrapper>();
!   test_assign_empty_it<N, T, random_access_iterator_wrapper>();
  
    test_assign_empty_other<N, T>;
  }
*************** constexpr void
*** 339,361 ****
  test_assigns()
  {
    using namespace __gnu_test;
!   // TODO make test iterators consteval
!   if !consteval {
!     test_assign_range<test_forward_range<int>>();
!     test_assign_range<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
  
!     test_assign_range<test_input_range<int>>();
!     test_assign_range<test_input_sized_range<int>>();
!     test_assign_range<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
  
!     test_assign_range<test_range<int, input_iterator_wrapper_nocopy>>();
!     test_assign_range<test_sized_range<int, input_iterator_wrapper_nocopy>>();
!     test_assign_range<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
  
!     test_assign_iterators<T, input_iterator_wrapper>();
!     test_assign_iterators<T, forward_iterator_wrapper>();
!     test_assign_iterators<T, random_access_iterator_wrapper>();
!   }
  
    test_assign_initializer_list<T>();
    test_assign_repeated<T>();
--- 335,354 ----
  test_assigns()
  {
    using namespace __gnu_test;
!   test_assign_range<test_forward_range<int>>();
!   test_assign_range<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
  
!   test_assign_range<test_input_range<int>>();
!   test_assign_range<test_input_sized_range<int>>();
!   test_assign_range<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
  
!   test_assign_range<test_range<int, input_iterator_wrapper_nocopy>>();
!   test_assign_range<test_sized_range<int, input_iterator_wrapper_nocopy>>();
!   test_assign_range<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
  
!   test_assign_iterators<T, input_iterator_wrapper>();
!   test_assign_iterators<T, forward_iterator_wrapper>();
!   test_assign_iterators<T, random_access_iterator_wrapper>();
  
    test_assign_initializer_list<T>();
    test_assign_repeated<T>();
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc	Sun Jul 27 22:32:19 2025
***************
*** 0 ****
--- 1,43 ----
+ // { dg-do compile { target c++26 } }
+ 
+ #include <inplace_vector>
+ 
+ template<size_t N, typename T>
+ constexpr bool
+ test_pop_back_on_empty()
+ {
+   std::inplace_vector<T, N> v;
+   v.pop_back(); // { dg-error "in 'constexpr' expansion of" }
+   return true;
+ }
+ 
+ template<size_t N, typename T>
+ constexpr bool
+ test_erase_begin_on_empty()
+ {
+   std::inplace_vector<T, N> v;
+   v.erase(v.begin()); // { dg-error "in 'constexpr' expansion of" }
+   return true;
+ }
+ 
+ template<size_t N, typename T>
+ constexpr bool
+ test_erase_end(size_t size = 0)
+ {
+   std::inplace_vector<T, N> v(size, T());
+   v.erase(v.end()); // { dg-error "in 'constexpr' expansion of" }
+   return true;
+ }
+ 
+ static_assert(test_pop_back_on_empty<0, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_pop_back_on_empty<4, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_erase_begin_on_empty<0, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_erase_begin_on_empty<4, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_erase_end<0, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_erase_end<4, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_erase_end<4, int>(2)); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_erase_end<4, int>(4)); // { dg-error "in 'constexpr' expansion of" }
+ 
+ // { dg-prune-output "non-constant condition for static assertion" }
+ // { dg-prune-output "is not a constant expression" }
+ // { dg-prune-output "call to non-'constexpr' function" }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc	Sun Jul 27 22:32:19 2025
*************** constexpr void
*** 227,238 ****
  test_add_to_full()
  {
    using namespace __gnu_test;
!   // TODO make test iterators consteval
!   if !consteval {
!     test_add_to_full_it<N, T, input_iterator_wrapper>();
!     test_add_to_full_it<N, T, forward_iterator_wrapper>();
!     test_add_to_full_it<N, T, random_access_iterator_wrapper>();
!   }
    test_add_to_full_other<N, T>();
  }
  
--- 227,236 ----
  test_add_to_full()
  {
    using namespace __gnu_test;
!   test_add_to_full_it<N, T, input_iterator_wrapper>();
!   test_add_to_full_it<N, T, forward_iterator_wrapper>();
!   test_add_to_full_it<N, T, random_access_iterator_wrapper>();
! 
    test_add_to_full_other<N, T>();
  }
  
*************** constexpr void
*** 566,599 ****
  test_inserts()
  {
    using namespace __gnu_test;
!   // TODO make test iterators consteval
!   if !consteval {
!     do_test_ranges<test_forward_range<int>>();
!     do_test_ranges<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
  
!     do_test_ranges<test_input_range<int>>();
!     do_test_ranges<test_input_sized_range<int>>();
!     do_test_ranges<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
  
!     do_test_ranges<test_range<int, input_iterator_wrapper_nocopy>>();
!     do_test_ranges<test_sized_range<int, input_iterator_wrapper_nocopy>>();
!     do_test_ranges<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
  
!     test_insert_iterators<T, input_iterator_wrapper>();
!     test_insert_iterators<T, forward_iterator_wrapper>();
!     test_insert_iterators<T, random_access_iterator_wrapper>();
!   }
  
!   test_insert_initializer_list<T>();
!   test_insert_repeated<T>();
  }
  
  int main()
  {
!   auto test_all = []{
!     test_add_to_full<0, int>();
!     test_add_to_full<0, X>();
!     test_add_to_full<4, int>();
  
      test_inserts<int>();
  #ifdef __cpp_lib_constexpr_inplace_vector
--- 564,594 ----
  test_inserts()
  {
    using namespace __gnu_test;
!   do_test_ranges<test_forward_range<int>>();
!   do_test_ranges<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
  
!   do_test_ranges<test_input_range<int>>();
!   do_test_ranges<test_input_sized_range<int>>();
!   do_test_ranges<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
  
!   do_test_ranges<test_range<int, input_iterator_wrapper_nocopy>>();
!   do_test_ranges<test_sized_range<int, input_iterator_wrapper_nocopy>>();
!   do_test_ranges<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>();
  
!   test_insert_iterators<T, input_iterator_wrapper>();
!   test_insert_iterators<T, forward_iterator_wrapper>();
!   test_insert_iterators<T, random_access_iterator_wrapper>();
  
! test_insert_initializer_list<T>();
! test_insert_repeated<T>();
  }
  
  int main()
  {
! auto test_all = []{
!   test_add_to_full<0, int>();
!   test_add_to_full<0, X>();
!   test_add_to_full<4, int>();
  
      test_inserts<int>();
  #ifdef __cpp_lib_constexpr_inplace_vector
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc	Sun Jul 27 22:32:19 2025
***************
*** 0 ****
--- 1,42 ----
+ // { dg-do compile { target c++26 } }
+ 
+ #include <inplace_vector>
+ 
+ template<size_t N, typename T>
+ constexpr bool
+ test_unchecked_emplace_back()
+ {
+   std::inplace_vector<T, N> v(N, T(1));
+   v.unchecked_emplace_back(); // { dg-error "in 'constexpr' expansion of" }
+   return true;
+ }
+ 
+ template<size_t N, typename T>
+ constexpr bool
+ test_push_back_lvalue()
+ {
+   auto val = T();;
+   std::inplace_vector<T, N> v(N, T(1));
+   v.unchecked_push_back(val); // { dg-error "in 'constexpr' expansion of" }
+   return true;
+ }
+ 
+ template<size_t N, typename T>
+ constexpr bool
+ test_push_back_rvalue()
+ {
+   std::inplace_vector<T, N> v(N, T(1));
+   v.unchecked_push_back(T()); // { dg-error "in 'constexpr' expansion of" }
+   return true;
+ }
+ 
+ static_assert(test_unchecked_emplace_back<0, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_unchecked_emplace_back<4, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_push_back_lvalue<0, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_push_back_lvalue<4, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_push_back_rvalue<0, int>()); // { dg-error "in 'constexpr' expansion of" }
+ static_assert(test_push_back_rvalue<4, int>()); // { dg-error "in 'constexpr' expansion of" }
+ 
+ // { dg-prune-output "non-constant condition for static assertion" }
+ // { dg-prune-output "is not a constant expression" }
+ // { dg-prune-output "call to non-'constexpr' function" }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc	Thu Jan  1 00:00:00 1970
***************
*** 1,99 ****
- // { dg-do run { target c++23 } }
- #include <mdspan>
- 
- #include <testsuite_hooks.h>
- 
- constexpr size_t dyn = std::dynamic_extent;
- 
- template<typename Accessor>
-   constexpr void
-   test_accessor_policy()
-   {
-     static_assert(std::copyable<Accessor>);
-     static_assert(std::is_nothrow_move_constructible_v<Accessor>);
-     static_assert(std::is_nothrow_move_assignable_v<Accessor>);
-     static_assert(std::is_nothrow_swappable_v<Accessor>);
-   }
- 
- constexpr bool
- test_access()
- {
-   std::default_accessor<double> accessor;
-   std::array<double, 5> a{10, 11, 12, 13, 14};
-   VERIFY(accessor.access(a.data(), 0) == 10);
-   VERIFY(accessor.access(a.data(), 4) == 14);
-   return true;
- }
- 
- constexpr bool
- test_offset()
- {
-   std::default_accessor<double> accessor;
-   std::array<double, 5> a{10, 11, 12, 13, 14};
-   VERIFY(accessor.offset(a.data(), 0) == a.data());
-   VERIFY(accessor.offset(a.data(), 4) == a.data() + 4);
-   return true;
- }
- 
- class Base
- { };
- 
- class Derived : public Base
- { };
- 
- constexpr void
- test_ctor()
- {
-   // T -> T
-   static_assert(std::is_nothrow_constructible_v<std::default_accessor<double>,
- 						std::default_accessor<double>>);
-   static_assert(std::is_convertible_v<std::default_accessor<double>,
- 				      std::default_accessor<double>>);
- 
-   // T -> const T
-   static_assert(std::is_convertible_v<std::default_accessor<double>,
- 				      std::default_accessor<const double>>);
-   static_assert(std::is_convertible_v<std::default_accessor<Derived>,
- 				      std::default_accessor<const Derived>>);
- 
-   // const T -> T
-   static_assert(!std::is_constructible_v<std::default_accessor<double>,
- 					 std::default_accessor<const double>>);
-   static_assert(!std::is_constructible_v<std::default_accessor<Derived>,
- 					 std::default_accessor<const Derived>>);
- 
-   // T <-> volatile T
-   static_assert(std::is_convertible_v<std::default_accessor<int>,
- 				      std::default_accessor<volatile int>>);
-   static_assert(!std::is_constructible_v<std::default_accessor<int>,
- 					 std::default_accessor<volatile int>>);
- 
-   // size difference
-   static_assert(!std::is_constructible_v<std::default_accessor<char>,
- 					 std::default_accessor<int>>);
- 
-   // signedness
-   static_assert(!std::is_constructible_v<std::default_accessor<int>,
- 					 std::default_accessor<unsigned int>>);
-   static_assert(!std::is_constructible_v<std::default_accessor<unsigned int>,
- 					 std::default_accessor<int>>);
- 
-   // Derived <-> Base
-   static_assert(!std::is_constructible_v<std::default_accessor<Base>,
- 					 std::default_accessor<Derived>>);
-   static_assert(!std::is_constructible_v<std::default_accessor<Derived>,
- 					 std::default_accessor<Base>>);
- 
- }
- 
- int
- main()
- {
-   test_accessor_policy<std::default_accessor<double>>();
-   test_access();
-   static_assert(test_access());
-   test_offset();
-   static_assert(test_offset());
-   test_ctor();
-   return 0;
- }
--- 0 ----
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc	Thu Jan  1 00:00:00 1970
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc	Sun Jul 27 22:32:19 2025
***************
*** 0 ****
--- 1,125 ----
+ // { dg-do run { target c++23 } }
+ #include <mdspan>
+ 
+ #include <testsuite_hooks.h>
+ 
+ template<typename Accessor>
+   constexpr bool
+   test_class_properties()
+   {
+     static_assert(std::is_trivially_copyable_v<Accessor>);
+     static_assert(std::semiregular<Accessor>);
+     return true;
+   }
+ 
+ template<typename Accessor>
+   constexpr bool
+   test_accessor_policy()
+   {
+     static_assert(std::copyable<Accessor>);
+     static_assert(std::is_nothrow_move_constructible_v<Accessor>);
+     static_assert(std::is_nothrow_move_assignable_v<Accessor>);
+     static_assert(std::is_nothrow_swappable_v<Accessor>);
+     return true;
+   }
+ 
+ class Base
+ { };
+ 
+ class Derived : public Base
+ { };
+ 
+ template<template<typename T> typename Accessor>
+   constexpr bool
+   test_ctor()
+   {
+     // T -> T
+     static_assert(std::is_nothrow_constructible_v<Accessor<double>,
+ 						  Accessor<double>>);
+     static_assert(std::is_convertible_v<Accessor<double>, Accessor<double>>);
+ 
+     // T -> const T
+     static_assert(std::is_convertible_v<Accessor<double>,
+ 					Accessor<const double>>);
+     static_assert(std::is_convertible_v<Accessor<Derived>,
+ 					Accessor<const Derived>>);
+ 
+     // const T -> T
+     static_assert(!std::is_constructible_v<Accessor<double>,
+ 					   Accessor<const double>>);
+     static_assert(!std::is_constructible_v<Accessor<Derived>,
+ 					   Accessor<const Derived>>);
+ 
+     // T <-> volatile T
+     static_assert(std::is_convertible_v<Accessor<int>, Accessor<volatile int>>);
+     static_assert(!std::is_constructible_v<Accessor<int>,
+ 					   Accessor<volatile int>>);
+ 
+     // size difference
+     static_assert(!std::is_constructible_v<Accessor<char>, Accessor<int>>);
+ 
+     // signedness
+     static_assert(!std::is_constructible_v<Accessor<int>,
+ 					   Accessor<unsigned int>>);
+     static_assert(!std::is_constructible_v<Accessor<unsigned int>,
+ 					   Accessor<int>>);
+ 
+     // Derived <-> Base
+     static_assert(!std::is_constructible_v<Accessor<Base>, Accessor<Derived>>);
+     static_assert(!std::is_constructible_v<Accessor<Derived>, Accessor<Base>>);
+     return true;
+   }
+ 
+ template<template<typename T> typename Accessor>
+   constexpr bool
+   test_properties()
+   {
+     test_class_properties<Accessor<double>>();
+     test_accessor_policy<Accessor<double>>();
+     test_ctor<Accessor>();
+     return true;
+   }
+ 
+ static_assert(test_properties<std::default_accessor>());
+ 
+ template<typename A>
+   constexpr size_t
+   accessor_alignment = alignof(typename A::element_type);
+ 
+ template<typename Accessor>
+   constexpr void
+   test_access(Accessor accessor)
+   {
+     constexpr size_t N = accessor_alignment<Accessor>;
+     alignas(N) std::array<double, 5> a{10, 11, 12, 13, 14};
+     for (size_t i = 0; i < a.size(); ++i)
+       VERIFY(accessor.access(a.data(), i) == 10 + i);
+   }
+ 
+ template<typename Accessor>
+   constexpr void
+   test_offset(Accessor accessor)
+   {
+     constexpr size_t N = accessor_alignment<Accessor>;
+     alignas(N) std::array<double, 5> a{10, 11, 12, 13, 14};
+     for (size_t i = 0; i < a.size(); ++i)
+       VERIFY(accessor.offset(a.data(), i) == a.data() + i);
+   }
+ 
+ template<typename Accessor>
+   constexpr bool
+   test_all()
+   {
+     auto accessor = Accessor{};
+     test_offset(accessor);
+     test_access(accessor);
+     return true;
+   }
+ 
+ int
+ main()
+ {
+   test_all<std::default_accessor<double>>();
+   static_assert(test_all<std::default_accessor<double>>());
+   return 0;
+ }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc	Sun Jul 27 22:32:19 2025
*************** test_all()
*** 35,54 ****
    auto expected = std::extents<int, 1, 2, 3>(1, 2, 3);
  
    // From all extents.
!   VERIFY((std::extents<int, 1, 2, 3>(1, 2, 3)) == expected);
!   VERIFY((std::extents<int, dyn, 2, 3>(1, 2, 3)) == expected);
!   VERIFY((std::extents<int, dyn, 2, dyn>(1, 2, 3)) == expected);
  
!   VERIFY((std::extents<int, 1, 2, 3>{1, 2, 3}) == expected);
!   VERIFY((std::extents<int, dyn, 2, 3>{1, 2, 3}) == expected);
!   VERIFY((std::extents<int, dyn, 2, dyn>{1, 2, 3}) == expected);
  
    // From only dynamic extents.
!   VERIFY((std::extents<int, dyn, 2, 3>(1)) == expected);
!   VERIFY((std::extents<int, dyn, 2, dyn>(1, 3)) == expected);
  
!   VERIFY((std::extents<int, dyn, 2, 3>{1}) == expected);
!   VERIFY((std::extents<int, dyn, 2, dyn>{1, 3}) == expected);
  
    return true;
  }
--- 35,54 ----
    auto expected = std::extents<int, 1, 2, 3>(1, 2, 3);
  
    // From all extents.
!   VERIFY(std::extents<int, 1, 2, 3>(1, 2, 3) == expected);
!   VERIFY(std::extents<int, dyn, 2, 3>(1, 2, 3) == expected);
!   VERIFY(std::extents<int, dyn, 2, dyn>(1, 2, 3) == expected);
  
!   VERIFY(std::extents<int, 1, 2, 3>{1, 2, 3} == expected);
!   VERIFY(std::extents<int, dyn, 2, 3>{1, 2, 3} == expected);
!   VERIFY(std::extents<int, dyn, 2, dyn>{1, 2, 3} == expected);
  
    // From only dynamic extents.
!   VERIFY(std::extents<int, dyn, 2, 3>(1) == expected);
!   VERIFY(std::extents<int, dyn, 2, dyn>(1, 3) == expected);
  
!   VERIFY(std::extents<int, dyn, 2, 3>{1} == expected);
!   VERIFY(std::extents<int, dyn, 2, dyn>{1, 3} == expected);
  
    return true;
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc	Sun Jul 27 22:32:19 2025
*************** namespace all_extents
*** 66,74 ****
      test_ctor(Shape shape)
      {
        auto expected = std::extents<int, 1, 2, 3>();
!       VERIFY((std::extents<int, 1, dyn, 3>(shape)) == expected);
!       VERIFY((std::extents<int, dyn, dyn, dyn>(shape)) == expected);
!       VERIFY((std::extents<int, 1, 2, 3>(shape)) == expected);
      }
  
    constexpr void
--- 66,74 ----
      test_ctor(Shape shape)
      {
        auto expected = std::extents<int, 1, 2, 3>();
!       VERIFY(std::extents<int, 1, dyn, 3>(shape) == expected);
!       VERIFY(std::extents<int, dyn, dyn, dyn>(shape) == expected);
!       VERIFY(std::extents<int, 1, 2, 3>(shape) == expected);
      }
  
    constexpr void
*************** namespace all_extents
*** 90,97 ****
      auto span = std::span<int, 0>(shape);
  
      auto expected = std::extents<int>();
!     VERIFY((std::extents<int>(shape)) == expected);
!     VERIFY((std::extents<int>(span)) == expected);
    }
  
    constexpr bool
--- 90,97 ----
      auto span = std::span<int, 0>(shape);
  
      auto expected = std::extents<int>();
!     VERIFY(std::extents<int>(shape) == expected);
!     VERIFY(std::extents<int>(span) == expected);
    }
  
    constexpr bool
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h	Sun Jul 27 22:32:19 2025
***************
*** 1,83 ****
  #ifndef TEST_MDSPAN_LAYOUT_LIKE_H
  #define TEST_MDSPAN_LAYOUT_LIKE_H 1
  
! struct LayoutLike
! {
!   template<typename Extents>
!     class mapping
!     {
!     public:
!       using extents_type = Extents;
!       using index_type = typename extents_type::index_type;
!       using size_type = typename extents_type::size_type;
!       using rank_type = typename extents_type::rank_type;
!       using layout_type = LayoutLike;
! 
!       constexpr
!       mapping() noexcept = default;
  
!       constexpr
!       mapping(Extents exts)
!       : m_exts(exts)
!       { }
  
!       constexpr const extents_type&
!       extents() const noexcept { return m_exts; }
  
!       constexpr index_type
!       required_span_size() const noexcept
!       {
! 	for (size_t i = 0; i < extents_type::rank(); ++i)
! 	  if (m_exts.extent(i) == 0)
! 	    return 0;
! 	return 1;
!       }
  
-       template<typename... Indices>
- 	requires (sizeof...(Indices) == extents_type::rank())
  	constexpr index_type
! 	operator()(Indices...) const noexcept
  	{ return 0; }
  
!       static constexpr index_type
!       stride(rank_type) noexcept
!       { return 0; }
  
!       static constexpr bool
!       is_always_unique() noexcept
!       { return false; }
  
!       static constexpr bool
!       is_always_exhaustive() noexcept
!       { return true; }
  
!       static constexpr bool
!       is_always_strided() noexcept
!       { return true; }
  
!       constexpr bool
!       is_unique() noexcept
!       {
! 	if (required_span_size() == 0)
  	  return true;
  
! 	for (size_t i = 0; i < extents_type::rank(); ++i)
! 	  if (m_exts.extent(i) > 1)
! 	    return false;
! 	return true;
!       }
  
!       static constexpr bool
!       is_exhaustive() noexcept
!       { return true; }
  
!       static constexpr bool
!       is_strided() noexcept
!       { return true; }
  
!     private:
!       Extents m_exts;
!     };
! };
  
  #endif
--- 1,87 ----
  #ifndef TEST_MDSPAN_LAYOUT_LIKE_H
  #define TEST_MDSPAN_LAYOUT_LIKE_H 1
  
! template<bool Noexcept>
!   struct CustomLayout
!   {
!     template<typename Extents>
!       class mapping
!       {
!       public:
! 	using extents_type = Extents;
! 	using index_type = typename extents_type::index_type;
! 	using size_type = typename extents_type::size_type;
! 	using rank_type = typename extents_type::rank_type;
! 	using layout_type = CustomLayout;
  
! 	constexpr
! 	mapping() noexcept = default;
  
! 	constexpr
! 	mapping(Extents exts)
! 	: m_exts(exts)
! 	{ }
  
! 	constexpr const extents_type&
! 	extents() const noexcept(Noexcept) { return m_exts; }
  
  	constexpr index_type
! 	required_span_size() const noexcept(Noexcept)
! 	{
! 	  for (size_t i = 0; i < extents_type::rank(); ++i)
! 	    if (m_exts.extent(i) == 0)
! 	      return 0;
! 	  return 1;
! 	}
! 
! 	template<typename... Indices>
! 	  requires (sizeof...(Indices) == extents_type::rank())
! 	  constexpr index_type
! 	  operator()(Indices...) const noexcept(Noexcept)
! 	  { return 0; }
! 
! 	static constexpr index_type
! 	stride(rank_type) noexcept(Noexcept)
  	{ return 0; }
  
! 	static constexpr bool
! 	is_always_unique() noexcept(Noexcept)
! 	{ return false; }
  
! 	static constexpr bool
! 	is_always_exhaustive() noexcept(Noexcept)
! 	{ return true; }
  
! 	static constexpr bool
! 	is_always_strided() noexcept(Noexcept)
! 	{ return true; }
  
! 	constexpr bool
! 	is_unique() const noexcept(Noexcept)
! 	{
! 	  if (required_span_size() == 0)
! 	    return true;
  
! 	  for (size_t i = 0; i < extents_type::rank(); ++i)
! 	    if (m_exts.extent(i) > 1)
! 	      return false;
  	  return true;
+ 	}
  
! 	static constexpr bool
! 	is_exhaustive() noexcept(Noexcept)
! 	{ return true; }
  
! 	static constexpr bool
! 	is_strided() noexcept(Noexcept)
! 	{ return true; }
  
!       private:
! 	Extents m_exts;
!       };
!   };
  
! using LayoutLike = CustomLayout<true>;
! using ThrowingLayout = CustomLayout<false>;
  
  #endif
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc	Sun Jul 27 22:32:19 2025
***************
*** 4,9 ****
--- 4,10 ----
  #include <testsuite_hooks.h>
  #include "int_like.h"
  #include "layout_like.h"
+ #include <stdexcept>
  
  constexpr auto dyn = std::dynamic_extent;
  
*************** test_class_properties_all()
*** 114,119 ****
--- 115,141 ----
    return true;
  }
  
+ template<typename T>
+   class ThrowingDefaultAccessor
+   {
+   public:
+     using element_type = T;
+     using reference = element_type&;
+     using data_handle_type = element_type*;
+     using offset_policy = ThrowingDefaultAccessor;
+ 
+     ThrowingDefaultAccessor() noexcept(false)
+     { }
+ 
+     reference
+     access(data_handle_type p, size_t i) const
+     { return p[i]; }
+ 
+     typename offset_policy::data_handle_type
+     offset(data_handle_type p, size_t i) const
+     { return p + i; }
+   };
+ 
  constexpr bool
  test_default_ctor()
  {
*************** test_default_ctor()
*** 130,135 ****
--- 152,169 ----
    return true;
  }
  
+ template<template<typename T> typename Accessor, bool Expected>
+   constexpr void
+   test_nothrow_default_ctor()
+   {
+     using Extents = std::extents<int, dyn>;
+     using Layout = std::layout_left;
+     using MDSpan = std::mdspan<double, Extents, Layout, Accessor<double>>;
+ 
+     static_assert(std::is_default_constructible_v<MDSpan>);
+     static_assert(std::is_nothrow_default_constructible_v<MDSpan> == Expected);
+   }
+ 
  constexpr bool
  test_from_other()
  {
*************** test_from_pointer_and_shape()
*** 206,214 ****
      assert_deduced_typedefs<double, std::dextents<size_t, 2>>(md);
      VERIFY(md.rank() == 2);
      VERIFY(md.rank_dynamic() == 2);
!     VERIFY((md[0, 0]) == data[0]);
!     VERIFY((md[0, 1]) == data[1]);
!     VERIFY((md[1, 0]) == data[3]);
    };
  
    verify(std::mdspan(data.data(), shape[0], shape[1]));
--- 240,248 ----
      assert_deduced_typedefs<double, std::dextents<size_t, 2>>(md);
      VERIFY(md.rank() == 2);
      VERIFY(md.rank_dynamic() == 2);
!     VERIFY(md[0, 0] == data[0]);
!     VERIFY(md[0, 1] == data[1]);
!     VERIFY(md[1, 0] == data[3]);
    };
  
    verify(std::mdspan(data.data(), shape[0], shape[1]));
*************** test_from_opaque_accessor()
*** 428,437 ****
    using MDSpan = decltype(md);
    static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>);
  
!   VERIFY((md[0, 0, 0]) == 0.0);
    VERIFY(md.accessor().access_count == 1);
  
!   VERIFY((md[2, 4, 6]) == 0.0);
    VERIFY(md.accessor().access_count == 2);
  }
  
--- 462,471 ----
    using MDSpan = decltype(md);
    static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>);
  
!   VERIFY(md[0, 0, 0] == 0.0);
    VERIFY(md.accessor().access_count == 1);
  
!   VERIFY(md[2, 4, 6] == 0.0);
    VERIFY(md.accessor().access_count == 2);
  }
  
*************** test_from_base_class_accessor()
*** 480,487 ****
    using MDSpan = decltype(md);
    static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>);
    static_assert(std::same_as<decltype(md[0, 0, 0]), Base&>);
!   VERIFY((md[0, 0, 0].value) == 1.0);
!   VERIFY((md[2, 4, 6].value) == 1.0);
  }
  
  constexpr bool
--- 514,521 ----
    using MDSpan = decltype(md);
    static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>);
    static_assert(std::same_as<decltype(md[0, 0, 0]), Base&>);
!   VERIFY(md[0, 0, 0].value == 1.0);
!   VERIFY(md[2, 4, 6].value == 1.0);
  }
  
  constexpr bool
*************** test_from_mapping_like()
*** 490,497 ****
    double data = 1.1;
    auto m = LayoutLike::mapping<std::extents<int, 1, 2, 3>>{};
    auto md = std::mdspan(&data, m);
!   VERIFY((md[0, 0, 0]) == data);
!   VERIFY((md[0, 1, 2]) == data);
    return true;
  }
  
--- 524,531 ----
    double data = 1.1;
    auto m = LayoutLike::mapping<std::extents<int, 1, 2, 3>>{};
    auto md = std::mdspan(&data, m);
!   VERIFY(md[0, 0, 0] == data);
!   VERIFY(md[0, 1, 2] == data);
    return true;
  }
  
*************** template<typename Int, bool ValidForPack
*** 535,547 ****
  	  {
  	    storage[mapping(i, j, k)] = 1.0;
  	    if constexpr (ValidForPacks)
! 	      VERIFY((md[Int(i), Int(j), Int(k)]) == 1.0);
  
  	    if constexpr (ValidForArrays)
  	      {
  		std::array<Int, 3> ijk{Int(i), Int(j), Int(k)};
! 		VERIFY((md[ijk]) == 1.0);
! 		VERIFY((md[std::span(ijk)]) == 1.0);
  	      }
  	    storage[mapping(i, j, k)] = 0.0;
  	  }
--- 569,581 ----
  	  {
  	    storage[mapping(i, j, k)] = 1.0;
  	    if constexpr (ValidForPacks)
! 	      VERIFY(md[Int(i), Int(j), Int(k)] == 1.0);
  
  	    if constexpr (ValidForArrays)
  	      {
  		std::array<Int, 3> ijk{Int(i), Int(j), Int(k)};
! 		VERIFY(md[ijk] == 1.0);
! 		VERIFY(md[std::span(ijk)] == 1.0);
  	      }
  	    storage[mapping(i, j, k)] = 0.0;
  	  }
*************** test_nothrow_movable_all()
*** 650,655 ****
--- 684,704 ----
    test_nothrow_movable<false, false>();
  }
  
+ template<typename Layout, bool Expected>
+   constexpr void
+   test_nothrow_is_methods()
+   {
+     using Extents = std::extents<int, dyn>;
+     using MDSpan = std::mdspan<double, Extents, Layout>;
+     static_assert(noexcept(MDSpan::is_always_unique()) == Expected);
+     static_assert(noexcept(MDSpan::is_always_exhaustive()) == Expected);
+     static_assert(noexcept(MDSpan::is_always_strided()) == Expected);
+ 
+     static_assert(noexcept(std::declval<MDSpan>().is_unique()) == Expected);
+     static_assert(noexcept(std::declval<MDSpan>().is_exhaustive()) == Expected);
+     static_assert(noexcept(std::declval<MDSpan>().is_strided()) == Expected);
+   }
+ 
  int
  main()
  {
*************** main()
*** 668,673 ****
--- 717,725 ----
    test_default_ctor();
    static_assert(test_default_ctor());
  
+   test_nothrow_default_ctor<std::default_accessor, true>();
+   test_nothrow_default_ctor<ThrowingDefaultAccessor, false>();
+ 
    test_from_other();
    static_assert(test_from_other());
  
*************** main()
*** 713,717 ****
--- 765,771 ----
    test_swap_adl();
  
    test_nothrow_movable_all();
+   test_nothrow_is_methods<std::layout_right, true>();
+   test_nothrow_is_methods<ThrowingLayout, false>();
    return 0;
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test(Alloc alloc)
*** 42,55 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range>(std::allocator<bool>());
!   do_test<Range>(__gnu_test::uneq_allocator<bool>(42));
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 42,57 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range>(std::allocator<bool>());
!   if not consteval {
!     do_test<Range>(__gnu_test::uneq_allocator<bool>(42));
!   }
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 71,79 ****
  
    // Not lvalue-convertible to bool
    struct C {
!     C(bool v) : val(v) { }
!     operator bool() && { return val; }
!     bool operator==(bool b) const { return b == val; }
      bool val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 73,81 ----
  
    // Not lvalue-convertible to bool
    struct C {
!     constexpr C(bool v) : val(v) { }
!     constexpr operator bool() && { return val; }
!     constexpr bool operator==(bool b) const { return b == val; }
      bool val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 82,97 ****
    return true;
  }
  
- constexpr bool
- test_constexpr()
- {
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::span<bool>>(std::allocator<bool>());
-   return true;
- }
- 
  int main()
  {
    test_ranges();
!   static_assert( test_constexpr() );
  }
--- 84,91 ----
    return true;
  }
  
  int main()
  {
    test_ranges();
!   static_assert( test_ranges() );
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 59,72 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<bool>>();
    do_test<Range, __gnu_test::SimpleAllocator<bool>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 59,72 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<bool>>();
    do_test<Range, __gnu_test::SimpleAllocator<bool>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 88,96 ****
  
    // Not lvalue-convertible to bool
    struct C {
!     C(bool v) : val(v) { }
!     operator bool() && { return val; }
!     bool operator==(bool b) const { return b == val; }
      bool val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 88,96 ----
  
    // Not lvalue-convertible to bool
    struct C {
!     constexpr C(bool v) : val(v) { }
!     constexpr operator bool() && { return val; }
!     constexpr bool operator==(bool b) const { return b == val; }
      bool val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 99,114 ****
    return true;
  }
  
- constexpr bool
- test_constexpr()
- {
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::span<short>, std::allocator<bool>>();
-   return true;
- }
- 
  int main()
  {
    test_ranges();
!   static_assert( test_constexpr() );
  }
--- 99,106 ----
    return true;
  }
  
  int main()
  {
    test_ranges();
!   static_assert( test_ranges() );
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 38,51 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<bool>>();
    do_test<Range, __gnu_test::SimpleAllocator<bool>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 38,51 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<bool>>();
    do_test<Range, __gnu_test::SimpleAllocator<bool>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 67,75 ****
  
    // Not lvalue-convertible to bool
    struct C {
!     C(bool v) : val(v) { }
!     operator bool() && { return val; }
!     bool operator==(bool b) const { return b == val; }
      bool val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 67,75 ----
  
    // Not lvalue-convertible to bool
    struct C {
!     constexpr C(bool v) : val(v) { }
!     constexpr operator bool() && { return val; }
!     constexpr bool operator==(bool b) const { return b == val; }
      bool val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 81,88 ****
  constexpr bool
  test_constexpr()
  {
!   // XXX: this doesn't test the non-forward_range code paths are constexpr.
!   do_test<std::span<short>, std::allocator<bool>>();
  
    // Some basic tests for overlapping ranges in constant expressions.
    using I = std::vector<bool>::iterator;
--- 81,87 ----
  constexpr bool
  test_constexpr()
  {
!   test_ranges();
  
    // Some basic tests for overlapping ranges in constant expressions.
    using I = std::vector<bool>::iterator;
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 55,68 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<bool>>();
    do_test<Range, __gnu_test::SimpleAllocator<bool>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 55,68 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<bool>>();
    do_test<Range, __gnu_test::SimpleAllocator<bool>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 84,92 ****
  
    // Not lvalue-convertible to bool
    struct C {
!     C(bool v) : val(v) { }
!     operator bool() && { return val; }
!     bool operator==(bool b) const { return b == val; }
      bool val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 84,92 ----
  
    // Not lvalue-convertible to bool
    struct C {
!     constexpr C(bool v) : val(v) { }
!     constexpr operator bool() && { return val; }
!     constexpr bool operator==(bool b) const { return b == val; }
      bool val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 95,110 ****
    return true;
  }
  
- constexpr bool
- test_constexpr()
- {
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::span<bool>, std::allocator<bool>>();
-   return true;
- }
- 
  int main()
  {
    test_ranges();
!   static_assert( test_constexpr() );
  }
--- 95,102 ----
    return true;
  }
  
  int main()
  {
    test_ranges();
!   static_assert( test_ranges() );
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test(Alloc alloc)
*** 58,71 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range>(std::allocator<int>());
!   do_test<Range>(__gnu_test::uneq_allocator<int>(42));
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 58,73 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range>(std::allocator<int>());
!   if not consteval {
!     do_test<Range>(__gnu_test::uneq_allocator<int>(42));
!   }
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 87,95 ****
  
    // Not lvalue-convertible to int
    struct C {
!     C(int v) : val(v) { }
!     operator int() && { return val; }
!     bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 89,97 ----
  
    // Not lvalue-convertible to int
    struct C {
!     constexpr C(int v) : val(v) { }
!     constexpr operator int() && { return val; }
!     constexpr bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 98,111 ****
    return true;
  }
  
- constexpr bool
- test_constexpr()
- {
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::span<short>>(std::allocator<int>());
-   return true;
- }
- 
  void
  test_pr120367()
  {
--- 100,105 ----
*************** test_pr120367()
*** 130,135 ****
  int main()
  {
    test_ranges();
!   static_assert( test_constexpr() );
    test_pr120367();
  }
--- 124,129 ----
  int main()
  {
    test_ranges();
!   static_assert( test_ranges() );
    test_pr120367();
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 42,55 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<int>>();
    do_test<Range, __gnu_test::SimpleAllocator<int>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 42,55 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<int>>();
    do_test<Range, __gnu_test::SimpleAllocator<int>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 71,79 ****
  
    // Not lvalue-convertible to int
    struct C {
!     C(int v) : val(v) { }
!     operator int() && { return val; }
!     bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 71,79 ----
  
    // Not lvalue-convertible to int
    struct C {
!     constexpr C(int v) : val(v) { }
!     constexpr operator int() && { return val; }
!     constexpr bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 82,88 ****
    return true;
  }
  
! void
  test_overlapping()
  {
    using __gnu_test::test_input_range;
--- 82,88 ----
    return true;
  }
  
! constexpr void
  test_overlapping()
  {
    using __gnu_test::test_input_range;
*************** test_overlapping()
*** 199,262 ****
    }
  }
  
! constexpr bool
! test_constexpr()
  {
!   // XXX: this doesn't test the non-forward_range code paths are constexpr.
!   do_test<std::span<short>, std::allocator<int>>();
! 
!   // Some basic tests for overlapping ranges in constant expressions.
!   struct InputRange
!   {
!     struct Sent { const void* end; };
! 
!     struct Iter
!     {
!       using value_type = int;
!       using difference_type = int;
!       constexpr explicit Iter(int* p) : ptr(p) { }
!       constexpr Iter& operator++() { ++ptr; return *this; }
!       constexpr Iter operator++(int) { auto i = *this; ++ptr; return i; }
!       constexpr int operator*() const { return *ptr; }
!       constexpr bool operator==(const Iter&) const = default;
!       constexpr bool operator==(const Sent& s) const { return ptr == s.end; }
!       int* ptr;
!     };
! 
!     Iter iter;
!     Sent sent;
! 
!     constexpr InputRange(int* f, int* l) : iter{f}, sent{l} { }
!     constexpr Iter begin() const { return iter; }
!     constexpr Sent end() const { return sent; }
    };
-   static_assert( std::ranges::input_range<InputRange> );
-   static_assert( ! std::ranges::forward_range<InputRange> );
- 
-   std::vector<int> vec(5);
- 
-   // Test overlapping input ranges
-   vec.resize(vec.capacity());
-   vec.append_range(InputRange(vec.data(), vec.data() + 3)); // no capacity
-   vec.reserve(vec.capacity() + 2);
-   vec.append_range(InputRange(vec.data(), vec.data() + 4)); // some capacity
-   vec.reserve(vec.capacity() + 6);
-   vec.append_range(InputRange(vec.data(), vec.data() + 5)); // enough capacity
- 
-   // Test overlapping forward ranges
-   vec.resize(vec.capacity());
-   vec.append_range(std::span<int>(vec));               // no capacity
-   vec.reserve(vec.size() + 2);
-   vec.append_range(std::span<int>(vec).subspan(1, 4)); // some capacity
-   vec.reserve(vec.size() + 6);
-   vec.append_range(std::span<int>(vec).subspan(1, 5)); // enough capacity
  
!   return true;
! }
! 
! int main()
! {
!   test_ranges();
!   test_overlapping();
!   static_assert( test_constexpr() );
  }
--- 199,212 ----
    }
  }
  
! int main()
  {
!   auto test_all = [] {
!     test_ranges();
!     test_overlapping();
!     return true;
    };
  
!   test_all();
!   static_assert( test_all() );
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 63,76 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<int>>();
    do_test<Range, __gnu_test::SimpleAllocator<int>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 63,76 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<int>>();
    do_test<Range, __gnu_test::SimpleAllocator<int>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 92,100 ****
  
    // Not lvalue-convertible to int
    struct C {
!     C(int v) : val(v) { }
!     operator int() && { return val; }
!     bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 92,100 ----
  
    // Not lvalue-convertible to int
    struct C {
!     constexpr C(int v) : val(v) { }
!     constexpr operator int() && { return val; }
!     constexpr bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 103,118 ****
    return true;
  }
  
- constexpr bool
- test_constexpr()
- {
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::span<short>, std::allocator<int>>();
-   return true;
- }
- 
  int main()
  {
    test_ranges();
!   static_assert( test_constexpr() );
  }
--- 103,110 ----
    return true;
  }
  
  int main()
  {
    test_ranges();
!   static_assert( test_ranges() );
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc	Sun Jul 27 22:32:19 2025
*************** do_test()
*** 59,72 ****
  }
  
  template<typename Range>
! void
  do_test_a()
  {
    do_test<Range, std::allocator<int>>();
    do_test<Range, __gnu_test::SimpleAllocator<int>>();
  }
  
! bool
  test_ranges()
  {
    using namespace __gnu_test;
--- 59,72 ----
  }
  
  template<typename Range>
! constexpr void
  do_test_a()
  {
    do_test<Range, std::allocator<int>>();
    do_test<Range, __gnu_test::SimpleAllocator<int>>();
  }
  
! constexpr bool
  test_ranges()
  {
    using namespace __gnu_test;
*************** test_ranges()
*** 88,96 ****
  
    // Not lvalue-convertible to int
    struct C {
!     C(int v) : val(v) { }
!     operator int() && { return val; }
!     bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
--- 88,96 ----
  
    // Not lvalue-convertible to int
    struct C {
!     constexpr C(int v) : val(v) { }
!     constexpr operator int() && { return val; }
!     constexpr bool operator==(int b) const { return b == val; }
      int val;
    };
    using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
*************** test_ranges()
*** 99,114 ****
    return true;
  }
  
- constexpr bool
- test_constexpr()
- {
-   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-   do_test<std::span<short>, std::allocator<int>>();
-   return true;
- }
- 
  int main()
  {
    test_ranges();
!   static_assert( test_constexpr() );
  }
--- 99,106 ----
    return true;
  }
  
  int main()
  {
    test_ranges();
!   static_assert( test_ranges() );
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/24_iterators/random_access/string_vector_iterators.cc gcc-16-20250727/libstdc++-v3/testsuite/24_iterators/random_access/string_vector_iterators.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/24_iterators/random_access/string_vector_iterators.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/24_iterators/random_access/string_vector_iterators.cc	Sun Jul 27 22:32:19 2025
***************
*** 17,254 ****
  // along with this program; see the file COPYING3.  If not see
  // <http://www.gnu.org/licenses/>.
  
- 
  #include <string>
  #include <vector>
  #include <testsuite_hooks.h>
  
! int 
  string_stuff()
  {
-    int failures(0);
- 
     std::string s("abcde");
  
     std::string::iterator i1(s.begin());
!    if (*i1 != 'a')
!       ++failures;
  
     ++i1;
!    if (*i1 != 'b')
!       ++failures;
  
!    if (*i1++ != 'b')
!        ++failures;
!    if (*i1 != 'c')
!       ++failures;
  
     ++ ++i1;
!    if (*i1 != 'e')
!       ++failures;
  
     --i1;
!    if (*i1 != 'd')
!       ++failures;
  
!    if (*i1-- != 'd')
!       ++failures;
!    if (*i1 != 'c')
!       ++failures;
  
     -- --i1;
!    if (*i1 != 'a')
!       ++failures;
  
     std::string::iterator i2;
     i2 = s.end();
     std::iterator_traits<std::string::iterator>::difference_type d1;
     d1 = i2 - i1;
!    if (d1 != 5)
!       ++failures;
  
     std::iterator_traits<std::string::iterator>::value_type v1;
     v1 = i1[0];
!    if (v1 != 'a')
!       ++failures;
  
     std::iterator_traits<std::string::iterator>::reference r1(i1[0]);
!    if (r1 != 'a')
!       ++failures;
     r1 = 'x';
!    if (r1 != 'x')
!       ++failures;
     r1 = 'a';
  
!    if ((i1 != i2) != true)
!       ++failures;
!    if ((i1 == i2) != false)
!       ++failures;
!    if ((i1 <  i2) != true)
!       ++failures;
!    if ((i1 >  i2) != false)
!       ++failures;
!    if ((i1 <= i2) != true)
!       ++failures;
!    if ((i1 >= i2) != false)
!       ++failures;
  
     std::string::iterator i3;
     i3 = i1;
!    if ((i3 == i1) != true)
!       ++failures;
  
     i3 += 5;
!    if ((i3 == i2) != true)
!       ++failures;
  
     i3 -= 5;
!    if ((i3 == i1) != true)
!       ++failures;
! 
!    if (i3 + 5 != i2)
!       ++failures;
! 
!    if (5 + i3 != i2)
!       ++failures;
  
!    if (i2 - 5 != i3)
!       ++failures;
  
!    if (i1[0] != 'a')
!       ++failures;
  
     i1[4] = 'x';
!    if (i2[-1] != 'x')
!       ++failures;
     i1[4] = 'e';
  
     i1[2] = 'x';
!    if (i2[-3] != 'x')
!       ++failures;
     i1[2] = 'c';
  
     std::string::const_iterator ci1(s.begin());
!    if (*ci1 != 'a')
!       ++failures;
  
     ++ci1;
!    if (*ci1 != 'b')
!       ++failures;
  
!    if (*ci1++ != 'b')
!       ++failures;
!    if (*ci1 != 'c')
!       ++failures;
  
     ++ ++ci1;
!    if (*ci1 != 'e')
!       ++failures;
  
     --ci1;
!    if (*ci1 != 'd')
!       ++failures;
  
!    if (*ci1-- != 'd')
!       ++failures;
!    if (*ci1 != 'c')
!       ++failures;
  
     -- --ci1;
!    if (*ci1 != 'a')
!       ++failures;
  
     std::string::const_iterator ci2;
     ci2 = s.end();
     std::iterator_traits<std::string::const_iterator>::difference_type d2;
     d2 = ci2 - ci1;
!    if (d2 != 5)
!      ++failures;
  
     std::iterator_traits<std::string::const_iterator>::value_type v2;
     v2 = ci1[0];
!    if (v2 != 'a')
!      ++failures;
  
     std::iterator_traits<std::string::const_iterator>::reference r2(ci1[0]);
!    if (r2 != 'a')
!       ++failures;
  
!    if ((ci1 != ci2) != true)
!       ++failures;
!    if ((ci1 == ci2) != false)
!       ++failures;
!    if ((ci1 <  ci2) != true)
!       ++failures;
!    if ((ci1 >  ci2) != false)
!       ++failures;
!    if ((ci1 <= ci2) != true)
!       ++failures;
!    if ((ci1 >= ci2) != false)
!       ++failures;
  
     std::string::const_iterator ci3;
     ci3 = ci1;
!    if ((ci3 == ci1) != true)
!       ++failures;
  
     ci3 += 5;
!    if ((ci3 == ci2) != true)
!       ++failures;
  
     ci3 -= 5;
!    if ((ci3 == ci1) != true)
!       ++failures;
! 
!    if (ci3 + 5 != ci2)
!       ++failures;
! 
!    if (5 + ci3 != ci2)
!       ++failures;
! 
!    if (ci2 - 5 != ci3)
!       ++failures;
  
!    if (ci1[2] != 'c')
!       ++failures;
  
!    if (ci2[-1] != 'e')
!       ++failures;
  
     // iterator and const_iterator
     std::string::const_iterator ci4(i1);
!    if ((ci4 == i1) != true)
!       ++failures;
!    if ((ci4 != i1) != false)
!       ++failures;
!    if ((ci4 < i1)  != false)
!      ++failures;
!    if ((ci4 > i1)  != false)
!      ++failures;
!    if ((ci4 <= i1) != true)
!      ++failures;
!    if ((ci4 >= i1) != true)
!      ++failures;
     ci4 = i2;
!    if ((i2 == ci4) != true)
!      ++failures;
!    if ((i2 < ci4)  != false)
!      ++failures;
!    if ((i2 > ci4)  != false)
!      ++failures;
!    if ((i2 <= ci4) != true)
!      ++failures;
!    if ((i2 >= ci4) != true)
!      ++failures;
  
     const std::string cs("ABCDE");
     std::string::const_iterator ci5(cs.begin());
!    if (ci5[0] != 'A')
!       ++failures;
! 
!    return failures;
  }
  
! int 
  vector_stuff()
  {
     int failures(0);
--- 17,178 ----
  // along with this program; see the file COPYING3.  If not see
  // <http://www.gnu.org/licenses/>.
  
  #include <string>
  #include <vector>
  #include <testsuite_hooks.h>
  
! void
  string_stuff()
  {
     std::string s("abcde");
  
     std::string::iterator i1(s.begin());
!    VERIFY( *i1 == 'a' );
  
     ++i1;
!    VERIFY( *i1 == 'b' );
  
!    VERIFY( *i1++ == 'b' );
!    VERIFY( *i1 == 'c' );
  
     ++ ++i1;
!    VERIFY( *i1 == 'e' );
  
     --i1;
!    VERIFY( *i1 == 'd' );
  
!    VERIFY( *i1-- == 'd' );
!    VERIFY( *i1 == 'c' );
  
     -- --i1;
!    VERIFY( *i1 == 'a' );
  
     std::string::iterator i2;
     i2 = s.end();
     std::iterator_traits<std::string::iterator>::difference_type d1;
     d1 = i2 - i1;
!    VERIFY( d1 == 5 );
  
     std::iterator_traits<std::string::iterator>::value_type v1;
     v1 = i1[0];
!    VERIFY( v1 == 'a' );
  
     std::iterator_traits<std::string::iterator>::reference r1(i1[0]);
!    VERIFY( r1 == 'a' );
     r1 = 'x';
!    VERIFY( r1 == 'x' );
     r1 = 'a';
  
!    VERIFY( (i1 != i2) == true );
!    VERIFY( (i1 == i2) == false );
!    VERIFY( (i1 <  i2) == true );
!    VERIFY( (i1 >  i2) == false );
!    VERIFY( (i1 <= i2) == true );
!    VERIFY( (i1 >= i2) == false );
  
     std::string::iterator i3;
     i3 = i1;
!    VERIFY( (i3 == i1) == true );
  
     i3 += 5;
!    VERIFY( (i3 == i2) == true );
  
     i3 -= 5;
!    VERIFY( (i3 == i1) == true );
  
!    VERIFY( i3 + 5 == i2 );
!    VERIFY( 5 + i3 == i2 );
!    VERIFY( i2 - 5 == i3 );
  
!    VERIFY( i1[0] == 'a' );
  
     i1[4] = 'x';
!    VERIFY( i2[-1] == 'x' );
     i1[4] = 'e';
  
     i1[2] = 'x';
!    VERIFY( i2[-3] == 'x' );
     i1[2] = 'c';
  
     std::string::const_iterator ci1(s.begin());
!    VERIFY( *ci1 == 'a' );
  
     ++ci1;
!    VERIFY( *ci1 == 'b' );
  
!    VERIFY( *ci1++ == 'b' );
!    VERIFY( *ci1 == 'c' );
  
     ++ ++ci1;
!    VERIFY( *ci1 == 'e' );
  
     --ci1;
!    VERIFY( *ci1 == 'd' );
  
!    VERIFY( *ci1-- == 'd' );
!    VERIFY( *ci1 == 'c' );
  
     -- --ci1;
!    VERIFY( *ci1 == 'a' );
  
     std::string::const_iterator ci2;
     ci2 = s.end();
     std::iterator_traits<std::string::const_iterator>::difference_type d2;
     d2 = ci2 - ci1;
!    VERIFY( d2 == 5 );
  
     std::iterator_traits<std::string::const_iterator>::value_type v2;
     v2 = ci1[0];
!    VERIFY( v2 == 'a' );
  
     std::iterator_traits<std::string::const_iterator>::reference r2(ci1[0]);
!    VERIFY( r2 == 'a' );
  
!    VERIFY( (ci1 != ci2) == true );
!    VERIFY( (ci1 == ci2) == false );
!    VERIFY( (ci1 <  ci2) == true );
!    VERIFY( (ci1 >  ci2) == false );
!    VERIFY( (ci1 <= ci2) == true );
!    VERIFY( (ci1 >= ci2) == false );
  
     std::string::const_iterator ci3;
     ci3 = ci1;
!    VERIFY( ci3 == ci1 );
  
     ci3 += 5;
!    VERIFY( ci3 == ci2 );
  
     ci3 -= 5;
!    VERIFY( ci3 == ci1 );
  
!    VERIFY( ci3 + 5 == ci2 );
!    VERIFY( 5 + ci3 == ci2 );
!    VERIFY( ci2 - 5 == ci3 );
  
!    VERIFY( ci1[2] == 'c' );
!    VERIFY( ci2[-1] == 'e' );
  
     // iterator and const_iterator
     std::string::const_iterator ci4(i1);
!    VERIFY( (ci4 == i1) == true );
!    VERIFY( (ci4 != i1) == false );
!    VERIFY( (ci4 < i1) == false );
!    VERIFY( (ci4 > i1) == false );
!    VERIFY( (ci4 <= i1) == true );
!    VERIFY( (ci4 >= i1) == true );
     ci4 = i2;
!    VERIFY( (i2 == ci4) == true );
!    VERIFY( (i2 < ci4) == false );
!    VERIFY( (i2 > ci4) == false );
!    VERIFY( (i2 <= ci4) == true );
!    VERIFY( (i2 >= ci4) == true );
  
     const std::string cs("ABCDE");
     std::string::const_iterator ci5(cs.begin());
!    VERIFY( ci5[0] == 'A' );
  }
  
! void
  vector_stuff()
  {
     int failures(0);
*************** vector_stuff()
*** 261,607 ****
     v.push_back(int(5));
  
     std::vector<int>::iterator i1(v.begin());
!    if (*i1 != 1)
!       ++failures;
  
     ++i1;
!    if (*i1 != 2)
!       ++failures;
  
!    if (*i1++ != 2)
!       ++failures;
!    if (*i1 != 3)
!       ++failures;
  
     ++ ++i1;
!    if (*i1 != 5)
!       ++failures;
  
     --i1;
!    if (*i1 != 4)
!       ++failures;
  
!    if (*i1-- != 4)
!       ++failures;
!    if (*i1 != 3)
!       ++failures;
  
     -- --i1;
!    if (*i1 != 1)
!       ++failures;
  
     std::vector<int>::iterator i2;
     i2 = v.end();
     std::iterator_traits<std::vector<int>::iterator>::difference_type d1;
     d1 = i2 - i1;
!    if (d1 != 5)
!       ++failures;
  
     std::iterator_traits<std::vector<int>::iterator>::value_type v1;
     v1 = i1[0];
!    if (v1 != 1)
!       ++failures;
  
     std::iterator_traits<std::vector<int>::iterator>::reference r1(i1[0]);
!    if (r1 != 1)
!       ++failures;
     r1 = 9;
!    if (r1 != 9)
!       ++failures;
     r1 = 1;
  
!    if ((i1 != i2) != true)
!       ++failures;
!    if ((i1 == i2) != false)
!       ++failures;
!    if ((i1 <  i2) != true)
!       ++failures;
!    if ((i1 >  i2) != false)
!       ++failures;
!    if ((i1 <= i2) != true)
!       ++failures;
!    if ((i1 >= i2) != false)
!       ++failures;
  
     std::vector<int>::iterator i3;
     i3 = i1;
!    if ((i3 == i1) != true)
!       ++failures;
  
     i3 += 5;
!    if ((i3 == i2) != true)
!       ++failures;
  
     i3 -= 5;
!    if ((i3 == i1) != true)
!       ++failures;
! 
!    if (i3 + 5 != i2)
!       ++failures;
! 
!    if (5 + i3 != i2)
!       ++failures;
  
!    if (i2 - 5 != i3)
!       ++failures;
  
!    if (i1[0] != 1)
!       ++failures;
  
     i1[4] = 9;
!    if (i2[-1] != 9)
!       ++failures;
     i1[4] = 5;
  
     i1[2] = 9;
!    if (i2[-3] != 9)
!       ++failures;
     i1[2] = 3;
  
     std::vector<int>::const_iterator ci1(v.begin());
!    if (*ci1 != 1)
!       ++failures;
  
     ++ci1;
!    if (*ci1 != 2)
!       ++failures;
  
!    if (*ci1++ != 2)
!       ++failures;
!    if (*ci1 != 3)
!       ++failures;
  
     ++ ++ci1;
!    if (*ci1 != 5)
!       ++failures;
  
     --ci1;
!    if (*ci1 != 4)
!       ++failures;
  
!    if (*ci1-- != 4)
!       ++failures;
!    if (*ci1 != 3)
!       ++failures;
  
     -- --ci1;
!    if (*ci1 != 1)
!       ++failures;
  
     std::vector<int>::const_iterator ci2;
     ci2 = v.end();
     std::iterator_traits<std::vector<int>::const_iterator>::difference_type d2;
     d2 = ci2 - ci1;
!    if (d2 != 5)
!       ++failures;
  
     std::iterator_traits<std::vector<int>::const_iterator>::value_type v2;
     v2 = ci1[0];
!    if (v2 != 1)
!       ++failures;
  
     std::iterator_traits<std::vector<int>::const_iterator>::reference
        r2(ci1[0]);
!    if (r2 != 1)
!       ++failures;
  
!    if ((ci1 != ci2) != true)
!       ++failures;
!    if ((ci1 == ci2) != false)
!       ++failures;
!    if ((ci1 <  ci2) != true)
!       ++failures;
!    if ((ci1 >  ci2) != false)
!       ++failures;
!    if ((ci1 <= ci2) != true)
!       ++failures;
!    if ((ci1 >= ci2) != false)
!       ++failures;
  
     std::vector<int>::const_iterator ci3;
     ci3 = ci1;
!    if ((ci3 == ci1) != true)
!       ++failures;
  
     ci3 += 5;
!    if ((ci3 == ci2) != true)
!       ++failures;
  
     ci3 -= 5;
!    if ((ci3 == ci1) != true)
!       ++failures;
! 
!    if (ci3 + 5 != ci2)
!       ++failures;
! 
!    if (5 + ci3 != ci2)
!       ++failures;
  
!    if (ci2 - 5 != ci3)
!       ++failures;
  
!    if (ci1[2] != 3)
!       ++failures;
  
!    if (ci2[-1] != 5)
!       ++failures;
  
     // iterator to const_iterator
     std::vector<int>::const_iterator ci4(i1);
!    if ((ci4 == i1) != true)
!       ++failures;
!    if ((ci4 != i1) != false)
!       ++failures;
!    if ((ci4 < i1)  != false)
!      ++failures;
!    if ((ci4 > i1)  != false)
!      ++failures;
!    if ((ci4 <= i1) != true)
!      ++failures;
!    if ((ci4 >= i1) != true)
!      ++failures;
     ci4 = i2;
!    if ((i2 == ci4) != true)
!      ++failures;
!    if ((i2 < ci4)  != false)
!      ++failures;
!    if ((i2 > ci4)  != false)
!      ++failures;
!    if ((i2 <= ci4) != true)
!      ++failures;
!    if ((i2 >= ci4) != true)
!      ++failures;
  
     const std::vector<int> cv(v);
     std::vector<int>::const_iterator ci5(cv.begin());
!    if (ci5[0] != 1)
!       ++failures;
  
     std::vector<std::string> vs;
     vs.push_back(std::string("abc"));
     std::vector<std::string>::iterator ivs(vs.begin());
!    if (ivs->c_str()[1] != 'b')
!       ++failures;
! 
!    return failures;
  }
  
! int 
  reverse_stuff()
  {
-    int failures(0);
- 
     std::string s("abcde");
  
     std::string::reverse_iterator ri(s.rbegin());
!    if (*ri != 'e')
!       ++failures;
  
     std::iterator_traits<std::string::reverse_iterator>::difference_type d;
     d = s.rend() - ri;
!    if (d != 5)
!       ++failures;
  
     const std::string cs("abcde");
     std::string::const_reverse_iterator cri(cs.rend());
!    if (cri - 5 != cs.rbegin())
!       ++failures;
! 
!    return failures;
! }
! 
! // the following should be compiler errors
! // flag runtime errors in case they slip through the compiler
! int 
! wrong_stuff()
! {
!    int failures(0);
! 
! #ifdef ITER24_F1
!    extern void f(std::vector<std::string*>::iterator);
!    std::vector<std::string*> vs[2];
!    f(vs);                       // address of array is not an iterator
!    failures++;
! #endif
! 
! #ifdef ITER24_F2
!    std::string s;
!    char *i = s.begin();         // begin() doesn't return a pointer
!    failures++;
! #endif
! 
! #ifdef ITER24_F3
!    std::string::const_iterator ci;
!    std::string::iterator i;
!    if (i - ci)                  // remove const_ is a warning
!       i++;
!    // failures++;  only a warning
! #endif
! 
! #ifdef ITER24_F4
!    std::vector<char>::iterator iv;
!    std::string::iterator is(iv);// vector<char> is not string
!    failures++;
! #endif
! 
! #ifdef ITER24_F5
!    std::vector<char>::iterator iv;
!    std::string::iterator is;
!    if (iv == is)                // vector<char> is not string
!       ++iv;
!    failures++;
! #endif
! 
! #ifdef ITER24_F6
!    std::vector<char>::const_iterator ci;
!    std::vector<char>::iterator i = ci;  // remove const_ is a warning
!    ++i;
!    // failures++; only a warning
! #endif
! 
! #ifdef ITER24_F7
!    std::vector<int> v(1);
!    std::vector<int>::const_iterator ci(v.begin());
!    *ci = 1;                     // cannot assign through const_iterator
!    failures++;
! #endif
! 
! #ifdef ITER24_F8
!    std::vector<const int> v(1);
!    std::vector<const int>::reference r(v.begin()[0]);
!    r = 1;                       // cannot assign through reference to const
!    failures++;
! #endif
! 
!    return failures;
  }
  
  // libstdc++/6642
! int
  test6642()
  {
     std::string s;
     std::string::iterator it = s.begin();
     std::string::const_iterator cit = s.begin();
! 
!    return it - cit;
  }
  
  int
  main()
  {
!    int failures(0);
! 
!    failures += string_stuff();
! 
!    failures += vector_stuff();
! 
!    failures += reverse_stuff();
! 
!    failures += wrong_stuff();
! 
!    failures += test6642();
! 
!    VERIFY(failures == 0);
     return 0;
  }
--- 185,374 ----
     v.push_back(int(5));
  
     std::vector<int>::iterator i1(v.begin());
!    VERIFY( *i1 == 1 );
  
     ++i1;
!    VERIFY( *i1 == 2 );
  
!    VERIFY( *i1++ == 2 );
!    VERIFY( *i1 == 3 );
  
     ++ ++i1;
!    VERIFY( *i1 == 5 );
  
     --i1;
!    VERIFY( *i1 == 4 );
  
!    VERIFY( *i1-- == 4 );
!    VERIFY( *i1 == 3 );
  
     -- --i1;
!    VERIFY( *i1 == 1 );
  
     std::vector<int>::iterator i2;
     i2 = v.end();
     std::iterator_traits<std::vector<int>::iterator>::difference_type d1;
     d1 = i2 - i1;
!    VERIFY( d1 == 5 );
  
     std::iterator_traits<std::vector<int>::iterator>::value_type v1;
     v1 = i1[0];
!    VERIFY( v1 == 1 );
  
     std::iterator_traits<std::vector<int>::iterator>::reference r1(i1[0]);
!    VERIFY( r1 == 1 );
     r1 = 9;
!    VERIFY( r1 == 9 );
     r1 = 1;
  
!    VERIFY( (i1 != i2) == true );
!    VERIFY( (i1 == i2) == false );
!    VERIFY( (i1 <  i2) == true );
!    VERIFY( (i1 >  i2) == false );
!    VERIFY( (i1 <= i2) == true );
!    VERIFY( (i1 >= i2) == false );
  
     std::vector<int>::iterator i3;
     i3 = i1;
!    VERIFY( (i3 == i1) == true );
  
     i3 += 5;
!    VERIFY( (i3 == i2) == true );
  
     i3 -= 5;
!    VERIFY( (i3 == i1) == true );
  
!    VERIFY( i3 + 5 == i2 );
!    VERIFY( 5 + i3 == i2 );
!    VERIFY( i2 - 5 == i3 );
  
!    VERIFY( i1[0] == 1 );
  
     i1[4] = 9;
!    VERIFY( i2[-1] == 9 );
     i1[4] = 5;
  
     i1[2] = 9;
!    VERIFY( i2[-3] == 9 );
     i1[2] = 3;
  
     std::vector<int>::const_iterator ci1(v.begin());
!    VERIFY( *ci1 == 1 );
  
     ++ci1;
!    VERIFY( *ci1 == 2 );
  
!    VERIFY( *ci1++ == 2 );
!    VERIFY( *ci1 == 3 );
  
     ++ ++ci1;
!    VERIFY( *ci1 == 5 );
  
     --ci1;
!    VERIFY( *ci1 == 4 );
  
!    VERIFY( *ci1-- == 4 );
!    VERIFY( *ci1 == 3 );
  
     -- --ci1;
!    VERIFY( *ci1 == 1 );
  
     std::vector<int>::const_iterator ci2;
     ci2 = v.end();
     std::iterator_traits<std::vector<int>::const_iterator>::difference_type d2;
     d2 = ci2 - ci1;
!    VERIFY( d2 == 5 );
  
     std::iterator_traits<std::vector<int>::const_iterator>::value_type v2;
     v2 = ci1[0];
!    VERIFY( v2 == 1 );
  
     std::iterator_traits<std::vector<int>::const_iterator>::reference
        r2(ci1[0]);
!    VERIFY( r2 == 1 );
  
!    VERIFY( (ci1 != ci2) == true );
!    VERIFY( (ci1 == ci2) == false );
!    VERIFY( (ci1 <  ci2) == true );
!    VERIFY( (ci1 >  ci2) == false );
!    VERIFY( (ci1 <= ci2) == true );
!    VERIFY( (ci1 >= ci2) == false );
  
     std::vector<int>::const_iterator ci3;
     ci3 = ci1;
!    VERIFY( (ci3 == ci1) == true );
  
     ci3 += 5;
!    VERIFY( (ci3 == ci2) == true );
  
     ci3 -= 5;
!    VERIFY( (ci3 == ci1) == true );
  
!    VERIFY( ci3 + 5 == ci2 );
!    VERIFY( 5 + ci3 == ci2 );
!    VERIFY( ci2 - 5 == ci3 );
  
!    VERIFY( ci1[2] == 3 );
  
!    VERIFY( ci2[-1] == 5 );
  
     // iterator to const_iterator
     std::vector<int>::const_iterator ci4(i1);
!    VERIFY( (ci4 == i1) == true );
!    VERIFY( (ci4 != i1) == false );
!    VERIFY( (ci4 < i1) == false );
!    VERIFY( (ci4 > i1) == false );
!    VERIFY( (ci4 <= i1) == true );
!    VERIFY( (ci4 >= i1) == true );
     ci4 = i2;
!    VERIFY( (i2 == ci4) == true );
!    VERIFY( (i2 < ci4) == false );
!    VERIFY( (i2 > ci4) == false );
!    VERIFY( (i2 <= ci4) == true );
!    VERIFY( (i2 >= ci4) == true );
  
     const std::vector<int> cv(v);
     std::vector<int>::const_iterator ci5(cv.begin());
!    VERIFY( ci5[0] == 1 );
  
     std::vector<std::string> vs;
     vs.push_back(std::string("abc"));
     std::vector<std::string>::iterator ivs(vs.begin());
!    VERIFY( ivs->c_str()[1] == 'b' );
  }
  
! void 
  reverse_stuff()
  {
     std::string s("abcde");
  
     std::string::reverse_iterator ri(s.rbegin());
!    VERIFY( *ri == 'e' );
  
     std::iterator_traits<std::string::reverse_iterator>::difference_type d;
     d = s.rend() - ri;
!    VERIFY( d == 5 );
  
     const std::string cs("abcde");
     std::string::const_reverse_iterator cri(cs.rend());
!    VERIFY( cri - 5 == cs.rbegin() );
  }
  
  // libstdc++/6642
! void
  test6642()
  {
     std::string s;
     std::string::iterator it = s.begin();
     std::string::const_iterator cit = s.begin();
!    VERIFY( (it - cit) == 0 );
  }
  
  int
  main()
  {
!    string_stuff();
!    vector_stuff();
!    reverse_stuff();
     return 0;
  }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc gcc-16-20250727/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc	Sun Jul 20 22:32:41 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3900.cc	Sun Jul 27 22:32:19 2025
*************** bar(std::allocator_arg_t, std::pmr::memo
*** 13,16 ****
  }
  
  // { dg-error "static assertion failed" "" { target *-*-* } 0 }
! // { dg-error "no matching function .*memory_resource&" "" { target *-*-* } 0 }
--- 13,17 ----
  }
  
  // { dg-error "static assertion failed" "" { target *-*-* } 0 }
! // { dg-error "could not convert 'const std::pmr::memory_resource'" "" { target *-*-* } 0 }
! // { dg-error "no matching function \[^\n\r\]*memory_resource&" "" { target *-*-* } 0 }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc	Sun Jul 20 22:32:43 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/29_atomics/atomic/requirements/types_neg.cc	Sun Jul 27 22:32:19 2025
***************
*** 20,25 ****
--- 20,26 ----
  #include <atomic>
  
  std::atomic<const int> a; // { dg-error "here" }
+ // { dg-error "assignment to read-only type" "" { target *-*-* } 0 }
  
  struct MoveOnly
  {
*************** struct NoMove
*** 40,42 ****
--- 41,44 ----
  std::atomic<NoMove> c; // { dg-error "here" }
  
  // { dg-error "static assertion failed" "" { target *-*-* } 0 }
+ // { dg-error "use of deleted function" "" { target *-*-* } 0 }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc	Sun Jul 20 22:32:43 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/destructible_neg.cc	Sun Jul 27 22:32:20 2025
*************** test02(std::stop_token& tok, G& g)
*** 54,56 ****
--- 54,57 ----
  }
  
  // { dg-error "static assertion failed" "" { target *-*-* } 0 }
+ // { dg-error "private within this context" "" { target *-*-* } 0 }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc	Sun Jul 20 22:32:43 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/30_threads/stop_token/stop_callback/invocable_neg.cc	Sun Jul 27 22:32:20 2025
*************** test01(std::stop_token& tok, F& f)
*** 32,34 ****
--- 32,35 ----
  }
  
  // { dg-error "static assertion failed" "" { target *-*-* } 0 }
+ // { dg-error "no match for call" "" { target *-*-* } 0 }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc	Sun Jul 20 22:32:43 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc	Sun Jul 27 22:32:20 2025
*************** void test_const_arg()
*** 42,44 ****
--- 42,45 ----
  }
  
  // { dg-prune-output "no matching function for call to .*::basic_format_arg<" }
+ // { dg-prune-output "use of deleted function" }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/std/format/string_neg.cc gcc-16-20250727/libstdc++-v3/testsuite/std/format/string_neg.cc
*** gcc-16-20250720/libstdc++-v3/testsuite/std/format/string_neg.cc	Sun Jul 20 22:32:43 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/std/format/string_neg.cc	Sun Jul 27 22:32:20 2025
*************** auto s = std::format(" {9} "); // { dg-e
*** 8,10 ****
--- 8,12 ----
  struct X { };
  std::format_string<X> str(""); // { dg-error "here" }
  // { dg-error "std::formatter must be specialized" "" { target *-*-* } 0 }
+ 
+ // { dg-prune-output "use of deleted function" }
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/util/testsuite_allocator.h gcc-16-20250727/libstdc++-v3/testsuite/util/testsuite_allocator.h
*** gcc-16-20250720/libstdc++-v3/testsuite/util/testsuite_allocator.h	Sun Jul 20 22:32:43 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/util/testsuite_allocator.h	Sun Jul 27 22:32:20 2025
*************** namespace __gnu_test
*** 517,535 ****
--- 517,540 ----
        constexpr SimpleAllocator() noexcept { }
  
        template <class T>
+ 	constexpr
          SimpleAllocator(const SimpleAllocator<T>&) { }
  
+       _GLIBCXX20_CONSTEXPR
        Tp *allocate(std::size_t n)
        { return std::allocator<Tp>().allocate(n); }
  
+       _GLIBCXX20_CONSTEXPR
        void deallocate(Tp *p, std::size_t n)
        { std::allocator<Tp>().deallocate(p, n); }
      };
  
    template <class T, class U>
+     constexpr
      bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&)
      { return true; }
    template <class T, class U>
+     constexpr
      bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&)
      { return false; }
  
diff -Nrcpad gcc-16-20250720/libstdc++-v3/testsuite/util/testsuite_iterators.h gcc-16-20250727/libstdc++-v3/testsuite/util/testsuite_iterators.h
*** gcc-16-20250720/libstdc++-v3/testsuite/util/testsuite_iterators.h	Sun Jul 20 22:32:43 2025
--- gcc-16-20250727/libstdc++-v3/testsuite/util/testsuite_iterators.h	Sun Jul 27 22:32:20 2025
*************** namespace __gnu_test
*** 61,70 ****
        T* first;
        T* last;
  
        BoundsContainer(T* _first, T* _last) : first(_first), last(_last)
        { }
  
!       std::size_t size() const { return last - first; }
      };
  
    // Simple container for holding state of a set of output iterators.
--- 61,72 ----
        T* first;
        T* last;
  
+       _GLIBCXX_CONSTEXPR
        BoundsContainer(T* _first, T* _last) : first(_first), last(_last)
        { }
  
!       _GLIBCXX_CONSTEXPR std::size_t
!       size() const { return last - first; }
      };
  
    // Simple container for holding state of a set of output iterators.
*************** namespace __gnu_test
*** 74,84 ****
--- 76,88 ----
        T* incrementedto;
        bool* writtento;
  
+       _GLIBCXX20_CONSTEXPR
        OutputContainer(T* _first, T* _last)
        : BoundsContainer<T>(_first, _last), incrementedto(_first),
  	writtento(new bool[this->size()]())
        { }
  
+       _GLIBCXX20_CONSTEXPR
        ~OutputContainer()
        { delete[] writtento; }
      };
*************** namespace __gnu_test
*** 92,103 ****
--- 96,109 ----
      public:
        OutputContainer<T>* SharedInfo;
  
+       _GLIBCXX_CONSTEXPR
        WritableObject(T* ptr_in, OutputContainer<T>* SharedInfo_in):
  	ptr(ptr_in), SharedInfo(SharedInfo_in)
        { }
  
  #if __cplusplus >= 201103L
        template<class U>
+       _GLIBCXX14_CONSTEXPR
        typename std::enable_if<std::is_assignable<T&, U>::value>::type
        operator=(U&& new_val) const
        {
*************** namespace __gnu_test
*** 107,112 ****
--- 113,119 ----
        }
  #else
        template<class U>
+       _GLIBCXX14_CONSTEXPR
        void
        operator=(const U& new_val)
        {
*************** namespace __gnu_test
*** 128,133 ****
--- 135,141 ----
    struct output_iterator_wrapper
    {
    protected:
+     _GLIBCXX_CONSTEXPR
      output_iterator_wrapper() : ptr(0), SharedInfo(0)
      { }
  
*************** namespace __gnu_test
*** 142,147 ****
--- 150,156 ----
      T* ptr;
      ContainerType* SharedInfo;
  
+     _GLIBCXX14_CONSTEXPR
      output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
      : ptr(_ptr), SharedInfo(SharedInfo_in)
      {
*************** namespace __gnu_test
*** 155,160 ****
--- 164,170 ----
      operator=(const output_iterator_wrapper&) = default;
  #endif
  
+     _GLIBCXX14_CONSTEXPR
      WritableObject<T>
      operator*() const
      {
*************** namespace __gnu_test
*** 163,168 ****
--- 173,179 ----
        return WritableObject<T>(ptr, SharedInfo);
      }
  
+     _GLIBCXX14_CONSTEXPR
      output_iterator_wrapper&
      operator++()
      {
*************** namespace __gnu_test
*** 173,178 ****
--- 184,190 ----
        return *this;
      }
  
+     _GLIBCXX14_CONSTEXPR
      output_iterator_wrapper
      operator++(int)
      {
*************** namespace __gnu_test
*** 224,236 ****
        struct deref_proxy
        {
  	T* ptr;
! 	operator const T&() const { return *ptr; }
        } p;
  
!       deref_proxy operator*() const { return p; }
      };
  
    protected:
      input_iterator_wrapper() : ptr(0), SharedInfo(0)
      { }
  
--- 236,254 ----
        struct deref_proxy
        {
  	T* ptr;
! 
! 	_GLIBCXX_CONSTEXPR
! 	operator const T&() const
! 	{ return *ptr; }
        } p;
  
!       _GLIBCXX_CONSTEXPR
!       deref_proxy operator*() const
!       { return p; }
      };
  
    protected:
+     _GLIBCXX_CONSTEXPR
      input_iterator_wrapper() : ptr(0), SharedInfo(0)
      { }
  
*************** namespace __gnu_test
*** 245,250 ****
--- 263,269 ----
      T* ptr;
      ContainerType* SharedInfo;
  
+     _GLIBCXX14_CONSTEXPR
      input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
      : ptr(_ptr), SharedInfo(SharedInfo_in)
      { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); }
*************** namespace __gnu_test
*** 256,261 ****
--- 275,281 ----
      operator=(const input_iterator_wrapper&) = default;
  #endif
  
+     _GLIBCXX14_CONSTEXPR
      bool
      operator==(const input_iterator_wrapper& in) const
      {
*************** namespace __gnu_test
*** 264,295 ****
        return ptr == in.ptr;
      }
  
      bool
      operator!=(const input_iterator_wrapper& in) const
      {
        return !(*this == in);
      }
  
!     T*
!     base() const
      {
        return ptr;
      }
  
!     T&
!     operator*() const
      {
        ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
        ITERATOR_VERIFY(ptr >= SharedInfo->first);
        return *ptr;
      }
  
!     T*
!     operator->() const
      {
        return &**this;
      }
  
      input_iterator_wrapper&
      operator++()
      {
--- 284,317 ----
        return ptr == in.ptr;
      }
  
+     _GLIBCXX14_CONSTEXPR
      bool
      operator!=(const input_iterator_wrapper& in) const
      {
        return !(*this == in);
      }
  
!     _GLIBCXX_CONSTEXPR
!     T* base() const
      {
        return ptr;
      }
  
!     _GLIBCXX14_CONSTEXPR
!     T& operator*() const
      {
        ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
        ITERATOR_VERIFY(ptr >= SharedInfo->first);
        return *ptr;
      }
  
!     _GLIBCXX14_CONSTEXPR
!     T* operator->() const
      {
        return &**this;
      }
  
+     _GLIBCXX14_CONSTEXPR
      input_iterator_wrapper&
      operator++()
      {
*************** namespace __gnu_test
*** 300,305 ****
--- 322,328 ----
        return *this;
      }
  
+     _GLIBCXX14_CONSTEXPR
      post_inc_proxy
      operator++(int)
      {
*************** namespace __gnu_test
*** 340,349 ****
--- 363,374 ----
      typedef BoundsContainer<T> ContainerType;
      typedef std::forward_iterator_tag iterator_category;
  
+     _GLIBCXX14_CONSTEXPR
      forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
      : input_iterator_wrapper<T>(_ptr, SharedInfo_in)
      { }
  
+     _GLIBCXX14_CONSTEXPR
      forward_iterator_wrapper()
      { }
  
*************** namespace __gnu_test
*** 354,370 ****
      operator=(const forward_iterator_wrapper&) = default;
  #endif
  
!     T&
!     operator*() const
      {
        ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
        return *(this->ptr);
      }
  
!     T*
!     operator->() const
      { return &**this; }
  
      forward_iterator_wrapper&
      operator++()
      {
--- 379,396 ----
      operator=(const forward_iterator_wrapper&) = default;
  #endif
  
!     _GLIBCXX14_CONSTEXPR
!     T& operator*() const
      {
        ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
        return *(this->ptr);
      }
  
!     _GLIBCXX14_CONSTEXPR
!     T* operator->() const
      { return &**this; }
  
+     _GLIBCXX14_CONSTEXPR
      forward_iterator_wrapper&
      operator++()
      {
*************** namespace __gnu_test
*** 373,378 ****
--- 399,405 ----
        return *this;
      }
  
+     _GLIBCXX14_CONSTEXPR
      forward_iterator_wrapper
      operator++(int)
      {
*************** namespace __gnu_test
*** 382,389 ****
      }
  
  #if __cplusplus >= 201402L
!     bool
!     operator==(const forward_iterator_wrapper& it) const noexcept
      {
        // Since C++14 value-initialized forward iterators are comparable.
        if (this->SharedInfo == nullptr || it.SharedInfo == nullptr)
--- 409,416 ----
      }
  
  #if __cplusplus >= 201402L
!     constexpr
!     bool operator==(const forward_iterator_wrapper& it) const noexcept
      {
        // Since C++14 value-initialized forward iterators are comparable.
        if (this->SharedInfo == nullptr || it.SharedInfo == nullptr)
*************** namespace __gnu_test
*** 394,401 ****
        return base_this == base_that;
      }
  
!     bool
!     operator!=(const forward_iterator_wrapper& it) const noexcept
      {
        return !(*this == it);
      }
--- 421,428 ----
        return base_this == base_that;
      }
  
!     constexpr
!     bool operator!=(const forward_iterator_wrapper& it) const noexcept
      {
        return !(*this == it);
      }
*************** namespace __gnu_test
*** 415,424 ****
--- 442,453 ----
      typedef BoundsContainer<T> ContainerType;
      typedef std::bidirectional_iterator_tag iterator_category;
  
+     _GLIBCXX14_CONSTEXPR
      bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
      : forward_iterator_wrapper<T>(_ptr, SharedInfo_in)
      { }
  
+     _GLIBCXX14_CONSTEXPR
      bidirectional_iterator_wrapper()
      : forward_iterator_wrapper<T>()
      { }
*************** namespace __gnu_test
*** 431,436 ****
--- 460,466 ----
      operator=(const bidirectional_iterator_wrapper&) = default;
  #endif
  
+     _GLIBCXX14_CONSTEXPR
      bidirectional_iterator_wrapper&
      operator++()
      {
*************** namespace __gnu_test
*** 439,444 ****
--- 469,475 ----
        return *this;
      }
  
+     _GLIBCXX14_CONSTEXPR
      bidirectional_iterator_wrapper
      operator++(int)
      {
*************** namespace __gnu_test
*** 447,452 ****
--- 478,484 ----
        return tmp;
      }
  
+     _GLIBCXX14_CONSTEXPR
      bidirectional_iterator_wrapper&
      operator--()
      {
*************** namespace __gnu_test
*** 455,460 ****
--- 487,493 ----
        return *this;
      }
  
+     _GLIBCXX14_CONSTEXPR
      bidirectional_iterator_wrapper
      operator--(int)
      {
*************** namespace __gnu_test
*** 478,487 ****
--- 511,522 ----
      typedef BoundsContainer<T> ContainerType;
      typedef std::random_access_iterator_tag iterator_category;
  
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
      : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in)
      { }
  
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper()
      : bidirectional_iterator_wrapper<T>()
      { }
*************** namespace __gnu_test
*** 494,499 ****
--- 529,535 ----
      operator=(const random_access_iterator_wrapper&) = default;
  #endif
  
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper&
      operator++()
      {
*************** namespace __gnu_test
*** 502,507 ****
--- 538,544 ----
        return *this;
      }
  
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper
      operator++(int)
      {
*************** namespace __gnu_test
*** 510,515 ****
--- 547,553 ----
        return tmp;
      }
  
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper&
      operator--()
      {
*************** namespace __gnu_test
*** 518,523 ****
--- 556,562 ----
        return *this;
      }
  
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper
      operator--(int)
      {
*************** namespace __gnu_test
*** 526,531 ****
--- 565,571 ----
        return tmp;
      }
  
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper&
      operator+=(std::ptrdiff_t n)
      {
*************** namespace __gnu_test
*** 542,551 ****
--- 582,593 ----
        return *this;
      }
  
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper&
      operator-=(std::ptrdiff_t n)
      { return *this += -n; }
  
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper
      operator-(std::ptrdiff_t n) const
      {
*************** namespace __gnu_test
*** 553,558 ****
--- 595,601 ----
        return tmp -= n;
      }
  
+     _GLIBCXX14_CONSTEXPR
      std::ptrdiff_t
      operator-(const random_access_iterator_wrapper<T>& in) const
      {
*************** namespace __gnu_test
*** 560,601 ****
        return this->ptr - in.ptr;
      }
  
!     T&
!     operator[](std::ptrdiff_t n) const
      { return *(*this + n); }
  
!     bool
!     operator<(const random_access_iterator_wrapper<T>& in) const
      {
        ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
        return this->ptr < in.ptr;
      }
  
!     bool
!     operator>(const random_access_iterator_wrapper<T>& in) const
      {
        return in < *this;
      }
  
!     bool
!     operator>=(const random_access_iterator_wrapper<T>& in) const
      {
        return !(*this < in);
      }
  
!     bool
!     operator<=(const random_access_iterator_wrapper<T>& in) const
      {
        return !(*this > in);
      }
    };
  
    template<typename T>
      random_access_iterator_wrapper<T>
      operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n)
      { return it += n; }
  
    template<typename T>
      random_access_iterator_wrapper<T>
      operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it)
      { return it += n; }
--- 603,646 ----
        return this->ptr - in.ptr;
      }
  
!     _GLIBCXX14_CONSTEXPR
!     T& operator[](std::ptrdiff_t n) const
      { return *(*this + n); }
  
!     _GLIBCXX14_CONSTEXPR
!     bool operator<(const random_access_iterator_wrapper<T>& in) const
      {
        ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
        return this->ptr < in.ptr;
      }
  
!     _GLIBCXX14_CONSTEXPR
!     bool operator>(const random_access_iterator_wrapper<T>& in) const
      {
        return in < *this;
      }
  
!     _GLIBCXX14_CONSTEXPR
!     bool operator>=(const random_access_iterator_wrapper<T>& in) const
      {
        return !(*this < in);
      }
  
!     _GLIBCXX14_CONSTEXPR
!     bool operator<=(const random_access_iterator_wrapper<T>& in) const
      {
        return !(*this > in);
      }
    };
  
    template<typename T>
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper<T>
      operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n)
      { return it += n; }
  
    template<typename T>
+     _GLIBCXX14_CONSTEXPR
      random_access_iterator_wrapper<T>
      operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it)
      { return it += n; }
*************** namespace __gnu_test
*** 613,626 ****
--- 658,674 ----
    {
      typename ItType<T>::ContainerType bounds;
  
+     _GLIBCXX_CONSTEXPR
      test_container(T* _first, T* _last) : bounds(_first, _last)
      { }
  
      template<std::size_t N>
        explicit
+       _GLIBCXX_CONSTEXPR
        test_container(T (&arr)[N]) : bounds(arr, arr+N)
        { }
  
+     _GLIBCXX14_CONSTEXPR
      ItType<T>
      it(int pos)
      {
*************** namespace __gnu_test
*** 628,633 ****
--- 676,682 ----
        return ItType<T>(bounds.first + pos, &bounds);
      }
  
+     _GLIBCXX14_CONSTEXPR
      ItType<T>
      it(T* pos)
      {
*************** namespace __gnu_test
*** 635,652 ****
--- 684,705 ----
        return ItType<T>(pos, &bounds);
      }
  
+     _GLIBCXX_CONSTEXPR
      const T&
      val(int pos)
      { return (bounds.first)[pos]; }
  
+     _GLIBCXX14_CONSTEXPR
      ItType<T>
      begin()
      { return it(bounds.first); }
  
+     _GLIBCXX14_CONSTEXPR
      ItType<T>
      end()
      { return it(bounds.last); }
  
+     _GLIBCXX_CONSTEXPR
      std::size_t
      size() const
      { return bounds.size(); }
*************** namespace __gnu_test
*** 686,691 ****
--- 739,745 ----
        // Use an integer-class type to try and break the library code.
        using difference_type = std::ranges::__detail::__max_diff_type;
  
+       constexpr
        contiguous_iterator_wrapper&
        operator++()
        {
*************** namespace __gnu_test
*** 693,698 ****
--- 747,753 ----
  	return *this;
        }
  
+       constexpr
        contiguous_iterator_wrapper&
        operator--()
        {
*************** namespace __gnu_test
*** 700,705 ****
--- 755,761 ----
  	return *this;
        }
  
+       constexpr
        contiguous_iterator_wrapper
        operator++(int)
        {
*************** namespace __gnu_test
*** 708,713 ****
--- 764,770 ----
  	return tmp;
        }
  
+       constexpr
        contiguous_iterator_wrapper
        operator--(int)
        {
*************** namespace __gnu_test
*** 716,721 ****
--- 773,779 ----
  	return tmp;
        }
  
+       constexpr
        contiguous_iterator_wrapper&
        operator+=(difference_type n)
        {
*************** namespace __gnu_test
*** 724,746 ****
  	return *this;
        }
  
!       friend contiguous_iterator_wrapper
        operator+(contiguous_iterator_wrapper iter, difference_type n)
        { return iter += n; }
  
!       friend contiguous_iterator_wrapper
        operator+(difference_type n, contiguous_iterator_wrapper iter)
        { return iter += n; }
  
        contiguous_iterator_wrapper&
        operator-=(difference_type n)
        { return *this += -n; }
  
!       friend contiguous_iterator_wrapper
        operator-(contiguous_iterator_wrapper iter, difference_type n)
        { return iter -= n; }
  
!       friend difference_type
        operator-(contiguous_iterator_wrapper l, contiguous_iterator_wrapper r)
        {
  	const random_access_iterator_wrapper<T>& lbase = l;
--- 782,809 ----
  	return *this;
        }
  
!       friend constexpr
!       contiguous_iterator_wrapper
        operator+(contiguous_iterator_wrapper iter, difference_type n)
        { return iter += n; }
  
!       friend constexpr
!       contiguous_iterator_wrapper
        operator+(difference_type n, contiguous_iterator_wrapper iter)
        { return iter += n; }
  
+       constexpr
        contiguous_iterator_wrapper&
        operator-=(difference_type n)
        { return *this += -n; }
  
!       friend constexpr
!       contiguous_iterator_wrapper
        operator-(contiguous_iterator_wrapper iter, difference_type n)
        { return iter -= n; }
  
!       friend constexpr
!       difference_type
        operator-(contiguous_iterator_wrapper l, contiguous_iterator_wrapper r)
        {
  	const random_access_iterator_wrapper<T>& lbase = l;
*************** namespace __gnu_test
*** 748,753 ****
--- 811,817 ----
  	return static_cast<difference_type>(lbase - rbase);
        }
  
+       constexpr
        decltype(auto) operator[](difference_type n) const
        {
  	auto d = static_cast<std::ptrdiff_t>(n);
*************** namespace __gnu_test
*** 765,770 ****
--- 829,835 ----
      {
        using input_iterator_wrapper<T>::input_iterator_wrapper;
  
+       constexpr
        input_iterator_wrapper_nocopy()
  	: input_iterator_wrapper<T>(nullptr, nullptr)
        { }
*************** namespace __gnu_test
*** 779,784 ****
--- 844,850 ----
  
        using input_iterator_wrapper<T>::operator++;
  
+       constexpr
        input_iterator_wrapper_nocopy&
        operator++()
        {
*************** namespace __gnu_test
*** 795,800 ****
--- 861,867 ----
  
        using input_iterator_wrapper<T>::operator++;
  
+       constexpr
        input_iterator_wrapper_rval&
        operator++()
        {
*************** namespace __gnu_test
*** 802,809 ****
  	return *this;
        }
  
!       T&&
!       operator*() const
        { return std::move(input_iterator_wrapper<T>::operator*()); }
      };
  
--- 869,876 ----
  	return *this;
        }
  
!       constexpr
!       T&& operator*() const
        { return std::move(input_iterator_wrapper<T>::operator*()); }
      };
  
*************** namespace __gnu_test
*** 821,827 ****
  
  	using Iter<T>::operator++;
  
! 	iterator& operator++() { Iter<T>::operator++(); return *this; }
        };
  
        template<typename I>
--- 888,896 ----
  
  	using Iter<T>::operator++;
  
! 	constexpr
! 	iterator& operator++()
!        	{ Iter<T>::operator++(); return *this; }
        };
  
        template<typename I>
*************** namespace __gnu_test
*** 829,849 ****
  	{
  	  T* end;
  
! 	  friend bool operator==(const sentinel& s, const I& i) noexcept
  	  { return s.end == i.ptr; }
  
! 	  friend auto operator-(const sentinel& s, const I& i) noexcept
  	    requires std::random_access_iterator<I>
  	  { return std::iter_difference_t<I>(s.end - i.ptr); }
  
! 	  friend auto operator-(const I& i, const sentinel& s) noexcept
  	    requires std::random_access_iterator<I>
  	  { return std::iter_difference_t<I>(i.ptr - s.end); }
  	};
  
      protected:
!       auto
!       get_iterator(T* p)
        {
  	if constexpr (std::default_initializable<Iter<T>>)
  	  return Iter<T>(p, &bounds);
--- 898,921 ----
  	{
  	  T* end;
  
! 	  friend constexpr bool
! 	  operator==(const sentinel& s, const I& i) noexcept
  	  { return s.end == i.ptr; }
  
! 	  friend constexpr
! 	  auto operator-(const sentinel& s, const I& i) noexcept
  	    requires std::random_access_iterator<I>
  	  { return std::iter_difference_t<I>(s.end - i.ptr); }
  
! 	  friend constexpr auto
! 	  operator-(const I& i, const sentinel& s) noexcept
  	    requires std::random_access_iterator<I>
  	  { return std::iter_difference_t<I>(i.ptr - s.end); }
  	};
  
      protected:
!       constexpr
!       auto get_iterator(T* p)
        {
  	if constexpr (std::default_initializable<Iter<T>>)
  	  return Iter<T>(p, &bounds);
*************** namespace __gnu_test
*** 852,868 ****
        }
  
      public:
        test_range(T* first, T* last) : bounds(first, last)
        { }
  
        template<std::size_t N>
! 	explicit
  	test_range(T (&arr)[N]) : test_range(arr, arr+N)
  	{ }
  
!       auto begin() & { return get_iterator(bounds.first); }
  
!       auto end() &
        {
  	using I = decltype(get_iterator(bounds.last));
  	return sentinel<I>{bounds.last};
--- 924,942 ----
        }
  
      public:
+       constexpr
        test_range(T* first, T* last) : bounds(first, last)
        { }
  
        template<std::size_t N>
! 	explicit constexpr
  	test_range(T (&arr)[N]) : test_range(arr, arr+N)
  	{ }
  
!       constexpr auto begin() &
!       { return get_iterator(bounds.first); }
  
!       constexpr auto end() &
        {
  	using I = decltype(get_iterator(bounds.last));
  	return sentinel<I>{bounds.last};
*************** namespace __gnu_test
*** 875,881 ****
    template<typename T, template<typename> class Iter>
      struct test_range_nocopy : test_range<T, Iter>
      {
!       test_range_nocopy(T* first, T* last) : test_range<T, Iter>(first, last)
        {}
  
        test_range_nocopy(test_range_nocopy&&) = default;
--- 949,957 ----
    template<typename T, template<typename> class Iter>
      struct test_range_nocopy : test_range<T, Iter>
      {
!       constexpr
!       test_range_nocopy(T* first, T* last)
!       : test_range<T, Iter>(first, last)
        {}
  
        test_range_nocopy(test_range_nocopy&&) = default;
*************** namespace __gnu_test
*** 910,915 ****
--- 986,992 ----
      {
        using test_range<T, Iter>::test_range;
  
+       constexpr
        std::size_t size() const noexcept
        { return this->bounds.size(); }
      };
*************** namespace __gnu_test
*** 945,962 ****
  	{
  	  T* end;
  
! 	  friend bool operator==(const sentinel& s, const I& i) noexcept
  	  { return s.end == i.ptr; }
  
! 	  friend std::iter_difference_t<I>
  	  operator-(const sentinel& s, const I& i) noexcept
  	  { return std::iter_difference_t<I>(s.end - i.ptr); }
  
! 	  friend std::iter_difference_t<I>
  	  operator-(const I& i, const sentinel& s) noexcept
  	  { return std::iter_difference_t<I>(i.ptr - s.end); }
  	};
  
        auto end() &
        {
  	using I = decltype(this->get_iterator(this->bounds.last));
--- 1022,1043 ----
  	{
  	  T* end;
  
! 	  friend constexpr
! 	  bool operator==(const sentinel& s, const I& i) noexcept
  	  { return s.end == i.ptr; }
  
! 	  friend constexpr
! 	  std::iter_difference_t<I>
  	  operator-(const sentinel& s, const I& i) noexcept
  	  { return std::iter_difference_t<I>(s.end - i.ptr); }
  
! 	  friend constexpr
! 	  std::iter_difference_t<I>
  	  operator-(const I& i, const sentinel& s) noexcept
  	  { return std::iter_difference_t<I>(i.ptr - s.end); }
  	};
  
+       constexpr
        auto end() &
        {
  	using I = decltype(this->get_iterator(this->bounds.last));
