[Bug c++/108238] returns_nonnull attribute with auto return type fails to compile
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108238 --- Comment #2 from Barnabás Pőcze --- Here is a change that I believe might address this. It seems to work but I have never done anything in gcc, so probably has shortcomings. The error points to the return expression, like this: asd2.cpp: In function ‘auto f2()’: asd2.cpp:9:20: error: ‘returns_nonnull’ attribute on a function not returning a pointer 9 | auto f2() { return 42; } |^~ --- diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 4667f6de311..50f5ad6b8f1 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -5761,8 +5761,9 @@ static tree handle_returns_nonnull_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { + auto type_code = TREE_CODE (TREE_TYPE (*node)); // Even without a prototype we still have a return type we can check. - if (TREE_CODE (TREE_TYPE (*node)) != POINTER_TYPE) + if (type_code != POINTER_TYPE && type_code != TEMPLATE_TYPE_PARM) { error ("%qE attribute on a function not returning a pointer", name); *no_add_attrs = true; diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 1656d02d6d1..b3ae608b350 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -12305,6 +12305,10 @@ apply_deduced_return_type (tree fco, tree return_type) if (return_type == error_mark_node) return; + tree returns_nonnull = lookup_attribute("returns_nonnull", TYPE_ATTRIBUTES (TREE_TYPE (fco))); + if (returns_nonnull && TREE_CODE (return_type) != POINTER_TYPE) +error ("% attribute on a function not returning a pointer"); + if (DECL_CONV_FN_P (fco)) DECL_NAME (fco) = make_conv_op_name (return_type);
[Bug c++/107532] [13 Regression] -Werror=dangling-reference false positives in libcamera-0.0.1
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107532 Barnabás Pőcze changed: What|Removed |Added CC||pobrn at protonmail dot com --- Comment #8 from Barnabás Pőcze --- Here is another very simple example that only uses STL types: https://gcc.godbolt.org/z/43cKxdqr3 void f(const std::vector& v) { const int& r = std::span(v)[0]; }
[Bug tree-optimization/108802] New: missed inlining of call via pointer to member function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108802 Bug ID: 108802 Summary: missed inlining of call via pointer to member function Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com Target Milestone: --- See https://gcc.godbolt.org/z/j833EGfGY struct A { int f(int x) { return 2 * x; } }; int f1() { A a; return [&](auto&& f) { return (a.*f)(42); } (&A::f); } clang optimizes `f1()` to `return 84`, but gcc does not do so. This seems to have been changed somewhere between gcc 9 and 10 because 9.5 does the inlining but 10.1 does not do it.
[Bug c++/107532] [13 Regression] -Werror=dangling-reference false positives in libcamera-0.0.1
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107532 --- Comment #17 from Barnabás Pőcze --- The simple test case with std::span still triggers the warning: https://gcc.godbolt.org/z/43cKxdqr3. I feel that without deeper code analysis such a warning will generate too many false positives and people will simply turn it off.
[Bug c++/105667] [C++20] lambas in template argument sometimes causes an ICE (seg fault)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105667 Barnabás Pőcze changed: What|Removed |Added CC||pobrn at protonmail dot com --- Comment #6 from Barnabás Pőcze --- Another snippet that I believe triggers the same issue: template struct get { }; template struct thing { using T = decltype([](auto) { }); static constexpr auto value = [](auto) { return get(); }(0); }; thing<0> X; --- In this case template_parms_to_args() is called with a nullptr. template_parms_to_args (parms=0x0) at /usr/src/debug/gcc/gcc/cp/pt.cc:4912 tsubst_template_decl (t=0x77177280, args=, complain=3, lambda_fntype=0x7717b738) at /usr/src/debug/gcc/gcc/cp/pt.cc:14543 tsubst_lambda_expr (t=, args=0x77171d80, complain=3, in_decl=0x77173800) at /usr/src/debug/gcc/gcc/cp/pt.cc:19855 tsubst_copy_and_build (t=, args=0x77171d80, complain=, in_decl=0x77177000, function_p=, integral_constant_expression_p=false) at /usr/src/debug/gcc/gcc/cp/pt.cc:21446 tsubst (t=0x771760a8, args=0x77171d80, complain=3, in_decl=0x77177000) at /usr/src/debug/gcc/gcc/cp/pt.cc:16400 tsubst_template_args (t=0x77171a20, args=args@entry=0x77171d80, complain=complain@entry=3, in_decl=in_decl@entry=0x77177000) at /usr/src/debug/gcc/gcc/cp/pt.cc:13580 [...] --- GCC 12.2.0, but GCC trunk on Compiler Explorer also exhibits the same issue (as do GCC 11.1, 11.2, 11.3, 12.1, and 12.2)
[Bug middle-end/104151] [10/11/12/13 Regression] x86: excessive code generated for 128-bit byteswap
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104151 Barnabás Pőcze changed: What|Removed |Added CC||pobrn at protonmail dot com --- Comment #15 from Barnabás Pőcze --- Sorry, I haven't found a better issue. But I think the example below exhibits the same or a very similar issue. I would expect the following code void f(unsigned char *p, std::uint32_t x, std::uint32_t y) { p[0] = x >> 24; p[1] = x >> 16; p[2] = x >> 8; p[3] = x >> 0; p[4] = y >> 24; p[5] = y >> 16; p[6] = y >> 8; p[7] = y >> 0; } to be compiled to something along the lines of f(unsigned char*, unsigned int, unsigned int): bswap esi bswap edx mov DWORD PTR [rdi], esi mov DWORD PTR [rdi+4], edx ret however, I get scores of bitwise operations instead if `-fno-tree-vectorize` is not specified. https://gcc.godbolt.org/z/z51K6qorv
[Bug sanitizer/95137] Sanitizers seem to be missing support for coroutines
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95137 Barnabás Pőcze changed: What|Removed |Added CC||pobrn at protonmail dot com --- Comment #46 from Barnabás Pőcze --- (In reply to stream009 from comment #42) > I got strange compile error when I use coroutine with UBSAN. > > The weird thing is error is reported in compile time not runtime. > The code compile fine without UBSAN. > [...] > === begin compile error === > : In function 'void _Z5errori.actor(error(int)::_Z5errori.frame*)': > :21:9: warning: '' may be used uninitialized > [-Wmaybe-uninitialized] >21 | co_return; > | ^ > :21:9: note: '' was declared here >21 | co_return; > | ^ > === end compile error === I am not familiar with the internals of gcc at all, but it appears that this is due to incorrect code generation. When ubsan is not used, the generated gimple looks like this: if (_13 == 0) goto ; else goto ; : _14 = &frame_ptr->__p; result::promise_type::return_void (_14); goto final.suspend; : _15 = &frame_ptr->__p; result::promise_type::return_void (_15); when ubsan is used, however: if (_8 == 0) goto ; else goto ; : D.9938 = &frame_ptr->__p; .UBSAN_NULL (D.9938, 4B, 0); result::promise_type::return_void (D.9938); goto final.suspend; : .UBSAN_NULL (D.9938, 4B, 0); result::promise_type::return_void (D.9938); `D.9938` is not initialized, and I guess hence the warning. --- I have noticed that this does not happen on f6f2d6cfec1c2fe9570b98211be58329d8d7749b, so out of curiosity I tried to bisect gcc: > git bisect start > # new: [f6f2d6cfec1c2fe9570b98211be58329d8d7749b] Daily bump. > git bisect new f6f2d6cfec1c2fe9570b98211be58329d8d7749b > # old: [7ca388565af176bd4efd4f8db1e5e9e11e98ef45] Update ChangeLog and > version files for release > git bisect old 7ca388565af176bd4efd4f8db1e5e9e11e98ef45 > # old: [250f234988b6231669a720c52101d3686d645072] testsuite: Fix up > gcc.target/s390/zero-scratch-regs-1.c > git bisect old 250f234988b6231669a720c52101d3686d645072 > # old: [79513dc0b2d980bfd1b109d0d502de487c02b894] compiler: don't pad > zero-sized trailing field in results struct > git bisect old 79513dc0b2d980bfd1b109d0d502de487c02b894 > # new: [1b62cddcf091fb8cadf575246a7d3ff778650a6b] Fix ipa-modref pure/const > discovery > git bisect new 1b62cddcf091fb8cadf575246a7d3ff778650a6b > # new: [247bac507e63b32d4dc23ef1c55f300aafea24c6] libstdc++: Simplify > std::basic_regex::assign > git bisect new 247bac507e63b32d4dc23ef1c55f300aafea24c6 > # new: [d5f8abe1d3f718a75cbff0a453c1d961be5939b7] Use on-demand ranges in > ssa_name_has_boolean_range before querying nonzero bits. > git bisect new d5f8abe1d3f718a75cbff0a453c1d961be5939b7 > # new: [7d79c3ebc3f3f6f8aecf83726c97474ae5cfe957] Don't record string > concatenation data for 'RESERVED_LOCATION_P' > git bisect new 7d79c3ebc3f3f6f8aecf83726c97474ae5cfe957 > # new: [8137be3958be4e5421c283cce3e5b50dbb80b84e] mips: Fix macro typo > git bisect new 8137be3958be4e5421c283cce3e5b50dbb80b84e > # old: [caef5203d64e61da506909d58890035af32a6239] Fix internal error on > pointer-to-pointer binding in LTO mode > git bisect old caef5203d64e61da506909d58890035af32a6239 > # new: [cc1e28878a228b6c4a0872e56d97ac88971b7725] libstdc++: Check for TLS > support on mingw cross-compilers > git bisect new cc1e28878a228b6c4a0872e56d97ac88971b7725 > # new: [70ee703c479081ac2ea67eb67041551216e66783] coroutines: Make proxy vars > for the function arg copies. > git bisect new 70ee703c479081ac2ea67eb67041551216e66783 > # old: [bd55fa102715c7442c050b193dadfdb5337e2377] Fix PR ada/101970 > git bisect old bd55fa102715c7442c050b193dadfdb5337e2377 > # old: [f008fd3a480e3718436156697ebe7eeb47841457] c++: Fix > __is_*constructible/assignable for templates [PR102305] > git bisect old f008fd3a480e3718436156697ebe7eeb47841457 > # old: [de07cff96abd43f6f65dcf333958899c2ec42598] c++: empty union member > activation during constexpr [PR102163] > git bisect old de07cff96abd43f6f65dcf333958899c2ec42598 > # skip: [c5a735fa9df7eca4666c8da5e51ed9c5ab7cc81a] coroutines: Expose > implementation state to the debugger. > git bisect skip c5a735fa9df7eca4666c8da5e51ed9c5ab7cc81a > # only skipped commits left to test > # possible first new commit: [70ee703c479081ac2ea67eb67041551216e66783] > coroutines: Make proxy vars for the function arg copies. > # possible first new commit: [c5a735fa9df7eca4666c8da5e51ed9c5ab7cc81a] > coroutines: Expose implementation state to the debugger. Unfortunately, when I got to c5a735fa9df7eca4666c8da5e51ed9c5ab7cc81a, it did not build; I am not sure where I had gone wrong: > g++ -std=c+
[Bug c++/108238] New: returns_nonnull attribute with auto return type fails to compile
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108238 Bug ID: 108238 Summary: returns_nonnull attribute with auto return type fails to compile Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com Target Milestone: --- See the following example code (https://gcc.godbolt.org/z/76vPhPe6z): [[gnu::returns_nonnull]] auto f() { return new int(42); } It produces the following error: :2:8: error: 'returns_nonnull' attribute on a function not returning a pointer 2 | auto f() { |^ I think this should compile.
[Bug c++/113835] New: compiling std::vector with const size in C++20 is slow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113835 Bug ID: 113835 Summary: compiling std::vector with const size in C++20 is slow Product: gcc Version: 13.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com Target Milestone: --- Consider the following code: #include const std::size_t N = 1'000'000; std::vector x(N); int main() {} Then: $ hyperfine 'g++ -std=c++20 -O2 x.cpp' 'g++ -std=c++17 -O2 x.cpp' Benchmark 1: g++ -std=c++20 -O2 x.cpp Time (mean ± σ): 4.945 s ± 0.116 s[User: 4.676 s, System: 0.229 s] Range (min … max):4.770 s … 5.178 s10 runs Benchmark 2: g++ -std=c++17 -O2 x.cpp Time (mean ± σ): 491.3 ms ± 24.0 ms[User: 440.9 ms, System: 46.3 ms] Range (min … max): 465.6 ms … 538.0 ms10 runs Summary g++ -std=c++17 -O2 x.cpp ran 10.07 ± 0.55 times faster than g++ -std=c++20 -O2 x.cpp If you remove the `const` from `N`, the runtime will be closer to C++17 levels. `-ftime-report` suggests that "constant expression evaluation" is the reason. I imagine this is related to C++20 making std::vector constexpr.
[Bug c++/115219] New: ICE on conditionally noexcept class operator delete
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115219 Bug ID: 115219 Summary: ICE on conditionally noexcept class operator delete Product: gcc Version: 14.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com Target Milestone: --- Consider the following piece of C++ code: ``` #include #include template struct B { static void * operator new(std::size_t s, std::size_t) { return ::operator new(s); } static void operator delete(void *) noexcept(std::is_nothrow_destructible_v) { } }; struct A : B { }; void test() { new (42) A(); } ``` gcc 14.1.1 and trunk (on CE) trigger the following ICE ( https://gcc.godbolt.org/z/z7av1Mf3Y ): ``` : In function 'void test()': :19:16: internal compiler error: in type_throw_all_p, at cp/except.cc:1234 19 | new (42) A(); |^ 0x268e9ac internal_error(char const*, ...) ???:0 0xa5b247 fancy_abort(char const*, int, char const*) ???:0 0xb08bb3 fnptr_conv_p(tree_node*, tree_node*) ???:0 0xaa0ae6 instantiate_type(tree_node*, tree_node*, int) ???:0 0xa75b7e build_op_delete_call(tree_code, tree_node*, tree_node*, bool, tree_node*, tree_node*, int) ???:0 0xb82ab0 build_new(unsigned int, vec**, tree_node*, tree_node*, vec**, int, int) ???:0 0xc63d8a c_parse_file() ???:0 0xdb95b9 c_common_parse_file() ???:0 ``` Removing the conditional noexcept specification makes the ICE go away. Here is a more detailed stack trace from the arch linux build of gcc (about 14.1.1): ``` Breakpoint 1, internal_error (gmsgid=gmsgid@entry=0x2b4b860 "in %s, at %s:%d") at /usr/src/debug/gcc/gcc/gcc/diagnostic.cc:2227 2227{ (gdb) bt #0 internal_error (gmsgid=gmsgid@entry=0x2b4b860 "in %s, at %s:%d") at /usr/src/debug/gcc/gcc/gcc/diagnostic.cc:2227 #1 0x00703e88 in fancy_abort (file=0x2b5c798 "/usr/src/debug/gcc/gcc/gcc/cp/except.cc", line=1234, function=0x2aa87dc "type_throw_all_p") at /usr/src/debug/gcc/gcc/gcc/diagnostic.cc:2353 #2 0x006b97f2 in type_throw_all_p (type=) at /usr/src/debug/gcc/gcc/gcc/cp/except.cc:1231 #3 type_throw_all_p (type=) at /usr/src/debug/gcc/gcc/gcc/cp/except.cc:1231 #4 noexcept_conv_p (to=0x76c24498, from=0x76a15930) at /usr/src/debug/gcc/gcc/gcc/cp/cvt.cc:2130 #5 fnptr_conv_p (to=, from=) at /usr/src/debug/gcc/gcc/gcc/cp/cvt.cc:2157 #6 0x0072a772 in instantiate_type (lhstype=0x76c24498, rhs=0x76a10690, complain=0) at /usr/src/debug/gcc/gcc/gcc/cp/class.cc:9085 #7 0x0072cede in build_op_delete_call (code=DELETE_EXPR, addr=0x76a1e1e0, size=0x76e212d0, global_p=, placement=0x76a1b340, alloc_fn=0x76de9700, complain=3) at /usr/src/debug/gcc/gcc/gcc/cp/call.cc:7893 #8 0x00804299 in build_new_1 (placement=placement@entry=0x7fffcd78, type=, nelts=, nelts@entry=0x0, init=init@entry=0x7fffcd70, globally_qualified_p=globally_qualified_p@entry=false, complain=complain@entry=3) at /usr/src/debug/gcc/gcc/gcc/cp/init.cc:3784 #9 0x008055ca in build_new (loc=64384747, placement=0x7fffcd78, type=, nelts=0x0, init=0x7fffcd70, use_global_new=0, complain=3) at /usr/src/debug/gcc/gcc/gcc/cp/init.cc:4054 #10 0x00867ab7 in cp_parser_new_expression (parser=parser@entry=0x76fb4dc8) at /usr/src/debug/gcc/gcc/gcc/cp/parser.cc:9659 #11 0x0086258b in cp_parser_unary_expression (parser=0x76fb4dc8, pidk=, address_p=, cast_p=, decltype_p=) at /usr/src/debug/gcc/gcc/gcc/cp/parser.cc:9245 #12 0x00864664 in cp_parser_binary_expression (parser=parser@entry=0x76fb4dc8, cast_p=cast_p@entry=false, no_toplevel_fold_p=no_toplevel_fold_p@entry=false, decltype_p=decltype_p@entry=false, prec=prec@entry=PREC_NOT_OPERATOR, pidk=pidk@entry=0x0) at /usr/src/debug/gcc/gcc/gcc/cp/parser.cc:10393 #13 0x008653bd in cp_parser_assignment_expression (parser=parser@entry=0x76fb4dc8, pidk=pidk@entry=0x0, cast_p=cast_p@entry=false, decltype_p=decltype_p@entry=false) at /usr/src/debug/gcc/gcc/gcc/cp/parser.cc:10737 #14 0x00865994 in cp_parser_expression (parser=parser@entry=0x76fb4dc8, pidk=pidk@entry=0x0, cast_p=cast_p@entry=false, decltype_p=decltype_p@entry=false, warn_comma_p=warn_comma_p@entry=false) at /usr/src/debug/gcc/gcc/gcc/cp/parser.cc:10903 #15 0x0086622e in cp_parser_expression_statement (parser=0x76fb4dc8, in_statement_expr=0x0) at /usr/src/debug/gcc/gcc/gcc/cp/parser.cc:13166 #16 0x00876d31 in cp_parser_statement (parser=parser@entry=0x76fb4dc8, in_statement_expr=in_statement_expr@entry=0x0, in_compound=in_compound@entry=true, if_p=if_p@entry=0x0, chain=chain@entry=0x0, loc_after_labels=loc_after_labels@entry=0x0) at /usr/src/debug/gcc/gcc/gcc/cp/parser.cc:12947 #17 0x00
[Bug c++/115219] [11/12/13/14/15 Regression] [c++17+] ICE on depdendent noexcept class operator delete
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115219 --- Comment #3 from Barnabás Pőcze --- That reduced test case compiles fine for me. On CE, too. Am I missing some compilation flags?
[Bug c++/115222] New: clang does not think libstdc++'s std::optional is nothrow destructible
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115222 Bug ID: 115222 Summary: clang does not think libstdc++'s std::optional is nothrow destructible Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com Target Milestone: --- clang and gcc disagree whether libstdc++'s std::optional is nothrow destructible when T is not. My reading of https://eel.is/c++draft/optional.dtor suggests that the destructor should be `noexcept(true)` (by omission). Consider the following piece of C++ code: ``` #include #include struct A { ~A() noexcept(false); }; static_assert(std::is_nothrow_destructible_v>); ``` the assertion passes on gcc, while it fails on clang: https://gcc.godbolt.org/z/1ndxK1avM Now I have tried to reduce the input, and arrived at something like this ( https://gcc.godbolt.org/z/orx5j1Eaf ): ``` template _Tp declval() noexcept; template inline constexpr bool is_nothrow_destructible_v = noexcept(declval<_Tp>()); template struct _Optional_payload_base { union _Storage { _Tp _M_value; } _M_payload; }; template struct _Optional_payload : _Optional_payload_base<_Tp> { ~_Optional_payload(); }; struct A { ~A() noexcept(false); }; static_assert(is_nothrow_destructible_v<_Optional_payload>); ``` The assertion passes on gcc, but fails on clang (and edg).
[Bug c++/115229] New: inconsistent `error: possibly dangling reference to a temporary`
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115229 Bug ID: 115229 Summary: inconsistent `error: possibly dangling reference to a temporary` Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com Target Milestone: --- Consider the following piece of C++ code: ``` struct A { int q; int *p; }; struct B { A value_or() { return A {}; } }; B f(); void test() { const auto& x = f().value_or(); } ``` gcc 15, 14 show the following diagnostic: ``` : In function 'void test()': :15:21: error: possibly dangling reference to a temporary [-Werror=dangling-reference] 15 | const auto& x = f().value_or(); | ^ :15:37: note: the temporary was destroyed at the end of the full expression 'f().B::value_or()' 15 | const auto& x = f().value_or(); | ^~ ``` while gcc 13 does not. Could someone help me understand why this warning is even shown? I would assume lifetime extension should extend the lifetime of the returned value as needed. Note that removing `int *p` from `A` makes the warning go away, so I am not sure if this warning has anything to do with the lifetime of the returned value, but then I am confused why the error points to `x`.
[Bug c++/115229] inconsistent `error: possibly dangling reference to a temporary`
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115229 --- Comment #2 from Barnabás Pőcze --- So because `A::p` might point into the temporary of type `B` returned by `f()`, the warning is shown? If so, why don't I get a warning if `x` is not a reference? The same potential issue is possible in that case, no?
[Bug c++/108238] auto return type and some attributes don't get along
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108238 --- Comment #5 from Barnabás Pőcze --- Based on a suggestion from Jakub Jelínek, I have tried to modify `is_late_template_attribute()` instead, but it appears that function does not run in this case.
[Bug c/80454] -Wmissing-braces wrongly warns about universal zero initializer {0}
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80454 Barnabás Pőcze changed: What|Removed |Added CC||pobrn at protonmail dot com --- Comment #7 from Barnabás Pőcze --- Created attachment 56319 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=56319&action=edit proposed patch I would like to see this fixed, so I have tried something, see the attached patch. It's a bit of a hack at the moment, and I am not sure it fixes everything (it improves the status quo in any case), any thoughts?
[Bug libstdc++/112934] New: excessive code for std::map::erase(key)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112934 Bug ID: 112934 Summary: excessive code for std::map::erase(key) Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com Target Milestone: --- It is probably expected that calling erase(key) is equivalent to or better than auto it = m.find(k); if (it != m.end()) m.erase(it); However, currently that is not the case: https://gcc.godbolt.org/z/f1Mh3bodf This is because std::map::erase(key) calls erase(key) on the underlying tree, which then uses equal_range() and tries to delete a range of iterators. This is unnecessary since a map enforces unique keys. libc++ has an __erase_unique() method on the underlying tree type to handle this, which does essentially what - I assume - most people expect erase(key) to do: https://github.com/llvm/llvm-project/blob/b88b480640f173582ffbfd2faae690f2bc895d14/libcxx/include/__tree#L2453 I believe the same applies to std::set.
[Bug sanitizer/113053] New: local variable misaligned with AddressSanitizer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113053 Bug ID: 113053 Summary: local variable misaligned with AddressSanitizer Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: sanitizer Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org, jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at gcc dot gnu.org Target Milestone: --- Created attachment 56895 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=56895&action=edit source code and tree/rtl dumps Consider the following code: #include #include struct thing { int x[5] __attribute__((aligned(64))); }; __attribute__((noinline)) void f(void *x) { assert((uintptr_t) x % 64 == 0); } int main() { struct thing t; static_assert(_Alignof(t) == 64); assert((uintptr_t) &t % 64 == 0); f(&t); } When compiled with `gcc -O2 -fsanitize=address`, the following assembly is generated: 10d0 : 10d0: 55 push rbp 10d1: 48 89 e5movrbp,rsp 10d4: 41 55 push r13 10d6: 41 54 push r12 10d8: 53 push rbx 10d9: 48 83 e4 c0 andrsp,0xffc0 10dd: 48 81 ec c0 00 00 00subrsp,0xc0 10e4: 8b 05 56 30 00 00 moveax,DWORD PTR [rip+0x3056] # 4140 <__asan_option_detect_stack_use_after_return@@Base> 10ea: 48 8d 5c 24 20 learbx,[rsp+0x20] # ? 10ef: 49 89 ddmovr13,rbx 10f2: 85 c0 test eax,eax 10f4: 0f 85 95 00 00 00 jne118f 10fa: 48 8d 05 df 0f 00 00learax,[rip+0xfdf]# 20e0 <__PRETTY_FUNCTION__.0+0x40> 1101: 49 89 dcmovr12,rbx 1104: 48 c7 03 b3 8a b5 41movQWORD PTR [rbx],0x41b58ab3 110b: 48 8d 7b 20 leardi,[rbx+0x20] # ? ... 114d: e8 ae 01 00 00 call 1300 ... 118f: bf 80 00 00 00 movedi,0x80 1194: e8 a7 fe ff ff call 1040 <__asan_stack_malloc_1@plt> 1199: 48 85 c0test rax,rax 119c: 48 0f 45 d8 cmovne rbx,rax 11a0: e9 55 ff ff ff jmp10fa Assume that stack-user-after-return detection is enabled (`ASAN_OPTIONS=detect_stack_use_after_return=1`). In that case the jump at 0x10f4 will be taken, if __asan_stack_malloc_1 returns a 64 byte aligned address, then the lea at 0x110b will add 32 to the address, making it not 64 byte aligned anymore. Now confusingly, the error cannot be reproduced on the Compiler Explorer or in the GCC docker container because the assembly is different, for example they call `__asan_stack_malloc_2`, and there is still a +64 to get the address of the variable, but it is done as a single step, not split up into two parts. But this code is generated on both current Arch Linux (GCC 13.2.1 20230801), and Ubuntu 22.04 (GCC 11.4.0-1ubuntu1~22.04). One can easily trigger this error for example in an Arch container: $ docker run --rm -it archlinux # pacman -Syu gcc nano --noconfirm # nano x.c # etc... # gcc -O2 -fsanitize=address x.c # ASAN_OPTIONS=detect_stack_use_after_return=1 ./a.out a.out: x.c:11: f: Assertion `(uintptr_t) x % 64 == 0' failed. Aborted (core dumped) GCC on Arch Linux is configured as follows: https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/blob/64b6b1ded75259ba7e9311d0e5b1ab44320b92d5/PKGBUILD#L111
[Bug other/115581] New: missed argument forwarding in lambda
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115581 Bug ID: 115581 Summary: missed argument forwarding in lambda Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: other Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com Target Milestone: --- Consider the following piece of C++ code: ``` struct thing { int x[64]; }; void g(const thing &); void f1(thing x) { g(x); } auto *f2 = +[](thing x) { g(x); }; struct f3 { void operator()(thing); }; void f3::operator()(thing x) { g(x); } ``` Checking the generated code on an x86-64 linux system at -O2, note that `f1()` and `f3::operator()()` simply "forward" their by-value arguments to `g()`: ``` f1(thing): sub rsp, 8 lea rdi, [rsp+16] callg(thing const&) add rsp, 8 ret ``` Notice that this is not done in the case of `f2`, the generated function from the lambda makes a copy of `x`: ``` f2::{lambda(thing)#1}::_FUN(thing): sub rsp, 264 movdqu xmm0, XMMWORD PTR [rsp+272] mov rdi, rsp movaps XMMWORD PTR [rsp], xmm0 movdqu xmm0, XMMWORD PTR [rsp+288] [...] movdqu xmm0, XMMWORD PTR [rsp+512] movaps XMMWORD PTR [rsp+240], xmm0 callg(thing const&) add rsp, 264 ret ``` See https://gcc.godbolt.org/z/n43a6MPjY, clang does the same copy, so maybe there is a rule in C++ that prevents this optimization and that I failed to consider?
[Bug middle-end/115581] could remove copy of struct if original otherwise not used
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115581 --- Comment #3 from Barnabás Pőcze --- Isn't your testcase a bit different? I guess my question is, why does gcc feel the need to make a local copy of a by-value argument when calling a function with a reference to it, but seemingly only in a function generated from a lambda?
[Bug c++/118632] New: 0 vs nullptr mixup in template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118632 Bug ID: 118632 Summary: 0 vs nullptr mixup in template Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: pobrn at protonmail dot com Target Milestone: --- Consider the following piece of code: #include template > * = nullptr> class Matrix {}; template void operator*(Matrix, int rgb) { Matrix{} * rgb; } -- https://gcc.godbolt.org/z/GTqMf69K4 It fails on gcc 15 with the following error: : In function 'void operator*(Matrix, int)': :7:17: error: no match for 'operator*' (operand types are 'Matrix' and 'int') [-Wtemplate-body] 7 | Matrix{} * rgb; | ~~^ :7:17: note: there is 1 candidate :6:28: note: candidate 1: 'template void operator*(Matrix, int)' 6 | template void operator*(Matrix, int rgb) { |^~~~ :6:28: note: template argument deduction/substitution failed: :7:19: note: template argument '0' does not match 'nullptr' 7 | Matrix{} * rgb; | ^~~ This does not happen with clang, msvc, or earlier gcc versions.
[Bug libstdc++/112934] excessive code for std::map::erase(key)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112934 --- Comment #5 from Barnabás Pőcze --- If I'm not mistaken, GCC 15.1 has been released, so I am wondering if the patch could now be merged?
[Bug libstdc++/112934] excessive code for std::map::erase(key)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112934 --- Comment #3 from Barnabás Pőcze --- Any idea as to when it might get merged?