Link to the Compiler Explorer: https://godbolt.org/z/PMGTPGPab Reproducer: bool a; int b, c; inline const bool &d(bool &e, const bool &f) { return f < e ? f : e; } void g(char e, bool f[], bool h[], bool p4[]) { for (;;) if (p4) for (char j = 0; j < 6; j += (f[0] & c ? p4[0] : int(0 >= e)) ? 0 : d(p4[0], p4[0] > h[0]) + 1) { a = 0; b = 0; } } Error: >$ g++ -O3 -c func.cpp during GIMPLE pass: thread func.cpp: In function 'void g(char, bool*, bool*, bool*)': func.cpp:4:6: internal compiler error: in upper_bound, at value-range.h:950 4 | void g(char e, bool f[], bool h[], bool p4[]) { | ^ 0x995922 irange::upper_bound() const /testing/gcc/gcc_src_master/gcc/value-range.h:950 0x9961f0 irange::upper_bound() const /testing/gcc/gcc_src_master/gcc/tree.h:3653 0x9961f0 operator_lt::op2_range(irange&, tree_node*, irange const&, irange const&, relation_trio) const /testing/gcc/gcc_src_master/gcc/range-op.cc:952 0x20cc69f gori_compute::refine_using_relation(tree_node*, vrange&, tree_node*, vrange&, fur_source&, relation_kind_t) /testing/gcc/gcc_src_master/gcc/gimple-range-gori.cc:1034 0x20ce404 gori_compute::compute_operand1_range(vrange&, gimple_range_op_handler&, vrange const&, tree_node*, fur_source&, value_relation*) /testing/gcc/gcc_src_master/gcc/gimple-range-gori.cc:1092 0x20cd0e5 gori_compute::compute_operand_range(vrange&, gimple*, vrange const&, tree_node*, fur_source&, value_relation*) /testing/gcc/gcc_src_master/gcc/gimple-range-gori.cc:700 0x20d0ad8 gori_compute::outgoing_edge_range_p(vrange&, edge_def*, tree_node*, range_query&) /testing/gcc/gcc_src_master/gcc/gimple-range-gori.cc:1358 0x141362d path_range_query::compute_ranges_in_block(basic_block_def*) /testing/gcc/gcc_src_master/gcc/gimple-range-path.cc:454 0x1413d3a path_range_query::compute_ranges(bitmap_head const*) /testing/gcc/gcc_src_master/gcc/gimple-range-path.cc:622 0x149cd3a back_threader::find_taken_edge_cond(vec<basic_block_def*, va_heap, vl_ptr> const&, gcond*) /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:324 0x149cf33 back_threader::maybe_register_path(back_threader_profitability&) /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:248 0x149d2d0 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&) /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:371 0x149d789 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&) /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:479 0x149d789 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&) /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:479 0x149d789 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&) /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:479 0x149d789 back_threader::find_paths_to_names(basic_block_def*, bitmap_head*, unsigned int, back_threader_profitability&) /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:479 0x149e258 back_threader::maybe_thread_block(basic_block_def*) /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:551 0x149e321 back_threader::thread_blocks() /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:975 0x149e398 execute /testing/gcc/gcc_src_master/gcc/tree-ssa-threadbackward.cc:1077 gcc version 13.0.1 20230201 (a2c848c92c3f13c2dd9bd92d22beb44c1ff848b4)
Confirmed. We have VR_UNDEFINED as other_op in #4 0x00000000030c3df4 in gori_compute::refine_using_relation (this=0x490b310, op1=<ssa_name 0x7ffff643c360 42>, op1_range=..., op2=<ssa_name 0x7ffff643c678 53>, op2_range=..., src=..., k=VREL_LT) at /home/rguenther/src/trunk/gcc/gimple-range-gori.cc:1034 1034 if (!op_handler.op2_range (new_result, type, (gdb) l 1029 src.get_operand (other_op, def_op1); 1030 1031 // Using op1_range as the LHS, and relation REL, evaluate op2. 1032 tree type = TREE_TYPE (def_op2); 1033 Value_Range new_result (type); 1034 if (!op_handler.op2_range (new_result, type, 1035 op1_def_p ? op1_range : op2_range, 1036 other_op, relation_trio::lhs_op2 (k))) must be a quite recent regression.
Started with r13-2974-g67166c9ec35d58ef.
The ICE is when operator_lt::op2_range does: 976 case BRS_FALSE: 977 build_le (r, type, op1.upper_bound ()); 978 break; lhs is [irange] bool [0, 0] NONZERO 0x0 and rhs is [irange] UNDEFINED which is why op1.upper_bound () ICEs - it has no pairs. I wonder if operator_lt::op?_range and other operators shouldn't start with relop_early_resolve or at least empty_range_varying or something similar to deal with op?.undefined_p ().
Perhaps just adding if (op2.undefined_p ()) return false; above most of the switch (get_bool_state (r, lhs, type)) lines (in methods that refer to op2; and similarly for op1) for the comparison operators.
> Perhaps just adding if (op2.undefined_p ()) return false; above most of the > switch (get_bool_state (r, lhs, type)) lines (in methods that refer to op2; > and similarly for op1) for the comparison operators. This feels like the right approach. We also do something similar in some of the binary operators. For example, plus/minus_expr do: if (lhs.undefined_p ()) return false; For this testcase we have: [0,0] = UNDEFINED < op2 I don't think we can determine anything for op2 in this situation, so the right thing would be to return false, which amounts to returning VARYING. The binary operators would also have to handle operators of undefined, but those seem to all have gates on singleton_p() or go through the fold_range() routine for the inverse operation, so they'd be handled correctly. So yeah, it looks like just handling the op[12]_range operators above the get_bool_state would do the trick. Hmmm, it seems like there are 2 operators that have possible problematic handling of op2.undefined_p(): 1. operator_cast::op1_range (irange &r, tree type, The assert looks at the op2 type. That will ICE with an UNDEFINED. The truncating_cast_p path will also look at op2's type blindly. 2. operator_bitwise_xor::op1_range Imagine: [0,0] = x ^ UNDEFINED op1_range won't ICE, but it will do: case BRS_FALSE: r = op2; I don't think we know anything about x in this case. Though if, op2 is UNDEFINED, I guess it wouldn't hurt to assume op1 is also UNDEFINED. Also earlier in the function, for: UNDEFINED = x ^ op2 will return x = UNDEFINED for any op2. So at least #1 would also have to be handled because it could ICE. Also, range-op-float.cc needs the same treatment prior all the get_bool_state calls. As you mention, another alternative would be to always call empty_range_varying, as we're doing for abs::op[12]_range: if (empty_range_varying (r, type, lhs, op2)) return true; Thoughts? Andrew? Hmmm, I wonder why we haven't tripped over this scenario in past releases (LHS being defined, but op2 being UNDEFINED).
This is the first release that we process relations in GORI. Up until recently it was fairly ad-hoc what got passed in as a relation trio to the op?_range routines. A couple of days ago I fleshed it out fully. I am surprised that isn't what caused this. Anyway, the reason its tripping: if (_42 != 0) goto <bb 10>; [50.00%] else goto <bb 6>; [50.00%] bb6: _27 = *h_29(D); _53 = _27 < _42; if (_42 > _53) we start by trying to evaluate the outgoing edge for _42 on the true side: [1,1] = (_42 > _53) The problem is we have determined that _42 is bool [0, 0] at this point. Knowing _42 is [0, 0], the definition of _53 can never be true, so it is also bool [0,0] in order for _53 to be [0,0] AND _42 to be [0,0], the bool value for _27 is nonsensical.. and thus its being calculated as undefined. This branch is eventually going to be removed since it can never be taken, but that hasnt happened at this point yet. we could fix it at the call site, but you do point out that the opX_range routines are not gracefully dealing with undefined values. We probably should audit them all to make sure we handled undefined gracefully before accessing a bound.
So --- gcc/range-op.cc.jj 2023-02-03 10:51:40.699003658 +0100 +++ gcc/range-op.cc 2023-02-03 16:04:39.264159294 +0100 @@ -642,7 +642,8 @@ operator_equal::op1_range (irange &r, tr case BRS_FALSE: // If the result is false, the only time we know anything is // if OP2 is a constant. - if (wi::eq_p (op2.lower_bound(), op2.upper_bound())) + if (!op2.undefined_p () + && wi::eq_p (op2.lower_bound(), op2.upper_bound())) { r = op2; r.invert (); @@ -755,7 +756,8 @@ operator_not_equal::op1_range (irange &r case BRS_TRUE: // If the result is true, the only time we know anything is if // OP2 is a constant. - if (wi::eq_p (op2.lower_bound(), op2.upper_bound())) + if (!op2.undefined_p () + && wi::eq_p (op2.lower_bound(), op2.upper_bound())) { r = op2; r.invert (); @@ -920,6 +922,9 @@ operator_lt::op1_range (irange &r, tree const irange &op2, relation_trio) const { + if (op2.undefined_p ()) + return false; + switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -942,6 +947,9 @@ operator_lt::op2_range (irange &r, tree const irange &op1, relation_trio) const { + if (op1.undefined_p ()) + return false; + switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -1031,6 +1039,9 @@ operator_le::op1_range (irange &r, tree const irange &op2, relation_trio) const { + if (op2.undefined_p ()) + return false; + switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -1053,6 +1064,9 @@ operator_le::op2_range (irange &r, tree const irange &op1, relation_trio) const { + if (op1.undefined_p ()) + return false; + switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -1141,6 +1155,9 @@ operator_gt::op1_range (irange &r, tree const irange &lhs, const irange &op2, relation_trio) const { + if (op2.undefined_p ()) + return false; + switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -1163,6 +1180,9 @@ operator_gt::op2_range (irange &r, tree const irange &op1, relation_trio) const { + if (op1.undefined_p ()) + return false; + switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -1252,6 +1272,9 @@ operator_ge::op1_range (irange &r, tree const irange &op2, relation_trio) const { + if (op2.undefined_p ()) + return false; + switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: @@ -1274,6 +1297,9 @@ operator_ge::op2_range (irange &r, tree const irange &op1, relation_trio) const { + if (op1.undefined_p ()) + return false; + switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: then plus testcase?
Unfortunately that would mean for the non-equality cases that if lhs.undefined_p () we don't return undefined but false (aka VARYING). Another option is to add those if (op?.undefined_p ()) return false; to both case BRS_TRUE: and case BRS_FALSE:.
(In reply to Jakub Jelinek from comment #8) > Unfortunately that would mean for the non-equality cases that if > lhs.undefined_p () we don't return undefined but false (aka VARYING). > Another option is to add those if (op?.undefined_p ()) return false; to both > case BRS_TRUE: and case BRS_FALSE:. Well, if the LHS is undefined, (or even one of the operands) we are typically in dead code or edge anyway.. I'm not sure it really matters? An alternate question as well is why is the threader even looking at this impossible path. It should know that the branch can never be true
(In reply to Andrew Macleod from comment #9) > (In reply to Jakub Jelinek from comment #8) > > Unfortunately that would mean for the non-equality cases that if > > lhs.undefined_p () we don't return undefined but false (aka VARYING). > > Another option is to add those if (op?.undefined_p ()) return false; to both > > case BRS_TRUE: and case BRS_FALSE:. > > Well, if the LHS is undefined, (or even one of the operands) we are > typically in dead code or edge anyway.. I'm not sure it really matters? Ok, I'll test the patch then. > An alternate question as well is why is the threader even looking at this > impossible path. It should know that the branch can never be true I think range-op shouldn't assume nothing will call it with UNDEFINED ranges.
(In reply to Jakub Jelinek from comment #10) > (In reply to Andrew Macleod from comment #9) > > (In reply to Jakub Jelinek from comment #8) > > > Unfortunately that would mean for the non-equality cases that if > > > lhs.undefined_p () we don't return undefined but false (aka VARYING). > > > Another option is to add those if (op?.undefined_p ()) return false; to both > > > case BRS_TRUE: and case BRS_FALSE:. > > > > Well, if the LHS is undefined, (or even one of the operands) we are > > typically in dead code or edge anyway.. I'm not sure it really matters? > > Ok, I'll test the patch then. > > > An alternate question as well is why is the threader even looking at this > > impossible path. It should know that the branch can never be true > > I think range-op shouldn't assume nothing will call it with UNDEFINED ranges. Oh I wasn't suggesting otherwise,we should be bulletproof. Just wondering why the threader is spending any time evaluating ranges on a path it should know is impossible.
(In reply to Jakub Jelinek from comment #7) > So > --- gcc/range-op.cc.jj 2023-02-03 10:51:40.699003658 +0100 > +++ gcc/range-op.cc 2023-02-03 16:04:39.264159294 +0100 > @@ -642,7 +642,8 @@ operator_equal::op1_range (irange &r, tr > case BRS_FALSE: > // If the result is false, the only time we know anything is > // if OP2 is a constant. > - if (wi::eq_p (op2.lower_bound(), op2.upper_bound())) > + if (!op2.undefined_p () > + && wi::eq_p (op2.lower_bound(), op2.upper_bound())) > { > r = op2; > r.invert (); > @@ -755,7 +756,8 @@ operator_not_equal::op1_range (irange &r > case BRS_TRUE: > // If the result is true, the only time we know anything is if > // OP2 is a constant. > - if (wi::eq_p (op2.lower_bound(), op2.upper_bound())) > + if (!op2.undefined_p () > + && wi::eq_p (op2.lower_bound(), op2.upper_bound())) > { > r = op2; > r.invert (); > @@ -920,6 +922,9 @@ operator_lt::op1_range (irange &r, tree > const irange &op2, > relation_trio) const > { > + if (op2.undefined_p ()) > + return false; > + > switch (get_bool_state (r, lhs, type)) > { > case BRS_TRUE: > @@ -942,6 +947,9 @@ operator_lt::op2_range (irange &r, tree > const irange &op1, > relation_trio) const > { > + if (op1.undefined_p ()) > + return false; > + > switch (get_bool_state (r, lhs, type)) > { > case BRS_TRUE: > @@ -1031,6 +1039,9 @@ operator_le::op1_range (irange &r, tree > const irange &op2, > relation_trio) const > { > + if (op2.undefined_p ()) > + return false; > + > switch (get_bool_state (r, lhs, type)) > { > case BRS_TRUE: > @@ -1053,6 +1064,9 @@ operator_le::op2_range (irange &r, tree > const irange &op1, > relation_trio) const > { > + if (op1.undefined_p ()) > + return false; > + > switch (get_bool_state (r, lhs, type)) > { > case BRS_TRUE: > @@ -1141,6 +1155,9 @@ operator_gt::op1_range (irange &r, tree > const irange &lhs, const irange &op2, > relation_trio) const > { > + if (op2.undefined_p ()) > + return false; > + > switch (get_bool_state (r, lhs, type)) > { > case BRS_TRUE: > @@ -1163,6 +1180,9 @@ operator_gt::op2_range (irange &r, tree > const irange &op1, > relation_trio) const > { > + if (op1.undefined_p ()) > + return false; > + > switch (get_bool_state (r, lhs, type)) > { > case BRS_TRUE: > @@ -1252,6 +1272,9 @@ operator_ge::op1_range (irange &r, tree > const irange &op2, > relation_trio) const > { > + if (op2.undefined_p ()) > + return false; > + > switch (get_bool_state (r, lhs, type)) > { > case BRS_TRUE: > @@ -1274,6 +1297,9 @@ operator_ge::op2_range (irange &r, tree > const irange &op1, > relation_trio) const > { > + if (op1.undefined_p ()) > + return false; > + > switch (get_bool_state (r, lhs, type)) > { > case BRS_TRUE: > then plus testcase? Looks good to me. Do you mind adding this bit to your testing? diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 136b709385c..fdc0a6c05fd 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -2678,7 +2678,6 @@ operator_cast::op1_range (irange &r, tree type, if (lhs.undefined_p ()) return false; tree lhs_type = lhs.type (); - gcc_checking_assert (types_compatible_p (op2.type(), type)); // If we are calculating a pointer, shortcut to what we really care about. if (POINTER_TYPE_P (type)) @@ -2705,6 +2704,8 @@ operator_cast::op1_range (irange &r, tree type, return true; } + if (op2.undefined_p ()) + return false; if (truncating_cast_p (op2, lhs)) { if (lhs.varying_p ()) This catches the cast operator which will ICE in truncating_cast_p when op2 is undefined. I've removed the checking assert since any number of operations further down will ICE if the types don't match.
Created attachment 54404 [details] frange changes These are the analogous changes to range-op-float.cc. Patch in testing.
Created attachment 54405 [details] gcc13-pr108647.patch Here is what I'm about to test momentarily, though I must say I don't understand those operator_cast changes at all. I thought casts are unary operators and so I don't understand what kind of range would be op2 in that case.
(In reply to Jakub Jelinek from comment #14) > Created attachment 54405 [details] > gcc13-pr108647.patch > > Here is what I'm about to test momentarily, though I must say I don't > understand those operator_cast changes at all. I thought casts are unary > operators and so I don't understand what kind of range would be op2 in that > case. Oh poop, sorry. Unary operators always have the resulting type passed as VARYING in op2. It would never be undefined. Sorry for the noise; you can disregard the cast changes.
The master branch has been updated by Aldy Hernandez <aldyh@gcc.gnu.org>: https://gcc.gnu.org/g:10bd26d6efe88a8cf03a6a325351bc470a910cab commit r13-5695-g10bd26d6efe88a8cf03a6a325351bc470a910cab Author: Aldy Hernandez <aldyh@redhat.com> Date: Fri Feb 3 17:28:52 2023 +0100 range-ops: Handle undefined ranges in frange op[12]_range [PR108647] This patch gracefully handles undefined operand ranges for the floating point op[12]_range operators. This is very low risk, as we would have ICEd otherwise. We don't have a testcase that ICEs for floating point ranges, but it's only a matter of time. Besides, this dovetails nicely with the integer versions Jakub is testing. gcc/ChangeLog: PR tree-optimization/108647 * range-op-float.cc (foperator_lt::op1_range): Handle undefined ranges. (foperator_lt::op2_range): Same. (foperator_le::op1_range): Same. (foperator_le::op2_range): Same. (foperator_gt::op1_range): Same. (foperator_gt::op2_range): Same. (foperator_ge::op1_range): Same. (foperator_ge::op2_range): Same. (foperator_unordered_lt::op1_range): Same. (foperator_unordered_lt::op2_range): Same. (foperator_unordered_le::op1_range): Same. (foperator_unordered_le::op2_range): Same. (foperator_unordered_gt::op1_range): Same. (foperator_unordered_gt::op2_range): Same. (foperator_unordered_ge::op1_range): Same. (foperator_unordered_ge::op2_range): Same.
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:e753080ab8abd4021381699bc7e857f5b4a083c4 commit r13-5698-ge753080ab8abd4021381699bc7e857f5b4a083c4 Author: Jakub Jelinek <jakub@redhat.com> Date: Fri Feb 3 21:39:16 2023 +0100 range-op: Handle op?.undefined_p () in op[12]_range of comparisons [PR108647] As mentioned in the PR, we ICE because lhs is singleton [0, 0] or [1, 1] but op2 (or in other cases op1) is undefined and op?.*_bound () ICEs on those because there are no pairs for UNDEFINED. The following patch makes us set r to varying or return false in those cases. 2023-02-03 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/108647 * range-op.cc (operator_equal::op1_range, operator_not_equal::op1_range): Don't test op2 bound equality if op2.undefined_p (), instead set_varying. (operator_lt::op1_range, operator_le::op1_range, operator_gt::op1_range, operator_ge::op1_range): Return false if op2.undefined_p (). (operator_lt::op2_range, operator_le::op2_range, operator_gt::op2_range, operator_ge::op2_range): Return false if op1.undefined_p (). * g++.dg/torture/pr108647.C: New test.
Should be fixed now.
This is now resulting in build error in harfbuzz on aarch64 which did not happen before, the testcase is here https://uclibc.org/~kraj/hb-aat-layout.cc.i Compile cmd used is /mnt/b/cross/aarch64-linux-musl/tools/bin/aarch64-linux-musl-g++ --sysroot=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/recipe-sysroot -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -Isrc/libharfbuzz.so.0.60600.0.p -Isrc -I../harfbuzz-6.0.0/src -I. -I../harfbuzz-6.0.0 -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -std=c++11 -fno-rtti -fno-exceptions -fno-rtti -fno-threadsafe-statics -fvisibility-inlines-hidden -DHAVE_CONFIG_H -O2 -pipe -g -feliminate-unused-debug-types -fmacro-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/harfbuzz-6.0.0=/usr/src/debug/harfbuzz/6.0.0-r0 -fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/harfbuzz-6.0.0=/usr/src/debug/harfbuzz/6.0.0-r0 -fmacro-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/build=/usr/src/debug/harfbuzz/6.0.0-r0 -fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/build=/usr/src/debug/harfbuzz/6.0.0-r0 -fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/recipe-sysroot= -fmacro-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/recipe-sysroot= -fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/cortexa72-yoe-linux/harfbuzz/6.0.0-r0/recipe-sysroot-native= -fvisibility-inlines-hidden -fPIC -pthread -Wno-non-virtual-dtor -MD -MQ src/libharfbuzz.so.0.60600.0.p/hb-aat-layout.cc.o -MF src/libharfbuzz.so.0.60600.0.p/hb-aat-layout.cc.o.d -o src/libharfbuzz.so.0.60600.0.p/hb-aat-layout.cc.o -c ../harfbuzz-6.0.0/src/hb-aat-layout.cc
How could these changes result in ../harfbuzz-6.0.0/src/hb-map.hh:295:5: error: no match for ‘operator|’ (operand types are ‘hb_filter_iter_t<hb_array_t<hb_hashmap_t<unsigned int, unsigned int, true>::item_t>, bool (hb_hashmap_t<unsigned int, unsigned int, true>::item_t::*)() const, const<unnamed struct>&, 0>’ and ‘hb_reduce_t<hb_hashmap_t<unsigned int, unsigned int, true>::hash() const::<lambda(uint32_t, const hb_hashmap_t<unsigned int, unsigned int, true>::item_t&)>, unsigned int>’) errors? I can see that with a cross-compiler, so VRP miscompiling the C++ FE is not an option.
Seems it is r13-5684-g59e0376f607805ef9b67fd7b0a4a3084ab3571a5 aka PR107461 change. So, please file a separate bugreport, it has nothing to do with this PR.
(In reply to Jakub Jelinek from comment #20) > How could these changes result in > ../harfbuzz-6.0.0/src/hb-map.hh:295:5: error: no match for ‘operator|’ > (operand types are ‘hb_filter_iter_t<hb_array_t<hb_hashmap_t<unsigned int, > unsigned int, true>::item_t>, bool (hb_hashmap_t<unsigned int, unsigned int, > true>::item_t::*)() const, const<unnamed struct>&, 0>’ and > ‘hb_reduce_t<hb_hashmap_t<unsigned int, unsigned int, true>::hash() > const::<lambda(uint32_t, const hb_hashmap_t<unsigned int, unsigned int, > true>::item_t&)>, unsigned int>’) > errors? I can see that with a cross-compiler, so VRP miscompiling the C++ > FE is not an option. argh my bad, filled in wrong tab. Sorry about this.