[Bug c++/104765] New: Expression statement with a return in a lambda-parameter-default causes segfault when called in a different function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104765 Bug ID: 104765 Summary: Expression statement with a return in a lambda-parameter-default causes segfault when called in a different function Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: erich.keane at intel dot com Target Milestone: --- See this example: template void call_lambda(T&& L) { L(); } int g() { auto x = [](char c = ({return 5;'c';})){}; call_lambda(x); return 0; } int main() { return g(); } :https://godbolt.org/z/T1cs766cM Output is: during RTL pass: expand : In function 'void call_lambda(T&&) [with T = g()::&]': :3:6: internal compiler error: Segmentation fault 3 | void call_lambda(T&& L) { | ^~~ 0x217ccb9 internal_error(char const*, ...) ???:0 0x1288575 coalesce_ssa_name(_var_map*) ???:0 0x120fadb rewrite_out_of_ssa(ssaexpand*) ???:0 Please submit a full bug report, with preprocessed source (by using -freport-bug). Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. Compiler returned: 1 This gets somewhat more interesting when the return value of 'call_lambda' is non-int: https://godbolt.org/z/rE619qbz3 : In function 'long int call_lambda(T&&)': :5:1: warning: no return statement in function returning non-void [-Wreturn-type] 5 | } | ^ : In function 'long int call_lambda(T&&) [with T = g()::&]': :3:6: error: invalid conversion in return statement 3 | long call_lambda(T&& L) { | ^~~ long int int return D.2194; :3:6: internal compiler error: 'verify_gimple' failed 0x217ccb9 internal_error(char const*, ...) ???:0 0x1183efd verify_gimple_in_seq(gimple*) ???:0 0xdf13b1 gimplify_body(tree_node*, bool) ???:0 0xdf1677 gimplify_function_tree(tree_node*) ???:0 0xbf78f7 cgraph_node::analyze() ???:0 0xbfbe0d symbol_table::finalize_compilation_unit() ???:0 Please submit a full bug report, with preprocessed source (by using -freport-bug). Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. Compiler returned: 1 IMO, expression-statements in default-lambda parameters are... awkward and perhaps worth just prohibiting.
[Bug c++/94960] extern template prevents inlining of standard library objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94960 --- Comment #9 from Erich Keane --- > But in C++20 every function is 'constexpr' now, so every function is inline > anyway, right? Even the large functions that aren't good candidates for > inlining (see also PR 93008). So The 'inline' keyword has lost all meaning > in now. Do you mean 'every function in std::string'? If so, you'd know better than I. In a general case, every function is NOT 'constexpr', and that didn't pass EWG.
[Bug c++/94960] extern template prevents inlining of standard library objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94960 --- Comment #6 from Erich Keane --- (In reply to Jonathan Wakely from comment #5) > (In reply to Erich Keane from comment #3) > > As you know, "extern template" is a hint to the compiler that we don't need > > to emit the template as a way to save on compile time. > > > > Both GCC and clang will NOT instantiate these templates in O0 mode. > > However, in O1+ modes, both will actually still instantiate the templates in > > the frontend, BUT only for 'inline' functions. Basically, we're using > > 'inline' as a heuristic that there is benefit in sending these functions to > > the optimizer (basically, sacrificing the compile time gained by 'extern > > template' in exchange for a better inlining experience). > > Hmm, I've seen different behaviours for clang and g++ in this respect, with > clang inlining a lot more of std::string's members. So I'm surprised they > use the same heuristic. > > Do they both instantiate the function templates marked 'inline' even at -O1? > Presumably not at -O0. My understanding of Clang is based on a brief debugging session. My understanding of GCC's behavior here is a brief amount of time messing around on godbolt. I could very well be incorrect. > > > In the submitter's case, the std::string constructor calls "_M_construct". > > The constructor is inlined, but _M_construct is not, since it never gets to > > the optimizer. > > > > libc++ uses an __init function to do the same thing as _M_construct, however > > IT is marked inline, and thus doesn't have the problem. > > > > I believe the submitter wants to have you mark more of the functions in > > extern-templated classes 'inline' so that it matches the heuristic better. > > And that's what I don't want to do. I think it's wrong for the human to say > "inline this!" because humans are stupid (well, I am anyway). And I don't > want to have to examine the GIMPLE/asm again for every new GCC release to > decide whether 'inline' is still in the right places (and whether the answer > should be different for every different version of Clang or ICC!) > > And when I say "I don't want to" I mean "I am never ever going to". > > > I don't think that there is a good way to change the compiler itself without > > making 'extern template' absolutely meaningless. > > I absolutely disagree. > > It would still give a reduction in object file size for cases where the > compiler decides not to inline, and still make compilation much faster for > -O0 and -O1. That is fair, I guess it would slightly reduce 'link' time because of that. I doubt people would be willing to put up with the STL compiling that much slower though (which seems to be the major user of this feature in my experience). > One property of -O2 and -O3 is that we try to optimize aggressively even if > that takes a long time to compile. So we could instantiate things that have > an explicit instantiation declaration (thus doing "redundant" work) to see > if inlining them would be beneficial. That would take longer to compile, but > might produce faster code. If the heuristics decide the instantiation ends > up too big to inline, it could just discard it (because we know there's a > definition elsewhere). That is essentially what the frontends DO, except only with the 'inline' functions. If the inliner chooses to not inline it, it gets thrown out (since we've marked it 'available externally'). > If the only way to get that is to mark every function as 'inline' (and then > "trick" the compiler into doing all that extra work even at -O1?) then we > might as well add 'inline' to every single function template in and > , , etc. so they're all potential candiates > for inlining. > > And if we have to mark every single function as 'inline' then maybe the > compiler shouldn't be using it as a hint. I don't think the idea is to mark EVERY function 'inline', simply ones that are pretty tiny and really good candidates for inlining.
[Bug libstdc++/94960] extern template prevents inlining of standard library objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94960 Erich Keane changed: What|Removed |Added CC||erich.keane at intel dot com --- Comment #3 from Erich Keane --- (In reply to Jonathan Wakely from comment #2) > Please provide complete testcases, not just URLs, as required by > https://gcc.gnu.org/bugs > > #include > > int main() > { > std::string(size_t(0), 0); > } > > > I still think it's wrong for GCC to treat the 'inline' specifier as an > inlining hint. The compiler should be a better judge of inlining decisions > than the developer. > > (In reply to Andrew Pinski from comment #1) > > g:1a289fa36294627c252492e4c18d7877a7c80dc1 changed that. > > Well that commit just meant that the explicit instantiations are declared > for C++17 as well, where previously they were only declared for < C++17. It > didn't add the explicit instantiations. Hi Jon! I helped the submitter in #llvm debug this a little, so I perhaps have a better understanding of his issue: As you know, "extern template" is a hint to the compiler that we don't need to emit the template as a way to save on compile time. Both GCC and clang will NOT instantiate these templates in O0 mode. However, in O1+ modes, both will actually still instantiate the templates in the frontend, BUT only for 'inline' functions. Basically, we're using 'inline' as a heuristic that there is benefit in sending these functions to the optimizer (basically, sacrificing the compile time gained by 'extern template' in exchange for a better inlining experience). In the submitter's case, the std::string constructor calls "_M_construct". The constructor is inlined, but _M_construct is not, since it never gets to the optimizer. libc++ uses an __init function to do the same thing as _M_construct, however IT is marked inline, and thus doesn't have the problem. I believe the submitter wants to have you mark more of the functions in extern-templated classes 'inline' so that it matches the heuristic better. I don't think that there is a good way to change the compiler itself without making 'extern template' absolutely meaningless.
[Bug libstdc++/94203] New: experimental/executor and socket header issues-
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94203 Bug ID: 94203 Summary: experimental/executor and socket header issues- Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: erich.keane at intel dot com Target Milestone: --- Again detected by trying to compile these headers with clang, I get two more issues. They can be reproduced here: https://godbolt.org/z/L-UVGq though that still shows the previous version's issue with service_already_exists. First, it appears that _TgtImpl attempts to add 'const' to the return type of the overridden function: ../include/c++/10.0.1/experimental/executor:1170:2: error: return type of virtual function 'target' is not covariant with the return type of the function it overrides (class type 'const void *' is more qualified than class type 'void *' target(const std::type_info& __ti) const ^ ../include/c++/10.0.1/experimental/executor:1138:21: note: overridden virtual function is here virtual void* target(const std::type_info&) const = 0; The second issue is that socket_errc doesn't pass is_error_code_enum in __basic_socket_impl: ../include/c++/10.0.1/experimental/socket:571:9: error: no viable overloaded '=' __ec = socket_errc::already_open; ^ ~ ../include/c++/10.0.1/system_error:208:7: note: candidate template ignored: requirement 'is_error_code_enum::value' was not satisfied [with _ErrorCodeEnum = std::experimental::net::v1::socket_errc] operator=(_ErrorCodeEnum __e) noexcept ^ (it then goes on to show a bunch of other options). However, I believe this is because Clang is instantiating this check right away, but the explicit specialization for socket_errc is after it: https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/experimental/socket#L2605 In fact, clang diagnoses this as well: ../include/c++/10.0.1/experimental/socket:2606:12: error: explicit specialization of 'std::is_error_code_enum' after instantiation struct is_error_code_enum ^~ ../include/c++/10.0.1/system_error:206:26: note: implicit instantiation first required here typename enable_if::value, ^
[Bug libstdc++/94199] std::experimental::net::v1::make_service function template not instantiatable
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94199 --- Comment #4 from Erich Keane --- Thanks Jonathan!
[Bug libstdc++/94199] New: std::experimental::net::v1::make_service function template not instantiatable
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94199 Bug ID: 94199 Summary: std::experimental::net::v1::make_service function template not instantiatable Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: erich.keane at intel dot com Target Milestone: --- Discovered in Clang, since Clang diagnoses the issue without an instantiation, here is a GCC repro: https://godbolt.org/z/7guiic The function template tries to throw service_already_exists, which isn't default constructible: /opt/compiler-explorer/gcc-trunk-20200316/include/c++/10.0.1/experimental/executor:581:8: error: use of deleted function 'std::experimental::net::v1::service_already_exists::service_already_exists()' 581 | throw service_already_exists(); Clang diagnoses just attempting to #include the file: https://godbolt.org/z/yH9kNp
[Bug c++/81355] New: SegFault when using attribute target dispatch with empty parameter
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81355 Bug ID: 81355 Summary: SegFault when using attribute target dispatch with empty parameter Product: gcc Version: 7.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: erich.keane at intel dot com Target Milestone: --- This very simple repro causes a segfault: __attribute__((target("default"))) int foo() {return 99;} __attribute__((target("sse4.2",""))) int foo() {return 1;} int main() { return foo(); } As you can see, this does dispatch, and should otherwise be valid. However, the blank string causes a segfault: https://godbolt.org/g/dmuCaZ Additionally of interest, ONLY the 1st parameter to target participates in dispatch.
[Bug c++/67824] constexpr char* compare operations not constexpr, but char[] operations ARE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67824 --- Comment #3 from Erich Keane --- Don't know if it is a result of the red-hat packaging, or the .1 release, but the 3.7.1 release from here: http://llvm.org/releases/download.html seems to no longer crash.(In reply to Erich Keane from comment #2) > Don't know if it is a result of the red-hat packaging, or the .1 release, > but the 3.7.1 release from here: http://llvm.org/releases/download.html > > seems to no longer crash. Er, sorry, this is for a different bug meant for clang. Please disregard, I don't see how to delete it.
[Bug c++/67824] constexpr char* compare operations not constexpr, but char[] operations ARE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67824 --- Comment #2 from Erich Keane --- Don't know if it is a result of the red-hat packaging, or the .1 release, but the 3.7.1 release from here: http://llvm.org/releases/download.html seems to no longer crash.
[Bug c++/67824] constexpr char* compare operations not constexpr, but char[] operations ARE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67824 --- Comment #1 from Erich Keane --- I just reconfirmed this in 5.3.1 on Fedora: gcc (GCC) 5.3.1 20151207 (Red Hat 5.3.1-2) Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Error message for the previous example is: constexpr_gcc_bug.cpp: In function βint main()β: constexpr_gcc_bug.cpp:8:5: error: non-constant condition for static assertion static_assert(root2 < root2 + 1, "This fails"); ^ constexpr_gcc_bug.cpp:8:25: error: β(((const char*)"12") < (((const char*)"12") + 1u))β is not a constant expression static_assert(root2 < root2 + 1, "This fails");
[Bug c/67824] New: constexpr char* compare operations not constexpr, but char[] operations ARE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67824 Bug ID: 67824 Summary: constexpr char* compare operations not constexpr, but char[] operations ARE Product: gcc Version: 5.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: erich.keane at intel dot com Target Milestone: --- The below code reproduces this bug, found in 4.9.2, but also reproduced in 5.2.1 Version results for both: g++ (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6) Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. g++ (SUSE Linux) 5.2.1 20150721 [gcc-5-branch revision 226027] Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This code compiles correctly on clang++ 3.5 and 3.6.1. it seems that the 'root' variable below gets treated correctly, yet the root2, despite being a valid string as well, doesn't allow pointer operations on it. This is painful, since it breaks constexpr iterators on constexpr const char* items. static constexpr const char root[] = "1234"; static constexpr const char* root2 = "1234"; int main() { static_assert(root < root + 1, "This works"); static_assert(root2 < root2 + 1, "This fails"); }