[Bug c++/119659] New: [OpenMP] append_args in iobj member function applies to the wrong paramater
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119659 Bug ID: 119659 Summary: [OpenMP] append_args in iobj member function applies to the wrong paramater Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: waffl3x at gcc dot gnu.org Target Milestone: --- Created attachment 61026 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61026&action=edit Output with -ftree-dump-gimple Another case that got found in the final stages of my current patch, already fixed, this is just for records. The issue is more obvious in the attached tree dump, despite append_args being specified for parameter 'a', it is instead adjusting the second parameter 'b' instead. https://godbolt.org/z/4o4cc46eY ``` struct S { template void v(int *, int *) {} #pragma omp declare variant(v) match(construct={dispatch}) \ adjust_args(need_device_ptr: a) template void b(int *a, int *b) {} }; void f(int *p0, int *p1) { S s{}; #pragma omp dispatch s.b(p0, p1); } ```
[Bug c++/119674] New: defaulted assignment operator with xobj syntax is an xobj function instead of an iobj function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119674 Bug ID: 119674 Summary: defaulted assignment operator with xobj syntax is an xobj function instead of an iobj function Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: minor Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: waffl3x at gcc dot gnu.org Target Milestone: --- dcl.fct.def.default p2 An explicitly defaulted special member function F1 is allowed to differ from the corresponding special member function F2 that would have been implicitly declared, as follows: (2.2) if F2 has an implicit object parameter of type “reference to C”, F1 may be an explicit object member function whose explicit object parameter is of (possibly different) type “reference to C”, in which case the type of F1 would differ from the type of F2 in that the type of F1 has an additional parameter; I am interpreting this to mean that the declaration of the function that is defaulted does not effect the actual function that is generated. I assume there is another passage somewhere that specifies this more directly. I'm not 100% sure if my interpretation is correct, but if it is our current implementation is not. ``` struct S0 { S0& operator=(S0 const&) = default; }; struct S1 { S1& operator=(this S1&, S1 const&) = default; }; int main() { // well-formed, accepted S0& (S0::* p0)(S0 const&) = &S0::operator=; // well-formed, rejected S1& (S1::* p1)(S1 const&) = &S1::operator=; // ill-formed, rejected S0& (* p2)(S0&, S0 const&) = &S0::operator=; // ill-formed, accepted S1& (* p3)(S1&, S1 const&) = &S1::operator=; } ```
[Bug c++/119659] [OpenMP] append_args in iobj member function applies to the wrong paramater
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119659 --- Comment #1 from Alex --- I accidentally left the template head in the original test case, it doesn't change the results at all but does slightly over complicate the test case. ``` struct S { void v(int *, int *) {} #pragma omp declare variant(v) match(construct={dispatch}) \ adjust_args(need_device_ptr: a) void b(int *a, int *b) {} }; void f(int *p0, int *p1) { S s{}; #pragma omp dispatch s.b(p0, p1); } ```
[Bug c++/119736] New: rejected/ICEs when non type template parameter used as an argument to a const ref non type template parameter
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119736 Bug ID: 119736 Summary: rejected/ICEs when non type template parameter used as an argument to a const ref non type template parameter Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: waffl3x at gcc dot gnu.org Target Milestone: --- https://godbolt.org/z/aE7xEnzzq ``` template struct takes_static_ref {}; template struct make_static_ref { static constexpr auto const& ref = Data; }; using ice = takes_static_ref::ref>; ``` https://godbolt.org/z/EEjMj9ab4 ``` template void takes_static_ref_f() {} template struct make_static_ref { static constexpr auto const& ref = Data; }; template void takes_static_ref_f::ref>(); ``` This only triggers in C++17 and up, I am fairly certain this is valid code but it doesn't seem like it was ever accepted in GCC, it's just the ICE that is new. All the cases beyond here are not regressions, but I do believe they are all valid code. https://godbolt.org/z/qG66n6Mse ``` template struct takes_static_ref {}; template struct make_static_ref { using direct = takes_static_ref; static constexpr auto const& ref = Data; using from_member = takes_static_ref; }; using direct = make_static_ref<42>::direct; using from_member = make_static_ref<42>::from_member; ``` And finally these are what should be a fairly exhaustive list of cases, the ones you would expect to work still work and are just included to illustrate that the problematic cases are probably valid C++ code. https://godbolt.org/z/7KabYPqTr ``` template struct takes_static_ref {}; template struct takes_value {}; template void takes_static_ref_f() {} template struct make_static_ref { static constexpr int const& ref = Data; }; template inline constexpr const auto& make_static_ref_inline = Data; inline int my_global_var = 42; using with_global = takes_static_ref; template void takes_static_ref_f(); struct S { inline static int my_static_member = 42; using with_static_member = takes_static_ref; }; using with_static_member = takes_static_ref; template void takes_static_ref_f(); void f() { static int my_static_var = 42; takes_static_ref with_local_static; takes_static_ref_f(); static constexpr auto data_0 = make_static_ref<42>::ref; static constexpr auto data_1 = make_static_ref_inline<42>; static constexpr auto const& data_ref_0 = make_static_ref<42>::ref; static constexpr auto const& data_ref_1 = make_static_ref_inline<42>; takes_value v_0; takes_value v_1; takes_static_ref r_0; takes_static_ref r_1; takes_static_ref_f(); takes_static_ref_f(); } using sr_0 = takes_value::ref>; using sr_1 = takes_value>; using sr_0 = takes_static_ref::ref>; using sr_1 = takes_static_ref>; template void takes_static_ref_f::ref>(); template void takes_static_ref_f>(); ```
[Bug c++/119775] New: [OpenMP] ICE with append_args in iobj member function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119775 Bug ID: 119775 Summary: [OpenMP] ICE with append_args in iobj member function Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: waffl3x at gcc dot gnu.org Target Milestone: --- https://godbolt.org/z/PYff7Gxoa ``` enum omp_interop_t : __UINTPTR_TYPE__; struct S { void v(int, omp_interop_t) {} #pragma omp declare variant(v) match(construct={dispatch}) \ append_args(interop(target)) void b(int) {} }; void f() { #pragma omp dispatch S{}.b(42); } ``` :14:3: internal compiler error: tree check: accessed operand 6 of call_expr with 5 operands in modify_call_for_omp_dispatch, at gimplify.cc:3969 14 | S{}.b(42); | ^ I noticed this while preparing my PR119659 patch for submission, it's right around the same area, similar cause This will be fixed alongside that patch.
[Bug c++/119602] [OpenMP] append_args dependent prefer_type uses value from first instantiation in all instantiations
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119602 --- Comment #1 from Alex --- I somehow botched the test case in my original post, here is the fixed version. https://godbolt.org/z/no9Pbv78K ``` typedef enum omp_interop_t : __UINTPTR_TYPE__ { omp_interop_none = 0 } omp_interop_t; typedef enum omp_interop_fr_t { omp_ifr_cuda = 1, omp_ifr_cuda_driver = 2, omp_ifr_opencl = 3, omp_ifr_sycl = 4, omp_ifr_hip = 5, omp_ifr_level_zero = 6, omp_ifr_hsa = 7, omp_ifr_last = omp_ifr_hsa } omp_interop_fr_t; template struct FR {}; template void v_dependent_fr(FR x, T2 y) { } #pragma omp declare variant(v_dependent_fr) match(construct={dispatch}) \ append_args(interop(target, \ prefer_type(V))) template void b_dependent_fr(FR x) { } template void v_cuda(T x, T2 y) { } #pragma omp declare variant(v_cuda) match(construct={dispatch}) \ append_args(interop(target, \ prefer_type(omp_ifr_cuda_driver))) template void b_cuda(T x) { } template void v_hip(T x, T2 y) { } #pragma omp declare variant(v_hip) match(construct={dispatch}) \ append_args(interop(target, \ prefer_type(omp_ifr_hip))) template void b_hip(T x) { } template void v_hsa(T x, T2 y) { } #pragma omp declare variant(v_hsa) match(construct={dispatch}) \ append_args(interop(target, \ prefer_type(omp_ifr_hsa))) template void b_hsa(T x) { } void f () { #pragma omp dispatch b_dependent_fr (FR{}); #pragma omp dispatch b_dependent_fr (FR{}); #pragma omp dispatch b_dependent_fr (FR{}); #pragma omp dispatch b_dependent_fr (FR{}); #pragma omp dispatch b_cuda (0); #pragma omp dispatch b_hip (0); #pragma omp dispatch b_hsa (0); } ```
[Bug middle-end/120021] Offloading vs. C++ 'std::initializer_list'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120021 Alex changed: What|Removed |Added Summary|Offloading vs. C++ |Offloading vs. C++ |'std::valarray' |'std::initializer_list' CC||waffl3x at gcc dot gnu.org --- Comment #3 from Alex --- This appears to be related to std::initializer_list ``` #include bool initializer_list() { int sum; #pragma omp target map(from: sum) { auto il = {0, 1, 2, 3, 4, 5}; int n = 0; auto end = il.end(); for (auto it = il.begin(); it != end; ++it) n += *it; sum = n; } return sum == 15; } int main() { return initializer_list() ? 0 : 1; } ``` I'm sure a better reduced case exists, seems specifically be reading the elements of the list as the following passes. ``` /* std::initializer_list in target region. */ #include bool initializer_list() { bool ok; #pragma omp target map(from: ok) { auto il = {0, 1, 2, 3, 4, 5}; ok = il.begin() != il.end(); } return ok; } int main() { return initializer_list() ? 0 : 1; } ```