[Bug c++/111419] New: Eager instantiation of function return type in concept causes compilation error
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111419 Bug ID: 111419 Summary: Eager instantiation of function return type in concept causes compilation error Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: ldionne.2 at gmail dot com Target Milestone: --- The following code fails to compile on GCC: template auto invoke(F f) -> decltype(f()); template concept invocable = requires(F&& f) { ::invoke(f); }; struct Incomplete; template struct Holder { T t; }; static_assert(invocable& ()>); It produces the following error on GCC: : In instantiation of 'struct Holder': :6:11: required from here :10:37: error: 'Holder::t' has incomplete type 10 | template struct Holder { T t; }; | ^ :9:8: note: forward declaration of 'struct Incomplete' 9 | struct Incomplete; |^~ Compiler returned: 1 My understanding is that this should be valid, because nothing actually requires instantiating the return type of `f()` here, but I'm not sufficiently well-versed in the details of concepts to know for sure. Clang and MSVC accept the code. Godbolt: https://godbolt.org/z/9G5zj47an
[Bug c++/103511] __builtin_bit_cast requires a constructor call
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103511 --- Comment #5 from Louis Dionne --- Note that my claim about TriviallyCopyable is taken from the Standard here, for reference (even though Jason probably knows this by heart :-). https://eel.is/c++draft/class.prop#1: > A trivially copyable class is a class: > (1.1) that has at least one eligible copy constructor, move constructor, copy > assignment operator, or move assignment operator ([special], > [class.copy.ctor], [class.copy.assign]), > (1.2) where each eligible copy constructor, move constructor, copy assignment > operator, and move assignment operator is trivial, and > (1.3) that has a trivial, non-deleted destructor ([class.dtor]).
[Bug c++/103511] __builtin_bit_cast requires a constructor call
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103511 Louis Dionne changed: What|Removed |Added CC||ldionne.2 at gmail dot com --- Comment #3 from Louis Dionne --- I concur with the reporter of this issue. `bit_cast` requires the types to be TriviallyCopyable. In turn, TriviallyCopyable requires (for class types) that there's at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator. It doesn't say which of those has to be valid, but at least one of those has to be valid. However, GCC's implementation of __builtin_bit_cast seems to always require at least a copy or a move constructor, which seems like a bug to me. For example, the following code should be valid IIUC, but it fails with GCC: struct CopyAssignable { CopyAssignable() = default; int value = 0; CopyAssignable(const CopyAssignable&)= delete; CopyAssignable(CopyAssignable&&) = delete; CopyAssignable& operator=(const CopyAssignable&) = default; CopyAssignable& operator=(CopyAssignable&&) = delete; }; struct MoveAssignable { MoveAssignable() = default; int value = 0; MoveAssignable(const MoveAssignable&)= delete; MoveAssignable(MoveAssignable&&) = delete; MoveAssignable& operator=(const MoveAssignable&) = delete; MoveAssignable& operator=(MoveAssignable&&) = default; }; int main(int, char**) { CopyAssignable foo1; (void)__builtin_bit_cast(CopyAssignable, foo1); // doesn't work MoveAssignable foo2; (void)__builtin_bit_cast(MoveAssignable, foo2); // doesn't work } Full example on Godbolt showing that this is accepted by Clang and MSVC but rejected by GCC: https://godbolt.org/z/548YKndrK I am running into this issue while trying to fix something in libc++ here: https://reviews.llvm.org/D154613
[Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11 --- Comment #13 from Louis Dionne --- Nikolas already answered some, but just to expand on this: > But on the topic of this enhancement request, I don't see why functions > should be excluded from explicit instantiation if they're already abi-tagged. > Do you want to be able to change these functions in ABI-incompatible ways > between major revisions of the library? What we're trying to avoid here is that if a user has an explicit instantiation *declaration*, we don't want their code to start depending on the fact that some-implementation-detail-member-function exists in the class. So for example, if we have: template class vector { public: iterator begin() { ... } iterator end() { ... } void __push_back_helper(T const&) { ... } }; If the user has something like this in their code: extern template class vector; The compiler will then assume that the following methods are defined elsewhere (presumably where the explicit instantiation actually happens): iterator vector::begin(); iterator vector::end(); void vector::__push_back_helper(Foo const&); Whether those methods are ABI-tagged or not doesn't matter, the compiler will still emit code that contains external references to those methods. That's fine if we're OK with committing to these methods in the long term, but if we want to keep the flexibility of removing or changing these methods in arbitrary ways, what we really want here is for the compiler not to assume that the explicit instantiation includes these methods, and instead emit its own linkonce_odr copy in the TU (which then gets deduplicated across TUs in case the same function was defined elsewher too). Does this make sense? Regarding ABI tags, like Nikolas explained, the idea is that in most cases, users actually have a single version of libc++ in their whole program, so all the symbols from libc++ have the same ABI tag, and the linker will deduplicate everything. In case a users happens to mix versions of libc++ in different TUs, then the right thing will happen: functions with different ABI tags won't be deduplicated as-if they were token-for-token equivalent and only the functions that don't have an ABI tag will be deduplicated cause they're the same across all TUs (but we do commit to stability for those symbols).
[Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11 --- Comment #9 from Louis Dionne --- (In reply to Andrew Pinski from comment #3) > I am getting a feeling this attribute is well defined enough. > > Is it really just supposed to block explicit instantiation of templates? > Is there a decent set of testcases that can be used to match up the > implementations here? Because I suspect without those it will be implemented > slightly different. Is there anything specific you're thinking about that would be insufficiently defined? It's possible that that's the case, and if so then we can define it properly and make sure Clang/GCC are aligned on the semantics. This is quite a painful issue for libc++ on GCC since the current solution is to use `always_inline`, which has too many downsides. It used to be just an annoyance, but with the addition of libraries like `std::format`, using `always_inline` leads to a library that is literally unusable in some cases (compile times and code size just skyrockets). So yeah, we're much willing to collaborate in order to make this work.
[Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11 Louis Dionne changed: What|Removed |Added CC||ldionne.2 at gmail dot com --- Comment #1 from Louis Dionne --- I implemented the attribute in Clang and it was pretty easy for me even as a novice compiler person, so I expect it wouldn't be too hard to implement in GCC either. Removing always_inline does not only lead to better compile times, but also to better code generation and obviously a better debugging experience. We investigated various other alternatives that wouldn't require using the attribute but we concluded that we really had to if we wanted to keep a tight grip on our ABI surface while still allowing users to explicitly instantiate stdlib classes (which they are allowed to as long as they provide at least one user-defined type).
[Bug bootstrap/107795] recursion through breaks non-GNU implementations of the C++ stdlib
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107795 --- Comment #13 from Louis Dionne --- Let me rephrase my whole request here. I understand that what GCC does work for GCC and GCC-adjacent projects. This report is about making the behavior of more friendly to implementations that are not GCC-adjacent and that need to build on top of the GCC machinery. Those implementations expect that they can include_next GCC headers and that no crazy magic is required to make that work, an expectation that is not met at the moment. Is GCC interested in doing that? If not, you can close this bug as "not to be fixed". Frankly, I do hope there's such a desire, since on our side we (Clang and libc++) do try to be "friendly" to GCC/libstdc++. For example, Clang is careful to implement attributes and match GCC behavior, and libc++ similarly tries to match libstdc++ behavior and ensures that it works on GCC. This results in a better ecosystem for everyone, but it can't be a one-way street. If you don't want to even consider fixing this "because it's not a problem within the GCC stack", there's nothing I can do about it, but I think that would be a poor decision. If there's a technical reason why this can't or shouldn't be done, I'm all ears.
[Bug bootstrap/107795] recursion through breaks non-GNU implementations of the C++ stdlib
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107795 --- Comment #11 from Louis Dionne --- (In reply to Andrew Pinski from comment #9) > > GCC version specific includes > GCC version specific fixincludes > C library > includes > > That is for C. > C++ is: > libstdc++ library includes > ... (rest same as C). Okay, that's great. That's exactly what I want! I want to be able to do: libc++ library includes > ... (rest same as C) What I'm trying to say is precisely that this doesn't work as intended today, because somewhere inside "rest same as C", a header is taking for granted that libstdc++ does NOT implement a header. If it did, then libstdc++ would get the same issue that we are having. Is there a reason why GCC needs to indirect through and recursively include , telling it to recurse using _GCC_NEXT_LIMITS_H?
[Bug bootstrap/107795] recursion through breaks non-GNU implementations of the C++ stdlib
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107795 --- Comment #8 from Louis Dionne --- (In reply to Andrew Pinski from comment #5) > (In reply to Louis Dionne from comment #4) > > (In reply to Andrew Pinski from comment #2) > > > You should not be building on top of GCC's limits.h header at all really. > > > Rather implementations should have their own. > > > > What do you mean by "implementations"? Do you mean implementations of the C > > library or compiler implementations, or what? > > GCC limits.h is the implementation detail of GCC. > Yes I know it gets fuzzy. This is why GCC even has fixincludes to make sure > target headers are always correct. See the comment I posted. When compiling pure C with GCC, what's the order of includes? Is it "C Library includes > GCC builtin includes", or "GCC builtin includes > C Library includes"? > If clang/libc++ wants built on top of GCC's implementation of GCC's C > implementation, then it will need to similar tricks as GCC does for other > targets. GCC does fixincludes trick to support other targets besides Linux > even. That's exactly my point -- this bug report is about removing the need to do tricks just to build on top of GCC's . None of the other headers require it AFAICT, so why does this header require it? Is there a reason not to make GCC's friendly to #include_next?
[Bug bootstrap/107795] recursion through breaks non-GNU implementations of the C++ stdlib
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107795 --- Comment #4 from Louis Dionne --- (In reply to Andrew Pinski from comment #2) > You should not be building on top of GCC's limits.h header at all really. > Rather implementations should have their own. What do you mean by "implementations"? Do you mean implementations of the C library or compiler implementations, or what? (In reply to Jonathan Wakely from comment #3) > (In reply to Andrew Pinski from comment #2) > > Rather implementations should have their own. > > Or just use GCC's one without change, which is what libstdc++ does. We don't > provide any in libstdc++, only . When you #include > with G++ you just get GCC's own as-is. Yeah but we may need to add stuff to on some platforms, so we may need to have such a header. Also, I assume you only do that for a subset of headers, because you must have headers in libstdc++ for a few headers that require adding const-correct overloads of e.g. `memchr`?
[Bug libstdc++/107795] New: recursion through breaks non-GNU implementations of the C++ stdlib
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107795 Bug ID: 107795 Summary: recursion through breaks non-GNU implementations of the C++ stdlib Product: gcc Version: 12.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: ldionne.2 at gmail dot com Target Milestone: --- The header currently includes "syslimits.h", which then recursively includes after defining the _GCC_NEXT_LIMITS_H macro. The header seems to be generated from a bunch of stuff, including `gcc/limitx.h`, which seems to be responsible for that recursive inclusion. Incidentally, this seems to not have been modified in the last 30 years. This recursive inclusion with a macro is hostile to implementations that want to build on top of GCC's header, since they need to know about that recursive inclusion trick and the _GCC_NEXT_LIMITS_H macro. For example, libc++ currently needs to know about this wrinkle and implement its own header differently depending on whether it's built with GCC or another compiler. System headers should work such that they can be layered on top of each other without needing this sort of trick. To reproduce the issue we're seeing with a minimal example: #!/usr/bin/env bash rm -rf __fake_cxx_include && mkdir -p __fake_cxx_include cat < __fake_cxx_include/limits.h #ifndef __MY_LIMITS_H #define __MY_LIMITS_H # include_next #endif EOF cat < #include EOF When running this script, the output is (on our Docker image): . /llvm/__fake_cxx_include/limits.h .. /usr/lib/gcc/x86_64-linux-gnu/12/include/limits.h ... /usr/lib/gcc/x86_64-linux-gnu/12/include/syslimits.h /llvm/__fake_cxx_include/limits.h . /usr/include/wchar.h [...] .. /usr/include/x86_64-linux-gnu/bits/wchar.h [...] .. /usr/include/x86_64-linux-gnu/bits/wchar2.h In file included from /usr/include/wchar.h:867, from :2: /usr/include/x86_64-linux-gnu/bits/wchar2.h:398:3: error: #error "Assumed value of MB_LEN_MAX wrong" 398 | # error "Assumed value of MB_LEN_MAX wrong" | ^ Because this header does not know about the GCC-internal macro _GCC_NEXT_LIMITS_H, we fail to recursively re-include and then including fails in a rather obscure way. Also note that this only fails if we're using -O2 to compile, since -O2 seems to turn on some __fortify stuff which leads to including . Long story short, it would be great if GCC's header could be simplified to avoid recursively including itself through .
[Bug libstdc++/48101] obscure error message with std::set
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48101 Louis Dionne changed: What|Removed |Added CC||ldionne.2 at gmail dot com --- Comment #12 from Louis Dionne --- FWIW, we now consider it a bug in libc++ that we accept std::allocator, and we're trying to remove that "extension".
[Bug c++/104760] Attribute [[deprecated]] causes diagnostic in never-instantiated template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104760 --- Comment #3 from Louis Dionne --- (In reply to Marek Polacek from comment #2) > And I think this is the same problem as in > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33911#c18. Not sure if we want > to change anything. Yup, I agree this is the same problem. However, see my recent comment on that bug report -- I think we should still fix this, and the resolution of PR33911 was IMO incomplete.
[Bug c++/33911] attribute deprecated vs. templates
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33911 Louis Dionne changed: What|Removed |Added CC||ldionne.2 at gmail dot com --- Comment #21 from Louis Dionne --- (In reply to Martin Sebor from comment #20) > (In reply to Jonathan Wakely from comment #16) > > Although Clang doesn't, warning for uses of a deprecated primary seems > correct/useful to me because there's no way to define a specialization of > the primary that's not deprecated. In your test case, there is no > specialization of b() that would not use some specialization of the primary > class template, and since every specialization is a use of the primary, that > would not be subject to its deprecated attribute. (It seems analogous to > warning for an unused constexpr function that can never be used in a core > constant expression.) I believe it is important to *not* diagnose when the template is never instantiated. Indeed, imagine a library is providing these declarations. It needs to keep them around for backwards compatibility, but it also wants to mark them as deprecated to make sure that no users actually use them. With the current state of affairs, GCC will issue a warning just because the declarations exist and are marked as deprecated, even if the user doesn't actually use these declarations. This is not useful behavior -- it ends up being so noisy that the only reasonable solution is to remove deprecation warnings altogether, which defeats the whole thing. This is exactly what we're hitting with libc++ on GCC right now. I think it would be worth reconsidering the resolution of this issue to make GCC's behavior match Clang's behavior more closely. > If you feel it's important to only warn for code that's instantiated, rather > than reopening this bug I suggest opening a separate bug just for that. See https://gcc.gnu.org/PR104760.
[Bug c++/104760] New: Attribute [[deprecated]] causes diagnostic in never-instantiated template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104760 Bug ID: 104760 Summary: Attribute [[deprecated]] causes diagnostic in never-instantiated template Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: ldionne.2 at gmail dot com Target Milestone: --- When using the [[deprecated]] attribute on a class template, a diagnostic is produced even if that class template is never actually instantiated. For example, if that class template is only mentioned from another function template (which is never actually instantiated), we get a diagnostic: template struct [[deprecated]] unary_negate { explicit unary_negate(const Pred&); }; template [[deprecated]] unary_negate not1(const Pred& p) { return unary_negate(p); } We get: :8:1: warning: 'template struct unary_negate' is deprecated [-Wdeprecated-declarations] 8 | unary_negate not1(const Pred& p) { return unary_negate(p); } | ^~~~ :2:23: note: declared here 2 | struct [[deprecated]] unary_negate { | ^~~~ : In function 'unary_negate not1(const Pred&)': :8:49: warning: 'template struct unary_negate' is deprecated [-Wdeprecated-declarations] 8 | unary_negate not1(const Pred& p) { return unary_negate(p); } | ^~~~ :2:23: note: declared here 2 | struct [[deprecated]] unary_negate { | ^~~~ We are encountering this issue in libc++, where we do mark several things as [[deprecated]] (per the Standard), and those warnings fire off when the headers are used not as system headers. Any other non-system header library would have the same problem. Note that in comparison, Clang does not issue a warning in this case. It only issues a warning if we actually instantiate `not1` or `unary_negate`. Godbolt: https://godbolt.org/z/559EfKn9K
[Bug c++/70816] bogus error __builtin_strcmp is not a constant expression in a constexpr function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816 Louis Dionne changed: What|Removed |Added CC||ldionne.2 at gmail dot com --- Comment #3 from Louis Dionne --- We are having to add a workaround in libc++ to implement constexpr std::string: https://reviews.llvm.org/D115795 It would be awesome if this could be fixed! (if so, please drop us a line and we'll remove our workaround)
[Bug c++/102247] New: Overload resolution with brace-init is ambiguous when it shouldn't be
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102247 Bug ID: 102247 Summary: Overload resolution with brace-init is ambiguous when it shouldn't be Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: ldionne.2 at gmail dot com Target Milestone: --- The following code fails to compile when I believe it should succeed (https://godbolt.org/z/z9aved8Wb): #include template struct pair { template constexpr pair(U1&&, U2&&) { } }; struct BraceInit { BraceInit() = default; }; struct ExplicitBraceInit { explicit ExplicitBraceInit() = default; }; constexpr int f(pair) { return 1; } constexpr int f(pair) { return 2; } static_assert(f({{}, {}}) == 2, ""); Indeed, the error is :15:16: error: call of overloaded 'f()' is ambiguous 15 | static_assert(f({{}, {}}) == 2, ""); | ~^~ :12:15: note: candidate: 'constexpr int f(pair)' 12 | constexpr int f(pair) { return 1; } | ^ :13:15: note: candidate: 'constexpr int f(pair)' 13 | constexpr int f(pair) { return 2; } | ^ Compiler returned: 1 I think it should succeed because `f(pair)` can never be selected, since selecting it would require using the explicit constructor of `ExplicitBraceInit`. And indeed, if we try to call `f(pair)` alone, we get (https://godbolt.org/z/W33Pvnnoe): :15:16: error: converting to 'ExplicitBraceInit' from initializer list would use explicit constructor 'constexpr ExplicitBraceInit::ExplicitBraceInit()' 15 | static_assert(f({{}, {}}) == 2, ""); | ~^~ Compiler returned: 1 So I'm not sure why that overload is considered valid for overload resolution (leading to the ambiguity), but it seems like GCC itself doesn't think it's valid when there are no other candidates. Also note that Clang compiles this code without issue, calling the non-explicit BraceInit version as expected. This issue was uncovered while implementing http://wg21.link/P1951 in libc++.
[Bug c++/97675] GCC does not allow turning off the warning for exceptions being caught by an earlier handler
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675 --- Comment #3 from Louis Dionne --- Thanks a lot!
[Bug c++/97675] New: GCC does not allow turning off the warning for exceptions being caught by an earlier handler
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675 Bug ID: 97675 Summary: GCC does not allow turning off the warning for exceptions being caught by an earlier handler Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: ldionne.2 at gmail dot com Target Milestone: --- In the LLVM libc++abi test suite, we test that an exception of type 'Child' is being caught by an earlier handler of type 'Base'. As a result, GCC (and Clang) produce a warning saying that the later catch clause (of type 'Child') will never be used. This is fine. However, Clang allows turning off that specific warning using -Wno-exceptions (or the appropriate warning pragma). GCC doesn't provide that option, which is problematic because we compile our test suite with -Werror. The options that are left are: - To disable these tests with GCC altogether - To disable -Werror on these tests Instead, it would be nice if GCC allowed controlling that warning (and perhaps other related warnings I'm not aware of) using a compiler flag. Reproducer: cat <: In function 'int main()': :6:5: warning: exception of type 'Child' will be caught :5:5: warning:by earlier handler for 'Base' Expectation: Some warning flag (e.g. -Wno-exceptions) allows turning off that warning.