Marek Polacek [Thu, 7 May 2026 20:38:34 +0000 (16:38 -0400)]
c++/reflection: fixes for comparing reflections [PR125208]
This fixes two bugs:
1) crash in cp_tree_equal when comparing reflections with binfos;
cp_tree_equal doesn't handle those. We're coming from
lookup_template_class -> spec_hasher::equal -> comp_template_args
-> cp_tree_equal. We should use compare_reflections in cp_tree_equal.
2) the fix for 1) revealed that compare_reflections is buggy when
comparing two aliases: we shouldn't fall back to same_type_p
because given
using A = int;
using B = int;
^^A != ^^B should hold.
PR c++/125208
gcc/cp/ChangeLog:
* reflect.cc (compare_reflections): Use == when comparing two
aliases.
* tree.cc (cp_tree_equal) <case REFLECT_EXPR>: Use
compare_reflections.
gcc/testsuite/ChangeLog:
* g++.dg/reflect/alias3.C: New test.
* g++.dg/reflect/bases_of5.C: New test.
Andrew Pinski [Mon, 11 May 2026 21:34:58 +0000 (14:34 -0700)]
contrib: Fix check_GNU_style.py for some .opt issues [PR125275]
I noticed while reviewing a patch check_GNU_style.py would fail
for the .opt files in a few ways. First greater than 80 columns
is expected. Second is the space after the "function".
Both of these are not useful for .opt so let's ignore then here.
PR other/125275
contrib/ChangeLog:
* check_GNU_style_lib.py (LineLengthCheck.check): Ignore
filenames that end with .opt.
(FunctionParenthesisCheck.check): Likewise.
Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
Jason Merrill [Mon, 11 May 2026 15:55:06 +0000 (11:55 -0400)]
c-family: look through non-user-facing typedef [PR124621]
'aka' printing shouldn't differ between in-tree and installed compilers due
to difference in whether libstdc++ headers are considered to be system
headers. The problem was that if we encounter a non-user-facing typedef
like __iter_type<T>, we stopped there instead of continuing to look through
typedefs to find the underlying user type.
Jerry DeLisle [Sat, 9 May 2026 18:49:21 +0000 (11:49 -0700)]
fortran: Add -fcoarray=shared option to auto-link -lcaf_shmem
The new -fcoarray=shared option provides a convenient shorthand for
the common invocation -fcoarray=lib -lcaf_shmem. The driver transforms
-fcoarray=shared into -fcoarray=lib for the frontend and automatically
appends -lcaf_shmem to the link command. Existing uses of -fcoarray=lib
are unaffected.
* lang.opt (fcoarray=): Add shared enum value; update help text.
* gfortranspec.cc (CAF_SHMEM_LIBRARY): New macro.
(lang_specific_driver): Detect -fcoarray=shared in first pass and
set need_caf_shmem flag. In second pass, transform -fcoarray=shared
to -fcoarray=lib for cc1. Append -lcaf_shmem when need_caf_shmem
is set and linking is active.
xtensa: Assert the results of several validate_change() calls
I regret that I've been using validate_change() thoughtlessly until now,
and should at least verify whether the RTX changes were successful.
I hope this patch doesn't cause any problems, but if not, I will take some
kind of new action.
gcc/ChangeLog:
* config/xtensa/xtensa.cc
(FPreg_neg_scaled_simm12b, convert_SF_const, constantsynth_pass1,
litpool_set_src_1, litpool_set_src):
Change each call to validate_change() and apply_change_group() to
trigger an ICE if the result is not true.
* config/xtensa/xtensa.cc
(xtensa_can_eliminate_callee_saved_reg_p):
Change the arguments that return values from being passed by pointer
to C++ reference.
(xtensa_expand_prologue):
Adjust the call to xtensa_can_eliminate_callee_saved_reg_p() to
match the above changes.
Since the commit of the preceding patch for IRA, "ira: Scale save/restore
costs of callee save registers with block frequency" (3b9b8d6cfdf59337f4b7ce10ce92a98044b2657b),
the Xtensa ISA has shown a tendency to allocate slightly more function stack
frames, especially when using the CALL0 ABI.
/* example */
extern void foo(void);
int test(int a) {
int array[252];
foo();
asm volatile (""::"m"(array));
return a;
}
Pan Li [Fri, 8 May 2026 01:41:01 +0000 (09:41 +0800)]
Match: Move saturation alu patterns into match-sat-alu.pd [NFC]
Given there are lots of sat alu patterns in match.pd, and
there will more in short future. Move all of them into
a separated file for better org.
The below test suites are passed for this patch:
1. The rv64gcv fully regression tests.
2. The x86 bootstrap tests.
3. The x86 fully regression tests.
gcc/ChangeLog:
* Makefile.in: Add match-sat-alu.pd as dependency.
* match.pd: Remove saturation alu related patterns.
* match-sat-alu.pd: Add new file for saturation alu patterns.
Oleg Tolmatcev [Wed, 6 May 2026 17:20:31 +0000 (19:20 +0200)]
i386: Keep SEH enabled for Win64 sysv_abi functions
TARGET_SEH currently depends on TARGET_64BIT_MS_ABI. For Win64
functions compiled with SysV ABI, that makes the SEH hooks drop out
even though exception handling still emits .seh_handlerdata. The
result is assembly with .seh_handlerdata outside any .seh_proc block.
Keep TARGET_SEH enabled for all 64-bit Windows functions when unwind
tables are requested so SEH prologue and handler state remains
consistent across ABI variants.
Add a regression test covering a SysV ABI wrapper trampoline that
references a throwing callee on x86_64 mingw.
gcc/ChangeLog:
* config/i386/cygming.h (TARGET_SEH): Keep SEH enabled for all
64-bit Windows functions when unwind tables are requested.
gcc/testsuite/ChangeLog:
* g++.target/i386/seh-sysvabi-wrap1.C: New test.
Signed-off-by: oltolm <oleg.tolmatcev@gmail.com> Signed-off-by: Jonathan Yong <10walls@gmail.com>
Richard Biener [Mon, 11 May 2026 08:25:57 +0000 (10:25 +0200)]
tree-optimization/125250 - LIM speculating not noop load/store
The following avoids speculating a load/store pair for modes
that cannot transfer bits or, as for the testcase, bitfield
loads that are either value changing or invoke UB when out-of-bound
(and that we'd rewrite to be defined with explicit truncation).
PR tree-optimization/125250
* tree-ssa-loop-im.cc (execute_sm): For modes that cannot
transfer bits, _Bool and bitfield accesses force the
multi-threaded model.
LIU Hao [Fri, 8 May 2026 13:02:23 +0000 (21:02 +0800)]
mingw: Ensure symbols are quoted in Intel syntax
Previously, this code
extern int shl;
int get_shl(void) { return shl; }
gave errors like
$ x86_64-w64-mingw32-gcc -masm=intel test.c
ccUSyr0f.s: Assembler messages:
ccUSyr0f.s:24: Error: invalid use of operator "shl"
because it contained
.refptr.shl:
.quad shl
This `shl` should have referenced the symbol, but it appeared in an expression
context, where, in Intel syntax, it got interpreted as the shift-left operator.
This commit fixes the issue by emitting the target symbol with
`ASM_OUTPUT_LABELREF`, which will quote it properly with regard to the output
assembler syntax.
PR target/53929
gcc/ChangeLog:
* config/mingw/winnt.cc (mingw_pe_file_end): Use `ASM_OUTPUT_LABELREF`
to emit `name`.
Signed-off-by: LIU Hao <lh_mouse@126.com> Signed-off-by: Jonathan Yong <10walls@gmail.com>
Tomasz Kamiński [Wed, 6 May 2026 13:22:06 +0000 (15:22 +0200)]
libstdc++: Reorder compile-time checks for __formatter_str::_M_format_range.
If _M_format_range was called with prvalue of span S (or any contiguous_range),
the previous chain of if-contexpr will call _M_format_range<S&>, then
_M_format_range<const S&> and then format(string_view). By checking for
contiguous_range first, it calls format(string_view) direclty, removing
unnecessary instantiations and symbols.
Similary, for all prvalues of type R, that meet __simply_formattable_range R,
we were instantiating _M_format_range<R&> and then _M_format_range<const R&>.
By moving the if for __simply_formattable_range before is_lvalue_reference_v,
we call _M_format_range<const R&> direclty.
libstdc++-v3/ChangeLog:
* include/std/format (__formatter_str::_M_format_range):
Reorder constexpr checks, to reduce number of instantiations.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
Richard Biener [Wed, 6 May 2026 11:43:27 +0000 (13:43 +0200)]
adjust OMP SIMD call cost
The following adds special handling to OMP SIMD vector call costs
which were not costed at all and for which a single simple vector
stmt isn't appropriate. PR125174 shows that even when AVX imposes
more overhead (from also slightly bogus costing) than SSE, when
there's two OMP SIMD calls involved doing less of those should trump
that.
PR target/125174
* config/i386/i386.cc (ix86_vector_costs::add_stmt_cost):
Cost calls as 10 times FMA.
combine: Reject any resulting insns using hard reg constraints [PR121426]
This fixes
t.c:6:1: error: unable to find a register to spill
6 | }
| ^
for target avr. In the PR we are given a patch which makes use of hard
register constraints in the machine description for divmodhi4. Prior
combine we have for the test from the PR
The patched instruction divmodhi4 constraints operand 2 (here pseudo
48) to hard register 22. Combine merges insn 7 into 9 by crossing a
hard register assignment of register 22.
This leaves us with a conflict for pseudo 48 in the updated insn 9 since
register 22 is live here.
Fixed by pulling the sledge hammer and rejecting any resulting insn
which makes use of hard register constraints. Ideally we would skip
based on the fact whether a combination crosses a hard register
assignment and the corresponding hard register is also referred by a
single register constraint of the resulting insn.
PR rtl-optimization/121426
gcc/ChangeLog:
* combine.cc (recog_for_combine_1): Reject insns which make use
of hard register constraints.
Naveen [Mon, 11 May 2026 05:45:41 +0000 (22:45 -0700)]
[PATCH] [Aarch64]: Use fmov for some low-lane FP SIMD constant vectors
Extend AdvSIMD constant materialization to recognize vectors where only
the low element is a representable floating-point constant and all other
elements are zero.
Bootstrapped and tested on aarch64-linux-gnu.
PR target/113856
gcc/ChangeLog:
* config/aarch64/aarch64-protos.h
(aarch64_output_simd_mov_imm_low): New.
(aarch64_const_vec_fmov_p): New.
* config/aarch64/aarch64-simd.md (mov<mode>): Do not expand constant
vectors handled by aarch64_const_vec_fmov_p into VDUP.
(*aarch64_simd_mov<VDMOV:mode>): Add Dc alternatives for FMOV based
SIMD constant moves.
(*aarch64_simd_mov<VQMOV:mode>): Likewise.
* config/aarch64/aarch64.cc (aarch64_const_vec_fmov_p): New function.
(aarch64_output_simd_mov_imm_low): New function.
* config/aarch64/constraints.md (Dc): New constraint.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/pr113856.c: New test.
[PATCH] combine: Check against CLOBBER in make_compound_operation_int [PR125209]
In combine_simplify_rtx, CLOBBER can be returned, which is propagated to
make_compound_operation. When make_compound_operation_int then calls
simplify_subreg, it triggers a gcc_assert, because the mode is neither inner,
nor void. This results in an ICE.
We fix this by checking if we got CLOBBER before calling simplify_subreg from
make_compound_operation and bail out; we return NULL_RTX.
Testcase from the bug report by Zhendong Su.
Bootstrapped and tested on x86_64-linux-gnu.
PR rtl-optimization/125209
gcc/
* combine.cc (make_compound_operation_int): Return NULL_RTX if we got CLOBBER.
gcc/testsuite/
* gcc.dg/pr125209.c: New test.
Signed-off-by: Boudewijn van der Heide <boudewijn@delta-utec.com>
The first operand of the IOR clears the low bit of the source register leaving
everything else unchanged. The second operand of the IOR clears everything but
the low bit and flips the low bit. When we IOR those together we get the
original value with the lowest bit flipped. The key is to realize we have the
same pseudo in both arms and there are no bits in common for the constants. So
this works for an arbitrary bit(s) as long as the constants have the right
form.
That gets us good code on riscv and almost certainly helps other targets.
There is another form which shows up on the H8 and possibly other targets
sub-word arithmetic. op0 and op1 are respectively:
Note we're in QImode. op1 just flips the highest QImode bit. If there are
carry-outs, we don't really care about them. The net is we can capture that
case on the H8 by verifying this form flips the highest bit for the given mode.
Otherwise the carry-outs are relevant and our transformation is incorrect.
Plan is to commit Friday. While it has been tested with the usual bootstraps
as well as testing on various cross platforms, I'm more comfortable giving
folks time to take a looksie to see if Shreya or I missed anything critical.
For the testcase in question before/afters look like this:
PR rtl-optimization/80770
gcc/
* rtl.h (simplify_context::simplify_ior_with_common_term): Add
new method.
(simplify_context::simplify_binary_operation_1): Use new method.
* simplify-rtx.cc (simplify_context::simplify_ior_with_common_term):
New method.
gcc/testsuite/
* gcc.target/riscv/pr80770.c: New test.
* gcc.target/riscv/pr80770-2.c: New test.
* gcc.target/h8300/pr80770.c: New test.
* gcc.target/h8300/pr80770-2.c: New test.
Co-authored-by: Jeff Law <jeffrey.law@oss.qualcomm.com>
Eric Botcazou [Sun, 10 May 2026 10:51:44 +0000 (12:51 +0200)]
Ada: Fix Image for derived enumeration type with representation clause
The problem is that Expand_Image_Attribute incorrectly fetches the root type
for enumeration types, thus bypassing a clause present on the derived type.
The fix is to change the two fields Lit_Indexes and Lit_Strings defined for
enumeration types and subtypes to be formally present on root types only, as
well as to make Expand_Image_Attribute stick to base types.
gcc/ada/
PR ada/125240
* gen_il-gen-gen_entities.adb (Enumeration_Kind): Make
Lit_Indexes and Lit_Strings be defined for root types only.
* einfo.ads (Lit_Hash): Adjust description.
(Lit_Indexes): Likewise.
(Lit_Strings): Likewise.
(E_Enumeration_Type): Likewise.
* exp_imgv.adb (Expand_Image_Attribute): Do not fetch the root type
for enumeration types, except for character types, and adjust.
PR target/125238
* config/i386/i386-features.cc (ix86_broadcast_inner): Set kind
to X86_CSE_CONST_VECTOR if the vector load can be converted to
constant integer load.
gcc/testsuite/
PR target/125238
* gcc.target/i386/pr125238.c: New test.
Paul Thomas [Fri, 8 May 2026 05:34:21 +0000 (06:34 +0100)]
Fortran: Allow access to coarray elements within modules. [PR125051]
The parts of this patch is fix the problem are chunks 2 and 3. Chunk3 prevents
gfc_conv_intrinsic_caf_get from working in the module namespace, when the array
symbol is in a module. Equally, though, gfc_current_ns is not necessarily in
the referencing procedure namespace. The second chunk makes sure that this is
the case. As an aside, it seems to us that it makes considerably more sense that
gfc_current_ns be that of the current procedure. The first chunk makes sure that
result symbol initialization does not occur outside the function.
Passes regtesting with FC44/x86_64.
2026-05-10 Andre Vehreschild <vehre@gcc.gnu.org>
Paul Thomas <pault@gcc.gnu.org>
gcc/fortran
PR fortran/125051
* trans-decl.cc (gfc_get_symbol_decl): gfc_defer_symbol_init
must not be called for PDT types, classes or types with PDT
(gfc_generate_function_code): If gfc_current_ns is not the same
as the function namespace, stash it,change it to the function
namespace and restore after translation of the code.
* trans-intrinsic.cc (gfc_conv_intrinsic_caf_get): If the array
is in a module, use the symbol namespace.
* trans-openmp.cc (gfc_trans_omp_array_reduction_or_udr): If the
current namespace is not that of the procedure, change to the
procedure namspace and revert on leaving this function.
gcc/testsuite/
PR fortran/125051
* gfortran.dg/coarray/pr125051.f90: New test.
riscv_expand_epilogue will skip emitting sspopchk when cm.popret is
emitted. After this patch we will no longer emit cm.popret and instead
use cm.pop + sspopchk + a regular return:
sspush ra
cm.push {ra, s0-s1}, -32
..
cm.pop {ra, s0-s1}, 32
sspopchk ra
jr ra
Andrew Pinski [Sat, 9 May 2026 01:32:50 +0000 (18:32 -0700)]
cfghooks: constifify cfg_hooks [PR117871]
This constifies the hooks so the structs can't be changed at runtime.
The only odd place where we need to handle special is sel-sched.
This is because we make a copy of the current cfghooks and then
use its own. This changes things slightly there, there is still a
copy used but instead of copying back into the current cfghooks, we
just change the pointer back to the original one. This code is only
enabled by ia64 backend by default so I doubt it will change.
Boostrapped and tested on x86_64-linux-gnu.
PR middle-end/117871
gcc/ChangeLog:
* cfghooks.cc (cfg_hooks): Change the type
to be a pointer to a const struct cfg_hooks.
(get_cfg_hooks): Return the current pointer
rather the struct.
(set_cfg_hooks): Change the argument type and
set the cfg_hooks directly to it.
* cfghooks.h (gimple_cfg_hooks): Constify.
(rtl_cfg_hooks): Likewise.
(cfg_layout_rtl_cfg_hooks): Likewise.
(get_cfg_hooks): Update declration.
(set_cfg_hooks): Likewise.
* cfgrtl.cc (rtl_cfg_hooks): Constify.
(cfg_layout_rtl_cfg_hooks): Likewise.
* sel-sched-ir.cc (orig_cfg_hooks): Change to a pointer.
(sel_create_basic_block): Update
for orig_cfg_hooks being a pointer.
(sel_register_cfg_hooks): Update for the constification
of cfg_hooks.
* tree-cfg.cc (gimple_cfg_hooks): Constify.
Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
Andrew Pinski [Sat, 9 May 2026 00:51:54 +0000 (17:51 -0700)]
cfghooks: Remove name field
Now we have an IR field, we can remove the name field. The
only time the name is used was for internal errors so having
this field outside of the hooks is better anyways.
Bootstrapped and tested on x86_64-linux-gnu.
gcc/ChangeLog:
* cfghooks.cc (current_ir_name): New function.
(dump_bb_for_graph): Use current_ir_name
instead of accessing the name field.
(dump_bb_as_sarif_properties): Likewise.
(redirect_edge_and_branch): Likewise.
(can_remove_branch_p): Likewise.
(redirect_edge_and_branch_force): Likewise.
(split_block_1): Likewise.
(move_block_after): Likewise.
(delete_basic_block): Likewise.
(split_edge): Likewise.
(create_basic_block_1): Likewise.
(can_merge_blocks_p): Likewise.
(predict_edge): Likewise.
(predicted_by_p): Likewise.
(merge_blocks): Likewise.
(make_forwarder_block): Likewise.
(force_nonfallthru): Likewise.
(can_duplicate_block_p): Likewise.
(duplicate_block): Likewise.
(block_ends_with_call_p): Likewise.
(block_ends_with_condjump_p): Likewise.
(flow_call_edges_add): Likewise.
* cfghooks.h (struct cfg_hooks): Remove the name
field.
* cfgrtl.cc (rtl_cfg_hooks): Update for the removal
of the name field.
(cfg_layout_rtl_cfg_hooks): Likewise.
* tree-cfg.cc (struct cfg_hooks): Likewise.
Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
Andrew Pinski [Sat, 9 May 2026 00:16:10 +0000 (17:16 -0700)]
cfghooks: Move ir_type inside cfghooks
This is the first step in constification (and/or C++ification)
of the cfghooks. Currently we compare variables to figure out
what the current IR type is. Rather let's move the ir_type
into the cfghooks. This will help with constification due
to sel-sched overloading one of the hooks.
Bootstrapped and tested on x86_64-linux-gnu.
gcc/ChangeLog:
* cfghooks.cc (current_ir_type): Return cfghooks' ir field.
* cfghooks.h (struct cfg_hooks): Add ir field.
* cfgrtl.cc (rtl_cfg_hooks): Update for new ir field.
(cfg_layout_rtl_cfg_hooks): Likewise.
* tree-cfg.cc (gimple_cfg_hooks): Likewise.
Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
PR target/125239
* config/i386/i386-features.cc (ix86_place_single_vector_set):
For CONST_VECTOR source, check CONST0_RTX with
X86_CSE_CONST0_VECTOR and CONSTM1_RTX with X86_CSE_CONSTM1_VECTOR.
(ix86_broadcast_inner): Set x86_cse kind to X86_CSE_CONST0_VECTOR
for CONST0_RTX and X86_CSE_CONSTM1_VECTOR for CONSTM1_RTX.
gcc/testsuite/
PR target/125239
* gcc.target/i386/pr124407-1.c: Adjusted.
* gcc.target/i386/pr125239.c: New test.
Andrew Pinski [Fri, 8 May 2026 19:46:32 +0000 (12:46 -0700)]
match: Fix merged patterns for a!=b implies a and b are not zero [PR125234]
In r17-231-gc65691bc5a2873, I messed up the resulting constant for
`(a != b) & ((a | b) == 0)` and `(a == b) | ((a | b) != 0)`. I had
swapped which one was resulting in true/false. This fixes the issue
and adds a testcase to make sure it does not regress again.
Pushed as obvious after a bootstrap/test on x86_64-linux-gnu.
Marek Polacek [Thu, 7 May 2026 22:09:57 +0000 (18:09 -0400)]
c++: fix ICE with invalid targ [PR125043]
The patch that allowed DECL_NTTP_OBJECT_P in invalid_tparm_referent_p
also added the assert checking for tinfos/__func__ (r14-8189). But in
these tests we got to the assert with a temporary object coming from
create_temporary_var: either a reference temporary or compound literal
temporary. The former could be checked by seeing if the name starts
with _ZGR but the latter don't have it. So perhaps we can just check
DECL_IGNORED_P, always set for create_temporary_var objects.
PR c++/115181
PR c++/125043
PR c++/124979
gcc/cp/ChangeLog:
* pt.cc (invalid_tparm_referent_p): Allow DECL_IGNORED_P in an
assert.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1z/nontype-auto27.C: New test.
* g++.dg/cpp1z/nontype-auto28.C: New test.
* g++.dg/cpp2a/nontype-class75.C: New test.
Roger Sayle [Fri, 8 May 2026 20:06:54 +0000 (21:06 +0100)]
PR middle-end/124637: Fix passing padded constant structs in registers on big-endian targets
This patch resolves PR middle-end/124637, a wrong code regression when
passing a struct as a register on big-endian targets. On big-endian
targets, store_constructor fills fields from the most significant bits,
so for structs narrower than word size, any padding is incorrectly
placed in the least significant bytes. This issue is fixed (on
affected targets) by using a (unsigned) right shift on the value
determined by store_constructor to correctly align the structure in
the least significant bytes, and place the padding in the high bits.
Many thanks to Manjunath Matti for testing this patch on real hardware,
and Drea Pinski for reviewing/approving it. The new test case may be
a little fragile, but currently "works for me". Please feel free to
tweak it for powerpc variants/environments I've not consider/encountered.
2026-05-08 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
PR middle-end/124637
* calls.cc (load_register_parameters): If using store_constructor
to place a constant structure in a register, use a right shift to
align the structure/padding if required on big-endian targets.
gcc/testsuite/ChangeLog
PR middle-end/124637
* gcc.target/powerpc/pr124637.c: New test case.
Harald Anlauf [Fri, 8 May 2026 19:45:31 +0000 (21:45 +0200)]
libfortran: fix static analyser cppcheck warning in free_format_data [PR125087]
The static analyser cppcheck reported a pointless assignment in function
free_format_data. The intent of the assignment was to finally nullify the
pointer to allocated format data after memory has been freed. Since C does
not support references, add a level of indirection to the function argument
so that the dereferenced argument can be nullified.
PR libfortran/125087
libgfortran/ChangeLog:
* io/format.c (free_format_data): Change argument from pointer to
format_data to pointer to pointer of object.
(free_format_hash_table): Adjust argument passed to
free_format_data.
(save_parsed_format): Likewise.
* io/format.h (free_format_data): Adjust prototype.
* io/transfer.c (st_read_done_worker): Adjust argument passed to
free_format_data.
(st_write_done_worker): Likewise.
Jeff Law [Fri, 8 May 2026 17:40:29 +0000 (11:40 -0600)]
[V2][RISC-V][PR target/124955] Utilize slliw for some left shifted signed bitfield extractions
Some functional change as was already posted, this time with a testcase. Given
it's been in my tester and through the pre-commit CI system, I'm going forward
now.
--
So as the PR notes, this is an attempt to squeeze out some instructions from a
hot part of leela, the random number generator in particular.
The key is realizing that the the first two statements are just a sign extended
bitfield of length 20. That ultimately gets shifted left 12 bits. 20+12 = 32,
so we can at least conceptually use slliw (shift left sign extending result
from SI to DI). The andi just turns off the low bit.
Given a sign extracted bitfield starting at bit 0, of size N that is then left
shifted by M where N+M == 32 is a natural slliw instruction. However, when I
tried to recognize that and generate the slliw form I saw code quality
regressions that didn't look particularly reasonable to try and fix. So we
want to be more selective about recognizing that idiom. So we recognize it
when we subsequently mask off some bits and the mask can be encoded via andi.
This likely could be extended to other logical operations that don't ultimately
affect the SI sign bit.
PR target/124955
gcc/
* config/riscv/riscv.md (masked shifted bitfield extraction): New
splitter to utilize slliw to eliminate the need for sign extnesion.
Jeff Law [Fri, 8 May 2026 17:19:02 +0000 (11:19 -0600)]
[RISC-V][PR tree-optimization/93504] Handle (X & C) | ((X^Y) & ~C) -> X ^ ( Y & ~C) in simplify-rtx
This is a trivial generalization of existing simplify-rtx code. Essentially
the code in question was handling IOR, but not XOR. I'm keeping the bz open as
this probably should have been cleaned up before getting into RTL.
The net is something like this:
> #define N 0x202
> #define OP ^
>
> unsigned f(unsigned a, unsigned b)
> {
> unsigned t = a OP b;
> unsigned t1 = t&N;
> unsigned t2 = a&~N;
> return t1 | t2;
> }
>
Originally compiled into:
xor a1,a0,a1
andi a1,a1,514
andi a0,a0,-515
or a0,a1,a0
ret
After it compiles into:
andi a1,a1,514
xor a0,a1,a0
ret
Bootstrapped and regression tested on x86, aarch64 and various targets in qemu.
Also tested on the usual embedded targets.
PR tree-optimization/93504
gcc/
* simplify-rtx.cc (simplify_context::simplify_binary_operation_1):
Generalize existing code for (X & C) | ((X|Y) & ~C) to handle
(X & C) | ((X^Y) & ~C) as well.
gcc/testsuite
* gcc.target/riscv/pr93504.c: New test.
Harald Anlauf [Thu, 7 May 2026 20:34:52 +0000 (22:34 +0200)]
Fortran: fix automatic deallocation with derived type IO [PR111952,PR125059]
The implementation of derived type IO wrongly forced allocatable instances
of the DT as static, which prevented automatic deallocation of local
variables. The motivation was an attempt to prevent optimizations leading
to certain testcase failures. Howver, the underlying reason of the problem
was a wrong fnspec of _gfortran_transfer_derived that declared the IO
variable as being only read ('r'). Declare the corresponding parameter as
being written ('w').
PR fortran/111952
PR fortran/125059
gcc/fortran/ChangeLog:
* trans-decl.cc (gfc_finish_var_decl): Remove bogus code forcing
a DT variable with DTIO as static.
* trans-io.cc (gfc_build_io_library_fndecls): Fix fnspec attribute.
Roger Sayle [Fri, 8 May 2026 13:39:13 +0000 (14:39 +0100)]
[PATCH] Restore bootstrap on aarch64
My recent change to synth_mult broke bootstrap on aarch64, as gimple's
array bounds checking pass reports a (false positive) problem in some
unreachable code. This leads to -Werror stopping in stage2 of the
bootstrap.
The solution/workaround is add some more conditionals to the code that
make it clear(er) to range analysis the conditions under which the new
code is run. I believe these tests are redundant, and hopefully will be
optimized by the compiler (if not now then at some point in the future).
This patch has been tested on an aarch64-apple-darwin24.3.0, where I was
able to reproduce the failure. Committed to mainline as obvious (to
quickly resolve the current breakage).
2026-05-08 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
* expmed.cc (synth_mult): Add more constraints to recent change
to avoid "false positive" array bounds warnings during bootstrap.
Xi Ruoyao [Fri, 1 May 2026 19:31:09 +0000 (03:31 +0800)]
LoongArch: Allow printing symbolic name with "%c" in inline asm
The gcc.dg/ipa/pr122458.c test relies on this. The doc says "%c" is
for "constant operand" and I think there's no harm to consider symbolic
name a constant operand.
gcc/
* config/loongarch/loongarch.cc (loongarch_print_operand): Print
the symbol name for SYMBOL_REF with %c.
Xi Ruoyao [Tue, 28 Apr 2026 12:32:38 +0000 (20:32 +0800)]
LoongArch: harden SSP canary set and test routines [PR 125049]
Add the stack_protect_combined_{set,test} expanders to expand the
routines as unsplitable insns which does not leave any sensitive data
(the canary value, the canary address, and all the intermediate values
used materializing the address) in a register. This prevents the
attacker from defeating SSP by probing the canary value from the
register context or overwriting the address spilled onto the stack.
PR target/125049
gcc/
* config/loongarch/predicates.md (ssp_operand): New
define_predicate.
(ssp_normal_operand): New define_predicate.
* config/loongarch/constraints.md (ZE): New define_constraint.
(ZF): New define_constraint.
* config/loongarch/loongarch.md (UNSPEC_SSP): New unspec.
(cbranch4): Add "@" to create gen_cbranch4(machine_mode, ...).
(@stack_protect_combined_set_normal_<mode>): New define_insn.
(@stack_protect_combined_set_extreme_<mode>): New define_insn.
(@stack_protect_combined_test_internal_<mode>): New define_insn.
(stack_protect_combined_set): New define_expand.
(stack_protect_combined_test): New define_expand.
* config/loongarch/loongarch-protos.h
(loongarch_output_asm_load_canary): Declare.
* config/loongarch/loongarch.cc (loongarch_print_operand): Allow
'v' to print d/w for DImode/SImode.
(loongarch_output_asm_load_canary): Implement.
Xi Ruoyao [Wed, 25 Feb 2026 15:17:10 +0000 (23:17 +0800)]
LoongArch: eliminate redundant extension after ctz.w
The ctz.w instruction writes to the entire $rd. So due to the range of
the CTZ result ([0, 32]), $rd is already both sign-extended and
zero-extended from its lower half. But in pr90838.c we can see two
redundant sign-extension (slli.w ...,0). Now get rid of them.
The "andi" instructions in pr90393.c are really needed, because the
source code logic should produce 0 for zero input, but the ctz.[dw]
instructions actually produce 64/32.
gcc/
* config/loongarch/loongarch.md (*ctzsi2_extend): New
define_insn.
gcc/testsuite/
* gcc.dg/pr90838.c: Adjust expectation for LoongArch.
Vijay Shankar [Fri, 8 May 2026 07:36:21 +0000 (02:36 -0500)]
rs6000: Emit insn with proper rounding mode for nearbyint
This patch emits instruction with proper rounding mode for
vec_nearbyint.Previously, xvrdpi was emitted which uses nearest away
rounding mode but nearbyint requires rounding mode to be current
rounding mode.
Bootstrapped and regtested on powerpc64le-linux-gnu with no regressions.
Richard Biener [Wed, 6 May 2026 11:47:48 +0000 (13:47 +0200)]
tree-optimization/125174 - cost OMP SIMD calls
The following makes the target aware of OMP SIMD calls. Scalar
costing costs calls as scalar_stmt, so make sure to at least do
this level of costing for the vector side.
PR tree-optimization/125174
* tree-vect-stmts.cc (vectorizable_simd_clone_call): Cost
the number of OMP SIMD calls number of vector stmts.
Bohan Lei [Wed, 15 Apr 2026 07:42:20 +0000 (15:42 +0800)]
RISC-V: Implement even-odd shuffles with vnsrl
This patch tries to implement some even-odd shuffles with vnsrl instead
of vcompress, which is inspired by the current behavior of LLVM. Since
vcompress is slower than vnsrl on many implementations, and that
vcompress needs a mask load, using vnsrl seems to be more desirable.
gcc/ChangeLog:
* config/riscv/riscv-v.cc (shuffle_even_odd_patterns): Use vnsrl
when possible.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/rvv/autovec/vls-vlmax/shuffle-evenodd.c:
Match vnsrl patterns.
Thomas Schwinge [Fri, 8 May 2026 07:17:30 +0000 (09:17 +0200)]
testsuite: Fix test requirements: Adjust 'gcc.dg/plugin/diagnostic-test-paths-4.py'
Recent commit 4468e0da6e58f017faef1f248b4d1c4e27423b91
"testsuite: Fix test requirements" added a 'dg-require-effective-target signal'
line to 'gcc.dg/plugin/diagnostic-test-paths-4.c', which regressed:
PASS: gcc.dg/plugin/diagnostic-test-paths-4.c -fplugin=./diagnostic_plugin_test_paths.so (test for warnings, line [-13)-]{+14)+}
PASS: gcc.dg/plugin/diagnostic-test-paths-4.c -fplugin=./diagnostic_plugin_test_paths.so expected multiline pattern lines [-33-83-]{+34-84+}
PASS: gcc.dg/plugin/diagnostic-test-paths-4.c -fplugin=./diagnostic_plugin_test_paths.so (test for excess errors)
[-PASS:-]{+FAIL:+} gcc.dg/plugin/diagnostic-test-paths-4.c [-diagnostic-test-paths-4.py::test_path-]{+diagnostic-test-paths-4.py::test_paths - AssertionErro+}
..., as the latter file needs to be updated accordingly.
The narrow_gp_writes pass uses RTL-SSA and updates DF state via
df_insn_rescan / df_insn_delete. Both routines look up the insn's bb via
BLOCK_FOR_INSN to mark it dirty after a change, but pass_free_cfg has already
cleared those per-insn pointers by the time narrow_gp_writes runs. When
BLOCK_FOR_INSN returns NULL, the dirty-marking step is silently skipped,
leaving the DF stale.
Move the pass to run before pass_free_cfg.
Bootstrapped and regtested on aarch64-linux-gnu.
SPEC CPU 2017 shows no codegen differences (compared to previous placement).
OK for trunk?
Signed-off-by: Soumya AR <soumyaa@nvidia.com>
PR target/124895
gcc/ChangeLog:
* config/aarch64/aarch64-passes.def (pass_narrow_gp_writes): Move pass
before pass_free_cfg.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/narrow-gp-writes-8.c: New test.
1. Use CONST_VECTOR in REG_EQUAL note to avoid DF chain.
2. Keep constant integer load when crossing a function call since it is
faster than save and restore an integer register.
3. Convert CONST_VECTOR load no larger than integer register to constant
integer load even if there is no redundant CONST_VECTOR load.
Tested on Linux/x86-64.
gcc/
PR target/125100
* config/i386/i386-features.cc (x86_cse_kind): Add
X86_CSE_CONST_VECTOR.
(redundant_pattern): Add dest_mode.
(ix86_place_single_vector_set): Handle X86_CSE_CONST_VECTOR.
Generate SUBREG for constant integer source.
(ix86_broadcast_inner): Add an INSN argument. Use CONST_VECTOR
in REG_EQUAL note. Set load kind to X86_CSE_CONST_VECTOR for
native and converted CONST_VECTORs. Return CONST_VECTOR if it
can be converted to constant integer load.
(pass_x86_cse::candidate_vector_p): Add an INSN argument and
pass the insn to ix86_broadcast_inner.
(pass_x86_cse::x86_cse): Add a basic block bitmap for calls.
Pass the insn to candidate_vector_p. Handle X86_CSE_CONST_VECTOR.
Set dest_mode. Keep constant integer load when crossing a
function call. Convert CONST_VECTOR load no larger than integer
register to constant integer load even if there are no redundant
CONST_VECTOR loads.
Eikansh Gupta [Wed, 6 May 2026 12:38:45 +0000 (18:08 +0530)]
MATCH: Add simplification for MAX<a&CST0,a&CST1> and MIN<a&CST0,a&CST1> to match.pd [PR109878]
Min and max could be optimized if both operands are defined by
(same) variable restricted by an and(&). For signed types,
optimization can be done when both constant have same sign bit.
The patch also adds optimization for specific case of min/max(a, a&CST).
This patch adds match pattern for:
max (a & CST0, a & CST1) -> a & CST0 IFF CST0 & CST1 == CST1
min (a & CST0, a & CST1) -> a & CST0 IFF CST0 & CST1 == CST0
min (a, a & CST) --> a & CST
max (a, a & CST) --> a
The v2 of the patch has been approved. Patch link:
https://gcc.gnu.org/pipermail/gcc-patches/2024-July/657801.html
PR tree-optimization/109878
gcc/ChangeLog:
* match.pd(min/max (a & CST0, a & CST1)): New pattern.
(min/max (a, a & CST)): New pattern.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/pr109878-1.c: New test.
* gcc.dg/tree-ssa/pr109878-2.c: New test.
* gcc.dg/tree-ssa/pr109878-3.c: New test.
* gcc.dg/tree-ssa/pr109878.c: New test.
Jeff Law [Thu, 7 May 2026 22:52:25 +0000 (16:52 -0600)]
[RISC-V][tree-optimization/106244] Improve code when generating (1 << N) & 0x1
So as noted in the PR, GCC fails to optimize this well:
int8_t f(int8_t x)
{
int8_t sh = 1 << x;
return sh & 1;
}
I strongly suspect this kind of code is exceedingly rare in practice. I just
happened to notice that it could be improved when looking for bugs to pass
along to Shreya & Austin. As noted in the PR, most of the time this is cleaned
up in gimple, but in some cases it slips through.
I'd love to tackle this in simplify-rtx, but SHIFT_COUNT_TRUNCATED, mode
handling for shift counts, subregs to deal with 32 bit objects on 64 bit
targets, etc make it fairly messy. Rather than spend a ton of time on it, I've
just created a simple risc-v splitter to handle the case of a 32bit shift on
rv64. The other cases can't be optimized.
I purposefully added the masking of the shift count. While the RISC-V port
does not define SHIFT_COUNT_TRUNCATED, it does have patterns that optimize away
the the masking when they can. If the masking got optimized away on the
assumption the count would be used in a shift/rotate and thus masked by the
hardware, we could have junk in the upper bits. It's worth noting that
because of the need to sanitize the shift count we're generating 2 insns, thus
we can't really improve for rv32 or for 64 bit objects on rv64. If we didn't
need to do that this would be a define_insn that generated a single
instruction.
Bootstrapped and regression tested on rv64 for on both the BPI and the Pioneer.
Also regression tested on riscv32-elf and riscv64-elf. Planning to push once
pre-commit CI gives the green light.
PR tree-optimization/106244
gcc/
* config/riscv/riscv.md ((and (ashift X Y) const_int 1)): New splitter.
gcc/testsuite/
* gcc.target/riscv/pr106244.c: New test.
Marek Polacek [Thu, 7 May 2026 13:51:53 +0000 (09:51 -0400)]
c++/reflection: ICE with bases_of [PR125206]
Here we crash in strip_typedefs_expr because we recurse on a
REFLECT_EXPR with TREE_BINFO as its operand, which is not a code this
function handles. It seems to me that we don't need to recurse for
REFLECT_EXPRs at all. Alternatively, we could just handle TREE_BINFO.
PR c++/125206
gcc/cp/ChangeLog:
* tree.cc (strip_typedefs_expr) <case REFLECT_EXPR>: Always
return instead of recursing.
rtlanal: Tweak operator precedence for comparisons
One quirk of the commutative operand precedence rules is that:
- PLUS and MINUS have precedence 4
- other binary arithmetic operators have precedence 2
- NOT and NEG have precedence 1
- (binary) comparison operators have precedence 0
This means that the arithmetic inverse operator (NEG) has a lower
precedence than the binary arithmetic operators, but the logical
inverse operator (NOT) has a higher precedence than binary comparisons
that produce a logical result. In other words, we have:
some binary > some unary > some other binary
This patch shuffles the precedence values so that all binary operators
have precedence over all unary operators. It means that existing
aarch64.md patterns such as:
This patch tackles two problems with the make_compound_operation(_int)
handling of PLUS:
(a) The PLUS case had some simplifications related to multiplications
of negative numbers. Those simplifications assigned the simplified
form to the variable "new_rtx", but the rest of the case ignored
new_rtx and returned the original expression "x". This had the
effect of discarding both the simplification result and the
recursive make_compound_operation results.
(b) The PLUS case applied maybe_swap_commutative_operands after
substituting the recursive make_compound_operation results.
That's good enough for unchained PLUSes. However, if the
expression is a nest of PLUSes, we might need to redistribute
operands in the entire nest.
For example, expand_compound_operation converts sign and zero
extensions to shifts. The extensions have commutative operand
priority 0, whereas the shifts have priority 2. This means that:
is correctly ordered, since PLUS has priority 4, NOT has priority 1,
and ZERO_EXTEND has priority 0. But when expand_compound_operation
converts the extends to shifts, the NOT becomes the lowest priority
operand, giving:
since, considered in isolation, neither PLUS needs a swap.
This result is not canonical, since the NOT should be first.
Both problems can be dealt with by using simplify_gen_binary instead.
That already has the simplifications for (a) and knows how to
redistribute operands in nested operations.
Although the MINUS case seemed to be ok, the simplifications there
also duplicate what simplify_gen_binary would do.
This is likely to be needed for Muhammad's uaddc/usubc patches.
gcc/
* combine.cc (make_compound_operation_int): Remove PLUS and MINUS
simplifications and PLUS operand order swapping. Delegate those
tasks to simplify_gen_binary instead.
object_allocator only allowed allocations to use the default constructor.
This patch generalises it to other constructors, in the same way as
rtl-ssa does for obstack allocations.
The first use case is likely to be Robin's backprop patch.
gcc/
* alloc-pool.h (object_allocator::allocate): Generalize to handle
non-default constructors.
Add post_ra_split_completed and use it for the RX port
Some targets need to be able to introduce new clobbers of the
condition-code register during register allocation. The main approach
for handling that situation is to ensure that the CC register is never
live before or during RA. This allows new clobbers to be introduced at
any time when !reload_completed.
This works well. However:
(a) Explicit uses and sets of the CC register are usually introduced by
the first post-reload split, rather than directly after RA.
(b) If the CC register is never live before and during RA, there is
no real need for patterns to have an explicit clobber of the CC
register at that point. Not having a CC clobber would allow more
recog attempts to succeed, both before and during RA. (AFAIK, only
combine and RTL-SSA keep tabs on when new CC clobbers can be
introduced as part of a recog attempt.)
(c) If a clobber of the CC register is hidden, it would need to be
made explicit before, or at the same time as, the explicit uses
and sets from (a).
The idea of this patch is therefore to allow the boundary between
"CC is never live" and "CC might be live" to be moved from
reload_completed to the first post-RA split. It converts the
RX port to this form.
gcc/
* rtl.h (post_ra_split_completed): Declare.
* final.cc (rest_of_clean_state): Set it to false.
* recog.cc (post_ra_split_completed): New variable.
(split_insn): Temporarily set post_ra_split_completed while walking
the new instructions.
(split_all_insns, split_all_insns_noflow): Set post_ra_split_completed
after completing a post-reload split.
* config/rx/rx.md (*cmpsi, *tstsi, *cmpsf, *conditional_branch)
(*sccc, *stcc, *stcc_reg, *abssi2_flags, *addsi3_flags, adc_internal)
(*adc_flags, *andsi3_flags, *negsi2_flags, *one_cmplsi2_flags)
(*iorsi3_flags, *rotlsi3_flags, *rotrsi3_flags, *ashrsi3_flags)
(*lshrsi3_flags, *ashlsi3_flags, *sat, *subsi3_flags, sbb_internal)
(*sbb_flags, *xorsi3_flags, *bmcc): Require post_ra_split_completed
rather than reload_completed.
(comparesi3_<extend_types:code><small_int_modes:mode>, addsi3_flags)
(subsi3_flags): Require post_ra_split_completed.
Mikael Morin [Thu, 7 May 2026 18:48:26 +0000 (20:48 +0200)]
fortran: Add bounds checking code to the scalarizer block [PR125192]
In gfc_conv_expr_descriptor, the array bounds checking code is added
to the root block, which is a different block from the scalarizer block
used to generate the array descriptor reference. This causes the array
bounds checking code to come before, which can be problematic if the
descriptor reference uses variables generated by the scalarizer, as they
are used in bounds checking code before their definition in that case.
This change adds the bounds checking code to the same block the
scalarizer uses to generate the array descriptor reference, solving the
use before definition problem.
PR fortran/125192
PR fortran/125198
gcc/fortran/ChangeLog:
* trans-array.cc (gfc_conv_expr_descriptor): Add bounds checking
code to the outermost loop's preliminary block.
Mikael Morin [Thu, 7 May 2026 18:48:13 +0000 (20:48 +0200)]
fortran: Only pass the block for bounds check generation
Among the scalarized expression SE passed as argument to the array
bounds check generation function, only the PRE block field is used,
to populate it with the bounds checking code.
This change refactors the code, so that only the block is passed as
argument and not a full scalarized expression.
gcc/fortran/ChangeLog:
* trans-array.cc (trans_array_bound_check): Replace references
to SE->PRE with references to the new argument BLOCK. Remove
argument SE.
(array_bound_check_elemental): Likewise. Update caller.
(conv_array_index_offset): Update caller.
(gfc_conv_expr_descriptor): Update caller.
This patch resolves PR middle-end/122871 by improving RTL expansion of
doubleword multiplications. The main change is to synth_mult adding
support for the case where the constant being multiplied has BITS_PER_WORD
or more trailing zeros. The shift_cost tables in expmed are only
parameterized for shifts less than BITS_PER_WORD, so doubleword shifts
by more than this can't use the usual code path. This patch teaches
synth_mult that for scalar doubleword multiplications, a doubleword shift
by more than BITS_PER_WORD typically requires two instructions; one to
set the result lowpart to zero, and the other a wordmode shift to
calculate the result highpart.
For the testcase given in the PR:
long long ashll_fn (long long a)
{
long long c;
c = a << 33;
c += a;
return c;
}
GCC for arm-linux-gnueabihf currently generates with -O2:
Additionally, this patch includes a clean-up (identified by A. Pinski)
to prevent RTL expansion of doubleword multiplications from
initially emitting multiply instructions by immediate constants 0, 1
or 2. These dubious multiplications eventually get tidied up by later
RTL optimization passes, but being sensible during RTL expansion
both speeds up the compiler and reduces unnecessary memory usage.
2026-05-07 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
PR middle-end/122871
* expmed.cc (synth_mult): Handle doubleword left shifts by
BITS_PER_WORD bits or more, for scalar modes.
* optabs.cc (expand_doubleword_mult): Avoid generating multiply
instructions by immediate constants 0, 1 or 2.
gcc/testsuite/ChangeLog
PR middle-end/122871
* gcc.target/arm/muldi-1.c: New test case.
Jakub Jelinek [Thu, 7 May 2026 15:31:09 +0000 (17:31 +0200)]
c++: Improve REFLECT_EXPR printing [PR125007]
The following patch fixes REFLECT_EXPR printing. Currently it prints everything
as ^^ followed by dumping the decl/type/expr handle of the REFLECT_EXPR_HANDLE
except the weird printing of data member specifications.
E.g. annotations are printed as ^^ and dump_expr on the REFLECT_EXPR_HANDLE,
which is a TREE_LIST so it prints the TREE_VALUE of TREE_VALUE of that in
the end and prints e.g. reflection of [[=1]] as ^^1.
The following patch prints reflections of annotations as ^^[[=1]] which is
also not valid C++ syntax, but because the IL doesn't store the decl/type
etc. in whose DECL_ATTRIBUTES/TYPE_ATTRIBUTES it appears, I'm afraid we
can't do much better (like print annotations_of(^^something)[N]).
For REFLECT_BASE/REFLECT_PARM/REFLECT_DATA_MEMBER_SPEC/REFLECT_VALUE/REFLECT_OBJECT,
it attempts to use the C++ valid syntax, so prints
bases_of(^^type,std::meta::access_context::unchecked())[N] {aka base_type}
parameters_of(^^decl)[N] {aka param_name}
data_member_spec(^^type,{.name="foo"})
std::meta::reflect_constant(X)
std::meta::reflect_object(X)
etc.
2026-05-07 Jakub Jelinek <jakub@redhat.com>
PR c++/125007
* cp-tree.h (maybe_update_function_parm): Declare.
* reflect.cc (maybe_update_function_parm): No longer static.
* error.cc (dump_expr) <case REFLECT_EXPR>: Improve printing
of various reflections.
Jakub Jelinek [Thu, 7 May 2026 15:29:23 +0000 (17:29 +0200)]
testsuite: Fix up gcc.dg/analyzer/divide-by-zero-6.c test
On Thu, May 07, 2026 at 01:35:07PM +0800, H.J. Lu wrote:
> I got
>
> FAIL: gcc.dg/analyzer/divide-by-zero-6.c (test for warnings, line 14)
> FAIL: gcc.dg/analyzer/divide-by-zero-6.c at line 15 (test for
> warnings, line 14)
> FAIL: gcc.dg/analyzer/divide-by-zero-6.c (test for excess errors)
> Excess errors:
> /export/gnu/import/git/gitlab/x86-gcc/gcc/testsuite/gcc.dg/analyzer/divide-by-zero-6.c:14:18:
> warning: use of uninitialized value '*f.y' [CWE-457]
> [-Wanalyzer-use-of-uninitialized-value]
The warnings are correct, but I guess the test wasn't meant to test two
completely different thing, one on 64-bit targets and one on 32-bit ones.
struct foo { int x; int y; };
has sizeof (8) on most targets (except on non-32-bit int), but the test
was using __builtin_memset (f, 0, sizeof (f)) where f is a pointer.
Now, this happens to clear the whole structure on 64-bit targets but only
first half of it on 32-bit ones, so on 64-bit it emits the expected warning
about division by zero, while on 32-bit about using uninitialized value.
I think the testcase was meant to clear the whole structure on all arches,
the following patch does that.
2026-05-07 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/analyzer/divide-by-zero-6.c (init_foo): Use sizeof (*f)
rather than sizeof (f).
Jakub Jelinek [Thu, 7 May 2026 13:50:14 +0000 (15:50 +0200)]
c++: Constant evaluation of __builtin_{,dynamic_}object_size [PR124347]
The following patch tries to support constexpr folding of
__builtin_object_size and __builtin_dynamic_object_size.
There is already folding of this builtin in builtins.cc, but it doesn't look
through pointer conversions in the argument, only handles the case where
the argument is ADDR_EXPR (plus of course when inside of the objsz passes it
handles more through SSA_NAME tracking).
I've tried to handle this in builtins.cc first, see
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124347#c1 but unfortunately
that resulted in some serious security regressions where some of __bos
or __bdos builtins were folded prematurely, in particular e.g. for cases
where we have __builtin_object_size (something, 1) and the whole object
size is unknown but object size of the element is known. With the patch
it would just return the remaining subobject size, when it actually should
return MIN_EXPR <object_size, remaining subobject size>. For mode 1
it is conservatively correct, but larger than necessary with security
implications of not caching out of bounds accesses.
So, this patch instead handles this in the FE, only for manifestly constant
evaluation, by stripping the pointer casts on the first argument in that
case.
2026-05-07 Jakub Jelinek <jakub@redhat.com>
PR c++/124347
* constexpr.cc (cxx_eval_builtin_function_call): For
mce_true strip nops in first argument of BUILT_IN*_OBJECT_SIZE
if the inner expression is ADDR_EXPR.
* g++.dg/ext/builtin-object-size4.C: New test.
* g++.dg/ext/builtin-object-size5.C: New test.
* g++.dg/ext/builtin-object-size6.C: New test.
Avinash Jayakar [Wed, 4 Mar 2026 10:00:24 +0000 (05:00 -0500)]
rs6000: Builtins for AES acceleration instructions [RFC02657]
This patch adds new builtins for AES acceleration instructions which
may or may not be supported in a future processor. Note, the names of
the builtins may change in future.
The following new builtins for AES acceleration can be used with
-mcpu=future option:
__vector_pair __builtin_aes_encrypt_paired (__vector_pair,
__vector_pair, uint2);
__vector_pair __builtin_aes128_encrypt_paired (__vector_pair,
__vector_pair);
__vector_pair __builtin_aes192_encrypt_paired (__vector_pair,
__vector_pair);
__vector_pair __builtin_aes256_encrypt_paired (__vector_pair,
__vector_pair);
__vector_pair __builtin_aes_decrypt_paired (__vector_pair,
__vector_pair, uint2);
__vector_pair __builtin_aes128_decrypt_paired (__vector_pair,
__vector_pair);
__vector_pair __builtin_aes192_decrypt_paired (__vector_pair,
__vector_pair);
__vector_pair __builtin_aes256_decrypt_paired (__vector_pair,
__vector_pair);
__vector_pair __builtin_aes_genlastkey_paired (__vector_pair, uint2);
__vector_pair __builtin_aes128_genlastkey_paired (__vector_pair);
__vector_pair __builtin_aes192_genlastkey_paired (__vector_pair);
__vector_pair __builtin_aes256_genlastkey_paired (__vector_pair);
vec_t __builtin_galois_field_mult (vec_t, vec_t, uint1);
vec_t __builtin_galois_field_mult_gcm (vec_t, vec_t);
vec_t __builtin_galois_field_mult_xts (vec_t, vec_t);
gcc/ChangeLog:
* config/rs6000/crypto.md (UNSPEC_XXAESENCP): New unspec entry.
(UNSPEC_XXAES128ENCP): Likewise.
(UNSPEC_XXAES192ENCP): Likewise.
(UNSPEC_XXAES256ENCP): Likewise.
(UNSPEC_XXAESDECP): Likewise.
(UNSPEC_XXAES128DECP): Likewise.
(UNSPEC_XXAES192DECP): Likewise.
(UNSPEC_XXAES256DECP): Likewise.
(UNSPEC_XXAESGENLKP): Likewise.
(UNSPEC_XXAES128GENLKP): Likewise.
(UNSPEC_XXAES192GENLKP): Likewise.
(UNSPEC_XXAES256GENLKP): Likewise.
(UNSPEC_XXGFMUL128): Likewise.
(UNSPEC_XXGFMUL128GCM): Likewise.
(UNSPEC_XXGFMUL128XTS): Likewise.
(AESACC_base_code): New iterator for xxaesencp and xxaesdecp base
mnemonics.
(AESACC_code): New iterator for xxaesencp and xxaesdecp extended
mnemonics.
(AESGENLKP_code): New iterator for xxaesgenlkp extended mnemonics.
(AESGF_code): New iterator for xxgfmul128 extended mnemonics.
(AESACC_base_insn): New attribute iterator for xxaesencp and xxaesdecp
base mnemonics.
(AESACC_insn): New attribute iterator for xxaesencp and xxaesdecp
extended mnemonics.
(AESGENLKP_insn): New attribute iterator for xxaesgenlkp extended
mnemonics.
(AESGF_insn): New attribute iterator for xxgfmul128 extended mnemonics.
(<AESACC_base_insn>): New define_insn for xxaesencp and xxaesdecp base
mnemonics.
(<AESACC_insn>): New define_insn for xxaesencp and xxaesdecp extended
mnemonics.
(<AESGENLKP_insn>): New define_insn for xxaesgenlkp extended mnemonics.
(xxaesgenlkp): New define_insn for genlkp base mnemonic.
(<AESGF_insn>): New define_insn for xxgfmul128 extended mnemonics.
(xxgfmul128): New define_insn for xxgfmul128 base mnemonic.
* config/rs6000/rs6000-builtins.def: Added new builtin definitions for
AES acceleration.
* doc/extend.texi: Add new section for AES acceleration builtins
for Future ISA.
gcc/testsuite/ChangeLog:
* gcc.target/powerpc/aes-builtin-1.c: New test.
* gcc.target/powerpc/aes-builtin-2.c: New test.
* gcc.target/powerpc/aes-builtin-3.c: New test.
Jonathan Wakely [Wed, 22 Apr 2026 14:37:16 +0000 (15:37 +0100)]
libstdc++: Constrain tuple(tuple&&) [PR78302]
Since C++20 the std::tuple move constructor should be constrained (as
modified by LWG 2899).
We already define the move constructor as defaulted, but it's not
implicitly defined as deleted for non-move-constructible element types
because the _Tuple_impl(_Tuple_impl&&) constructor is user-provided and
unconstrained. For C++20 and later we use a requires-clause to constrain
the defaulted tuple(tuple&&) constructor.
Ideally we'd make this change pre-C++20 as well, but that's harder to do
without using a requires-clause, so this change is only for C++20 and
later. I think that's OK, but if we need to change it for pre-C++20
later we can consider inheriting from _Enable_copy_move<..., tuple> to
make the defaulted move constructor defined as deleted.
Tomasz Kamiński [Wed, 7 Jan 2026 13:01:41 +0000 (14:01 +0100)]
libstdc++: Rework istreambuf_iterator::_M_sbuf handling to slice null-dereference warning [PR105580]
The warning was produced by following sequence, given an istream_iterator<char>
it, such that *it will result in hitting EoF in it->_M_get(), and thus clearing
_M_sbuf, the subsequent call to ++it, will result in _M_sbuf->sbumpc() call on
null pointer. This is however an false-positive, as in such situation
it == istream_iteator() returns true, and the iterator should not be
incremented in first place.
This patch addresses the above by clearing the _M_sbuf in operator++, instead
of _M_get(). This removes the need for making _M_sbuf mutable, and thus make
the implementation conforming with regards to C++11 [res.on.data.races] p3.
Also removes no longer needed "-Wnull-dereference" disabling pragmas from
streambuf (see r16-7844-gbfc2b87f8244a1).
This change should have zero or positive performance impact on the usual
iteration patterns, in form:
while (it != end) { process(*it); ++it; }
In case when it is end-of-stream iterator, the it != end returns in one call
of _M_sbuf->sgetc() both before and after the change. However we do not modify
_M_sbuf in this case. For non-empty range, we replace call to _M_sbuf->sbumpc()
with _M_sbuf->snextc() in pre-increment, and extract the check against EoF from
*it to ++it. However, as _M_sbuf is now cleared during increment, so last
it != end check avoids _M_sbuf->sgetc() call to check against EoF.
However, this change impact the behavior of the post-increment (*it++), as
we now load both current character (for return value) and next character (to
check against EoF). In consequence we call both sgetc() and snextc(),
in contrast to previous single sbumpc() call.
PR libstdc++/105580
libstdc++-v3/ChangeLog:
* include/bits/streambuf_iterator.h (istreambuf_iterator::_M_sbuf):
Remove mutable and adjust whitespace.
(istreambuf_iterator::_M_c): Adjust whitespace.
(istreambuf_iterator::operator++()): Clear _M_sbuf if next character
is EoF.
(istreambuf_iterator::operator++(int)): Use _M_sbuf->sgetc() to
load current character, and define in terms of ++*this.
(istreambuf_iterator::_M_get()): Do not clear _M_sbuf in case of EoF.
* include/std/streambuf (streambuf::gptr, streambuf::egptr)
(streambuf::gbump): Remove surrounding pragma disabling -Wnull-dereference.
* testsuite/24_iterators/istreambuf_iterator/2.cc: Test for using
multiple iterators to same rdbuf.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
Paul Thomas [Thu, 7 May 2026 07:04:27 +0000 (08:04 +0100)]
Fortran: Fix complex associate-name with inferred kind [PR125172]
2026-05-07 Samir Ouchene <samirmath01@gmail.com
gcc/fortran
PR fortran/125172
* resolve.cc (gfc_fixup_inferred_type_refs): Update kind for
INQUIRY_RE and INQUIRY_IM references on inferred complex
associate-name.
(resolve_variable): For an inferred-type associate-name with
no subobject ref, refresh e->ts from sym->ts.
(resolve_assoc_var): For an inferred-type complex/character
associate-name, refresh sym->ts from the resolved target when
only the kind differs.
gcc/testsuite
PR fortran/125172
* gfortran.dg/associate_79.f90: New test.
Jakub Jelinek [Thu, 7 May 2026 06:54:21 +0000 (08:54 +0200)]
c++: Fix up extract_ref [PR125111]
https://eel.is/c++draft/meta.reflection.extract#5.2 requests that
is_convertible_v<remove_reference_t<U>(*)[], remove_reference_t<T>(*)[]>
is tested and if it not true, the function throws.
If U/T are references to function/method/array[], we try to build
array of types which are not valid in arrays and ICE shortly after that.
The following patch makes sure we don't create arrays in that case
and instead just throw the exception. We can't have references to void
or references to references, so I think the other problematic cases
of creating arrays can't trigger.
2026-05-07 Jakub Jelinek <jakub@redhat.com>
PR c++/125111
* reflect.cc (extract_ref): Throw instead of trying to build
arrays of functions, methods or arrays with NULL TYPE_DOMAIN.
Jakub Jelinek [Thu, 7 May 2026 06:45:32 +0000 (08:45 +0200)]
c++: Reflection vs. CLASSTYPE_TYPEINFO_VAR/ANON_AGGR_TYPE_FIELD sharing [PR124991]
typeinfo_var element of lang_type is used for 2 purposes,
CLASSTYPE_TYPEINFO_VAR and ANON_AGGR_TYPE_FIELD, a VAR_DECL for types
for which we need typeid etc. and FIELD_DECL for anonymous union/struct
types inside of classes.
Without reflection one can't ask for typeid of the anonymous union/struct
types, so sharing the same tree for both purposes is fine, but with
reflection we can ICE.
As anonymous unions are fairly rare and asking about typeid of those will be
even rarer, the following patch attempts to fix that without actually
growing the lang_type struct size by using the same tree for both. If it
is NULL_TREE, both CLASSTYPE_TYPEINFO_VAR and ANON_AGGR_TYPE_FIELD
are NULL, if it is a VAR_DECL, it is the former, if it is a FIELD_DECL,
it is the latter, in the really rare case we need both it is turned
into a TREE_LIST where TREE_VALUE is CLASSTYPE_TYPEINFO_VAR and
TREE_PURPOSE is ANON_AGGR_TYPE_FIELD.
Note, CWG3130 fortunately disallows attempts to create a different object
of ANON_AGGR_TYPE_P type (will need to implement that part), so the other
worries from PR124991 (that one can create a variable or member or parameter
etc. with the anon union type and get confused by ANON_AGGR_TYPE_FIELD on it
or trying to tweak lookup rules etc.) are gone.
2026-05-07 Jakub Jelinek <jakub@redhat.com>
PR c++/124991
* cp-tree.h (struct lang_type): Document typeinfo_var member.
(get_classtype_typeinfo_var): New inline function.
(CLASSTYPE_TYPEINFO_VAR): Use it.
(set_classtype_typeinfo_var): New inline function.
(SET_CLASSTYPE_TYPEINFO_VAR): Define.
(get_anon_aggr_type_field): New inline function.
(ANON_AGGR_TYPE_FIELD): Use it.
(set_anon_aggr_type_field): New inline function.
(SET_ANON_AGGR_TYPE_FIELD): Define.
* decl.cc (fixup_anonymous_aggr): Use SET_ANON_AGGR_TYPE_FIELD
instead of ANON_AGGR_TYPE_FIELD.
* module.cc (trees_in::read_class_def): Use
SET_CLASSTYPE_TYPEINFO_VAR instead of setting
CLASSTYPE_TYPEINFO_VAR and do it even for ANON_AGGR_TYPE_P
types. Use SET_ANON_AGGR_TYPE_FIELD instead of setting
ANON_AGGR_TYPE_FIELD.
* rtti.cc (get_tinfo_decl_direct): Use SET_CLASSTYPE_TYPEINFO_VAR
instead of setting CLASSTYPE_TYPEINFO_VAR.
* semantics.cc (finish_member_declaration): Use
SET_ANON_AGGR_TYPE_FIELD instead of setting ANON_AGGR_TYPE_FIELD.
Pan Li [Tue, 5 May 2026 05:44:46 +0000 (13:44 +0800)]
RISC-V: Combine vec_duplicate + vmsgt.vv to vmsgt.vx on GR2VR cost
This patch would like to combine the vec_duplicate + vmsgt.vv to the
vmsgt.vx. From example as below code. The related pattern will depend
on the cost of vec_duplicate from GR2VR. Then the late-combine will
take action if the cost of GR2VR is zero, and reject the combination
if the GR2VR cost is greater than zero.
Assume we have asm code like below, GR2VR cost is 0.
Harald Anlauf [Tue, 5 May 2026 20:00:43 +0000 (22:00 +0200)]
Fortran: fix namelist read for input with comments [PR125095]
Namelist input may contain comments (initiated with a "!") after a
separator or in the first nonblank position of a namelist input record.
Skip comments until end of line, and eat leading whitespace in a subsequent
input record.
Martin Uecker [Sat, 25 Apr 2026 18:14:13 +0000 (20:14 +0200)]
c: Fix use of variably-modified structure/union types in nested context [PR124985]
If a nested function uses a variably-modified structure or union type
that depends on the enclosing context, it needs the static chain.
My recent change missed this, because in this case no decl was used.
To address this, we now call mark_decl_used also on TYPE_STUB_DECLs.
PR c/124985
gcc/c/ChangeLog:
* c-decl.cc (pushtag): Update comment.
(declspecs_add_type): Mark TYPE_STUB_DECL as used.
* c-typeck.cc (function_to_pointer_conversion): Fix grammar in comment.
gcc/testsuite/ChangeLog:
* gcc.dg/Wreturn-nested-3.c: New test.
* gcc.dg/pr124985.c: New test.
David Malcolm [Wed, 6 May 2026 14:22:57 +0000 (10:22 -0400)]
analyzer: show value ranges in svalue::dump
This patch adds value_range info where available to the various nodes
in svalue dumps, such as:
(gdb) call rhs2_sval->dump ()
(27): ‘long long unsigned int’: binop_svalue(bit_and_expr: ‘&’) value range: {[irange] long long unsigned int [0, 0]}
├─ (24): ‘long long unsigned int’: unaryop_svalue(nop_expr) value range: {[irange] long long unsigned int [0, 4294967295] MASK 0xffffffff VALUE 0x0}
│ ╰─ (22): ‘unsigned int’: initial_svalue value range: {[irange] unsigned int VARYING}
│ ╰─ m_reg: (21): ‘unsigned int’: decl_region(‘m’)
│ ╰─ parent: (4): globals
│ ╰─ parent: (0): root region
╰─ (26): ‘long long unsigned int’: constant_svalue (‘5497558138880’) value range: {[irange] long long unsigned int [5497558138880, 5497558138880]}
where we can see that sval 27 has value range [0,0] and
where that comes from (due to being a bit_and_expr of non-overlapping
ranges from sval 24 and 26).
gcc/analyzer/ChangeLog:
* svalue.cc (svalue::make_dump_widget): Show value ranges in
svalue dumps.
gcc/ChangeLog:
* value-range.cc (value_range::print): New, based on
value_range::dump.
* value-range.h (value_range::print): New decl.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Jonathan Wakely [Tue, 5 May 2026 12:54:02 +0000 (13:54 +0100)]
libstdc++: Simplify std::shared_ptr internals
Now that we don't use the EBO we can flatten the _Sp_counted_deleter and
_Sp_counted_ptr_inplace layouts by removing their _Impl classes.
libstdc++-v3/ChangeLog:
* include/bits/out_ptr.h (out_ptr_t::_Impl::~_Impl): Adjust
access to shared_ptr internals.
* include/bits/shared_ptr_base.h (_Sp_counted_deleter): Remove
_Impl class and replace _M_impl with the data members it
contained.
(_Sp_counted_ptr_inplace): Likewise.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Jonathan Wakely [Tue, 5 May 2026 12:39:24 +0000 (13:39 +0100)]
libstdc++: Replace uses of EBO with [[no_unique_address]]
Clang 9 added support for [[__no_unique_address__]] and we don't support
Intel icc any longer, so we can remove the code in <tuple> that works
around the absence of that attribute. We can also address a FIXME in
<bits/shared_ptr_base.h> and replace uses of EBO with the attribute.
libstdc++-v3/ChangeLog:
* include/bits/shared_ptr_base.h (_Sp_ebo_helper): Simplify by
using [[__no_unique_address__]] instead of EBO. Use the
attribute unconditionally for the unstable ABI.
(_Sp_counted_deleter::_Impl): Adjust uses of _Sp_ebo_helper.
(_Sp_counted_ptr_inplace::_Impl): Likewise.
* include/std/tuple (_Head_base): Remove implementation for
compilers that don't support [[__no_unique_address__]]. Use the
attribute unconditionally for the unstable ABI.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
David Malcolm [Wed, 6 May 2026 13:57:07 +0000 (09:57 -0400)]
analyzer: generating raw state for rewinding data flow
The previous patch used the states of the exploded nodes at each end of
an exploded edge for rewinding state, but this doesn't always work when
state purging is active (the default) due to the state purging
eliminating pertinent information. This can be see in
gcc.dg/analyzer/divide-by-zero-{4,5,6}.c, which required
-fno-analyzer-state-purge to rewind the data flow to locate where the
zero values were coming from.
This patch extends diagnostic_manager::annotate_exploded_path so that
it performs an initial forward walk through the exploded path, building
region_model instances along the path without any state purging or
merging, and updates the rewind_context to use these states to rewind
pertinent state for a diagnostic.
Doing so allows us to drop -fno-analyzer-state-purge from the testcases
which needed them before.
gcc/analyzer/ChangeLog:
* analyzer-logging.h (class text_art::canvas): New forward decl.
(logger::log_canvas): New decl.
* diagnostic-manager.cc (path_builder::get_supergraph): New.
(logger::log_canvas): New.
(dump_to_logger): New.
(log_region_model): New.
(epath_rewind_context::epath_rewind_context): Add params
src_model and dst_model, using them to initialize m_src_model and
m_dst_model.
(epath_rewind_context::get_src_region_model): New.
(epath_rewind_context::get_dst_region_model): New.
(epath_rewind_context::m_src_model): New.
(epath_rewind_context::m_dst_model): New.
(make_raw_dst_region_model): New.
(diagnostic_manager::annotate_exploded_path): Walk EPATH forwards,
populating new vectors src_models and dst_models without state
purging or merging, so that we can reliably rewind state. Pass
these models to epath_rewind_context when rewinding state.
* engine.cc (interprocedural_call::try_to_rewind_data_flow): Get
src and dst region_model instances via vfuncs of ctxt, rather than
accessing the eedge.
* ops.cc (rewind_context::on_data_origin): Get src and dst
region_model instances via vfuncs of ctxt, rather than accessing
the eedge.
(greturn_op::try_to_rewind_data_flow): Likewise.
* ops.h (rewind_context::rewind_context): Drop param "eedge".
(rewind_context::get_src_region_model): New vfunc.
(rewind_context::get_dst_region_model): New vfunc.
(rewind_context::m_eedge): Drop field.
int
test (int flag, int flag_2, int flag_3)
{
struct foo f;
int a = 42;
int b = get_zero ();
init_foo (&f, a, b);
return do_divide (&f);
}
Before this patch, we emit:
demo.c: In function ‘do_divide’:
demo.c:24:15: warning: division by zero [-Wanalyzer-div-by-zero]
24 | return f->x / f->y;
| ~~~~~^~~~~~
‘test’: events 1-2
│
│ 28 | test (int flag, int flag_2, int flag_3)
│ | ^~~~
│ | |
│ | (1) entry to ‘test’
│......
│ 34 | return do_divide (&f);
│ | ~~~~~~~~~~~~~~
│ | |
│ | (2) calling ‘do_divide’ from ‘test’
│
└──> ‘do_divide’: events 3-4
│
│ 22 | do_divide (struct foo *f)
│ | ^~~~~~~~~
│ | |
│ | (3) entry to ‘do_divide’
│ 23 | {
│ 24 | return f->x / f->y;
│ | ~~~~~~~~~~~
│ | |
│ | (4) ⚠️ division by zero
│
which doesn't convey where the zero value came from.
This patch adds various wording and new events to tracking where the
problematic value comes from. diagnostic_manager::annotate_exploded_path walks
backwards from the final enode, building a chain of instances of a new
state_transition class hierarchy. These state_transition instances are
associated with checker_events where possible (e.g. at function entry),
otherwise, new state_transition_events are added for them, highlighting
e.g. where the pertinent zero value is passed as a parameter.
With the patch, we emit:
demo.c: In function ‘do_divide’:
demo.c:24:15: warning: division by zero [-Wanalyzer-div-by-zero]
24 | return f->x / f->y;
| ~~~~~^~~~~~
‘test’: events 1-2
│
│ 28 | test (int flag, int flag_2, int flag_3)
│ | ^~~~
│ | |
│ | (1) entry to ‘test’
│......
│ 32 | int b = get_zero ();
│ | ~~~~~~~~~~~
│ | |
│ | (2) calling ‘get_zero’ from ‘test’
│
└──> ‘get_zero’: events 3-4
│
│ 7 | get_zero (void)
│ | ^~~~~~~~
│ | |
│ | (3) entry to ‘get_zero’
│ 8 | {
│ 9 | return 0;
│ | ~
│ | |
│ | (4) zero value originates here
│
<──────┘
│
‘test’: events 5-6
│
│ 32 | int b = get_zero ();
│ | ^~~~~~~~~~~
│ | |
│ | (5) returning zero from (4) from ‘get_zero’ here
│ 33 | init_foo (&f, a, b);
│ | ~~~~~~~~~~~~~~~~~~~
│ | |
│ | (6) passing zero from (5) from ‘test’ to ‘init_foo’ via parameter 3
│
└──> ‘init_foo’: events 7-8
│
│ 15 | init_foo (struct foo *f, int x, int y)
│ | ~~~~^
│ | |
│ | (7) entry to ‘init_foo’ with zero from (5) for ‘y’
│......
│ 18 | f->y = y;
│ | ~~~~~~~~
│ | |
│ | (8) copying zero value from (7) from ‘y’ to ‘*f.y’
│
<──────┘
│
‘test’: events 9-10
│
│ 33 | init_foo (&f, a, b);
│ | ^~~~~~~~~~~~~~~~~~~
│ | |
│ | (9) returning to ‘test’ from ‘init_foo’
│ 34 | return do_divide (&f);
│ | ~~~~~~~~~~~~~~
│ | |
│ | (10) calling ‘do_divide’ from ‘test’
│
└──> ‘do_divide’: events 11-13
│
│ 22 | do_divide (struct foo *f)
│ | ^~~~~~~~~
│ | |
│ | (11) entry to ‘do_divide’
│ 23 | {
│ 24 | return f->x / f->y;
│ | ~~~~~~~~~~~
│ | | |
│ | | (12) using zero value from (8) from ‘*f.y’
│ | (13) ⚠️ division by zero
│
Note:
* the new "(4) zero value originates here" state transition event,
* the precision-of-wording for the return event at (5),
* the precision-of-wording for the call event at (6),
* the precision-of-wording for the function entry event at (7), and the
underlining of the pertinent parameter
* the above call/return events no longer get optimized away, due to...
* the new "(8) copying zero value from (7) from ‘y’ to ‘*f.y’" state
transition event
* the new "(12) using zero value from (8) from ‘*f.y’" state transition
event
gcc/ChangeLog:
* Makefile.in (ANALYZER_OBJS): Add analyzer/state-transition.o.
* digraph.cc (test_path::append_edge): New.
(test_path::reverse): New.
* shortest-paths.h (get_shortest_path): Use append_edge and
reverse.
* tree-diagnostic.h
(tree_dump_pretty_printer::~tree_dump_pretty_printer): Only flush
when the buffer's stream is non-null.
gcc/analyzer/ChangeLog:
* analyzer.cc (printable_expr_p): New.
* call-info.cc: Include "analyzer/state-transition.h".
(call_info::add_events_to_path): Add state_transition param.
* call-info.h (call_info::add_events_to_path): Likewise.
* callsite-expr.h: New file, based on material from supergraph.h.
(class callsite_expr_element): New.
* checker-event.cc: Include "analyzer/callsite-expr.h" and
"analyzer/state-transition.h".
(event_kind_to_string): Handle event_kind::state_transition.
(state_transition_event::print_desc): New.
(state_transition_event::prepare_for_emission): New.
(function_entry_event::function_entry_event): Drop.
(function_entry_event::print_desc): Use any m_state_trans.
(function_entry_event::prepare_for_emission): New.
(call_event::call_event): Add "state_trans" param and store it in
m_state_trans.
(call_event::print_desc): Use m_state_trans if present to call
describe_call_with_state, adding a fallback wording for
pending_diagnostic subclasses that don't implement it.
(call_event::prepare_for_emission): New, storing event id into
state_transition.
(return_event::return_event): Add "state_trans" param and store it
in m_state_trans.
(return_event::print_desc): Use m_state_trans if present to call
describe_return_of_state.
(return_event::prepare_for_emission): New, storing event id into
state_transition.
* checker-event.h (enum class event_kind): Add state_transition.
(class state_transition_event): New.
(function_entry_event::function_entry_event): Add "state_trans"
param and store it in m_state_trans. Drop 2nd ctor.
(function_entry_event::prepare_for_emission): New decl.
(function_entry_event::get_state_transition_at_call): New.
(function_entry_event::m_state_trans): New.
(call_event::call_event): Add "state_trans" param.
(call_event::prepare_for_emission): New decl.
(call_event::get_state_transition_at_call): New.
(call_event::m_state_trans): New.
(return_event::return_event): Add "state_trans" param.
(return_event::prepare_for_emission): New decl.
(return_event::m_state_trans): New.
* common.h: Define INCLUDE_ALGORITHM.
(class state_transition): New forward decl
(class state_transition_at_call): New forward decl
(class state_transition_at_return): New forward decl
(printable_expr_p): New decl.
(struct diagnostic_state): New.
(struct rewind_context): New forward decl.
(custom_edge_info::add_events_to_path): Add "state_trans" param.
(try_to_rewind_data_flow): New vfunc.
* diagnostic-manager.cc (compatible_epath_p): Update for change
from m_edges to m_elements.
(diagnostic_manager::emit_saved_diagnostic): Make "epath"
non-const. Call annotate_exploded_path on it and log before and
after. Update for new param to add_events_for_eedge.
(class epath_rewind_context): New.
(diagnostic_manager::annotate_exploded_path): New.
(diagnostic_manager::build_emission_path): Update for change from
m_edges to m_elements. Pass any state transition to
add_events_for_eedge.
(diagnostic_manager::add_events_for_eedge): Add "state_trans"
parameter. Pass it when creating events, and if we don't create
an event referencing it, make a state_transition_event for it.
(diagnostic_manager::prune_for_sm_diagnostic): Handl
event_kind::state_transition.
* diagnostic-manager.h (saved_diagnostic::get_best_epath): Drop
"const" from return value.
(diagnostic_manager::annotate_exploded_path): New decl.
(diagnostic_manager::add_events_for_eedge): Add "state_trans"
param.
* engine.cc: Include "pretty-print-markup.h".
(leak_ploc_fixer_for_epath::fixup_for_epath): Update for change
from m_edges to m_elements.
(throw_custom_edge::add_events_to_path): Add state_transition
param.
(unwind_custom_edge::add_events_to_path): Likewise.
(interprocedural_call::print): Use get_gcall.
(interprocedural_call::update_model): Likewise.
(interprocedural_call::add_events_to_path): Likewise. Pass
state_transition if of correct subclass.
(interprocedural_call::try_to_rewind_data_flow): New.
(interprocedural_call::get_gcall): New.
(interprocedural_return::add_events_to_path): Add state_transition
param and pass if of correct subclass.
(interprocedural_return::try_to_rewind_data_flow): New.
(tainted_args_function_info::add_events_to_path): Add
state_transition param.
(tainted_args_call_info::add_events_to_path): Likewise.
* event-loc-info.h (event_loc_info_for_function_entry): New decl.
* exploded-graph.h (interprocedural_call::interprocedural_call):
Pass and store call_and_return_op rather than gcall.
(interprocedural_call::add_events_to_path): Add state_trans param.
(interprocedural_call::try_to_rewind_data_flow): New.
(interprocedural_call::m_call_stmt): Replace with...
(interprocedural_call::m_op): ...this.
(interprocedural_return::add_events_to_path): Add state_trans
param.
(interprocedural_return::try_to_rewind_data_flow): New.
(rewind_info_t::add_events_to_path): New.
* exploded-path.cc (exploded_path::exploded_path): Drop explicit
copy ctor.
(diagnostic_state::dump_to_pp): New.
(diagnostic_state::dump): New.
(exploded_path::find_stmt_backwards): Update for change from
m_edges to m_elements.
(exploded_path::get_final_enode): Likewise.
(exploded_path::feasible_p): Likewise.
(exploded_path::dump_to_pp): Likewise. Dump state transitions.
(exploded_path::maybe_log): New.
(exploded_path::reverse): New.
* exploded-path.h: Include "analyzer/checker-event.h" and
"analyzer/state-transition.h".
(struct exploded_path::element_t): New.
(exploded_path::exploded_path): Replace ctors with "= default".
(exploded_path::length): Reimplement.
(exploded_path::maybe_log): New decl.
(exploded_path::append_edge): New.
(exploded_path::reverse): New.
(exploded_path::m_edges): Replace with...
(exploded_path::m_elements): ...this, using std::vector rather
than auto_vec.
* feasible-graph.cc (feasible_graph::make_epath): Update for
change from m_edges to m_elements.
* infinite-recursion.cc
(infinite_recursion_diagnostic::add_function_entry_event): Add
"state_trans" param and pass it to base class call.
(recursive_function_entry_event::recursive_function_entry_event):
Pass nullptr for state transition.
* ops.cc: Include "analyzer/callsite-expr.h" and
"analyzer/state-transition.h".
(event_loc_info_for_function_entry): New.
(rewind_context::on_data_origin): New.
(rewind_context::on_data_flow): New.
(gassign_op::try_to_rewind_data_flow): New.
(greturn_op::try_to_rewind_data_flow): New.
(call_and_return_op::execute): Update for change to
interprocedural_call.
(call_and_return_op::try_to_rewind_data_flow): New.
(phis_for_edge_op::try_to_rewind_data_flow): New.
* ops.h (struct rewind_context): New.
(operation::try_to_rewind_data_flow): New vfunc.
(gassign_op::try_to_rewind_data_flow): New.
(predict_op::try_to_rewind_data_flow): New.
(greturn_op::try_to_rewind_data_flow): New.
(call_and_return_op::try_to_rewind_data_flow): New.
(control_flow_op::try_to_rewind_data_flow): New.
(phis_for_edge_op::try_to_rewind_data_flow): New.
* pending-diagnostic.cc (interesting_t::add_read_region): New.
(interesting_t::dump_to_pp): Dump m_read_regions.
(pending_diagnostic::add_function_entry_event): Add "state_trans"
param and pass it to function_entry_event. Call
event_loc_info_for_function_entry.
(pending_diagnostic::add_call_event): Add "state_trans" param and
pass it to call_event.
* pending-diagnostic.h: Include "analyzer/state-transition.h".
(struct interesting_t): Update leading comment.
(interesting_t::add_read_region): New.
(interesting_t::m_read_regions): New.
(struct origin_of_state): New.
(call_with_state::call_with_state): Add state_trans param and use
it to initialize m_state_trans and m_src_event_id.
(call_with_state::m_state_trans): New field.
(call_with_state::m_src_event_id): New field.
(return_of_state::return_of_state): Add state_trans param and use
it to initialize m_state_trans and m_src_event_id.
(return_of_state::m_state_trans): New field.
(return_of_state::m_src_event_id): New field.
(struct copy_of_state): New.
(struct use_of_state): New.
(pending_diagnostic::describe_origin_of_state): New vfunc.
(pending_diagnostic::describe_copy_of_state): New vfunc.
(pending_diagnostic::describe_use_of_state): New vfunc.
(pending_diagnostic::add_function_entry_event): Add "state_trans"
param.
(pending_diagnostic::add_call_event): Likewise.
* poisoned-value-diagnostic.cc
(poisoned_value_diagnostic::mark_interesting_stuff): Add call to
add_read_region.
* region-model.cc: Include "analyzer/state-transition.h".
(callsite_expr::maybe_get_param_location): New.
(callsite_expr::get_param_tree): New.
(div_by_zero_diagnostic::div_by_zero_diagnostic): Add
"divisor_reg" param and use it to initialize m_divisor_reg.
(div_by_zero_diagnostic::mark_interesting_stuff): New.
(div_by_zero_diagnostic::add_function_entry_event): New.
(div_by_zero_diagnostic::describe_origin_of_state): New.
(div_by_zero_diagnostic::describe_call_with_state): New.
(div_by_zero_diagnostic::describe_return_of_state): New.
(div_by_zero_diagnostic::describe_copy_of_state): New.
(div_by_zero_diagnostic::describe_use_of_state): New.
(div_by_zero_diagnostic::m_divisor_reg): New field.
(region_model::get_gassign_result): Pass region to calls to
make_shift_count_negative_diagnostic,
make_shift_count_overflow_diagnostic, and
div_by_zero_diagnostic.
(exception_thrown_from_unrecognized_call::add_events_to_path): Add
state_transition param.
* region-model.h (make_shift_count_negative_diagnostic): Add
"src_region" param.
(make_shift_count_overflow_diagnostic): Likewise.
* region.h: Include "analyzer/store.h" and
"text-art/tree-widget.h".
* setjmp-longjmp.cc (rewind_info_t::add_events_to_path): Add
state_transition param.
* shift-diagnostics.cc
(shift_count_negative_diagnostic::shift_count_negative_diagnostic):
Add src_region param and use it to initialize m_src_region.
(shift_count_negative_diagnostic::mark_interesting_stuff): New.
(shift_count_negative_diagnostic::m_src_region): New.
(make_shift_count_negative_diagnostic): Add src_region param.
(shift_count_overflow_diagnostic::shift_count_overflow_diagnostic):
Add src_region param and use it to initialize m_src_region.
(shift_count_overflow_diagnostic::mark_interesting_stuff): New.
(shift_count_overflow_diagnostic::m_src_region): New field.
(make_shift_count_overflow_diagnostic): Add src_region param.
* sm-signal.cc (signal_delivery_edge_info_t::add_events_to_path):
Add state_transition param.
* state-transition.cc: New file.
* state-transition.h: New file.
* supergraph.h (class callsite_expr): Move to callsite-expr.h.
* varargs.cc (va_arg_diagnostic::add_call_event): Add state_trans
param.
gcc/testsuite/ChangeLog:
* c-c++-common/analyzer/divide-by-zero-1.c: Add expected message
for origin of zero value.
* c-c++-common/analyzer/divide-by-zero-2.c: New test.
* c-c++-common/analyzer/divide-by-zero-3.c: New test.
* c-c++-common/analyzer/invalid-shift-1.c: Add expected messages
about call to op3 and about pertinent param of op3.
* c-c++-common/analyzer/invalid-shift-2.c: New test.
* c-c++-common/analyzer/invalid-shift-3.c: New test.
* c-c++-common/analyzer/invalid-shift-4.c: New test.
* g++.dg/analyzer/divide-by-zero-7.C: New test.
* gcc.dg/analyzer/divide-by-zero-4.c: New test.
* gcc.dg/analyzer/divide-by-zero-5.c: New test.
* gcc.dg/analyzer/divide-by-zero-6.c: New test.
* gcc.dg/analyzer/divide-by-zero-float.c: Add expected message
for origin of zero value.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Andrew MacLeod [Wed, 11 Feb 2026 15:57:24 +0000 (10:57 -0500)]
More memory efficient prange_storage.
* value-range-storage.cc (prange_storage::alloc): Use prange_format.
(prange_storage::prange_storage): Likewise.
(prange_format::prange_format): New.
(prange_storage::set_prange): Use prange_foramt and only write
required words to storage.
(prange_storage::get_prange): Only read required words.
(prange_storage::equal_p): Adjust for new enum.
(prange_storage::fits_p): Use prange_format to determine size.
* value-range-storage.h (enum prange_kind): New.
(class prange_format): New.
(get_low, get_high, get_value, get_mask): Replace with get_word.
(set_low, set_high, set_value, set_mask): Replace with set_word.
(get_word): New.
(set_word): New.