[gcc r15-7867] testsuite: Add test for already fixed PR [PR104826]
https://gcc.gnu.org/g:49ac89e03f2f171b401ac8b9d7c3cef72efbdc63 commit r15-7867-g49ac89e03f2f171b401ac8b9d7c3cef72efbdc63 Author: Jakub Jelinek Date: Thu Mar 6 17:29:03 2025 +0100 testsuite: Add test for already fixed PR [PR104826] ICE on this test was fixed by r15-2131. This just adds test for it. 2025-03-06 Jakub Jelinek PR fortran/104826 * gfortran.dg/gomp/pr104826.f90: New test. Diff: --- gcc/testsuite/gfortran.dg/gomp/pr104826.f90 | 8 1 file changed, 8 insertions(+) diff --git a/gcc/testsuite/gfortran.dg/gomp/pr104826.f90 b/gcc/testsuite/gfortran.dg/gomp/pr104826.f90 new file mode 100644 index ..9eae257d64dd --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/pr104826.f90 @@ -0,0 +1,8 @@ +! PR fortran/104826 +program pr104826 + character(:), allocatable :: x + save + !$omp target + x = 'abc' + !$omp end target +end
[gcc r15-7877] Documentation: Improve -Wstringop-overflow documentation [PR 113515]
https://gcc.gnu.org/g:888e70b322622528dac17f04738ffa232c6fb82d commit r15-7877-g888e70b322622528dac17f04738ffa232c6fb82d Author: Sandra Loosemore Date: Fri Mar 7 04:35:34 2025 + Documentation: Improve -Wstringop-overflow documentation [PR 113515] This option can warn about things other than string and memory functions. Say so explicitly, and give an example. I also did some copy-editing of the text and added some paragraph breaks. gcc/ChangeLog PR c/113515 * doc/invoke.texi (Warning Options): Improve -Wstringop-overflow documentation. Diff: --- gcc/doc/invoke.texi | 35 +-- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 304de88db07c..fd1ce063a376 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -8229,20 +8229,28 @@ void f (char *d) @item -Wno-stringop-overflow @item -Wstringop-overflow @itemx -Wstringop-overflow=@var{type} -Warn for calls to string manipulation functions such as @code{memcpy} and -@code{strcpy} that are determined to overflow the destination buffer. The +Warn for code that can be statically determined to cause buffer overflows or +memory overruns, such as calls to @code{memcpy} and +@code{strcpy} that overflow the destination buffer. The optional argument is one greater than the type of Object Size Checking to perform to determine the size of the destination. @xref{Object Size Checking}. -The argument is meaningful only for functions that operate on character arrays -but not for raw memory functions like @code{memcpy} which always make use -of Object Size type-0. The option also warns for calls that specify a size +The argument is meaningful only for string functions +that operate on character arrays; raw memory functions like @code{memcpy} +always use type-zero Object Size Checking. + +The option also warns for calls that specify a size in excess of the largest possible object or at most @code{SIZE_MAX / 2} bytes. + The option produces the best results with optimization enabled but can detect a small subset of simple buffer overflows even without optimization in calls to the GCC built-in functions like @code{__builtin_memcpy} that correspond to the standard functions. In any case, the option warns about just a subset of buffer overflows detected by the corresponding overflow -checking built-ins. For example, the option issues a warning for +checking built-ins, such as @code{__builtin___memcpy_chk}, which can perform +run-time checking if the access cannot be identified as safe +at compile time. + +For example, the option issues a warning for the @code{strcpy} call below because it copies at least 5 characters (the string @code{"blue"} including the terminating NUL) into the buffer of size 4. @@ -8264,6 +8272,21 @@ const char* f (enum Color clr) @} @end smallexample +The effect of this option is not limited to string or memory +manipulation functions. In this example, a warning is diagnosed +because a 1-element array is passed to a function requiring at least a +4-element array argument: + +@smallexample +void f (int[static 4]); + +void g (void) +@{ + int *p = (int *) malloc (1 * sizeof(int)); + f (p); // warning here +@} +@end smallexample + Option @option{-Wstringop-overflow=2} is enabled by default. @table @gcctabopt
[gcc r15-7849] c++: Don't replace INDIRECT_REFs by a const capture proxy too eagerly [PR117504]
https://gcc.gnu.org/g:fdf846fdddcc0467b9f025757f081c5d54319d08 commit r15-7849-gfdf846fdddcc0467b9f025757f081c5d54319d08 Author: Simon Martin Date: Thu Mar 6 10:10:45 2025 +0100 c++: Don't replace INDIRECT_REFs by a const capture proxy too eagerly [PR117504] We have been miscompiling the following valid code since GCC8, and r8-3497-g281e6c1d8f1b4c === cut here === struct span { span (const int (&__first)[1]) : _M_ptr (__first) {} int operator[] (long __i) { return _M_ptr[__i]; } const int *_M_ptr; }; void foo () { constexpr int a_vec[]{1}; auto vec{[&a_vec]() -> span { return a_vec; }()}; } === cut here === The problem is that perform_implicit_conversion_flags (via mark_rvalue_use) replaces "a_vec" in the return statement by a CONSTRUCTOR representing a_vec's constant value, and then takes its address when invoking span's constructor. So we end up with an instance that points to garbage instead of a_vec's storage. As per Jason's suggestion, this patch simply removes the calls to mark_*_use from perform_implicit_conversion_flags, which fixes the PR. PR c++/117504 gcc/cp/ChangeLog: * call.cc (perform_implicit_conversion_flags): Don't call mark_{l,r}value_use. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/constexpr-117504.C: New test. * g++.dg/cpp2a/constexpr-117504a.C: New test. Diff: --- gcc/cp/call.cc | 5 --- gcc/testsuite/g++.dg/cpp2a/constexpr-117504.C | 60 ++ gcc/testsuite/g++.dg/cpp2a/constexpr-117504a.C | 12 ++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index f7b4cccb1c7a..c1c8987ec8b1 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -13971,11 +13971,6 @@ perform_implicit_conversion_flags (tree type, tree expr, conversion *conv; location_t loc = cp_expr_loc_or_input_loc (expr); - if (TYPE_REF_P (type)) -expr = mark_lvalue_use (expr); - else -expr = mark_rvalue_use (expr); - if (error_operand_p (expr)) return error_mark_node; diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-117504.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-117504.C new file mode 100644 index ..290d3dfd61e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-117504.C @@ -0,0 +1,60 @@ +// PR c++/117504 - Initial report +// { dg-do "run" { target c++20 } } + +struct span { + span (const int (&__first)[1]) : _M_ptr (__first) {} + int operator[] (long __i) { return _M_ptr[__i]; } + const int *_M_ptr; +}; + +constexpr int a_global_vec[]{1}; +span myFunctor() { + return a_global_vec; +} + +int main() { + constexpr int a_vec[]{1}; + + // + // This PR's case, that used to be miscompiled. + // + auto lambda_1 = [&a_vec] () -> span { return a_vec; }; + auto vec_1 { lambda_1 () }; + if (vec_1[0] != 1) +__builtin_abort (); + + // Variant that used to be miscompiled as well. + auto lambda_2 = [&] () -> span { return a_vec; }; + auto vec_2 { lambda_2 () }; + if (vec_2[0] != 1) +__builtin_abort (); + + // + // Related cases that worked already. + // + auto lambda_3 = [&a_vec] () /* -> span */ { return a_vec; }; + auto vec_3 { lambda_3 () }; + if (vec_3[0] != 1) +__builtin_abort (); + + auto lambda_4 = [&] () /* -> span */ { return a_vec; }; + auto vec_4 { lambda_4 () }; + if (vec_4[0] != 1) +__builtin_abort (); + + const int (&vec_5)[1] = a_vec; + if (vec_5[0] != 1) +__builtin_abort (); + + span vec_6 (a_vec); + if (vec_6[0] != 1) +__builtin_abort (); + + auto vec_7 = myFunctor (); + if (vec_7[0] != 1) +__builtin_abort (); + + const int (&vec_8)[1] { a_vec }; + if (vec_8[0] != 1) +__builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-117504a.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-117504a.C new file mode 100644 index ..f6d4dc8cbc53 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-117504a.C @@ -0,0 +1,12 @@ +// PR c++/117504 - ICE discovered by ppalka@ when reducing. +// { dg-do "compile" { target c++20 } } + +struct span { + span (const int* __first) : _M_ptr (__first) {} + int operator[] (long __i) { return _M_ptr[__i]; } + const int *_M_ptr; +}; +int main() { + constexpr int a_vec[]{1}; + auto vec { [&a_vec]() -> span { return a_vec; } () }; +}
[gcc r15-7851] lto: Fix missing cleanup with incremental LTO.
https://gcc.gnu.org/g:50cd99795268aaaf10705fa876dd4b751453e2f6 commit r15-7851-g50cd99795268aaaf10705fa876dd4b751453e2f6 Author: Michal Jires Date: Thu Mar 6 06:49:20 2025 +0100 lto: Fix missing cleanup with incremental LTO. Incremental LTO disabled cleanup of output_files since they have to persist in ltrans cache. This unintetionally also kept temporary early debug "*.debug.temp.o" files. Bootstrapped/regtested on x86_64-linux. Ok for trunk? lto-plugin/ChangeLog: * lto-plugin.c (cleanup_handler): Keep only files in ltrans cache. Diff: --- lto-plugin/lto-plugin.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c index 3d272551fed5..09d5441ecc78 100644 --- a/lto-plugin/lto-plugin.c +++ b/lto-plugin/lto-plugin.c @@ -945,6 +945,17 @@ cleanup_handler (void) if (!flto_incremental) for (i = 0; i < num_output_files; i++) maybe_unlink (output_files[i]); + else +{ + /* Keep files in ltrans cache. */ + const char* suffix = ".ltrans.o"; + for (i = 0; i < num_output_files; i++) + { + int offset = strlen (output_files[i]) - strlen (suffix); + if (offset < 0 || strcmp (output_files[i] + offset, suffix)) + maybe_unlink (output_files[i]); + } +} free_2 (); return LDPS_OK;
[gcc r15-7861] lto/114501 - missed free-lang-data for CONSTRUCTOR index
https://gcc.gnu.org/g:fdd95e1cf29137a19baed25f8c817d320dfe63e3 commit r15-7861-gfdd95e1cf29137a19baed25f8c817d320dfe63e3 Author: Richard Biener Date: Thu Mar 6 13:48:16 2025 +0100 lto/114501 - missed free-lang-data for CONSTRUCTOR index The following makes sure to also walk CONSTRUCTOR element indexes which can be FIELD_DECLs, referencing otherwise unused types we need to clean. walk_tree only walks CONSTRUCTOR element data. PR lto/114501 * ipa-free-lang-data.cc (find_decls_types_r): Explicitly handle CONSTRUCTORs as walk_tree handling of those is incomplete. * g++.dg/pr114501_0.C: New testcase. Diff: --- gcc/ipa-free-lang-data.cc | 14 ++ gcc/testsuite/g++.dg/pr114501_0.C | 20 2 files changed, 34 insertions(+) diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc index 0b666cb225f3..2885975b4e08 100644 --- a/gcc/ipa-free-lang-data.cc +++ b/gcc/ipa-free-lang-data.cc @@ -841,6 +841,20 @@ find_decls_types_r (tree *tp, int *ws, void *data) fld_worklist_push (tem, fld); fld_worklist_push (BLOCK_ABSTRACT_ORIGIN (t), fld); } + /* walk_tree does not visit ce->index which can be a FIELD_DECL, pulling + in otherwise unused structure fields so handle CTORs explicitly. */ + else if (TREE_CODE (t) == CONSTRUCTOR) +{ + unsigned HOST_WIDE_INT idx; + constructor_elt *ce; + for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); idx++) + { + if (ce->index) + fld_worklist_push (ce->index, fld); + fld_worklist_push (ce->value, fld); + } + *ws = 0; +} if (TREE_CODE (t) != IDENTIFIER_NODE && CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPED)) diff --git a/gcc/testsuite/g++.dg/pr114501_0.C b/gcc/testsuite/g++.dg/pr114501_0.C new file mode 100644 index ..0439ee5f6e23 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr114501_0.C @@ -0,0 +1,20 @@ +// { dg-do compile } +// { dg-require-effective-target c++17 } +// { dg-require-effective-target lto } +// { dg-options "-flto" } + +typedef long unsigned int size_t; +struct basic_string_view { + typedef long unsigned int size_type; + constexpr size_type size() const { return 0; } +}; +struct array { + char _M_elems[1]; +}; +inline constexpr auto make_it() { + constexpr basic_string_view view; + array arr{}; + arr._M_elems[view.size()] = 'a'; + return arr; +} +auto bar = make_it();
[gcc r15-7862] Revert "ira: Add new hooks for callee-save vs spills [PR117477]"
https://gcc.gnu.org/g:2c6ab4c443ae32782579f9bf948e9cef4e812ace commit r15-7862-g2c6ab4c443ae32782579f9bf948e9cef4e812ace Author: Richard Sandiford Date: Thu Mar 6 15:24:53 2025 + Revert "ira: Add new hooks for callee-save vs spills [PR117477]" This reverts commit e836d80374aa03a5ea5bd6cca00d826020c461da. Diff: --- gcc/config/aarch64/aarch64.cc| 118 --- gcc/config/i386/i386.cc | 28 ++ gcc/doc/tm.texi | 77 ++- gcc/doc/tm.texi.in | 6 +- gcc/hard-reg-set.h | 15 --- gcc/ira-color.cc | 83 ++-- gcc/target.def | 87 +++-- gcc/target.h | 12 --- gcc/targhooks.cc | 27 -- gcc/targhooks.h | 5 - gcc/testsuite/gcc.target/aarch64/callee_save_1.c | 12 --- gcc/testsuite/gcc.target/aarch64/callee_save_2.c | 14 --- gcc/testsuite/gcc.target/aarch64/callee_save_3.c | 12 --- gcc/testsuite/gcc.target/aarch64/pr103350-1.c| 2 +- 14 files changed, 39 insertions(+), 459 deletions(-) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 9bea8ce88f9f..9196b8d906c8 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -15873,118 +15873,6 @@ aarch64_memory_move_cost (machine_mode mode, reg_class_t rclass_i, bool in) : base + aarch64_tune_params.memmov_cost.store_int); } -/* CALLEE_SAVED_REGS is the set of callee-saved registers that the - RA has already decided to use. Return the total number of registers - in class RCLASS that need to be saved and restored, including the - frame link registers. */ -static int -aarch64_count_saves (const HARD_REG_SET &callee_saved_regs, reg_class rclass) -{ - auto saved_gprs = callee_saved_regs & reg_class_contents[rclass]; - auto nregs = hard_reg_set_popcount (saved_gprs); - - if (TEST_HARD_REG_BIT (reg_class_contents[rclass], LR_REGNUM)) -{ - if (aarch64_needs_frame_chain ()) - nregs += 2; - else if (!crtl->is_leaf || df_regs_ever_live_p (LR_REGNUM)) - nregs += 1; -} - return nregs; -} - -/* CALLEE_SAVED_REGS is the set of callee-saved registers that the - RA has already decided to use. Return the total number of registers - that need to be saved above the hard frame pointer, including the - frame link registers. */ -static int -aarch64_count_above_hard_fp_saves (const HARD_REG_SET &callee_saved_regs) -{ - /* FP and Advanced SIMD registers are saved above the frame pointer - but SVE registers are saved below it. */ - if (known_le (GET_MODE_SIZE (aarch64_reg_save_mode (V8_REGNUM)), 16U)) -return aarch64_count_saves (callee_saved_regs, POINTER_AND_FP_REGS); - return aarch64_count_saves (callee_saved_regs, POINTER_REGS); -} - -/* Implement TARGET_CALLEE_SAVE_COST. */ -static int -aarch64_callee_save_cost (spill_cost_type spill_type, unsigned int regno, - machine_mode mode, unsigned int nregs, int mem_cost, - const HARD_REG_SET &callee_saved_regs, - bool existing_spill_p) -{ - /* If we've already committed to saving an odd number of GPRs, assume that - saving one more will involve turning an STR into an STP and an LDR - into an LDP. This should still be more expensive than not spilling - (meaning that the minimum cost is 1), but it should usually be cheaper - than a separate store or load. */ - if (GP_REGNUM_P (regno) - && nregs == 1 - && (aarch64_count_saves (callee_saved_regs, GENERAL_REGS) & 1)) -return 1; - - /* Similarly for saving FP registers, if we only need to save the low - 64 bits. (We can also use STP/LDP instead of STR/LDR for Q registers, - but that is less likely to be a saving.) */ - if (FP_REGNUM_P (regno) - && nregs == 1 - && known_eq (GET_MODE_SIZE (aarch64_reg_save_mode (regno)), 8U) - && (aarch64_count_saves (callee_saved_regs, FP_REGS) & 1)) -return 1; - - /* If this would be the first register that we save, add the cost of - allocating or deallocating the frame. For GPR, FPR, and Advanced SIMD - saves, the allocation and deallocation can be folded into the save and - restore. */ - if (!existing_spill_p - && !GP_REGNUM_P (regno) - && !(FP_REGNUM_P (regno) - && known_le (GET_MODE_SIZE (aarch64_reg_save_mode (regno)), 16U))) -return default_callee_save_cost (spill_type, regno, mode, nregs, mem_cost, -callee_saved_regs, existing_spill_p); - - return mem_cost; -} - -/* Implement TARGET_FRAME_ALLOCATION_COST. */ -static int -aarch64_frame_allocation_cost (frame_cost_type, - const HARD_REG_SET &callee_sa
[gcc r15-7855] libstdc++: Fix constexpr memory algo tests for COW std::string
https://gcc.gnu.org/g:6eede5ad12415055ee54e5cb3218a340d383183c commit r15-7855-g6eede5ad12415055ee54e5cb3218a340d383183c Author: Jonathan Wakely Date: Thu Mar 6 11:24:03 2025 + libstdc++: Fix constexpr memory algo tests for COW std::string The old COW std::string is not usable in constant expressions, so these new tests fail with -D_GLIBCXX_USE_CXX11_ABI=0. The parts of the tests using std::string can be conditionally skipped. libstdc++-v3/ChangeLog: * testsuite/20_util/specialized_algorithms/uninitialized_copy/constexpr.cc: Do not test COW std::string in constexpr contexts. * testsuite/20_util/specialized_algorithms/uninitialized_default_construct/constexpr.cc: Likewise. * testsuite/20_util/specialized_algorithms/uninitialized_fill/constexpr.cc: Likewise. * testsuite/20_util/specialized_algorithms/uninitialized_move/constexpr.cc: Likewise. * testsuite/20_util/specialized_algorithms/uninitialized_value_construct/constexpr.cc: Likewise. Reviewed-by: Giuseppe D'Angelo Diff: --- .../20_util/specialized_algorithms/uninitialized_copy/constexpr.cc | 2 ++ .../specialized_algorithms/uninitialized_default_construct/constexpr.cc | 2 ++ .../20_util/specialized_algorithms/uninitialized_fill/constexpr.cc | 2 ++ .../20_util/specialized_algorithms/uninitialized_move/constexpr.cc | 2 ++ .../specialized_algorithms/uninitialized_value_construct/constexpr.cc | 2 ++ 5 files changed, 10 insertions(+) diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constexpr.cc index 6f05b0ce309d..faf69689ee7f 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constexpr.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constexpr.cc @@ -51,7 +51,9 @@ test01() test01_impl({'a', 'b', 'c'}) && test01_impl({1, 2, 3, 4}) && test01_impl({1.0, 2.0, 3.0, 4.0}) && +#if _GLIBCXX_USE_CXX11_ABI test01_impl({"a", "b", "cc", "", ""}) && +#endif test01_impl>({ {0}, {0, 1}, {0, 1, 2}}); } diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/constexpr.cc index db39c8b4d051..151c1f95a30d 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/constexpr.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/constexpr.cc @@ -59,7 +59,9 @@ test01() test01_impl() && test01_impl() && test01_impl() && +#if _GLIBCXX_USE_CXX11_ABI test01_impl() && +#endif test01_impl>() && test01_impl>(); } diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/constexpr.cc index e43cd35a92d9..27461fa452ec 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/constexpr.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/constexpr.cc @@ -58,8 +58,10 @@ test01() test01_impl(0) && test01_impl(42) && test01_impl(3.14) && +#if _GLIBCXX_USE_CXX11_ABI test01_impl() && test01_impl(std::string("test")) && +#endif test01_impl>() && test01_impl>({1, 2, 3, 4}) && test01_impl>(nullptr); diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constexpr.cc index 47403ae706dc..f122a03991fc 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constexpr.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constexpr.cc @@ -43,7 +43,9 @@ test01() test01_impl({'a', 'b', 'c'}) && test01_impl({1, 2, 3, 4}) && test01_impl({1.0, 2.0, 3.0, 4.0}) && +#if _GLIBCXX_USE_CXX11_ABI test01_impl({"a", "b", "cc", "", ""}) && +#endif test01_impl>({ {0}, {0, 1}, {0, 1, 2}}) && test01_impl>(std::vector>(10)); } diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/constexpr.cc index 55dfc59b5ef3..f943973b0154 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/constexpr.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/constexpr.cc @@ -56,7 +56,9 @@ test01() test01_impl() && test01_impl() && test01_impl() && +#if _GLIBC
[gcc r15-7850] middle-end/119119 - re-gimplification of empty CTOR assignments
https://gcc.gnu.org/g:3bd61c1dfaa2d7153eb4be82f423533ea937d0f9 commit r15-7850-g3bd61c1dfaa2d7153eb4be82f423533ea937d0f9 Author: Richard Biener Date: Thu Mar 6 09:08:07 2025 +0100 middle-end/119119 - re-gimplification of empty CTOR assignments The following testcase runs into a re-gimplification issue during inlining when processing MEM[(struct e *)this_2(D)].a = {}; where re-gimplification does not handle assignments in the same way than the gimplifier but instead relies on rhs_predicate_for and gimplifying the RHS standalone. This fails to handle special-casing of CTORs. The is_gimple_mem_rhs_or_call predicate already handles clobbers but not empty CTORs so we end up in the fallback code trying to force the CTOR into a separate stmt using a temporary - but as we have a non-copyable type here that ICEs. The following generalizes empty CTORs in is_gimple_mem_rhs_or_call since those need no additional re-gimplification. PR middle-end/119119 * gimplify.cc (is_gimple_mem_rhs_or_call): All empty CTORs are OK when not a register type. * g++.dg/torture/pr11911.C: New testcase. Diff: --- gcc/gimplify.cc| 2 +- gcc/testsuite/g++.dg/torture/pr11911.C | 21 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 160e7fc9df66..6869f53ce701 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -607,7 +607,7 @@ is_gimple_mem_rhs_or_call (tree t) else return (is_gimple_val (t) || is_gimple_lvalue (t) - || TREE_CLOBBER_P (t) + || (TREE_CODE (t) == CONSTRUCTOR && CONSTRUCTOR_NELTS (t) == 0) || TREE_CODE (t) == CALL_EXPR); } diff --git a/gcc/testsuite/g++.dg/torture/pr11911.C b/gcc/testsuite/g++.dg/torture/pr11911.C new file mode 100644 index ..7dc836ff9b53 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr11911.C @@ -0,0 +1,21 @@ +// { dg-do compile } +// { dg-require-effective-target c++17 } + +struct b { + int a; +}; +struct c { + b d{}; + c() = default; + c(c &) = delete; +}; +struct e { + c a{}; + e() {} +}; +inline e f() { return {}; } +struct g { + e cx; + g() : cx{f()} {} +}; +void h() { g i; }
[gcc r15-7853] libstdc++: implement tuple protocol for std::complex (P2819R2)
https://gcc.gnu.org/g:de231924b73bc120bf2b7ada4eeccd884c249ee1 commit r15-7853-gde231924b73bc120bf2b7ada4eeccd884c249ee1 Author: Giuseppe D'Angelo Date: Thu Feb 27 22:47:27 2025 +0100 libstdc++: implement tuple protocol for std::complex (P2819R2) This commit implements P2819R2 for C++26, making std::complex destructurable and tuple-like (see [complex.tuple]). std::get needs to get forward declared in stl_pair.h (following the existing precedent for the implementation of P2165R4, cf. r14-8710-g65b4cba9d6a9ff), and implemented in . Also, std::get(complex) needs to return *references* to the real and imaginary parts of a std::complex object, honoring the value category and constness of the argument. In principle a straightforward task, it gets a bit convoluted by the fact that: 1) std::complex does not have existing getters that one can use for this (real() and imag() return values, not references); 2) there are specializations for language/extended floating-point types, which requires some duplication -- need to amend the primary and all the specializations; 3) these specializations use a `__complex__ T`, but the primary template uses two non-static data members, making generic code harder to write. The implementation choice used here is to add the overloads of std::get for complex as declared in [complex.tuple]. In turn they dispatch to a newly added getter that extracts references to the real/imaginary parts of a complex. This getter is private API, and the implementation depends on whether it's the primary (bind the data member) or a specialization (use the GCC language extensions for __complex__). To avoid duplication and minimize template instantiations, the getter uses C++23's deducing this (this avoids const overloads). The value category is dealt with by the std::get overloads. Add a test that covers the aspects of the tuple protocol, as well as the tuple-like interface. While at it, add a test for the existing tuple-like feature-testing macro. PR libstdc++/113310 libstdc++-v3/ChangeLog: * include/bits/stl_pair.h (get): Forward-declare std::get for std::complex. * include/bits/version.def (tuple_like): Bump the value of the feature-testing macro in C++26. * include/bits/version.h: Regenerate. * include/std/complex: Implement the tuple protocol for std::complex. (tuple_size): Specialize for std::complex. (tuple_element): Ditto. (__is_tuple_like_v): Ditto. (complex): Add a private getter to obtain references to the real and the imaginary part, on the primary class template and on its specializations. (get): Add overloads of std::get for std::complex. * testsuite/20_util/tuple/tuple_like_ftm.cc: New test. * testsuite/26_numerics/complex/tuple_like.cc: New test. Diff: --- libstdc++-v3/include/bits/stl_pair.h | 18 +++ libstdc++-v3/include/bits/version.def | 5 + libstdc++-v3/include/bits/version.h| 7 +- libstdc++-v3/include/std/complex | 91 +++ .../testsuite/20_util/tuple/tuple_like_ftm.cc | 17 ++ .../testsuite/26_numerics/complex/tuple_like.cc| 179 + 6 files changed, 316 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index c57e3c097652..8c57712b4617 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -101,6 +101,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct _Index_tuple; + template +class complex; + template constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& get(pair<_Tp1, _Tp2>& __in) noexcept; @@ -149,6 +152,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr const _Tp&& get(const array<_Tp, _Nm>&&) noexcept; +#if __glibcxx_tuple_like >= 202311 // >= C++26 + template +constexpr _Tp& +get(complex<_Tp>&) noexcept; + template +constexpr _Tp&& +get(complex<_Tp>&&) noexcept; + template +constexpr const _Tp& +get(const complex<_Tp>&) noexcept; + template +constexpr const _Tp&& +get(const complex<_Tp>&&) noexcept; +#endif + #if ! __cpp_lib_concepts // Concept utility functions, reused in conditionally-explicit // constructors. diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index eb2c6d8a3ee7..2af5a54bff28 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1797,6 +1797,11 @@ ftms = { ftms = { name = tuple_like; + values = { +v = 202311; +cxxmin = 26; +extra_cond = "__cpp_explicit_this_parameter >= 20
[gcc r15-7854] pair-fusion: Add singleton move_range asserts [PR114492]
https://gcc.gnu.org/g:d6d7da92fb598c50d25332011bffe6b6515c9669 commit r15-7854-gd6d7da92fb598c50d25332011bffe6b6515c9669 Author: Alex Coplan Date: Wed Mar 5 15:45:09 2025 + pair-fusion: Add singleton move_range asserts [PR114492] The PR claims that pair-fusion has invalid uses of gcc_assert (such that the pass will misbehave with --disable-checking). As noted in the comments, in the case of the calls to restrict_movement, the only way we can possibly depend on the side effects is if we call it with a non-singleton move range. However, the intent is that we always have a singleton move range here, and thus we do not rely on the side effects. This patch therefore adds asserts to check for a singleton move range before calling restrict_movement, thus clarifying the intent and hopefully dispelling any concerns that having the calls wrapped in asserts is problematic here. gcc/ChangeLog: PR rtl-optimization/114492 * pair-fusion.cc (pair_fusion_bb_info::fuse_pair): Check for singleton move range before calling restrict_movement. (pair_fusion::try_promote_writeback): Likewise. Diff: --- gcc/pair-fusion.cc | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gcc/pair-fusion.cc b/gcc/pair-fusion.cc index 72e642465340..a4ef72879675 100644 --- a/gcc/pair-fusion.cc +++ b/gcc/pair-fusion.cc @@ -1994,7 +1994,8 @@ pair_fusion_bb_info::fuse_pair (bool load_p, auto ignore = ignore_changing_insns (changes); for (unsigned i = 0; i < changes.length (); i++) -gcc_assert (rtl_ssa::restrict_movement (*changes[i], ignore)); +gcc_assert (changes[i]->move_range.singleton () + && rtl_ssa::restrict_movement (*changes[i], ignore)); // Check the pair pattern is recog'd. if (!rtl_ssa::recog (attempt, *pair_change, ignore)) @@ -3084,7 +3085,8 @@ pair_fusion::try_promote_writeback (insn_info *insn, bool load_p) auto ignore = ignore_changing_insns (changes); for (unsigned i = 0; i < ARRAY_SIZE (changes); i++) -gcc_assert (rtl_ssa::restrict_movement (*changes[i], ignore)); +gcc_assert (changes[i]->move_range.singleton () + && rtl_ssa::restrict_movement (*changes[i], ignore)); if (!rtl_ssa::recog (attempt, pair_change, ignore)) {
[gcc r15-7860] Fix 'libstdc++-v3/src/c++20/tzdb.cc' build for '__GTHREADS && !__GTHREADS_CXX0X' configurations
https://gcc.gnu.org/g:780932620d859fa9e0190edd0c408d0bedf9179e commit r15-7860-g780932620d859fa9e0190edd0c408d0bedf9179e Author: Jonathan Wakely Date: Thu Feb 20 14:08:11 2025 + Fix 'libstdc++-v3/src/c++20/tzdb.cc' build for '__GTHREADS && !__GTHREADS_CXX0X' configurations libstdc++-v3/ * src/c++20/tzdb.cc [__GTHREADS && !__GTHREADS_CXX0X]: Use '__gnu_cxx::__mutex'. Co-authored-by: Thomas Schwinge Diff: --- libstdc++-v3/src/c++20/tzdb.cc | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc index 9cf9eeccc599..1a1130f9b7bd 100644 --- a/libstdc++-v3/src/c++20/tzdb.cc +++ b/libstdc++-v3/src/c++20/tzdb.cc @@ -35,6 +35,9 @@ #include // atomic, atomic #include // atomic> #include // mutex +#if defined __GTHREADS && ! defined _GLIBCXX_HAS_GTHREADS +# include // __gnu_cxx::__mutex +#endif #include // filesystem::read_symlink #ifndef _AIX @@ -97,11 +100,18 @@ namespace std::chrono { namespace { -#if ! USE_ATOMIC_SHARED_PTR #ifndef __GTHREADS // Dummy no-op mutex type for single-threaded targets. struct mutex { void lock() { } void unlock() { } }; +#elif ! defined _GLIBCXX_HAS_GTHREADS +// Use __gnu_cxx::__mutex if std::mutex isn't available. +using mutex = __gnu_cxx::__mutex; +# if ! USE_ATOMIC_SHARED_PTR && defined __GTHREAD_MUTEX_INIT +# error "TODO: __gnu_cxx::__mutex can't be initialized with 'constinit'" +# endif #endif + +#if ! USE_ATOMIC_SHARED_PTR inline mutex& list_mutex() { #ifdef __GTHREAD_MUTEX_INIT
[gcc r15-7859] libstdc++: Avoid '-Wunused-parameter' for 'out' in member function 'std::codecvt_base::result std::_
https://gcc.gnu.org/g:bf07f9a9832494a7270a7099195f47f2126e8e07 commit r15-7859-gbf07f9a9832494a7270a7099195f47f2126e8e07 Author: Thomas Schwinge Date: Wed Feb 19 20:39:25 2025 +0100 libstdc++: Avoid '-Wunused-parameter' for 'out' in member function 'std::codecvt_base::result std::__format::{anonymous}::__encoding::conv(std::string_view, std::string&) const' In a newlib configuration: ../../../../../source-gcc/libstdc++-v3/src/c++20/format.cc: In member function ‘std::codecvt_base::result std::__format::{anonymous}::__encoding::conv(std::string_view, std::string&) const’: ../../../../../source-gcc/libstdc++-v3/src/c++20/format.cc:100:35: error: unused parameter ‘out’ [-Werror=unused-parameter] 100 | conv(string_view input, string& out) const | ^~~ libstdc++-v3/ * src/c++20/format.cc (conv): Tag 'out' as '[[maybe_unused]]'. Diff: --- libstdc++-v3/src/c++20/format.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libstdc++-v3/src/c++20/format.cc b/libstdc++-v3/src/c++20/format.cc index 1a24fcab7f76..6967d53259da 100644 --- a/libstdc++-v3/src/c++20/format.cc +++ b/libstdc++-v3/src/c++20/format.cc @@ -97,7 +97,7 @@ struct __encoding : locale::facet // Convert `input` to UTF-8, using `out` to hold the result. codecvt_base::result - conv(string_view input, string& out) const + conv(string_view input, [[maybe_unused]] string& out) const { if (input.empty()) [[unlikely]] return codecvt_base::noconv;
[gcc r15-7857] libstdc++: Avoid '-Wunused-parameter' for 'nofollow' in static member function 'static std::filesyst
https://gcc.gnu.org/g:5029c4bd330849fd6513b290d38bce853b320c5b commit r15-7857-g5029c4bd330849fd6513b290d38bce853b320c5b Author: Thomas Schwinge Date: Wed Feb 19 20:15:30 2025 +0100 libstdc++: Avoid '-Wunused-parameter' for 'nofollow' in static member function 'static std::filesystem::__gnu_posix::DIR* std::filesystem::_Dir_base::openat(const _At_path&, bool)' In a newlib configuration: In file included from ../../../../../source-gcc/libstdc++-v3/src/c++17/fs_dir.cc:37, from ../../../../../source-gcc/libstdc++-v3/src/c++17/cow-fs_dir.cc:26: ../../../../../source-gcc/libstdc++-v3/src/c++17/../filesystem/dir-common.h: In static member function ‘static std::filesystem::__gnu_posix::DIR* std::filesystem::_Dir_base::openat(const _At_path&, bool)’: ../../../../../source-gcc/libstdc++-v3/src/c++17/../filesystem/dir-common.h:210:36: error: unused parameter ‘nofollow’ [-Werror=unused-parameter] 210 | openat(const _At_path& atp, bool nofollow) | ~^~~~ libstdc++-v3/ * src/filesystem/dir-common.h (openat): Tag 'nofollow' as '[[maybe_unused]]'. Diff: --- libstdc++-v3/src/filesystem/dir-common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libstdc++-v3/src/filesystem/dir-common.h b/libstdc++-v3/src/filesystem/dir-common.h index 5ff621c3380a..c7d4bc4e6ed7 100644 --- a/libstdc++-v3/src/filesystem/dir-common.h +++ b/libstdc++-v3/src/filesystem/dir-common.h @@ -207,7 +207,7 @@ struct _Dir_base } static posix::DIR* - openat(const _At_path& atp, bool nofollow) + openat(const _At_path& atp, [[maybe_unused]] bool nofollow) { #if _GLIBCXX_HAVE_FDOPENDIR && defined O_RDONLY && defined O_DIRECTORY \ && ! _GLIBCXX_FILESYSTEM_IS_WINDOWS
[gcc r15-7858] libstdc++: Avoid '-Wunused-parameter' for 'is_directory' in member function 'bool std::filesystem::_
https://gcc.gnu.org/g:b122afef2a584d15dbc594074bbe444c4fa74cb7 commit r15-7858-gb122afef2a584d15dbc594074bbe444c4fa74cb7 Author: Thomas Schwinge Date: Wed Feb 19 20:18:52 2025 +0100 libstdc++: Avoid '-Wunused-parameter' for 'is_directory' in member function 'bool std::filesystem::__cxx11::_Dir::do_unlink(bool, std::error_code&) const' In a newlib configuration: ../../../../../source-gcc/libstdc++-v3/src/c++17/fs_dir.cc: In member function ‘bool std::filesystem::__cxx11::_Dir::do_unlink(bool, std::error_code&) const’: ../../../../../source-gcc/libstdc++-v3/src/c++17/fs_dir.cc:147:18: error: unused parameter ‘is_directory’ [-Werror=unused-parameter] 147 | do_unlink(bool is_directory, error_code& ec) const noexcept | ~^~~~ libstdc++-v3/ * src/c++17/fs_dir.cc (do_unlink): Tag 'is_directory' as '[[maybe_unused]]'. Diff: --- libstdc++-v3/src/c++17/fs_dir.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libstdc++-v3/src/c++17/fs_dir.cc b/libstdc++-v3/src/c++17/fs_dir.cc index cd75e0541d3e..9347a8a46dc0 100644 --- a/libstdc++-v3/src/c++17/fs_dir.cc +++ b/libstdc++-v3/src/c++17/fs_dir.cc @@ -144,7 +144,7 @@ struct fs::_Dir : _Dir_base } bool - do_unlink(bool is_directory, error_code& ec) const noexcept + do_unlink([[maybe_unused]] bool is_directory, error_code& ec) const noexcept { #if _GLIBCXX_HAVE_UNLINKAT const auto atp = current();
[gcc r15-7872] Fix comment typos
https://gcc.gnu.org/g:be0942afb3a7080b7b0420a5369bdcf3dcc74b52 commit r15-7872-gbe0942afb3a7080b7b0420a5369bdcf3dcc74b52 Author: Simon Martin Date: Thu Mar 6 20:36:26 2025 +0100 Fix comment typos While investigating PR c++/99538 I noticed two comment typos: "delared" and "paramter". The first has a single occurrence, but the second a few more. This patch fixes all of them. gcc/ChangeLog: * config/i386/x86-tune-sched.cc (ix86_fuse_mov_alu_p): Fix comment typo, paramter -> parameter. * config/lm32/lm32.cc (lm32_std_gimplify_va_arg_expr): Likewise. gcc/cp/ChangeLog: * cp-tree.h (processing_contract_condition): Fix comment typo, paramter -> parameter. * parser.cc (cp_parser_requires_expression): Fix comment typo, delared -> declared. gcc/rust/ChangeLog: * rust-diagnostics.h (RUST_ATTRIBUTE_GCC_DIAG): Fix comment typo, paramter -> parameter. gcc/testsuite/ChangeLog: * gcc.target/powerpc/ppc64-abi-1.c: Fix comment typos, paramter -> parameter. * gcc.target/powerpc/ppc64-abi-2.c: Likewise. Diff: --- gcc/config/i386/x86-tune-sched.cc | 3 +-- gcc/config/lm32/lm32.cc| 2 +- gcc/cp/cp-tree.h | 2 +- gcc/cp/parser.cc | 2 +- gcc/rust/rust-diagnostics.h| 2 +- gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c | 12 ++-- gcc/testsuite/gcc.target/powerpc/ppc64-abi-2.c | 12 ++-- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/gcc/config/i386/x86-tune-sched.cc b/gcc/config/i386/x86-tune-sched.cc index a51764e078c8..685a83c4311b 100644 --- a/gcc/config/i386/x86-tune-sched.cc +++ b/gcc/config/i386/x86-tune-sched.cc @@ -633,7 +633,7 @@ ix86_fuse_mov_alu_p (rtx_insn *mov, rtx_insn *alu) && !REG_P (op1) && !x86_64_immediate_operand (op1, VOIDmode)) return false; - /* Only one of two paramters must be move destination. */ + /* Only one of two parameters must be move destination. */ if (op1 && REG_P (op1) && REGNO (op1) == REGNO (reg)) return false; return true; @@ -786,4 +786,3 @@ ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp) return true; } - diff --git a/gcc/config/lm32/lm32.cc b/gcc/config/lm32/lm32.cc index 15728969fadd..9ec756cd478d 100644 --- a/gcc/config/lm32/lm32.cc +++ b/gcc/config/lm32/lm32.cc @@ -831,7 +831,7 @@ lm32_builtin_va_start (tree valist, rtx nextarg) /* * This was copied from "standard" implementation of va_arg, and then - * handling for overflow of the register paramters added + * handling for overflow of the register parameters added. */ static tree diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 583d04963642..a839ad6d28ac 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2025,7 +2025,7 @@ extern GTY(()) struct saved_scope *scope_chain; #define processing_omp_trait_property_expr scope_chain->x_processing_omp_trait_property_expr /* Nonzero if we are parsing the conditional expression of a contract - condition. These expressions appear outside the paramter list (like a + condition. These expressions appear outside the parameter list (like a trailing return type), but are potentially evaluated. */ #define processing_contract_condition scope_chain->x_processing_contract_condition diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 489c00e05227..c2b81fc281a8 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -32299,7 +32299,7 @@ cp_parser_requires_expression (cp_parser *parser) tree parms, reqs; { -/* Local parameters are delared as variables within the scope +/* Local parameters are declared as variables within the scope of the expression. They are not visible past the end of the expression. Expressions within the requires-expression are unevaluated. */ diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h index 42f3ba7fc6d8..a13dc6a2eaf8 100644 --- a/gcc/rust/rust-diagnostics.h +++ b/gcc/rust/rust-diagnostics.h @@ -25,7 +25,7 @@ #include "util/optional.h" // This macro is used to specify the position of format string & it's -// arguments within the function's paramter list. +// arguments within the function's parameter list. // 'm' specifies the position of the format string parameter. // 'n' specifies the position of the first argument for the format string. #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) diff --git a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c index 731c0d880aa8..4a3329042bc4 100644 --- a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c +++ b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-1.c @@ -102,7 +102,7 @@ typedef struct sf } stack_frame_t; -/* Paramter passing. +/* Parameter
[gcc r15-7873] Fortran: improve checking of substring bounds [PR119118]
https://gcc.gnu.org/g:ac8a70db59ac309daf866a65b5785e472e76d406 commit r15-7873-gac8a70db59ac309daf866a65b5785e472e76d406 Author: Harald Anlauf Date: Thu Mar 6 21:45:42 2025 +0100 Fortran: improve checking of substring bounds [PR119118] After the fix for pr98490 no substring bounds check was generated if the substring start was not a variable. While the purpose of that fix was to suppress a premature check before implied-do indices were substituted, this prevented a check if the substring start was an expression or a constant. A better solution is to defer the check until implied-do indices have been substituted in the start and end expressions. PR fortran/119118 gcc/fortran/ChangeLog: * dependency.cc (gfc_contains_implied_index_p): Helper function to determine if an expression has a dependence on an implied-do index. * dependency.h (gfc_contains_implied_index_p): Add prototype. * trans-expr.cc (gfc_conv_substring): Adjust logic to not generate substring bounds checks before implied-do indices have been substituted. gcc/testsuite/ChangeLog: * gfortran.dg/bounds_check_23.f90: Generalize test. * gfortran.dg/bounds_check_26.f90: New test. Diff: --- gcc/fortran/dependency.cc | 81 +++ gcc/fortran/dependency.h | 1 + gcc/fortran/trans-expr.cc | 4 +- gcc/testsuite/gfortran.dg/bounds_check_23.f90 | 18 +- gcc/testsuite/gfortran.dg/bounds_check_26.f90 | 24 5 files changed, 125 insertions(+), 3 deletions(-) diff --git a/gcc/fortran/dependency.cc b/gcc/fortran/dependency.cc index 6b3affa60574..8354b185f347 100644 --- a/gcc/fortran/dependency.cc +++ b/gcc/fortran/dependency.cc @@ -1888,6 +1888,87 @@ contains_forall_index_p (gfc_expr *expr) return false; } + +/* Traverse expr, checking all EXPR_VARIABLE symbols for their + implied_index attribute. Return true if any variable may be + used as an implied-do index. It is safe to pessimistically + return true, and assume a dependency. */ + +bool +gfc_contains_implied_index_p (gfc_expr *expr) +{ + gfc_actual_arglist *arg; + gfc_constructor *c; + gfc_ref *ref; + int i; + + if (!expr) +return false; + + switch (expr->expr_type) +{ +case EXPR_VARIABLE: + if (expr->symtree->n.sym->attr.implied_index) + return true; + break; + +case EXPR_OP: + if (gfc_contains_implied_index_p (expr->value.op.op1) + || gfc_contains_implied_index_p (expr->value.op.op2)) + return true; + break; + +case EXPR_FUNCTION: + for (arg = expr->value.function.actual; arg; arg = arg->next) + if (gfc_contains_implied_index_p (arg->expr)) + return true; + break; + +case EXPR_CONSTANT: +case EXPR_NULL: +case EXPR_SUBSTRING: + break; + +case EXPR_STRUCTURE: +case EXPR_ARRAY: + for (c = gfc_constructor_first (expr->value.constructor); + c; gfc_constructor_next (c)) + if (gfc_contains_implied_index_p (c->expr)) + return true; + break; + +default: + gcc_unreachable (); +} + + for (ref = expr->ref; ref; ref = ref->next) +switch (ref->type) + { + case REF_ARRAY: + for (i = 0; i < ref->u.ar.dimen; i++) + if (gfc_contains_implied_index_p (ref->u.ar.start[i]) + || gfc_contains_implied_index_p (ref->u.ar.end[i]) + || gfc_contains_implied_index_p (ref->u.ar.stride[i])) + return true; + break; + + case REF_COMPONENT: + break; + + case REF_SUBSTRING: + if (gfc_contains_implied_index_p (ref->u.ss.start) + || gfc_contains_implied_index_p (ref->u.ss.end)) + return true; + break; + + default: + gcc_unreachable (); + } + + return false; +} + + /* Determines overlapping for two single element array references. */ static gfc_dependency diff --git a/gcc/fortran/dependency.h b/gcc/fortran/dependency.h index 3f81d406082f..2fc2e567a4cf 100644 --- a/gcc/fortran/dependency.h +++ b/gcc/fortran/dependency.h @@ -41,6 +41,7 @@ bool gfc_dep_resolver (gfc_ref *, gfc_ref *, gfc_reverse *, bool identical = false); bool gfc_are_equivalenced_arrays (gfc_expr *, gfc_expr *); bool gfc_omp_expr_prefix_same (gfc_expr *, gfc_expr *); +bool gfc_contains_implied_index_p (gfc_expr *); gfc_expr * gfc_discard_nops (gfc_expr *); diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index fbe7333fd711..d965539f11e7 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -2814,8 +2814,8 @@ gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind, end.expr = gfc_evaluate_now (end.expr, &se->pre); if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) - && (ref->u.ss.start->symtree - && !ref->u.ss.star
[gcc r15-7874] [PR rtl-optimization/119099] Avoid infinite loop in ext-dce.
https://gcc.gnu.org/g:aef04968cfba0feb4420d96c61f766ee6c73f957 commit r15-7874-gaef04968cfba0feb4420d96c61f766ee6c73f957 Author: Alexey Merzlyakov Date: Thu Mar 6 14:42:59 2025 -0700 [PR rtl-optimization/119099] Avoid infinite loop in ext-dce. This fixes the ping-ponging of live sets in ext-dce which is left unresolved can lead to infinite loops in the ext-dce pass as seen by the P1 regression 119099. At its core instead of replacing the livein set with the just recomputed data, we IOR in the just recomputed data to the existing livein set. That ensures the existing livein set never shrinks. Bootstrapped and regression tested on x86. I've also thrown this into my tester to verify it across multiple targets and that we aren't regressing the (limited) tests we have in place for ext-dce's optimization behavior. While it's a generic patch, I'll wait for the RISC-V tester to run is course before committing. PR rtl-optimization/119099 gcc/ * ext-dce.cc (ext_dce_rd_transfer_n): Do not allow the livein set to shrink. gcc/testsuite/ * gcc.dg/torture/pr119099.c: New test. Co-authored-by: Jeff Law Diff: --- gcc/ext-dce.cc | 13 +++-- gcc/testsuite/gcc.dg/torture/pr119099.c | 19 +++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/gcc/ext-dce.cc b/gcc/ext-dce.cc index e257e3bc873a..626c431f601e 100644 --- a/gcc/ext-dce.cc +++ b/gcc/ext-dce.cc @@ -1089,16 +1089,9 @@ ext_dce_rd_transfer_n (int bb_index) ext_dce_process_bb (bb); - /* We may have narrowed the set of live objects at the start - of this block. If so, update the bitmaps and indicate to - the generic dataflow code that something changed. */ - if (!bitmap_equal_p (&livein[bb_index], livenow)) -{ - bitmap_copy (&livein[bb_index], livenow); - return true; -} - - return false; + /* We only allow widening the set of objects live at the start + of a block. Otherwise we run the risk of not converging. */ + return bitmap_ior_into (&livein[bb_index], livenow); } /* Dummy function for the df_simple_dataflow API. */ diff --git a/gcc/testsuite/gcc.dg/torture/pr119099.c b/gcc/testsuite/gcc.dg/torture/pr119099.c new file mode 100644 index ..21898593373b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr119099.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ + +int a, b; + +void func2(short); + +void func1() { + while (1) { +int loc = 8; +while (1) { + func2(loc); + if (a) +loc = 3; + else if (b) +break; + loc |= a; +} + } +}
[gcc r15-7856] libstdc++: Avoid '-Wunused-parameter' for '__what' in function 'void std::__throw_format_error(const
https://gcc.gnu.org/g:d87c0d5443ba860dcbc6be24921e0ffb463cc96f commit r15-7856-gd87c0d5443ba860dcbc6be24921e0ffb463cc96f Author: Thomas Schwinge Date: Wed Feb 19 20:34:25 2025 +0100 libstdc++: Avoid '-Wunused-parameter' for '__what' in function 'void std::__throw_format_error(const char*)' In a '-fno-exceptions' configuration: In file included from ../../../../../source-gcc/libstdc++-v3/src/c++20/format.cc:29: [...]/build-gcc/[...]/libstdc++-v3/include/format: In function ‘void std::__throw_format_error(const char*)’: [...]/build-gcc/[...]/libstdc++-v3/include/format:200:36: error: unused parameter ‘__what’ [-Werror=unused-parameter] 200 | __throw_format_error(const char* __what) |^~ libstdc++-v3/ * include/bits/c++config [!__cpp_exceptions] (_GLIBCXX_THROW_OR_ABORT): Reference '_EXC'. Co-authored-by: Jonathan Wakely Diff: --- libstdc++-v3/include/bits/c++config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 6a73507d0748..676f5eecbbb6 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -261,7 +261,7 @@ # if __cpp_exceptions # define _GLIBCXX_THROW_OR_ABORT(_EXC) (throw (_EXC)) # else -# define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort()) +# define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort(), (void)(_EXC)) # endif #endif
[gcc r15-7865] libstdc++: Ensure defines __pair_like
https://gcc.gnu.org/g:88a521cc3283ae6b6bccc7afefe4723399ddb975 commit r15-7865-g88a521cc3283ae6b6bccc7afefe4723399ddb975 Author: Jonathan Wakely Date: Thu Mar 6 11:20:23 2025 + libstdc++: Ensure defines __pair_like We need to include in C++23 and later, so that __pair_like_convertible_from can use __pair_like, and so that __is_tuple_like_v is declared before we define a partial specialization. libstdc++-v3/ChangeLog: * include/bits/ranges_util.h: Include . Reviewed-by: Patrick Palka Diff: --- libstdc++-v3/include/bits/ranges_util.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 51024ecbebe5..54e4f6261b05 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -35,6 +35,9 @@ # include # include # include // __can_use_memchr_for_find +#if __glibcxx_tuple_like // >= C++23 +# include // __pair_like, __is_tuple_like_v +#endif #ifdef __glibcxx_ranges namespace std _GLIBCXX_VISIBILITY(default)
[gcc r15-7866] libstdc++: Add assertions to std::list::pop_{front, back}
https://gcc.gnu.org/g:4412e9bb73754a0c9668e80c4b8ee2fefffbbb04 commit r15-7866-g4412e9bb73754a0c9668e80c4b8ee2fefffbbb04 Author: Jonathan Wakely Date: Thu Feb 27 21:59:41 2025 + libstdc++: Add assertions to std::list::pop_{front,back} The recently-approved Standard Library Hardening proposal (P3471R4) gives pop_front and pop_back member functions hardened preconditions, but std::list was missing assertions on them. Our other sequence containers do have assertions on those members. libstdc++-v3/ChangeLog: * include/bits/stl_list.h (list::pop_front, list::pop_back): Add non-empty assertions. Reviewed-by: Patrick Palka Diff: --- libstdc++-v3/include/bits/stl_list.h | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index f987d8b9d0a3..82ccb50ff182 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -1784,7 +1784,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ void pop_front() _GLIBCXX_NOEXCEPT - { this->_M_erase(begin()); } + { + __glibcxx_requires_nonempty(); + this->_M_erase(begin()); + } /** * @brief Add data to the end of the %list. @@ -1833,7 +1836,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ void pop_back() _GLIBCXX_NOEXCEPT - { this->_M_erase(iterator(this->_M_impl._M_node._M_prev)); } + { + __glibcxx_requires_nonempty(); + this->_M_erase(iterator(this->_M_impl._M_node._M_prev)); + } #if __cplusplus >= 201103L /**
[gcc r15-7869] c++: Fix up instantiation of pointer/reference/array types with attributes [PR119138]
https://gcc.gnu.org/g:0ba3e5ff14a48f1fb7ca53cb86194e08d5b5da66 commit r15-7869-g0ba3e5ff14a48f1fb7ca53cb86194e08d5b5da66 Author: Jakub Jelinek Date: Thu Mar 6 17:58:14 2025 +0100 c++: Fix up instantiation of pointer/reference/array types with attributes [PR119138] My r15-7822 PR118787 change unfortunately broke build on x86_64-w64-mingw32. The reduced testcase below shows what is going on. va_list on this target is char * with extra (non-dependent) attributes on it. Before my r15-7822 change, instantiation of such type used the fast path and just returned t, but as it has non-NULL TYPE_ATTRIBUTES, it now falls through, builds a pointer type and then calls apply_late_template_attributes. And in there triggers a bug, that function has been written for types with RECORD_TYPE/UNION_TYPE (or ENUMERAL_TYPE?) in mind, where we call apply_late_template_attributes with ATTR_FLAG_TYPE_IN_PLACE and can just apply the non-dependent attributes directly to TYPE_ATTRIBUTES. That is wrong for shared types like {POINTER,REFERENCE,ARRAY}_TYPE etc., we should just force cp_build_type_attribute_variant to build a variant type for the non-dependent attributes and then process dependent attributes (which given attr_flag will DTRT already). The second change in the patch is an optimization, we can actually return back to returning t even when TYPE_ATTRIBUTES is non-NULL, as long as it is non-dependent (dependent attributes are stored first, so it is enough to check the first attribute). 2025-03-06 Jakub Jelinek PR c++/119138 * pt.cc (apply_late_template_attributes): Set p to NULL if ATTR_FLAG_TYPE_IN_PLACE is not set in attr_flags. (tsubst) : Reuse original type even if TYPE_ATTRIBUTES is non-NULL, but all the attributes are non-dependent. * g++.dg/template/pr119138.C: New test. Diff: --- gcc/cp/pt.cc | 9 ++--- gcc/testsuite/g++.dg/template/pr119138.C | 16 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index c09a934580f2..2775af7701b8 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -12393,7 +12393,8 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, to our attributes parameter. */ gcc_assert (*p == attributes); } - else if (FUNC_OR_METHOD_TYPE_P (*decl_p)) + else if (FUNC_OR_METHOD_TYPE_P (*decl_p) + || (attr_flags & ATTR_FLAG_TYPE_IN_PLACE) == 0) p = NULL; else { @@ -16867,7 +16868,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) { if (type == TREE_TYPE (t) && TREE_CODE (type) != METHOD_TYPE - && TYPE_ATTRIBUTES (t) == NULL_TREE) + && (TYPE_ATTRIBUTES (t) == NULL_TREE + || !ATTR_IS_DEPENDENT (TYPE_ATTRIBUTES (t return t; /* [temp.deduct] @@ -17029,7 +17031,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) it will obviously be the same as T. */ if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t) - && TYPE_ATTRIBUTES (t) == NULL_TREE) + && (TYPE_ATTRIBUTES (t) == NULL_TREE + || !ATTR_IS_DEPENDENT (TYPE_ATTRIBUTES (t return t; /* These checks should match the ones in create_array_type_for_decl. diff --git a/gcc/testsuite/g++.dg/template/pr119138.C b/gcc/testsuite/g++.dg/template/pr119138.C new file mode 100644 index ..b0893872f2c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pr119138.C @@ -0,0 +1,16 @@ +// PR c++/119138 +// { dg-do compile } + +#include + +template +void +foo (va_list) +{ +} + +void +bar (va_list ap) +{ + foo (ap); +}
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Correction initialisation bornes temp alloc_comp_assign_12.f03
https://gcc.gnu.org/g:7b56cf43b2a02d05e762125fcb17ca4194b590e9 commit 7b56cf43b2a02d05e762125fcb17ca4194b590e9 Author: Mikael Morin Date: Wed Feb 19 20:06:10 2025 +0100 Correction initialisation bornes temp alloc_comp_assign_12.f03 Diff: --- gcc/fortran/trans-array.cc | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 7d31773c1ebf..0fb22ac1655a 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -3658,7 +3658,7 @@ set_temporary_descriptor (stmtblock_t *block, tree desc, tree class_src, tree lbound[GFC_MAX_DIMENSIONS], tree ubound[GFC_MAX_DIMENSIONS], tree stride[GFC_MAX_DIMENSIONS], int rank, - bool callee_allocated, bool rank_changer, + bool omit_bounds, bool rank_changer, bool shift_bounds) { int n; @@ -3686,7 +3686,7 @@ set_temporary_descriptor (stmtblock_t *block, tree desc, tree class_src, } tree offset = gfc_index_zero_node; - if (!callee_allocated) + if (!omit_bounds) { for (n = 0; n < rank; n++) { @@ -4018,6 +4018,8 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss, } } + bool bounds_known = size != NULL_TREE; + /* Get the size of the array. */ if (size && !callee_alloc) { @@ -4041,8 +4043,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss, dealloc); set_temporary_descriptor (pre, desc, class_expr, elemsize, data_ptr, - from, to, stride, total_dim, - size == NULL_TREE || callee_alloc, + from, to, stride, total_dim, !bounds_known, rank_changer, shift_bounds); while (ss->parent)
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Implémentation optional pour supprimer dépendance à c++17
https://gcc.gnu.org/g:557efc41ba45185055438d13c34f303ad02ee911 commit 557efc41ba45185055438d13c34f303ad02ee911 Author: Mikael Morin Date: Thu Mar 6 22:07:28 2025 +0100 Implémentation optional pour supprimer dépendance à c++17 Diff: --- gcc/cgraphunit.cc | 70 +++ 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index 158cbe010ca7..9c5b7f5b882b 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -213,7 +213,6 @@ along with GCC; see the file COPYING3. If not see #include "wide-int.h" #include "selftest.h" #include "tree-ssanames.h" -#include /* Queue of cgraph nodes scheduled to be added into cgraph. This is a secondary queue used during optimization to accommodate passes that @@ -2475,7 +2474,7 @@ public: data_value (tree type) : data_value (get_constant_type_size (type)) {} - data_value (const data_value &) = default; + data_value (const data_value &); data_value & operator= (const data_value &); value_type classify () const; value_type classify (unsigned offset, unsigned width) const; @@ -2593,7 +2592,50 @@ public: }; -static std::optional +template +class optional +{ + union u +{ + u (T arg) : value (arg) {} + u () : dummy (0) {} + u (const u & other, bool present) { if (present) { new (&value) T (other.value); } else { new (&dummy) char (0); } } + ~u () {} // TODO + T value; + char dummy; +} + u; + bool present; + +public: + optional () : u (), present (false) {} + optional (T arg) : u (arg), present (true) {} + optional (const optional & other) : u (other.u, other.present), present (other.present) {} + ~optional () {} // TODO + optional & operator= (const optional & other) { new (this) optional (other); return *this; } + T & operator * () const; + void emplace (T value); +}; + + +template +T & +optional::operator* () const +{ + gcc_assert (present); + return const_cast (u.value); +} + +template +void +optional::emplace (T arg) +{ + present = true; + u.value = arg; +} + + +static optional execute (struct function *func, exec_context &caller, context_printer & printer, vec * args); @@ -2660,7 +2702,7 @@ public: data_storage & get_storage (unsigned idx) const; context_printer & get_printer () const { return printer; } data_value evaluate (tree expr) const; - std::optional execute_function (struct function *); + optional execute_function (struct function *); edge select_leaving_edge (basic_block bb, gimple *last_stmt); void jump (edge e); }; @@ -3138,10 +3180,18 @@ data_storage::get_ref () const } +data_value::data_value (const data_value & other) + : bit_width (other.bit_width), + constant_mask (other.constant_mask), + address_mask (other.address_mask), + constant_value (other.constant_value), + addresses (other.addresses) +{} + + data_value & data_value::operator= (const data_value & other) { - gcc_assert (other.bit_width == bit_width); - set (other); + new (this) data_value (other); return *this; } @@ -4209,7 +4259,7 @@ exec_context::execute_call (gcall *g) return; tree lhs = gimple_call_lhs (g); - std::optional result; + optional result; if (gimple_call_builtin_p (g, BUILT_IN_MALLOC)) { gcc_assert (lhs != NULL_TREE); @@ -4225,7 +4275,7 @@ exec_context::execute_call (gcall *g) data_storage &storage = allocate (alloc_amount); storage_address address (storage.get_ref (), 0); - result->set_address (address); + (*result).set_address (address); } else { @@ -4376,7 +4426,7 @@ exec_context::jump (edge e) } -std::optional +optional exec_context::execute_function (struct function *func) { printer.print_function_entry (func); @@ -4413,7 +4463,7 @@ exec_context::execute_function (struct function *func) } -static std::optional +static optional execute (struct function * func, exec_context & caller, context_printer & printer, vec * arg_values) {
[gcc r15-7871] AArch64: Enable early scheduling for -O3 and higher (PR118351)
https://gcc.gnu.org/g:f870302515d5fcf7355f0108c3ead0038ff326fd commit r15-7871-gf870302515d5fcf7355f0108c3ead0038ff326fd Author: Wilco Dijkstra Date: Mon Mar 3 16:47:32 2025 + AArch64: Enable early scheduling for -O3 and higher (PR118351) Enable the early scheduler on AArch64 for O3/Ofast. This means GCC15 benefits from much faster build times with -O2, but avoids the regressions in lbm which is very sensitive to minor scheduling changes due to long FMA chains. gcc: PR target/118351 PR other/38768 * common/config/aarch64/aarch64-common.cc: Enable early scheduling with -O3 and higher. * doc/invoke.texi (-fschedule-insns): Update comment. Diff: --- gcc/common/config/aarch64/aarch64-common.cc | 4 +++- gcc/doc/invoke.texi | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc index 500bf784983d..b9ed83642ade 100644 --- a/gcc/common/config/aarch64/aarch64-common.cc +++ b/gcc/common/config/aarch64/aarch64-common.cc @@ -53,8 +53,10 @@ static const struct default_options aarch_option_optimization_table[] = { OPT_LEVELS_ALL, OPT_fomit_frame_pointer, NULL, 0 }, /* Enable -fsched-pressure by default when optimizing. */ { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, -/* Disable early scheduling due to high compile-time overheads. */ +/* Except for -O3 and higher, disable early scheduling due to high + compile-time overheads. */ { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 }, +{ OPT_LEVELS_3_PLUS, OPT_fschedule_insns, NULL, 1 }, /* Enable redundant extension instructions removal at -O2 and higher. */ { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_mearly_ra_, NULL, AARCH64_EARLY_RA_ALL }, diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 6f0779b900cb..304de88db07c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -13507,7 +13507,9 @@ helps machines that have slow floating point or memory load instructions by allowing other instructions to be issued until the result of the load or floating-point instruction is required. -Enabled at levels @option{-O2}, @option{-O3}. +Conventionally enabled at optimization levels @option{-O2} and @option{-O3}. +However, many targets override this behavior. For example, on x86, it is +disabled at all levels, while on AArch64, it is enabled only at @option{-O3}. @opindex fschedule-insns2 @item -fschedule-insns2
[gcc r15-7863] libstdc++: Fix failures in new std::complex test [PR119144]
https://gcc.gnu.org/g:d2b022e38a778d64350f4d4236a2c8a36e0e621c commit r15-7863-gd2b022e38a778d64350f4d4236a2c8a36e0e621c Author: Jonathan Wakely Date: Thu Mar 6 16:04:05 2025 + libstdc++: Fix failures in new std::complex test [PR119144] This test fails due to duplicate explicit instantiations on targets where size_t and unsigned int are the same type. It also fails with -D_GLIBCXX_USE_CXX11_ABI=0 due to using std::string in constexpr functions, and with --disable-libstdcxx-pch due to not including for ranges::fold_left. libstdc++-v3/ChangeLog: PR libstdc++/119144 * testsuite/26_numerics/complex/tuple_like.cc: Include , replace std::string with std::string_view, instantiate tests for long instead of size_t. Diff: --- libstdc++-v3/testsuite/26_numerics/complex/tuple_like.cc | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/testsuite/26_numerics/complex/tuple_like.cc b/libstdc++-v3/testsuite/26_numerics/complex/tuple_like.cc index 7d8d2ee99ce7..1150861ae0aa 100644 --- a/libstdc++-v3/testsuite/26_numerics/complex/tuple_like.cc +++ b/libstdc++-v3/testsuite/26_numerics/complex/tuple_like.cc @@ -2,7 +2,8 @@ #include #include -#include +#include +#include #include #include #include @@ -83,10 +84,10 @@ void test_tuple_cat() { std::complex cpx(T(1), T(2)); - std::pair p(42, "hello"); + std::pair p(42, "hello"); auto r = std::tuple_cat(cpx, p, cpx); - static_assert(std::is_same_v>); + static_assert(std::is_same_v>); VERIFY(std::get<0>(r) == T(1)); VERIFY(std::get<1>(r) == T(2)); VERIFY(std::get<2>(r) == 42); @@ -176,4 +177,4 @@ TEST(__gnu_cxx::__bfloat16_t) TEST(char) TEST(int) TEST(unsigned int) -TEST(size_t) +TEST(long)
[gcc r15-7864] libstdc++: Remove redundant std::span destructor
https://gcc.gnu.org/g:21c96f68f760ca303bb462134386ae201add4b44 commit r15-7864-g21c96f68f760ca303bb462134386ae201add4b44 Author: Jonathan Wakely Date: Wed Mar 5 18:12:09 2025 + libstdc++: Remove redundant std::span destructor This destructor declaration serves no purpose, as pointed out by LWG 3903 which was approved at Varna, June 2023. libstdc++-v3/ChangeLog: * include/std/span (span::~span): Remove, as per LWG 3903. Reviewed-by: Patrick Palka Diff: --- libstdc++-v3/include/std/span | 2 -- 1 file changed, 2 deletions(-) diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span index 247b942dc3b2..49ab9109d83e 100644 --- a/libstdc++-v3/include/std/span +++ b/libstdc++-v3/include/std/span @@ -257,8 +257,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_ptr(__s.data()), _M_extent(__s.size()) { } - ~span() noexcept = default; - constexpr span& operator=(const span&) noexcept = default;
[gcc r15-7868] libstdc++: Make std::unique_lock self-move-assignable
https://gcc.gnu.org/g:1ccbf8e2c2496779862a0153ed95459f72794521 commit r15-7868-g1ccbf8e2c2496779862a0153ed95459f72794521 Author: Jonathan Wakely Date: Thu Mar 6 13:29:41 2025 + libstdc++: Make std::unique_lock self-move-assignable LWG 4172 was approved in Hagenberg, February 2025, fixing std::unique_lock and std::shared_lock to work correctly for self-move-assignment. Our std::shared_lock was already doing the right thing (contradicting the standard) so just add a comment there. Our std::unique_lock needs to be fixed to do the right thing. libstdc++-v3/ChangeLog: * include/bits/unique_lock.h (unique_lock::operator=): Fix for self-move-assignment. * include/std/shared_mutex (shared_lock::operator=): Add comment. * testsuite/30_threads/shared_lock/cons/lwg4172.cc: New test. * testsuite/30_threads/unique_lock/cons/lwg4172.cc: New test. Reviewed-by: Patrick Palka Diff: --- libstdc++-v3/include/bits/unique_lock.h| 9 ++- libstdc++-v3/include/std/shared_mutex | 2 ++ .../30_threads/shared_lock/cons/lwg4172.cc | 28 ++ .../30_threads/unique_lock/cons/lwg4172.cc | 27 + 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/libstdc++-v3/include/bits/unique_lock.h b/libstdc++-v3/include/bits/unique_lock.h index 22ea7e9d7726..5b1518745caf 100644 --- a/libstdc++-v3/include/bits/unique_lock.h +++ b/libstdc++-v3/include/bits/unique_lock.h @@ -126,14 +126,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION unique_lock& operator=(unique_lock&& __u) noexcept { - if(_M_owns) - unlock(); - + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4172. unique_lock self-move-assignment is broken unique_lock(std::move(__u)).swap(*this); - - __u._M_device = 0; - __u._M_owns = false; - return *this; } diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex index cbdf58f403b3..94c8532399d9 100644 --- a/libstdc++-v3/include/std/shared_mutex +++ b/libstdc++-v3/include/std/shared_mutex @@ -780,6 +780,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION shared_lock& operator=(shared_lock&& __sl) noexcept { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4172. unique_lock self-move-assignment is broken shared_lock(std::move(__sl)).swap(*this); return *this; } diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/lwg4172.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/lwg4172.cc new file mode 100644 index ..0a3bf10b8bb5 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/lwg4172.cc @@ -0,0 +1,28 @@ +// { dg-do run { target c++14 } } + +// LWG 4172. unique_lock self-move-assignment is broken + +#include +#include + +void +test_self_move() +{ + struct Lockable + { +bool locked = false; +void lock_shared() { locked = true; } +void unlock_shared() { locked = false; } +bool try_lock_shared() { if (locked) return false; return locked = true; } + }; + + Lockable x; + std::shared_lock l(x); + l = std::move(l); + VERIFY(x.locked); +} + +int main() +{ + test_self_move(); +} diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/lwg4172.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/lwg4172.cc new file mode 100644 index ..37542b586a98 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/lwg4172.cc @@ -0,0 +1,27 @@ +// { dg-do run { target c++11 } } + +// LWG 4172. unique_lock self-move-assignment is broken + +#include +#include + +void +test_self_move() +{ + struct Lockable + { +bool locked = false; +void lock() { locked = true; } +void unlock() { locked = false; } + }; + + Lockable x; + std::unique_lock l(x); + l = std::move(l); + VERIFY(x.locked); +} + +int main() +{ + test_self_move(); +}
[gcc r15-7870] c++: Update TYPE_FIELDS of variant types if cp_parser_late_parsing_default_args etc. modify it [PR98
https://gcc.gnu.org/g:179e01085b0aed111ef1f7908c4b87c800f880e9 commit r15-7870-g179e01085b0aed111ef1f7908c4b87c800f880e9 Author: Jakub Jelinek Date: Thu Mar 6 18:26:37 2025 +0100 c++: Update TYPE_FIELDS of variant types if cp_parser_late_parsing_default_args etc. modify it [PR98533] The following testcases ICE during type verification, because TYPE_FIELDS of e.g. S RECORD_TYPE in pr119123.C is different from TYPE_FIELDS of const S. Various decls are added to S's TYPE_FIELDS first, then finish_struct indirectly calls fixup_type_variants to sync the variant copies. But later on cp_parser_class_specifier calls cp_parser_late_parsing_default_args and that apparently adds a lambda type (from default argument) to TYPE_FIELDS of S. Dunno if that is right or not, assuming it is right, the following patch fixes it by updating TYPE_FIELDS of variant types if there were any changes in the various functions cp_parser_class_specifier defers and calls on the outermost enclosing class. There was quite a lot of code repetition already before, so the patch uses a lambda to avoid the repetitions. To my surprise, in some of the contract testcases ( g++.dg/contracts/contracts-friend1.C g++.dg/contracts/contracts-nested-class1.C g++.dg/contracts/contracts-nested-class2.C g++.dg/contracts/contracts-redecl7.C g++.dg/contracts/contracts-redecl8.C ) it is actually setting class_type and pushing TRANSLATION_UNIT_DECL rather than some class types in some cases. Or should the lambda pushing into the containing class be somehow avoided? 2025-03-06 Jakub Jelinek PR c++/98533 PR c++/119123 * parser.cc (cp_parser_class_specifier): Update TYPE_FIELDS of variant types in case cp_parser_late_parsing_default_args etc. change TYPE_FIELDS on the main variant. Add switch_to_class lambda and use it to simplify repeated class switching code. * g++.dg/cpp0x/pr98533.C: New test. * g++.dg/cpp0x/pr119123.C: New test. Diff: --- gcc/cp/parser.cc | 63 ++- gcc/testsuite/g++.dg/cpp0x/pr119123.C | 10 ++ gcc/testsuite/g++.dg/cpp0x/pr98533.C | 25 ++ 3 files changed, 68 insertions(+), 30 deletions(-) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 69c27aa7b6e3..489c00e05227 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -27718,6 +27718,7 @@ cp_parser_class_specifier (cp_parser* parser) { tree decl; tree class_type = NULL_TREE; + tree class_type_fields = NULL_TREE; tree pushed_scope = NULL_TREE; unsigned ix; cp_default_arg_entry *e; @@ -27731,6 +27732,33 @@ cp_parser_class_specifier (cp_parser* parser) vec_safe_truncate (unparsed_funs_with_definitions, 0); } + auto switch_to_class = [&] (tree t) + { + if (class_type != t) + { + /* cp_parser_late_parsing_default_args etc. could have changed +TYPE_FIELDS (class_type), propagate that to all variants. */ + if (class_type + && RECORD_OR_UNION_TYPE_P (class_type) + && TYPE_FIELDS (class_type) != class_type_fields) + for (tree variant = TYPE_NEXT_VARIANT (class_type); +variant; variant = TYPE_NEXT_VARIANT (variant)) + TYPE_FIELDS (variant) = TYPE_FIELDS (class_type); + if (pushed_scope) + pop_scope (pushed_scope); + class_type = t; + class_type_fields = NULL_TREE; + if (t) + { + if (RECORD_OR_UNION_TYPE_P (class_type)) + class_type_fields = TYPE_FIELDS (class_type); + pushed_scope = push_scope (class_type); + } + else + pushed_scope = NULL_TREE; + } + }; + /* In a first pass, parse default arguments to the functions. Then, in a second pass, parse the bodies of the functions. This two-phased approach handles cases like: @@ -27746,13 +27774,7 @@ cp_parser_class_specifier (cp_parser* parser) decl = e->decl; /* If there are default arguments that have not yet been processed, take care of them now. */ - if (class_type != e->class_type) - { - if (pushed_scope) - pop_scope (pushed_scope); - class_type = e->class_type; - pushed_scope = push_scope (class_type); - } + switch_to_class (e->class_type); /* Make sure that any template parameters are in scope. */ maybe_begin_member_template_processing (decl); /* Parse the default argument expressions. */ @@ -27768,13 +27790,7 @@ cp_parser_class_specifier (cp_parser* parser) FOR_EACH_VEC_SAFE_ELT
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Sauvegarde implementation gimple-exec
https://gcc.gnu.org/g:c90a932447215c54e4b12692de475bc1fdd6e31f commit c90a932447215c54e4b12692de475bc1fdd6e31f Author: Mikael Morin Date: Mon Mar 3 17:29:47 2025 +0100 Sauvegarde implementation gimple-exec Diff: --- gcc/c-family/c.opt|4 + gcc/cgraphunit.cc | 4180 ++--- gcc/fortran/trans-decl.cc |2 +- gcc/selftest-run-tests.cc |2 + gcc/selftest.h|1 + 5 files changed, 3944 insertions(+), 245 deletions(-) diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 15698dc65bb2..d2e16ca50492 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -214,6 +214,10 @@ fgimple C Var(flag_gimple) Init(0) Enable parsing GIMPLE. +fgimple-exec +C Var(flag_gimple_exec) Init(0) +Enable execution of GIMPLE. + H C ObjC C++ ObjC++ Print the name of header files as they are used. diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index 82f205488e90..c6dfc0f486b0 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -210,6 +210,9 @@ along with GCC; see the file COPYING3. If not see #include "ipa-inline.h" #include "omp-offload.h" #include "symtab-thunks.h" +#include "wide-int.h" +#include "selftest.h" +#include "tree-ssanames.h" /* Queue of cgraph nodes scheduled to be added into cgraph. This is a secondary queue used during optimization to accommodate passes that @@ -2321,349 +2324,4038 @@ symbol_table::output_weakrefs (void) } } -/* Perform simple optimizations based on callgraph. */ -void -symbol_table::compile (void) +class exec_context; +class data_storage; + + + +static bool +get_constant_type_size (tree type, unsigned &result) { - if (seen_error ()) -return; + tree tree_size = TYPE_SIZE (type); + gcc_assert (TREE_CODE (tree_size) == INTEGER_CST); + wide_int wi_size = wi::to_wide (tree_size); - symtab_node::checking_verify_symtab_nodes (); + gcc_assert (wi::fits_uhwi_p (wi_size)); + unsigned HOST_WIDE_INT hwi_size = wi_size.to_uhwi (); - symtab_node::check_ifunc_callee_symtab_nodes (); + gcc_assert (hwi_size <= UINT_MAX); + result = hwi_size; + return true; +} - timevar_push (TV_CGRAPHOPT); - if (pre_ipa_mem_report) -dump_memory_report ("Memory consumption before IPA"); - if (!quiet_flag) -fprintf (stderr, "Performing interprocedural optimizations\n"); - state = IPA; - /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE. */ - if (flag_generate_lto || flag_generate_offload) -lto_streamer_hooks_init (); +static unsigned +get_constant_type_size (tree type) +{ + unsigned result; + gcc_assert (get_constant_type_size (type, result)); + return result; +} - /* Don't run the IPA passes if there was any error or sorry messages. */ - if (!seen_error ()) - { -timevar_start (TV_CGRAPH_IPA_PASSES); -ipa_passes (); -timevar_stop (TV_CGRAPH_IPA_PASSES); - } - /* Do nothing else if any IPA pass found errors or if we are just streaming LTO. */ - if (seen_error () - || ((!in_lto_p || flag_incremental_link == INCREMENTAL_LINK_LTO) - && flag_lto && !flag_fat_lto_objects)) -{ - timevar_pop (TV_CGRAPHOPT); - return; -} - global_info_ready = true; - if (dump_file) -{ - fprintf (dump_file, "Optimized "); - symtab->dump (dump_file); -} - if (post_ipa_mem_report) -dump_memory_report ("Memory consumption after IPA"); - timevar_pop (TV_CGRAPHOPT); +enum value_type +{ + VAL_NONE, + VAL_UNDEFINED, + VAL_ADDRESS, + VAL_CONSTANT, + VAL_MIXED +}; - /* Output everything. */ - switch_to_section (text_section); - (*debug_hooks->assembly_start) (); - if (!quiet_flag) -fprintf (stderr, "Assembling functions:\n"); - symtab_node::checking_verify_symtab_nodes (); - bitmap_obstack_initialize (NULL); - execute_ipa_pass_list (g->get_passes ()->all_late_ipa_passes); - bitmap_obstack_release (NULL); - mark_functions_to_output (); +struct storage_ref +{ + const exec_context & context; + unsigned storage_index; - /* When weakref support is missing, we automatically translate all - references to NODE to references to its ultimate alias target. - The renaming mechanism uses flag IDENTIFIER_TRANSPARENT_ALIAS and - TREE_CHAIN. + storage_ref (const exec_context & ctx, unsigned idx) +: context (ctx), storage_index (idx) + {} + data_storage & get () const; +}; - Set up this mapping before we output any assembler but once we are sure - that all symbol renaming is done. - FIXME: All this ugliness can go away if we just do renaming at gimple - level by physically rewriting the IL. At the moment we can only redirect - calls, so we need infrastructure for renaming references as well. */ -#ifndef ASM_OUTPUT_WEAKREF - symtab_node *node; +struct storage_address +{ + storage_ref storage; + unsigned offset; - FOR_EACH_SYMBOL (node) -if (node->alias - && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl))) -
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Sauvegarde gimple-exec
https://gcc.gnu.org/g:e33f2b7f2a145a1dfc843065b4c1f48662f81649 commit e33f2b7f2a145a1dfc843065b4c1f48662f81649 Author: Mikael Morin Date: Tue Mar 4 12:27:12 2025 +0100 Sauvegarde gimple-exec Diff: --- gcc/cgraphunit.cc | 337 ++ 1 file changed, 240 insertions(+), 97 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index 1bcf56daded8..dfeb89ab8194 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -2333,15 +2333,21 @@ class data_storage; static bool get_constant_type_size (tree type, unsigned &result) { - tree tree_size = TYPE_SIZE (type); - gcc_assert (TREE_CODE (tree_size) == INTEGER_CST); - wide_int wi_size = wi::to_wide (tree_size); + if (TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == BOOLEAN_TYPE) +result = TYPE_PRECISION (type); + else +{ + tree tree_size = TYPE_SIZE (type); + gcc_assert (TREE_CODE (tree_size) == INTEGER_CST); + wide_int wi_size = wi::to_wide (tree_size); - gcc_assert (wi::fits_uhwi_p (wi_size)); - unsigned HOST_WIDE_INT hwi_size = wi_size.to_uhwi (); + gcc_assert (wi::fits_uhwi_p (wi_size)); + unsigned HOST_WIDE_INT hwi_size = wi_size.to_uhwi (); - gcc_assert (hwi_size <= UINT_MAX); - result = hwi_size; + gcc_assert (hwi_size <= UINT_MAX); + result = hwi_size; +} return true; } @@ -2398,8 +2404,8 @@ namespace selftest void context_printer_print_first_data_ref_part_tests (); void context_printer_print_value_update_tests (); void exec_context_evaluate_tests (); - void exec_context_evaluate_unary_tests (); void exec_context_evaluate_literal_tests (); + void exec_context_evaluate_binary_tests (); void exec_context_execute_assign_tests (); void exec_context_execute_call_tests (); } @@ -2451,6 +2457,7 @@ public: data_storage *get_address_at (unsigned offset) const; data_value get_at (unsigned offset, unsigned width) const; bool is_fully_defined () const { return (~(constant_mask | address_mask)) == 0; } + tree to_tree (tree type) const; }; @@ -2561,9 +2568,9 @@ class exec_context context_printer & printer; vec storages; unsigned next_alloc_index; - //void add_variables (const exec_context &); data_value evaluate_constructor (tree cstr) const; - data_value evaluate_unary (enum tree_code code, tree arg) const; + data_value evaluate_unary (enum tree_code code, tree type, tree arg) const; + data_value evaluate_binary (enum tree_code code, tree type, tree lhs, tree rhs) const; template void add_variables (vec *variables, unsigned vars_count); template @@ -2578,32 +2585,18 @@ class exec_context data_storage *allocate (unsigned amount); void decompose_ref (tree data_ref, data_storage * & storage, int & offset) const; void execute_phi (gphi *phi, edge e); -#if 0 - template - exec_context (exec_context *caller, context_printer & printer, - unsigned storage_size, - vec *local_decls, vec *ssa_names); -#endif friend void selftest::data_value_print_tests (); friend void selftest::data_value_set_address_tests (); friend void selftest::data_value_set_tests (); - friend void selftest::exec_context_evaluate_unary_tests (); friend void selftest::exec_context_evaluate_literal_tests (); + friend void selftest::exec_context_evaluate_binary_tests (); friend void selftest::exec_context_execute_assign_tests (); friend void selftest::exec_context_execute_call_tests (); public: exec_context (exec_context *caller, context_printer & printer, vec & decls); -#if 0 - template - exec_context (exec_context *caller, context_printer & printer, - vec *local_decls, vec *ssa_names); - template - exec_context (exec_context *caller, context_printer & printer, - vec *local_decls, vec *ssa_names); -#endif const exec_context & root () const; int find (const data_storage &storage) const; data_storage *find_reachable_var (tree variable) const; @@ -2615,7 +2608,6 @@ public: data_value execute_function (struct function *); edge select_leaving_edge (basic_block bb, gimple *last_stmt); void jump (edge e); -// bool evaluate (tree var, tree *result) const; }; @@ -2685,24 +2677,6 @@ exec_context::exec_context (exec_context *caller, context_printer & printer, } -#if 0 -void -exec_context::add_variables (const exec_context & ctx) -{ - storages.reserve (ctx.storages.length ()); - - auto_vec ctx_vars(ctx.storages.length ()); - - data_storage *strgp; - unsigned i; - FOR_EACH_VEC_ELT (ctx.storages, i, strgp) -ctx_vars.quick_push (strgp->get_variable ()); - - add_variables (&ctx_vars); -} -#endif - - template void exec_context::add_variables (vec *variables, unsigned vars_count) @@ -2734,29 +2708,6 @@ exec_context::add_variables (vec *variables) add_variables (variables, vec_safe_length (variables)); } -#if 0 -template -exec_context::exec_context
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Déplacement evaluation constructeur en dehors des operateurs unaires
https://gcc.gnu.org/g:ad972e0735b2db691e91dc50f550bf2d51b6e1a0 commit ad972e0735b2db691e91dc50f550bf2d51b6e1a0 Author: Mikael Morin Date: Tue Mar 4 10:27:20 2025 +0100 Déplacement evaluation constructeur en dehors des operateurs unaires Diff: --- gcc/cgraphunit.cc | 27 --- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index fbefcd522efd..8a207f3b30fb 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -3668,6 +3668,9 @@ exec_context::evaluate (tree expr) const return result; } +case CONSTRUCTOR: + return evaluate_constructor (expr); + default: gcc_unreachable (); } @@ -3716,9 +3719,6 @@ exec_context::evaluate_unary (enum tree_code code, tree arg) const case NOP_EXPR: return evaluate (arg); -case CONSTRUCTOR: - return evaluate_constructor (arg); - default: gcc_unreachable (); } @@ -3839,18 +3839,15 @@ exec_context::execute_assign (gassign *g) data_value value (TREE_TYPE (lhs)); enum tree_code rhs_code = gimple_assign_rhs_code (g); - switch (rhs_code) + enum gimple_rhs_class rhs_class = get_gimple_rhs_class (rhs_code); + switch (rhs_class) { -case NOP_EXPR: -case CONSTRUCTOR: - value = evaluate_unary (rhs_code, gimple_assign_rhs1 (g)); +case GIMPLE_SINGLE_RHS: + value = evaluate (gimple_assign_rhs1 (g)); break; -case VECTOR_CST: -case INTEGER_CST: -case SSA_NAME: -case COMPONENT_REF: - value = evaluate (gimple_assign_rhs1 (g)); +case GIMPLE_UNARY_RHS: + value = evaluate_unary (rhs_code, gimple_assign_rhs1 (g)); break; default: @@ -5844,7 +5841,7 @@ exec_context_evaluate_literal_tests () } void -exec_context_evaluate_unary_tests () +exec_context_evaluate_constructor_tests () { context_printer printer; @@ -5870,7 +5867,7 @@ exec_context_evaluate_unary_tests () CONSTRUCTOR_APPEND_ELT (vec_elts, NULL_TREE, addr2); tree cstr = build_constructor (vec2ptr, vec_elts); - data_value val_cstr = ctx.evaluate_unary (CONSTRUCTOR, cstr); + data_value val_cstr = ctx.evaluate (cstr); data_storage *strg1 = val_cstr.get_address_at (0); ASSERT_NE (strg1, nullptr); ASSERT_PRED1 (strg1->matches, a); @@ -6340,7 +6337,7 @@ gimple_exec_cc_tests () context_printer_print_value_update_tests (); exec_context_evaluate_tests (); exec_context_evaluate_literal_tests (); - exec_context_evaluate_unary_tests (); + exec_context_evaluate_constructor_tests (); exec_context_execute_assign_tests (); exec_context_execute_call_tests (); }
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Changement du type attendu par set_address: data_storage -> storage_address
https://gcc.gnu.org/g:3c56cb41752b02cf1cbd25bded2ac814ba04010e commit 3c56cb41752b02cf1cbd25bded2ac814ba04010e Author: Mikael Morin Date: Tue Mar 4 22:10:01 2025 +0100 Changement du type attendu par set_address: data_storage -> storage_address Diff: --- gcc/cgraphunit.cc | 158 +- 1 file changed, 86 insertions(+), 72 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index f29e9aa846b8..5290f7f27cfd 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -2413,6 +2413,17 @@ struct storage_address {} }; + +struct stored_address +{ + storage_address address; + unsigned position; + + stored_address (storage_address addr, unsigned pos) +: address (addr), position (pos) + {} +}; + namespace selftest { void data_value_classify_tests (); @@ -2438,10 +2449,10 @@ class data_value wide_int constant_mask; wide_int address_mask; wide_int constant_value; - vec addresses; + vec addresses; void set_cst_at (unsigned dest_offset, unsigned value_width, const wide_int &val, unsigned src_offset); - storage_address *find_address (unsigned offset) const; + stored_address *find_address (unsigned offset) const; void set_at (unsigned dest_offset, unsigned value_width, const data_value & value_src, unsigned src_offset); @@ -2466,8 +2477,8 @@ public: value_type classify () const; value_type classify (unsigned offset, unsigned width) const; unsigned get_bitwidth () const { return bit_width; } - void set_address_at (data_storage &storage, unsigned offset); - void set_address (data_storage &); + void set_address_at (storage_address & address, unsigned offset); + void set_address (storage_address & address); void set_at (const data_value & value, unsigned offset); void set (const data_value & value); void set_cst_at (const wide_int & val, unsigned offset); @@ -3078,19 +3089,19 @@ data_value::classify (unsigned offset, unsigned width) const } -storage_address * +stored_address * data_value::find_address (unsigned offset) const { gcc_assert (offset <= bit_width - HOST_BITS_PER_PTR); - storage_address *result = nullptr; - storage_address *strg_address; + stored_address *result = nullptr; + stored_address *strd_address; unsigned i; - FOR_EACH_VEC_ELT (addresses, i, strg_address) -if (strg_address->offset == offset) + FOR_EACH_VEC_ELT (addresses, i, strd_address) +if (strd_address->position == offset) { gcc_assert (result == nullptr); - result = strg_address; + result = strd_address; } return result; @@ -3098,34 +3109,36 @@ data_value::find_address (unsigned offset) const void -data_value::set_address_at (data_storage &storage, unsigned offset) +data_value::set_address_at (storage_address & address, unsigned offset) { wide_int mask = wi::shifted_mask (offset, HOST_BITS_PER_PTR, false, bit_width); enum value_type type = classify (offset, HOST_BITS_PER_PTR); + /* Assume we don't store both regular integers and address + in the same variable over time. */ gcc_assert (type == VAL_ADDRESS || type == VAL_UNDEFINED); if (type == VAL_ADDRESS) { - storage_address *existing_address = find_address (offset); + stored_address *existing_address = find_address (offset); gcc_assert (existing_address != nullptr); /* Invalidate existing address. */ - existing_address->offset = -1; + existing_address->position = -1; } constant_mask &= ~mask; address_mask |= mask; - storage_address addr_info (storage.get_ref (), offset);; - addresses.safe_push (addr_info); + stored_address new_address (address, offset); + addresses.safe_push (new_address); } void -data_value::set_address (data_storage &storage) +data_value::set_address (storage_address & address) { gcc_assert (bit_width == HOST_BITS_PER_PTR); - set_address_at (storage, 0); + set_address_at (address, 0); } @@ -3180,14 +3193,14 @@ data_value::set_at (unsigned dest_offset, unsigned value_width, { if (value_width == HOST_BITS_PER_PTR) { - storage_address *found_address = value_src.find_address (src_offset); + stored_address *found_address = value_src.find_address (src_offset); gcc_assert (found_address != nullptr); - - data_storage &storage = found_address->storage.get (); - set_address_at (storage, dest_offset); + set_address_at (found_address->address, dest_offset); } else { + /* Several addresses side by side in the same area. Set them one + by one */ gcc_assert (value_width > HOST_BITS_PER_PTR); gcc_assert (value_width % HOST_BITS_PER_PTR == 0); gcc_assert (dest_offset % HOST_BITS_PER_PTR == 0); @@ -3259,32 +3272,6 @@ void data_value::set_at (const data_value &
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] data_value: Suppression champ context et déplacement méthode print vers context_printer
https://gcc.gnu.org/g:f0ebf3e471918909e1e27b498fb76c58f4652f75 commit f0ebf3e471918909e1e27b498fb76c58f4652f75 Author: Mikael Morin Date: Mon Mar 3 17:57:10 2025 +0100 data_value: Suppression champ context et déplacement méthode print vers context_printer Diff: --- gcc/cgraphunit.cc | 177 +- 1 file changed, 83 insertions(+), 94 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index c6dfc0f486b0..fbefcd522efd 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -2407,7 +2407,6 @@ namespace selftest class data_value { - const exec_context & context; unsigned bit_width; wide_int constant_mask; wide_int address_mask; @@ -2425,15 +2424,15 @@ class data_value friend void selftest::data_value_set_at_tests (); public: - data_value (const exec_context &ctx, unsigned width) -: context (ctx), bit_width (width), + data_value (unsigned width) +: bit_width (width), constant_mask (wi::shwi (HOST_WIDE_INT_0, width)), address_mask (wi::shwi (HOST_WIDE_INT_0, width)), constant_value (wi::shwi (HOST_WIDE_INT_0, width)), addresses () {} - data_value (const exec_context &ctx, tree type) -: data_value (ctx, get_constant_type_size (type)) + data_value (tree type) +: data_value (get_constant_type_size (type)) {} data_value (const data_value &) = default; data_value & operator= (const data_value &); @@ -2452,10 +2451,6 @@ public: data_storage *get_address_at (unsigned offset) const; data_value get_at (unsigned offset, unsigned width) const; bool is_fully_defined () const { return (~(constant_mask | address_mask)) == 0; } - void print_at (pretty_printer & pp, tree type, unsigned offset, -unsigned width) const; - void print_at (pretty_printer & pp, tree type, unsigned offset) const; - void print (pretty_printer & pp, tree type) const; }; @@ -2501,11 +2496,11 @@ class data_storage public: data_storage (const exec_context &ctx, tree decl) -: context (ctx), type (STRG_VARIABLE), value (ctx, TREE_TYPE (decl)), +: context (ctx), type (STRG_VARIABLE), value (TREE_TYPE (decl)), u (decl) {} data_storage (const exec_context &ctx, unsigned alloc_index, unsigned alloc_amount) -: context (ctx), type (STRG_ALLOC), value (ctx, alloc_amount), +: context (ctx), type (STRG_ALLOC), value (alloc_amount), u (alloc_index, alloc_amount) {} storage_type get_type () const { return type; } @@ -2550,6 +2545,9 @@ public: tree print_first_data_ref_part (exec_context & context, tree data_ref, unsigned offset); void print_value_update (exec_context & context, tree, const data_value &); void end_stmt (gimple *); + void print_at (const data_value & value, tree type, unsigned offset, unsigned width); + void print_at (const data_value & value, tree type, unsigned offset); + void print (const data_value & value, tree type); }; @@ -2962,7 +2960,7 @@ context_printer::print_value_update (exec_context & context, tree lhs, const dat pp_space (&pp); pp_equal (&pp); pp_space (&pp); - value.print_at (pp, type_output, previously_done, just_done); + print_at (value, type_output, previously_done, just_done); print_newline (); previously_done += just_done; } @@ -3318,7 +3316,7 @@ data_value::get_address () const data_value data_value::get_at (unsigned offset, unsigned width) const { - data_value result (context, width); + data_value result (width); switch (classify (offset, width)) { case VAL_CONSTANT: @@ -3339,26 +3337,26 @@ data_value::get_at (unsigned offset, unsigned width) const void -data_value::print_at (pretty_printer & pp, tree type, unsigned offset, - unsigned width) const +context_printer::print_at (const data_value & value, tree type, unsigned offset, + unsigned width) { if (TREE_CODE (type) == VECTOR_TYPE) { - gcc_assert (width == bit_width); + gcc_assert (width == value.get_bitwidth ()); gcc_assert (offset == 0); tree elt_type = TREE_TYPE (type); unsigned elt_width; gcc_assert (get_constant_type_size (elt_type, elt_width)); gcc_assert (elt_width != 0); - gcc_assert (bit_width % elt_width == 0); + gcc_assert (width % elt_width == 0); pp_left_brace (&pp); bool needs_comma = false; - for (unsigned i = 0; i < bit_width / elt_width; i++) + for (unsigned i = 0; i < width / elt_width; i++) { if (needs_comma) pp_comma (&pp); pp_space (&pp); - print_at (pp, elt_type, i * elt_width); + print_at (value, elt_type, i * elt_width); needs_comma = true; } pp_space (&pp); @@ -3366,14 +3364,14 @@ data_value::print_at (pretty_printer & pp, tree type, unsigned offset, } else { - enum value_type val_type = classify (offset, width)
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Correction offset MEM_REF
https://gcc.gnu.org/g:52a1d05062654f3ea48b6433ed4fd1fef19a35e1 commit 52a1d05062654f3ea48b6433ed4fd1fef19a35e1 Author: Mikael Morin Date: Wed Mar 5 13:08:43 2025 +0100 Correction offset MEM_REF Diff: --- gcc/cgraphunit.cc | 166 +- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index b556626adab5..e7b6e45386bf 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -3152,6 +3152,7 @@ data_value::set_cst_at (unsigned dest_offset, unsigned value_width, enum value_type orig_type = classify (dest_offset, value_width); wide_int dest_mask = wi::shifted_mask (dest_offset, value_width, false, bit_width); + gcc_assert (orig_type != VAL_ADDRESS); if (orig_type != VAL_CONSTANT) { constant_mask |= dest_mask; @@ -3417,6 +3418,15 @@ context_printer::print_at (const data_value & value, tree type, unsigned offset, storage_address *address = value.get_address_at (offset); data_storage &target_storage = address->storage.get (); target_storage.print (*this); + unsigned off = address->offset; + if (off > 0) + { + pp_string (&pp, " + "); + gcc_assert (off % CHAR_BIT == 0); + off /= CHAR_BIT; + pp_decimal_int (&pp, off); + pp_character (&pp, 'B'); + } } break; @@ -3672,6 +3682,7 @@ exec_context::evaluate (tree expr) const storage_address *address = val_ptr.get_address (); gcc_assert (address != nullptr); data_value storage_value = address->storage.get ().get_value (); + unsigned ptr_offset = address->offset; tree offset_bytes = TREE_OPERAND (expr, 1); data_value val_off = evaluate (offset_bytes); @@ -3701,7 +3712,7 @@ exec_context::evaluate (tree expr) const offset += additional_off.to_uhwi (); } - return storage_value.get_at (offset * CHAR_BIT, bit_width); + return storage_value.get_at (offset * CHAR_BIT + ptr_offset, bit_width); } break; @@ -5269,6 +5280,58 @@ data_value_print_tests () } +void +data_storage_set_at_tests () +{ + heap_memory mem; + context_printer printer; + + tree a5i = build_array_type_nelts (integer_type_node, 5); + tree v5i = create_var (a5i, "v5i"); + tree p = create_var (ptr_type_node, "p"); + + vec decls{}; + decls.safe_push (p); + decls.safe_push (v5i); + vec empty{}; + + context_builder builder {}; + builder.add_decls (&decls); + exec_context ctx = builder.build (mem, printer); + + data_storage *storage_p = ctx.find_reachable_var (p); + gcc_assert (storage_p != nullptr); + data_storage *storage_v5 = ctx.find_reachable_var (v5i); + gcc_assert (storage_v5 != nullptr); + + ASSERT_EQ (storage_p->get_value ().classify (), VAL_UNDEFINED); + + storage_address addr0 (storage_v5->get_ref (), 0); + data_value val0 (ptr_type_node); + val0.set_address (addr0); + + storage_p->set (val0); + + data_value valp0 = storage_p->get_value (); + ASSERT_EQ (valp0.classify (), VAL_ADDRESS); + storage_address *addrp0 = valp0.get_address (); + ASSERT_EQ (&addrp0->storage.get (), storage_v5); + ASSERT_EQ (addrp0->offset, 0); + + storage_address addr3 (storage_v5->get_ref (), 24); + data_value val3 (ptr_type_node); + val3.set_address (addr3); + + storage_p->set (val3); + + data_value valp3 = storage_p->get_value (); + ASSERT_EQ (valp3.classify (), VAL_ADDRESS); + storage_address *addrp3 = valp3.get_address (); + ASSERT_EQ (&addrp3->storage.get (), storage_v5); + ASSERT_EQ (addrp3->offset, 24); +} + + void context_printer_print_first_data_ref_part_tests () { @@ -5644,6 +5707,7 @@ context_printer_print_value_update_tests () const char *str = pp_formatted_text (&pp); ASSERT_STREQ (str, "# my_lhs = &my_var\n"); + context_printer printer2; pretty_printer & pp2 = printer2.pp; pp_buffer (&pp2)->m_flush_p = false; @@ -5748,6 +5812,33 @@ context_printer_print_value_update_tests () const char *str4 = pp_formatted_text (&pp4); ASSERT_STREQ (str4, "# v2i.der2i_i1 = 2\n# v2i.der2i_i2 = 11\n"); + + + heap_memory mem5; + context_printer printer5; + pretty_printer & pp5 = printer5.pp; + pp_buffer (&pp5)->m_flush_p = false; + + tree a5i = build_array_type_nelts (integer_type_node, 5); + tree v5i = create_var (a5i, "v5i"); + tree p = create_var (ptr_type_node, "p"); + + vec decls5{}; + decls5.safe_push (v5i); + decls5.safe_push (p); + + context_builder builder5; + builder5.add_decls (&decls5); + exec_context ctx5 = builder5.build (mem5, printer5); + + data_storage *strg_v5i = ctx5.find_reachable_var (v5i); + storage_address addr_v5i (strg_v5i->get_ref (), 24); + data_value val5 (ptr_type_node);; + val5.set_address (addr_v5i); + + printer5.print_value_update (ctx5, p, val5); + const char *str5 = pp_formatted_text (&
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Suppression méthode evaluate_litteral
https://gcc.gnu.org/g:787b605251ed17a6278effd8e847ebfb5ddd42ef commit 787b605251ed17a6278effd8e847ebfb5ddd42ef Author: Mikael Morin Date: Tue Mar 4 10:32:35 2025 +0100 Suppression méthode evaluate_litteral Diff: --- gcc/cgraphunit.cc | 22 +- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index 8a207f3b30fb..1bcf56daded8 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -2563,7 +2563,6 @@ class exec_context unsigned next_alloc_index; //void add_variables (const exec_context &); data_value evaluate_constructor (tree cstr) const; - data_value evaluate_literal (enum tree_code code, tree value) const; data_value evaluate_unary (enum tree_code code, tree arg) const; template void add_variables (vec *variables, unsigned vars_count); @@ -3724,25 +3723,6 @@ exec_context::evaluate_unary (enum tree_code code, tree arg) const } } -data_value -exec_context::evaluate_literal (enum tree_code code, tree value) const -{ - data_value result(TREE_TYPE (value)); - switch (code) -{ -case INTEGER_CST: - { - wide_int wi_val = wi::to_wide (value); - result.set_cst (wi_val); - } - break; - -default: - gcc_unreachable (); -} - return result; -} - void exec_context::decompose_ref (tree data_ref, data_storage * & storage, int & offset) const { @@ -5832,7 +5812,7 @@ exec_context_evaluate_literal_tests () tree cst = build_int_cst (integer_type_node, 13); - data_value val = ctx.evaluate_literal (INTEGER_CST, cst); + data_value val = ctx.evaluate (cst); ASSERT_EQ (val.classify (), VAL_CONSTANT); wide_int wi_value = val.get_cst (); ASSERT_PRED1 (wi::fits_shwi_p, wi_value);
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Affichage conditionnelle
https://gcc.gnu.org/g:b217573b49caeebc0126e5a6c4ff5109b6cdc64a commit b217573b49caeebc0126e5a6c4ff5109b6cdc64a Author: Mikael Morin Date: Thu Mar 6 11:01:40 2025 +0100 Affichage conditionnelle Diff: --- gcc/cgraphunit.cc | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index c7c2e2f2e24f..71eaf0509fdf 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -4257,8 +4257,15 @@ exec_context::execute (basic_block bb) edge exec_context::select_leaving_edge (basic_block bb, gimple *last_stmt) { + if (last_stmt != nullptr) +printer.begin_stmt (last_stmt); + if (last_stmt == nullptr || is_a (last_stmt)) -return single_succ_edge (bb); +{ + if (last_stmt != nullptr) + printer.end_stmt (last_stmt); + return single_succ_edge (bb); +} if (is_a (last_stmt)) { @@ -4291,6 +4298,8 @@ exec_context::select_leaving_edge (basic_block bb, gimple *last_stmt) selected = e; } + printer.end_stmt (last_stmt); + gcc_assert (selected != nullptr); return selected; }
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] gimple-exec Restauration tests print_first_data_ref_part
https://gcc.gnu.org/g:257774fde348f21e93360443a91197ae856b9336 commit 257774fde348f21e93360443a91197ae856b9336 Author: Mikael Morin Date: Thu Mar 6 11:10:40 2025 +0100 gimple-exec Restauration tests print_first_data_ref_part Diff: --- gcc/cgraphunit.cc | 353 +- 1 file changed, 349 insertions(+), 4 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index 71eaf0509fdf..51fa9143f7ca 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -2582,7 +2582,7 @@ public: void print_function_exit (struct function * func); void print_bb_jump (edge e); void print_bb_entry (basic_block bb); - tree print_first_data_ref_part (exec_context & context, tree data_ref, const data_value & value, unsigned offset, int * ignored_bits); + tree print_first_data_ref_part (exec_context & context, tree data_ref, unsigned offset, int * ignored_bits); void print_value_update (exec_context & context, tree, const data_value &); void end_stmt (gimple *); void print_at (const data_value & value, tree type, unsigned offset, unsigned width); @@ -2979,7 +2979,7 @@ find_mem_ref_replacement (exec_context & context, tree data_ref, tree -context_printer::print_first_data_ref_part (exec_context & context, tree data_ref, const data_value & value, unsigned offset, int * ignored_bits) +context_printer::print_first_data_ref_part (exec_context & context, tree data_ref, unsigned offset, int * ignored_bits) { switch (TREE_CODE (data_ref)) { @@ -2988,7 +2988,7 @@ context_printer::print_first_data_ref_part (exec_context & context, tree data_re tree mem_replacement = find_mem_ref_replacement (context, data_ref, offset); if (mem_replacement != NULL_TREE) - return print_first_data_ref_part (context, mem_replacement, value, 0, ignored_bits); + return print_first_data_ref_part (context, mem_replacement, 0, ignored_bits); } /* Fall through. */ @@ -3018,7 +3018,7 @@ context_printer::print_value_update (exec_context & context, tree lhs, const dat while (previously_done < width) { int ignored_bits = 0; - tree type_done = print_first_data_ref_part (context, lhs, value, + tree type_done = print_first_data_ref_part (context, lhs, previously_done, &ignored_bits); if (type_done == NULL_TREE) @@ -5466,6 +5466,350 @@ data_storage_set_at_tests () } +void +context_printer_print_first_data_ref_part_tests () +{ + vec empty{}; + + tree der2i = make_node (RECORD_TYPE); + tree der2i_i2 = build_decl (input_location, FIELD_DECL, + get_identifier ("der2i_i2"), integer_type_node); + DECL_CONTEXT (der2i_i2) = der2i; + DECL_CHAIN (der2i_i2) = NULL_TREE; + tree der2i_i1 = build_decl (input_location, FIELD_DECL, + get_identifier ("der2i_i1"), integer_type_node); + DECL_CONTEXT (der2i_i1) = der2i; + DECL_CHAIN (der2i_i1) = der2i_i2; + TYPE_FIELDS (der2i) = der2i_i1; + layout_type (der2i); + + tree var2i = create_var (der2i, "var2i"); + + heap_memory mem1; + context_printer printer1; + pretty_printer & pp1 = printer1.pp; + exec_context ctx1 = context_builder ().build (mem1, printer1); + + tree res1 = printer1.print_first_data_ref_part (ctx1, var2i, 0, nullptr); + + ASSERT_EQ (res1, integer_type_node); + const char * str1 = pp_formatted_text (&pp1); + ASSERT_STREQ (str1, "# var2i.der2i_i1"); + + + context_printer printer2; + pretty_printer & pp2 = printer2.pp; + + vec decls2{}; + decls2.safe_push (var2i); + + context_builder builder2 {}; + builder2.add_decls (&decls2); + exec_context ctx2 = builder2.build (mem1, printer2); + + tree mem_var2i = build2 (MEM_REF, der2i, + build1 (ADDR_EXPR, ptr_type_node, var2i), + build_zero_cst (ptr_type_node)); + + tree res2 = printer2.print_first_data_ref_part (ctx2, mem_var2i, 0, nullptr); + + ASSERT_EQ (res2, integer_type_node); + const char * str2 = pp_formatted_text (&pp2); + ASSERT_STREQ (str2, "# var2i.der2i_i1"); + + + context_printer printer3; + pretty_printer & pp3 = printer3.pp; + + context_builder builder3 {}; + builder3.add_decls (&decls2); + exec_context ctx3 = builder3.build (mem1, printer3); + + tree long_var2i = build2 (MEM_REF, long_integer_type_node, + build1 (ADDR_EXPR, ptr_type_node, var2i), + build_zero_cst (ptr_type_node)); + + tree res3 = printer3.print_first_data_ref_part (ctx3, long_var2i, 0, nullptr); + + ASSERT_EQ (res3, integer_type_node); + const char * str3 = pp_formatted_text (&pp3); + ASSERT_STREQ (str3, "# var2i.der2i_i1"); + + + tree der2s = make_node (RECORD_TYPE); + tree der2s_s2 = build_decl (input_location, FIELD_DECL, + get_identifier (
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Modification affichage MEM_REF d'alloc.
https://gcc.gnu.org/g:c346c506b4a5e5af0e8fa5677825e9f7bcb805ef commit c346c506b4a5e5af0e8fa5677825e9f7bcb805ef Author: Mikael Morin Date: Thu Mar 6 17:22:35 2025 +0100 Modification affichage MEM_REF d'alloc. Diff: --- gcc/cgraphunit.cc | 162 +++--- 1 file changed, 155 insertions(+), 7 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index 51fa9143f7ca..6edc4984906d 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -2433,6 +2433,7 @@ namespace selftest void data_value_set_at_tests (); void data_value_set_address_tests (); void data_value_print_tests (); + void context_printer_print_tests (); void context_printer_print_first_data_ref_part_tests (); void context_printer_print_value_update_tests (); void exec_context_evaluate_tests (); @@ -2568,6 +2569,7 @@ class context_printer friend void selftest::exec_context_evaluate_tests (); friend void selftest::data_value_print_tests (); + friend void selftest::context_printer_print_tests (); friend void selftest::context_printer_print_first_data_ref_part_tests (); friend void selftest::context_printer_print_value_update_tests (); @@ -2576,7 +2578,7 @@ public: context_printer (dump_flags_t f); pretty_printer & get_pretty_printer () const { return const_cast (pp); } void begin_stmt (gimple *); - void print (tree); + void print (exec_context *, tree); void print_newline (); void print_function_entry (struct function * func); void print_function_exit (struct function * func); @@ -2638,6 +2640,7 @@ class exec_context friend void selftest::data_value_print_tests (); friend void selftest::data_value_set_address_tests (); friend void selftest::data_value_set_tests (); + friend void selftest::context_printer_print_tests (); friend void selftest::exec_context_evaluate_literal_tests (); friend void selftest::exec_context_evaluate_unary_tests (); friend void selftest::exec_context_evaluate_binary_tests (); @@ -2808,9 +2811,50 @@ context_printer::begin_stmt (gimple *g) } void -context_printer::print (tree expr) +context_printer::print (exec_context * ctx, tree expr) { - dump_generic_node (&pp, expr, pp_indentation (&pp), flags, false); + switch (TREE_CODE (expr)) +{ +case MEM_REF: + { + gcc_assert (ctx != nullptr); + data_value val = ctx->evaluate (TREE_OPERAND (expr, 0)); + gcc_assert (val.classify () == VAL_ADDRESS); + storage_address *address = val.get_address (); + gcc_assert (address != nullptr); + + data_value val_off = ctx->evaluate (TREE_OPERAND (expr, 1)); + gcc_assert (val_off.classify () == VAL_CONSTANT); + wide_int wi_off = val_off.get_cst (); + wi_off = (wi_off * CHAR_BIT) + address->offset; + + if (!wi::fits_uhwi_p (wi_off)) + gcc_unreachable (); + unsigned offset_bits = wi_off.to_uhwi (); + gcc_assert (offset_bits % CHAR_BIT == 0); + unsigned offset_bytes = offset_bits / CHAR_BIT; + + unsigned size_bits; + if (!get_constant_type_size (TREE_TYPE (expr), size_bits)) + gcc_unreachable (); + gcc_assert (size_bits % CHAR_BIT == 0); + unsigned size_bytes = size_bits / CHAR_BIT; + + address->storage.get ().print (*this); + pp_left_bracket (&pp); + pp_decimal_int (&pp, offset_bytes); + pp_character (&pp, 'B'); + pp_colon (&pp); + pp_plus (&pp); + pp_decimal_int (&pp, size_bytes); + pp_character (&pp, 'B'); + pp_right_bracket (&pp); + } + break; + +default: + dump_generic_node (&pp, expr, pp_indentation (&pp), flags, false); +} } @@ -3005,7 +3049,7 @@ context_printer::print_first_data_ref_part (exec_context & context, tree data_re pp_indent (&pp); pp_character (&pp, '#'); pp_space (&pp); - print (ref); + print (&context, ref); return TREE_TYPE (ref); } } @@ -3478,7 +3522,7 @@ context_printer::print_at (const data_value & value, tree type, unsigned offset, tree int_type = make_signed_type (width); tree cst = wide_int_to_tree (int_type, wi_val); tree real = fold_build1 (VIEW_CONVERT_EXPR, type, cst); - print (real); + print (nullptr, real); } else pp_wide_int (&pp, wi_val, SIGNED); @@ -3542,7 +3586,7 @@ data_storage::print (context_printer & printer) const case STRG_VARIABLE: { tree decl = get_variable (); - printer.print (decl); + printer.print (nullptr, decl); } break; @@ -5466,6 +5510,109 @@ data_storage_set_at_tests () } +void +context_printer_print_tests () +{ + heap_memory mem1; + + context_printer printer1; + pretty_printer & pp1 = printer1.pp; + + tree p1 = create_var (ptr_type_node, "p1"); + + vec decls1 {}; + decls1.safe_push (p1); + + context_builder builder1; + builder1.
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Prise en charge POINTER_PLUS_EXPR
https://gcc.gnu.org/g:e51be59ecf7e5d7ce9d2da0fd8fbc977c4b7aa79 commit e51be59ecf7e5d7ce9d2da0fd8fbc977c4b7aa79 Author: Mikael Morin Date: Wed Mar 5 10:55:56 2025 +0100 Prise en charge POINTER_PLUS_EXPR Diff: --- gcc/cgraphunit.cc | 165 ++ 1 file changed, 153 insertions(+), 12 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index c5907e55055e..b556626adab5 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -3114,9 +3114,6 @@ data_value::set_address_at (storage_address & address, unsigned offset) wide_int mask = wi::shifted_mask (offset, HOST_BITS_PER_PTR, false, bit_width); enum value_type type = classify (offset, HOST_BITS_PER_PTR); - /* Assume we don't store both regular integers and address - in the same variable over time. */ - gcc_assert (type == VAL_ADDRESS || type == VAL_UNDEFINED); if (type == VAL_ADDRESS) { @@ -3841,20 +3838,57 @@ exec_context::evaluate_binary (enum tree_code code, tree type, tree lhs, tree rh || (TREE_CODE (rhs) == INTEGER_CST && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE && TYPE_PRECISION (TREE_TYPE (lhs)) == TYPE_PRECISION (TREE_TYPE (rhs)) - && TYPE_UNSIGNED (TREE_TYPE (lhs)) == TYPE_UNSIGNED (TREE_TYPE (rhs; + && TYPE_UNSIGNED (TREE_TYPE (lhs)) == TYPE_UNSIGNED (TREE_TYPE (rhs))) + || code == POINTER_PLUS_EXPR); switch (code) { default: { gcc_assert (TREE_CODE (type) == INTEGER_TYPE - || TREE_CODE (type) == BOOLEAN_TYPE); - tree lval = evaluate (lhs).to_tree (TREE_TYPE (lhs)); - tree rval = evaluate (rhs).to_tree (TREE_TYPE (rhs)); - tree t = fold_binary (code, type, lval, rval); - gcc_assert (t != NULL_TREE); - data_value result (type); - result.set_cst (wi::to_wide (t)); - return result; + || TREE_CODE (type) == BOOLEAN_TYPE + || TREE_CODE (type) == POINTER_TYPE); + data_value val_lhs = evaluate (lhs); + data_value val_rhs = evaluate (rhs); + enum value_type lhs_type = val_lhs.classify (); + enum value_type rhs_type = val_rhs.classify (); + if (lhs_type == VAL_CONSTANT && rhs_type == VAL_CONSTANT) + { + tree lval = val_lhs.to_tree (TREE_TYPE (lhs)); + tree rval = val_rhs.to_tree (TREE_TYPE (rhs)); + tree t = fold_binary (code, type, lval, rval); + gcc_assert (t != NULL_TREE); + data_value result (type); + result.set_cst (wi::to_wide (t)); + return result; + } + else + { + data_value *val_address = nullptr, *val_offset = nullptr; + if (lhs_type == VAL_ADDRESS && rhs_type == VAL_CONSTANT) + { + val_address = &val_lhs; + val_offset = &val_rhs; + } + else if (lhs_type == VAL_CONSTANT && rhs_type == VAL_ADDRESS) + { + val_address = &val_rhs; + val_offset = &val_lhs; + } + else + gcc_unreachable (); + + storage_address *address = val_address->get_address (); + gcc_assert (address != nullptr); + wide_int offset = val_offset->get_cst (); + wide_int bit_offset = offset * CHAR_BIT; + wide_int total_offset = address->offset + bit_offset; + gcc_assert (wi::fits_uhwi_p (total_offset)); + storage_address final_address (address->storage, + total_offset.to_uhwi ()); + data_value result (type); + result.set_address (final_address); + return result; + } } } } @@ -6219,6 +6253,113 @@ exec_context_evaluate_binary_tests () wide_int wi_val2 = val2.get_cst (); ASSERT_PRED1 (wi::fits_uhwi_p, wi_val2); ASSERT_EQ (wi_val2.to_uhwi (), 1); + + + tree a12c = build_array_type_nelts (char_type_node, 12); + tree v12c = create_var (a12c, "v12c"); + tree p = create_var (ptr_type_node, "p"); + tree i = create_var (pointer_sized_int_node, "i"); + tree o = create_var (pointer_sized_int_node, "o"); + + vec decls3{}; + decls3.safe_push (v12c); + decls3.safe_push (p); + decls3.safe_push (i); + decls3.safe_push (o); + + context_builder builder3 {}; + builder3.add_decls (&decls3); + exec_context ctx3 = builder3.build (mem, printer); + + data_storage *v12_storage = ctx3.find_reachable_var (v12c); + gcc_assert (v12_storage != nullptr); + storage_address v12_address (v12_storage->get_ref (), 0); + + data_value pv12 (ptr_type_node); + pv12.set_address (v12_address); + + data_storage *p_storage = ctx3.find_reachable_var (p); + gcc_assert (p_storage != nullptr); + p_storage->set (pv12); + + data_storage *i_storage = ctx3.find_reachable_var (i); + gcc_assert (i_storage != nullptr); +
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Correction initialisation variable
https://gcc.gnu.org/g:2bfdabdbd12fdd2b175620d67f3c15e1ea49aa6a commit 2bfdabdbd12fdd2b175620d67f3c15e1ea49aa6a Author: Mikael Morin Date: Thu Mar 6 19:27:49 2025 +0100 Correction initialisation variable Diff: --- gcc/cgraphunit.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index 6edc4984906d..158cbe010ca7 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -6580,7 +6580,7 @@ exec_context_evaluate_tests () tree v9i = create_var (a9i, "v9i"); tree p = create_var (ptr_type_node, "p"); - vec decls9; + vec decls9 {}; decls9.safe_push (v9i); decls9.safe_push (p);
[gcc(refs/users/mikael/heads/refactor_descriptor_v01)] Changement type retour get_address: data_storage -> storage_address
https://gcc.gnu.org/g:f7b4f69154fbaf8483321bd1f2abe4fbe8008e85 commit f7b4f69154fbaf8483321bd1f2abe4fbe8008e85 Author: Mikael Morin Date: Tue Mar 4 22:32:21 2025 +0100 Changement type retour get_address: data_storage -> storage_address Diff: --- gcc/cgraphunit.cc | 91 --- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index 5290f7f27cfd..c5907e55055e 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -2485,8 +2485,8 @@ public: void set_cst (const wide_int & val); wide_int get_cst_at (unsigned offset, unsigned width) const; wide_int get_cst () const; - data_storage *get_address () const; - data_storage *get_address_at (unsigned offset) const; + storage_address *get_address () const; + storage_address *get_address_at (unsigned offset) const; data_value get_at (unsigned offset, unsigned width) const; bool is_fully_defined () const { return (~(constant_mask | address_mask)) == 0; } tree to_tree (tree type) const; @@ -2869,13 +2869,13 @@ find_mem_ref_replacement (exec_context & context, tree data_ref, unsigned offset if (ptr_val.classify () != VAL_ADDRESS) return NULL_TREE; - data_storage *ptr_target = ptr_val.get_address (); - gcc_assert (ptr_target != nullptr); - if (ptr_target->get_type () != STRG_VARIABLE) + storage_address *ptr_address = ptr_val.get_address (); + data_storage &ptr_target = ptr_address->storage.get (); + if (ptr_target.get_type () != STRG_VARIABLE) return NULL_TREE; tree access_type = TREE_TYPE (data_ref); - tree var_ref = ptr_target->get_variable (); + tree var_ref = ptr_target.get_variable (); tree var_type = TREE_TYPE (var_ref); if (var_type == access_type) @@ -3315,7 +3315,7 @@ data_value::get_cst () const return get_cst_at (0, bit_width); } -data_storage * +storage_address * data_value::get_address_at (unsigned offset) const { gcc_assert (classify (offset, HOST_BITS_PER_PTR) == VAL_ADDRESS); @@ -3324,13 +3324,13 @@ data_value::get_address_at (unsigned offset) const stored_address *addr_info = find_address (offset); if (addr_info != nullptr) -return &(addr_info->address.storage.get ()); +return &(addr_info->address); return nullptr; } -data_storage * +storage_address * data_value::get_address () const { gcc_assert (bit_width == HOST_BITS_PER_PTR); @@ -3351,9 +3351,7 @@ data_value::get_at (unsigned offset, unsigned width) const case VAL_ADDRESS: { gcc_assert (width == HOST_BITS_PER_PTR); - data_storage *storage = get_address_at (offset); - storage_address address (storage->get_ref (), 0); - result.set_address (address); + result.set_address (*get_address_at (offset)); } break; @@ -3419,9 +3417,9 @@ context_printer::print_at (const data_value & value, tree type, unsigned offset, { gcc_assert (width == HOST_BITS_PER_PTR); pp_ampersand (&pp); - data_storage *target_storage = value.get_address_at (offset); - gcc_assert (target_storage != nullptr); - target_storage->print (*this); + storage_address *address = value.get_address_at (offset); + data_storage &target_storage = address->storage.get (); + target_storage.print (*this); } break; @@ -3674,9 +3672,9 @@ exec_context::evaluate (tree expr) const tree ptr = TREE_OPERAND (expr, 0); data_value val_ptr = evaluate (ptr); gcc_assert (val_ptr.classify () == VAL_ADDRESS); - data_storage *storage = val_ptr.get_address (); - gcc_assert (storage != nullptr); - data_value storage_value = storage->get_value (); + storage_address *address = val_ptr.get_address (); + gcc_assert (address != nullptr); + data_value storage_value = address->storage.get ().get_value (); tree offset_bytes = TREE_OPERAND (expr, 1); data_value val_off = evaluate (offset_bytes); @@ -3927,7 +3925,7 @@ exec_context::decompose_ref (tree data_ref, data_storage * & storage, int & offs tree var = TREE_OPERAND (data_ref, 0); data_value addr = evaluate (var); gcc_assert (addr.classify () == VAL_ADDRESS); - storage = addr.get_address (); + storage = &(addr.get_address ()->storage.get ()); tree off = TREE_OPERAND (data_ref, 1); data_value off_val = evaluate (off); @@ -4835,14 +4833,14 @@ data_value_set_address_tests () val1.set_address (address_a); ASSERT_EQ (val1.classify (), VAL_ADDRESS); - ASSERT_EQ (val1.get_address (), storage_a); + ASSERT_EQ (&val1.get_address ()->storage.get (), storage_a); data_storage *storage_b = ctx.find_reachable_var (b); storage_address address_b (storage_b->get_ref (), 0); val1.set_address (address_b); ASSERT_EQ (val1.classify (), VAL_ADDRESS); - ASSERT_EQ (val1.get_address (), storage_b); + ASSERT_EQ (&