[Bug c++/94252] New: Can't use a lambda in a requires expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94252 Bug ID: 94252 Summary: Can't use a lambda in a requires expression Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This program: auto f = []{ return 0; }; static_assert(requires { f(); }); Fails to compile on trunk (https://godbolt.org/z/DEuoVM), with the error: :2:15: error: static assertion failed 2 | static_assert(requires { f(); }); | ^
[Bug libstdc++/90415] [9/10 Regression] std::is_copy_constructible> is incomplete
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90415 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #11 from Barry Revzin --- Here's an interesting reduction: #include struct any { any(); any(any const&); template , class = std::enable_if_t< !std::is_same::value && std::is_copy_constructible::value #ifdef LIBSTDCXX && std::is_constructible::value #endif > > any(ValueType&& value); }; struct X { X(X const&); X(any); }; static_assert(std::is_copy_constructible_v); This compiles fine, fails if you add -DLIBSTDCXX. I laid it out this way because libstdc++ has that check but libc++ doesn't. Although, this is especially weird because in this program, there is only one instantiation of any's constructor template and it's with ValueType=X const&, which means that we're checking is_copy_constructible && is_constructible... which should be identical and yet are somehow not.
[Bug c++/95085] New: diagnostic on designated-initializer from braced-init-list could be better
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95085 Bug ID: 95085 Summary: diagnostic on designated-initializer from braced-init-list could be better Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- In this program (note the typo in the call to f): struct A { int width, height; }; void f(A); void g() { f(A{.width=1, .hieght=2}); } gcc's diagnostic is absolutely excellent: :7:20: error: field designator 'hieght' does not refer to any field in type 'A'; did you mean 'height'? f(A{.width=1, .hieght=2}); ^~ height :2:16: note: 'height' declared here int width, height; ^ However, if instead of calling f(A{...}) we instead just call f({...}) (as is common to do if the type name is meaningless and is just used as a proxy for named function arguments): struct A { int width, height; }; void f(A); void g() { f({.width=1, .hieght=2}); } then we get a much worse diagnostic: :7:5: error: no matching function for call to 'f' f({.width=1, .hieght=2}); ^ :5:6: note: candidate function not viable: cannot convert initializer list argument to 'A' void f(A); ^ Basically just: "error". Would it be possible to get the same quality of diagnostic from the named call case as it is in the just-a-braced-init-list case?
[Bug c++/95262] New: Taking address of function pointer do full concept overload resolution
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95262 Bug ID: 95262 Summary: Taking address of function pointer do full concept overload resolution Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/61941173/2069064): template int f() { return 0; } template requires true int f() { return 1; } int (*p)() = &f; gcc complains that converting the function is ambiguous even though the second overload is a better candidate than the first. clang accepts.
[Bug c++/95383] New: Poor codegen when constructing a trivial Optional
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95383 Bug ID: 95383 Summary: Poor codegen when constructing a trivial Optional Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Here is a complete example: struct nullopt_t {} inline constexpr nullopt{}; template struct Optional { struct Empty { }; union { Empty _; T value; }; bool engaged; Optional(nullopt_t) : _(), engaged(false) { } Optional(T v) : value(v), engaged(true) { } }; Optional foo(bool b) { if (b) { return 42; } return nullopt; } Optional here is a valid implementation strategy for trivial types, like int. You can see some codegen examples here: https://godbolt.org/z/KwuWzB gcc 10.1 -O2 emits: foo(bool): testdil, dil mov eax, 0 movabs rdx, 4294967338 cmovne rax, rdx ret gcc 10.1 -O3 is worse: foo(bool): xor eax, eax mov ecx, 42 testdil, dil cmovne rdx, rcx mov ecx, 1 cmovne rax, rcx movabs rcx, -1095216660481 and rdx, rcx sal rax, 32 or rax, rdx ret gcc trunk (as of today) -O2 is the same as this bad -O3 version. clang 10, on the other hand, on -O2 or -O3, emits: foo(bool):# @foo(bool) shl rdi, 32 lea rax, [rdi + 42] ret which is much better. Using std::optional instead of this Optional (https://godbolt.org/z/By-fYx) for comparison, clang emits the same code as above. gcc 10 -O3 emits a branch: foo(bool): xor eax, eax testdil, dil je .L2 mov DWORD PTR [rsp-8], 42 mov eax, 1 .L2: mov BYTE PTR [rsp-4], al mov rax, QWORD PTR [rsp-8] ret
[Bug c++/95384] New: Poor codegen cause by using base class instead of member for Optional construction
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95384 Bug ID: 95384 Summary: Poor codegen cause by using base class instead of member for Optional construction Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Following up on #95383: struct nullopt_t {} inline constexpr nullopt{}; template struct OptionalStorage { struct Empty { }; union { Empty _; T value; }; bool engaged; OptionalStorage(nullopt_t) : _(), engaged(false) { } OptionalStorage(T v) : value(v), engaged(true) { } }; template struct OptionalWithBase : OptionalStorage { using OptionalStorage::OptionalStorage; }; template struct OptionalWithMember { OptionalStorage o; OptionalWithMember(nullopt_t) : o(nullopt) { } OptionalWithMember(T v) : o(v) { } }; OptionalWithBase foo_with_base(bool b) { if (b) { return 42; } return nullopt; } OptionalWithMember foo_with_member(bool b) { if (b) { return 42; } return nullopt; } OptionalWithBase and OptionalWithMember should be the same thing. It's just that one inherits from its storage and the other has it as a member. But the codegen is very different (https://godbolt.org/z/j8m68Y), probably something to do with tail padding? gcc 10.1 -O2: foo_with_base(bool): testdil, dil je .L2 mov DWORD PTR [rsp-8], 42 mov BYTE PTR [rsp-4], 1 mov rax, QWORD PTR [rsp-8] ret .L2: mov BYTE PTR [rsp-4], 0 mov rax, QWORD PTR [rsp-8] ret foo_with_member(bool): testdil, dil mov eax, 0 movabs rdx, 4294967338 cmovne rax, rdx ret gcc 10.2 -O3 or gcc trunk -O2: foo_with_base(bool): xor eax, eax testdil, dil je .L2 mov DWORD PTR [rsp-8], 42 mov eax, 1 .L2: mov BYTE PTR [rsp-4], al mov rax, QWORD PTR [rsp-8] ret foo_with_member(bool): xor edx, edx mov ecx, 42 testdil, dil cmovne rax, rcx mov ecx, 1 cmovne rdx, rcx movabs rcx, -1095216660481 and rax, rcx sal rdx, 32 or rax, rdx ret clang 10, -O2 or -O3: foo_with_base(bool): # @foo_with_base(bool) shl rdi, 32 lea rax, [rdi + 42] ret foo_with_member(bool): # @foo_with_member(bool) shl rdi, 32 lea rax, [rdi + 42] ret
[Bug c++/95384] Poor codegen cause by using base class instead of member for Optional construction
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95384 --- Comment #1 from Barry Revzin --- Here's a simpler example: https://godbolt.org/z/FD7uEQ If the engaged member is an int instead of a bool (to remove the tail padding), gcc generates better code. This follows up on "PR 95383"
[Bug c++/95567] New: Defaulted virtual <=> has the wrong behavior
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95567 Bug ID: 95567 Summary: Defaulted virtual <=> has the wrong behavior Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from Twitter user @feder_and_ink: #include struct B { B(int i) : i(i) {} VIRTUAL std::strong_ordering operator<=>(B const& other) const = default; int i; }; struct D : B { D(int i, int j) : B(i), j(j) {} int j; }; bool check() { return B(2) == D(2, 3); } With -DVIRTUAL=, check() returns true. With -DVIRTUAL=virtual, check() erroneously returns false. On compiler explorer: https://godbolt.org/z/hc3U5f
[Bug c++/95567] Defaulted virtual <=> has the wrong behavior
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95567 --- Comment #1 from Barry Revzin --- To follow up on this, it's not the operator<=> being virtual that's significant but rather the class itself being polymorphic. This exhibits the same behavior: #include struct B { B(int i) : i(i) {} VIRTUAL ~B() = default; std::strong_ordering operator<=>(B const& other) const = default; int i; }; struct D : B { D(int i, int j) : B(i), j(j) {} int j; }; bool check() { return B(2) == D(2, 3); } https://godbolt.org/z/ZFqB59
[Bug c++/95944] New: Concept diagnostic has multiple copies of irrelevant type and displays correct type incorrectly
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95944 Bug ID: 95944 Summary: Concept diagnostic has multiple copies of irrelevant type and displays correct type incorrectly Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Consider the following heavily reduced, and incorrect, attempt at an iterator: #include template struct range { struct iterator { using reference = T; using value_type = T; auto operator*() -> T; }; }; static_assert(std::indirectly_readable::iterator>); This fails to meet the requirements of indirectly_readable because operator*() needs to be const. This is the diagnostic I get from gcc trunk: source>:13:20: error: static assertion failed 13 | static_assert(std::indirectly_readable::iterator>); | ~^ :13:20: note: constraints not satisfied In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator_base_types.h:71, from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/iterator:61, from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/ranges:44, from :1: /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/iterator_concepts.h:446:13: required for the satisfaction of '__indirectly_readable_impl::type>::type>' [with _Tp = range::iterator] /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/iterator_concepts.h:446:42: in requirements with 'const _In __in' [with _Tp = range::iterator; _Tp = range::iterator; _In = range::iterator] /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/iterator_concepts.h:451:4: note: the required expression '* __in' is invalid 451 | { *__in } -> same_as>; |^ /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/iterator_concepts.h:452:21: note: the required expression 'std::ranges::__cust::iter_move(__in)' is invalid 452 | { ranges::iter_move(__in) } -> same_as>; |~^~ cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail Compiler returned: 1 There are two especially important lines in this diagnostic: the one that indicates the failed expression and the one that indicates the type of it. The one that indicates the types is this one: /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/iterator_concepts.h:446:42: in requirements with 'const _In __in' [with _Tp = range::iterator; _Tp = range::iterator; _In = range::iterator] There is only one type in the requirement (_In) but the description starts with some type _Tp. And then we get _Tp a second time, before finally getting to _In. _In is also displayed incorrectly: it is shown as range::iterator when it should be range::iterator. Ideally this line looks closer to: /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/iterator_concepts.h:446:42: in requirements with 'const _In __in' [with _In = range::iterator]
[Bug c++/96095] New: decltype((r)) inside of lambda with copy capture gives wrong type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96095 Bug ID: 96095 Summary: decltype((r)) inside of lambda with copy capture gives wrong type Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Couldn't find a dupe for this one. The example from what is now [expr.prim.id.unqual]/2 (http://eel.is/c++draft/expr.prim.id.unqual#2) doesn't have the expected behavior: template inline constexpr bool is_same_v = false; template inline constexpr bool is_same_v = true; void f(float x, float& r) { [=] { static_assert(is_same_v); static_assert(is_same_v); static_assert(is_same_v); static_assert(is_same_v); // error }(); } gcc reports decltype((r)) to be float&, not float const& here.
[Bug c++/96142] New: is_constant_evaluated() returns false for variable with constant initialization
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96142 Bug ID: 96142 Summary: is_constant_evaluated() returns false for variable with constant initialization Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/62822725/2069064), this program: #include int main() { int i = std::is_constant_evaluated(); return i; } with gcc returns 0. But it should return 1, this basically matches the example we have in [expr.const]/14 with the initialization of p.
[Bug c++/96142] is_constant_evaluated() returns false for variable with constant initialization
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96142 Barry Revzin changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #1 from Barry Revzin --- Never mind, "constant initialization" and "constant-initialized" are actually not the same thing, gcc is correct here.
[Bug c++/96169] New: Don't provide internal lambda names in diagnostics?
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96169 Bug ID: 96169 Summary: Don't provide internal lambda names in diagnostics? Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Consider the erroneous program: #include #include template F> void call_with_ints(F); void foo() { call_with_ints([](std::string const& s){ return s.size(); }); } This (correctly) doesn't compile, but the tail end of the diagnostic we get is: In file included from :1: /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/concepts: In instantiation of 'void call_with_ints(F) [with F = foo()::]': :10:6: required from here /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/concepts:338:13: required for the satisfaction of 'invocable<_Fn, _Args ...>' [with _Fn = foo::._anon_92; _Args = {int}] /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/concepts:342:13: required for the satisfaction of 'regular_invocable' [with F = foo::._anon_92] /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/concepts:338:25: note: the expression 'is_invocable_v<_Fn, _Args ...> [with _Fn = foo::._anon_92; _Args = {int}]' evaluated to 'false' 338 | concept invocable = is_invocable_v<_Fn, _Args...>; | ^ Compiler returned: 1 The lambda is initially introduced as "foo()::" but then throughout the rest of the error is presented as "foo::._anon_92". The former is a useful descriptor, especially in this specific example where the argument the lambda takes is critical in understanding the error. The latter is not useful - it doesn't really tell me anything. Could we use the former name in diagnostics, instead of the latter?
[Bug c++/96333] Regression on concepts constraint checking
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96333 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #1 from Barry Revzin --- Shorter repro: template int f(T ); template requires true int f(T const&); int i = f(42);
[Bug c++/96411] New: erroneous "trait used in its own initializer" error when using concepts in a requirement
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96411 Bug ID: 96411 Summary: erroneous "trait used in its own initializer" error when using concepts in a requirement Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/63202619/2069064): template constexpr bool trait = true; template concept C = trait; void f(auto) { [](){ requires { C; }; }; } int main() { f(42); } This fails on gcc 10.2 with: : In instantiation of 'void f(auto:1) [with auto:1 = int]': :10:18: required from here :2:31: required by the constraints of 'template concept C' :2:35: error: the value of 'trait' is not usable in a constant expression 2 | template concept C = trait; | ^~~~ :1:36: note: 'trait' used in its own initializer 1 | template constexpr bool trait = true; |^ Compiler returned: 1 But trait isn't used in its own initializer, and trait is certainly usable in a constant expression.
[Bug c++/96497] Compare std::variant with int using C++20 <=> is not a constant expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96497 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #1 from Barry Revzin --- Reduced (https://godbolt.org/z/1bY545): #include // this one is okay static_assert(std::partial_ordering(std::strong_ordering::less) < 0); // this one fails with non-constant condition static_assert(std::partial_ordering(1 <=> 2) < 0);
[Bug c++/96557] New: Diagnostics: Can you tell me why it's not a constant expression?
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96557 Bug ID: 96557 Summary: Diagnostics: Can you tell me why it's not a constant expression? Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Consider: struct X { char storage[100] = {}; char const* head = storage; }; void f() { constexpr X x = {}; } gcc correctly rejects this with: error: 'X{"", ((const char*)(& x.X::storage))}' is not a constant expression 7 | constexpr X x = {}; | ^ It'd be great if the error here actually indicated _why_ it's not a constant expression (or how to fix it). clang does a little bit better: :7:17: error: constexpr variable 'x' must be initialized by a constant expression constexpr X x = {}; ^ ~~ :7:17: note: pointer to subobject of 'x' is not a constant expression :7:17: note: declared here But ideally we get some message about specifically 'head' pointing to 'storage' and a fixup suggesting making the variable x static.
[Bug c++/96602] New: Partial ordering is ambiguous with default function arguments
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96602 Bug ID: 96602 Summary: Partial ordering is ambiguous with default function arguments Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/63390165/2069064): template constexpr int foo(int=0){ return 0; } template constexpr int foo(int=0, Args&&... args) { return 1; } static_assert(foo() == 0); gcc considers this call ambiguous. However, static_assert(foo(0) == 0); succeeds. But the presence of an explicit argument shouldn't matter here. Removing the leading, non-deduced T, gcc does accept: constexpr int foo(int=0){ return 0; } template constexpr int foo(int=0, Args&&... args) { return 1; } static_assert(foo() == 0); even without the argument. So there's some interplay here.
[Bug c++/53610] C++11: constructors accept silly initializers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53610 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #3 from Barry Revzin --- Shorter reproduction: struct S { S(int); }; S s{.why = 42}; This still compiles on trunk, even with all warnings and -pedantic. Made for a very difficult-to-track down bug, since designated initializers are a really nice way of mocking out named parameters (except when it's suddenly not).
[Bug c++/92776] New: Can't define member function out of line with non-type template parameter
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92776 Bug ID: 92776 Summary: Can't define member function out of line with non-type template parameter Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- From StackOverflow (https://stackoverflow.com/q/59163716/2069064): struct A {}; template struct B { void f(); }; template void B::f() { } On the gcc trunk on godbolt, this fails with: :9:14: error: invalid use of incomplete type 'struct B<((const A)a)>' 9 | void B::f() { } | ^ :4:8: note: declaration of 'struct B<((const A)a)>' 4 | struct B { |^ But compiles fine if you replace the declaration of A with something like "using A = int;"
[Bug c++/92974] New: diagnostic missing source information
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92974 Bug ID: 92974 Summary: diagnostic missing source information Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Here's the best reduction I was able to come up with thanks to creduce: # 1 "" 3 typedef unsigned char a; typedef unsigned b; enum { c }; class d { public: template int f(e const &, a const *, b); }; template d::f(e const &, a const *, b) { b g(c ?: g); } int h; unsigned char i; long j; class k { l() { m.f(h, &i, j); } d m; }; If you compile that snipped with -Wall -Wextra, you get: : In instantiation of ‘int d::f(const e&, const a*, b) [with e = int; a = unsigned char; b = unsigned int]’: :15:21: required from here cc1plus: warning: enumeral and non-enumeral type in conditional expression [-Wextra] The warning comes from cc1plus and has no source information attached to it. The comparison is on line 11, but the source printed is line 15 - which is the declaration of "class k". The kind of diagnostic I'd expect is (from a different reduction): reduction.cpp:4:21: warning: enumeral and non-enumeral type in conditional expression [-Wextra] 4 | void b() { long c(a ?: c); } | ~~^~~~ That is, actually pointing me to _where_ the comparison happens.
[Bug c++/92985] New: missed optimization opportunity for switch linear transformation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92985 Bug ID: 92985 Summary: missed optimization opportunity for switch linear transformation Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- From Peter Dimov on Slack: #include struct X { int x, y, z; int operator[]( std::size_t i ) const noexcept { switch( i ) { case 0: return x; case 1: return y; case 2: return z; default: __builtin_unreachable(); } } }; int f( X const& x, std::size_t i ) { return x[ i ]; } compiled with -O2 (or -O3) emits: f(X const&, unsigned long): cmp rsi, 1 je .L2 cmp rsi, 2 jne .L6 mov eax, DWORD PTR [rdi+8] ret .L2: mov eax, DWORD PTR [rdi+4] ret .L6: mov eax, DWORD PTR [rdi] ret But it should be able to just emit: mov eax, DWORD PTR [rdi+rsi*4] ret
[Bug c++/93016] New: erroneous new (nothrow_t) still throws an exception
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93016 Bug ID: 93016 Summary: erroneous new (nothrow_t) still throws an exception Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from SO (https://stackoverflow.com/q/59414654/2069064): #include int f() { int n = -1; try { int *p = new(std::nothrow) int[n]; if (!p) return 0; } catch (const std::bad_array_new_length&) { return 1; } return 2; } This function returns 1 (because the new expression throws bad_array_new_length), it should return 0 (because the "allocation function that would have been called has a non-throwing exception specification").
[Bug c++/93083] New: copy deduction rejected when doing CTAD for NTTP
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93083 Bug ID: 93083 Summary: copy deduction rejected when doing CTAD for NTTP Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced a bit from Jonathan Müller's example on Slack: using size_t = decltype(sizeof(0)); template struct string_literal { constexpr string_literal(const char*) {} string_literal(string_literal const&) = default; }; template string_literal(const char (&)[N]) -> string_literal; template struct type_string { }; template void foo() { type_string{}; } This does not compile on trunk with: : In function 'void foo()': :17:20: error: class template argument deduction failed: 17 | type_string{}; |^ :17:20: error: no matching function for call to 'string_literal(string_literal<...auto...>)' :7:5: note: candidate: 'template string_literal(const string_literal&)-> string_literal' 7 | string_literal(string_literal const&) = default; | ^~ :7:5: note: template argument deduction/substitution failed: :17:20: note: mismatched types 'const string_literal' and 'string_literal<...auto...>' 17 | type_string{}; |^ :6:15: note: candidate: 'template string_literal(const char*)-> string_literal' 6 | constexpr string_literal(const char*) {} | ^~ :6:15: note: template argument deduction/substitution failed: :17:20: note: couldn't deduce template parameter 'N' 17 | type_string{}; |^ :4:8: note: candidate: 'template string_literal(string_literal)-> string_literal' 4 | struct string_literal |^~ :4:8: note: template argument deduction/substitution failed: :17:20: note: mismatched types 'string_literal' and 'string_literal<...auto...>' 17 | type_string{}; |^ :10:1: note: candidate: 'template string_literal(const char (&)[N])-> string_literal<(N - 1)>' 10 | string_literal(const char (&)[N]) -> string_literal; | ^~ :10:1: note: template argument deduction/substitution failed: :17:20: note: mismatched types 'const char [N]' and 'string_literal<...auto...>' 17 | type_string{}; |^ This compiles fine: string_literal s = "hello"; string_literal t = s; So it's only in the NTTP context that this deduction fails to be considered properly.
[Bug c++/93107] unable to deduce initializer_list from function template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93107 --- Comment #1 from Barry Revzin --- Meant to add the StackOverflow link: https://stackoverflow.com/q/59517774/2069064
[Bug c++/93107] New: unable to deduce initializer_list from function template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93107 Bug ID: 93107 Summary: unable to deduce initializer_list from function template Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow: #include template void Task() {} auto a = &Task; auto b = { &Task }; std::initializer_list c = { &Task }; auto d = { static_cast(&Task) }; The declarations for 'a', 'c', and 'd' all compile. But the declaration for 'b' is rejected with: :7:23: error: unable to deduce 'std::initializer_list' from '{(& Task)}' 7 | auto b = { &Task }; | ^ :7:23: note: couldn't deduce template parameter 'auto' Compiler returned: 1 All four compile on clang.
[Bug libstdc++/93479] New: compare_three_way allows comparing arrays
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93479 Bug ID: 93479 Summary: compare_three_way allows comparing arrays Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This program: #include bool check(int(&x)[4], int(&y)[4]) { return std::compare_three_way{}(x, y) == 0; } Successfully compiles, with check() doing an address comparison on x and y. But compare_three_way is just the function object for <=> and x <=> y is ill-formed (gcc correctly rejects that). The check for __3way_builtin_ptr_cmp needs to reject arrays, since the expression declval() <=> declval() does not resolve to a built-in operator comparing pointers (it doesn't resolve to any operator).
[Bug c++/93480] New: Defaulted <=> doesn't expand array elements
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93480 Bug ID: 93480 Summary: Defaulted <=> doesn't expand array elements Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This example should be valid: #include struct C { int x[4]; auto operator<=>(C const&) const = default; }; bool check(C const& a, C const& b) { return (a <=> b) == 0; } a <=> b should check each array element in turn. But gcc defines C's operator<=> as deleted.
[Bug c++/91847] init-capture pack of references requires ... on wrong side
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91847 --- Comment #2 from Barry Revzin --- In the Prague meeting, this paper (https://brevzin.github.io/cpp_proposals/2095_lambda_pack_cwg/p2095r0.html) was adopted into what will become the C++20 standard, which moves the & in the grammar to the left side of the ellipses. So now I can say officially, [&...us=ts]{} is the correct spelling.
[Bug c++/93929] New: In copy elision cases, fallback to lvalue even if rvalue overload resolution succeeds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93929 Bug ID: 93929 Summary: In copy elision cases, fallback to lvalue even if rvalue overload resolution succeeds Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Example: struct X { X(); X(X const&); X(X&&) = delete; }; X make() { X a; return a; } This should be ill-formed. The rules are: > If the first overload resolution fails or was not performed, overload > resolution is performed again, considering the expression or operand as an > lvalue. and > If a best viable function exists and is unique, overload resolution succeeds > and produces it as the result. Overload resolution considering "a" as an rvalue finds the move constructor. That's successful overload resolution - we should pick it, and then reject the program (edg and msvc do this). But gcc (and clang) considers this as failing overload resolution and falls back to pick the copy constructor.
[Bug c++/93940] New: crazy codegen bug on Og with builtin_constant_p, coverage, and pthread
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93940 Bug ID: 93940 Summary: crazy codegen bug on Og with builtin_constant_p, coverage, and pthread Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This holds for gcc 8.x, 9.x, and trunk. The following program (thanks, creduce): using uint16_t = unsigned short; struct a { uint16_t b = 0; }; struct c { short d; }; class e { public: void f(); void init_session(c); }; #ifdef ADD_CONSTEXPR #define CONSTEXPR constexpr #else #define CONSTEXPR #endif auto htons = [](uint16_t s) { if CONSTEXPR (__builtin_constant_p(s)) { return uint16_t(uint16_t(s >> 8) | uint16_t(s << 8)); } else { return uint16_t(uint16_t(s >> 8) | uint16_t(s << 8)); } }; struct g { e h; void i(a k) { h.f(); auto j = c(); j.d = htons(k.b); h.init_session(j); } }; void test() { g().i({}); } The htons lambda is mimicking the htons macro, which leads with the __builtin_constant_p check before doing either a different builtin or direct asm. In this case, the __builtin_constant_p appears to be significant but the rest not so much. When compiling the above with -std=c++17 -Og -pthread --coverage, the generated asm for test() is: test(): sub rsp, 24 lock addQWORD PTR __gcov0.test()[rip], 1 lock addQWORD PTR __gcov0._ZN1g1iE1a[rip], 1 lea rdi, [rsp+15] calle::f() That's it. It only calls f(), there is no call to init_session(). On the other hand, when compiling the above with -std=c++17 -Og -pthread --coverage -DADD_CONSTEXPR, the generated asm for test() is: test(): sub rsp, 24 lock addQWORD PTR __gcov0.test()[rip], 1 lock addQWORD PTR __gcov0._ZN1g1iE1a[rip], 1 lea rdi, [rsp+15] calle::f() lock addQWORD PTR __gcov0._ZN1g1iE1a[rip+8], 1 mov esi, 0 lea rdi, [rsp+15] calle::init_session(c) lock addQWORD PTR __gcov0._ZN1g1iE1a[rip+16], 1 lock addQWORD PTR __gcov0.test()[rip+8], 1 add rsp, 24 ret It seems that this whole combination of flags (-Og, pthread, coverage) is significant, as is the fact that htons is a lambda and not a function, as are all sorts of other things. I have no idea. Link to compiler explorer: https://godbolt.org/z/6pgLF_
[Bug c++/93940] crazy codegen bug on Og with builtin_constant_p, coverage, and pthread
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93940 --- Comment #1 from Barry Revzin --- gcc 7.x has the same behavior. gcc 6.x work fine.
[Bug middle-end/93940] crazy codegen bug on Og with builtin_constant_p, coverage, and pthread
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93940 --- Comment #2 from Barry Revzin --- Slightly more reduced: https://godbolt.org/z/5R9A5g
[Bug libstdc++/93983] std::filesystem::path is not concept-friendly
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93983 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #1 from Barry Revzin --- Here's a shorter reproduction without filesystem: #include #include struct path { template ::value_type, char>> > path(Source const&); }; struct Bar { Bar(const path& p); }; #ifdef ADD_THIS static_assert(!std::constructible_from); #endif static_assert(std::copyable); If ADD_THIS isn't defined, the copyable check is a hard error. If it is defined, compiles fine. https://godbolt.org/z/FEoiwA
[Bug libstdc++/93983] std::filesystem::path is not concept-friendly
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93983 --- Comment #2 from Barry Revzin --- (From Tim) This is LWG 3244.
[Bug c++/56428] [C++11] "is not a constant expression" when comparing non-type template argument to nullptr
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56428 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #2 from Barry Revzin --- Mr. Wakely's example now passes on trunk, but this one fails: template struct Z { }; struct C { void f(); Z<&C::f == nullptr> z; }; I'm not sure incompleteness matters?
[Bug c++/88864] New: default template arguments not merged across all declarations
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88864 Bug ID: 88864 Summary: default template arguments not merged across all declarations Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Shorter repro from StackOverflow https://stackoverflow.com/q/54202462/2069064: struct B { template B(T t); }; template B::B(T t) { } B b(3); This is rejected by all versions of gcc because of an inability to deduce U.
[Bug c++/88998] New: bad codegen with mmx instructions for unordered_map
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88998 Bug ID: 88998 Summary: bad codegen with mmx instructions for unordered_map Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This program should be valid: #include #include #include [[gnu::noinline]] double prepare(int a, int b) { __m128i is = _mm_setr_epi32(a, b, 0, 0); __m128d ds =_mm_cvtepi32_pd(is); return ds[0] + ds[1]; } int main(int, char**) { double d = prepare(1, 2); std::unordered_map m; m.insert({0, 0}); m.insert({1, 1}); assert(m.load_factor() <= m.max_load_factor()); return d; } But if I use MMX instructions, the assertion triggers: $ g++ -std=c++11 -march=haswell -mtune=haswell -mavx -O3 foo.cxx && ./a.out a.out: foo.cxx:19: int main(int, char**): Assertion `m.load_factor() <= m.max_load_factor()' failed. Aborted (core dumped) Whereas it does not if I explicitly remove them: $ g++ -std=c++11 -march=haswell -mtune=haswell -mavx -mno-mmx -O3 foo.cxx && ./a.out $ Additionally, adding a call to _mm_empty() right before the return statement in prepare() fixes the issue. If you look at the load_factor(), it returns 2 (and then 3 on the next insert, etc.)
[Bug c++/89048] New: constant evaluation in trailing return type rejected
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89048 Bug ID: 89048 Summary: constant evaluation in trailing return type rejected Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This program is rejected by gcc: template struct X { }; template constexpr auto f(F f) -> X { return {}; } with: source>:3:53: error: template argument 1 is invalid 3 | template constexpr auto f(F f) -> X { return {}; } | ^ :3:53: error: template argument 1 is invalid :3:53: error: template argument 1 is invalid :3:53: error: template argument 1 is invalid :3:48: error: invalid template-id 3 | template constexpr auto f(F f) -> X { return {}; } |^ :3:51: error: use of parameter outside function body before '(' token 3 | template constexpr auto f(F f) -> X { return {}; } | ^ :3:38: error: deduced class type 'X' in function return type 3 | template constexpr auto f(F f) -> X { return {}; } | ^ :1:25: note: 'template struct X' declared here 1 | template struct X { }; | ^ Compiler returned: 1 On the other hand, this program is accepted: template struct X { }; template constexpr auto g(F f) { return X{}; } Clang accepts both. I think both programs are valid.
[Bug c++/89048] constant evaluation in trailing return type rejected
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89048 --- Comment #1 from Barry Revzin --- Actually, now I'm really not sure if this is a gcc bug, but then I really don't know what the language rule is that rejects this. Sorry for the spam, this needs some more thought.
[Bug c++/89062] New: class template argument deduction failure with parentheses
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89062 Bug ID: 89062 Summary: class template argument deduction failure with parentheses Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow https://stackoverflow.com/q/54369677/2069064: template struct Foo { Foo(T) {} }; template struct Bar { Bar(T) {}; }; Foo foo(Bar{1}); This fails with: :11:9: error: 'auto' parameter not permitted in this context Foo foo(Bar{1}); ^~~ Compiler returned: 1 Every other alternative is fine: Foo foo(Bar(1)); // ok Foo foo{Bar{1}}; // ok Foo foo{Bar(1)}; // ok Foo foo(Bar(1)); // ok Foo foo(Bar{1}); // ok Foo> foo(Bar{1}); // ok
[Bug c++/89062] class template argument deduction failure with parentheses
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89062 --- Comment #2 from Barry Revzin --- This may or may not be the same bug as https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87709, I do not know.
[Bug libstdc++/89164] New: can construct vector with non-copyable-but-trivially-copyable elements
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89164 Bug ID: 89164 Summary: can construct vector with non-copyable-but-trivially-copyable elements Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Consider (from https://stackoverflow.com/q/54498610/2069064): #include struct X { X() = default; X(const X&) = delete; }; std::vector v{X{}}; X is trivially copyable, but it isn't actually copy constructible... as a result X isn't Cpp17EmplaceConstructible into std::vector right? libstdc++ just emits a memmove anyway. libc++ rejects this.
[Bug c++/89226] New: codegen for copying a 512-bit object fails to use avx instructions
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89226 Bug ID: 89226 Summary: codegen for copying a 512-bit object fails to use avx instructions Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Consider the following example: #include // DUMB PAIR struct dumb_pair { alignas(2*sizeof(__m256i)) __m256i x[2]; }; void copy1(const dumb_pair& from, dumb_pair& to) { to = from; } // SMART PAIR struct foo512 { __m256i a; __m256i b; auto& operator=(const foo512& f) { a = f.a; b = f.b; return *this; } }; struct smart_pair { union { foo512 y; __m256i x[2]; }; smart_pair(const smart_pair& sp) { y = sp.y; } smart_pair& operator=(const smart_pair& sp) { y = sp.y; return *this; } }; void copy2(const smart_pair& from, smart_pair& to) { to = from; } when compiled with: g++ -mavx -O3 -march=corei7-avx -mtune=corei7-avx on latest gcc (either trunk or 8.2 or 7.4) emits (https://godbolt.org/z/mZj4VU): copy1(dumb_pair const&, dumb_pair&): vmovdqa xmm0, XMMWORD PTR [rdi] vmovaps XMMWORD PTR [rsi], xmm0 vmovdqa xmm1, XMMWORD PTR [rdi+16] vmovaps XMMWORD PTR [rsi+16], xmm1 vmovdqa xmm2, XMMWORD PTR [rdi+32] vmovaps XMMWORD PTR [rsi+32], xmm2 vmovdqa xmm3, XMMWORD PTR [rdi+48] vmovaps XMMWORD PTR [rsi+48], xmm3 ret copy2(smart_pair const&, smart_pair&): vmovdqa ymm0, YMMWORD PTR [rdi] vmovdqa ymm1, YMMWORD PTR [rdi+32] vmovdqa YMMWORD PTR [rsi], ymm0 vmovdqa YMMWORD PTR [rsi+32], ymm1 vzeroupper ret copy2() is better than copy1(). If we remove the user-provided copy assignment operator from foo512 (even though the user-provided implementation is the same as the default), the smart_pair code becomes the same as dumb_pair code. clang++ emits the same code in both cases: the same code as copy2() in this example.
[Bug c++/85612] New: ADL lookup with parameter pack and defaulted argument not considered ambiguous
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85612 Bug ID: 85612 Summary: ADL lookup with parameter pack and defaulted argument not considered ambiguous Product: gcc Version: 7.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Hopefully-minimal example: #ifdef WORKS template R foo(T&&...) { return 0; } #else template decltype(auto) foo(T&&...) { return 0; } #endif namespace N { struct X { }; template void foo(T&&...) = delete; } int main() { foo(N::X{}); } gcc accepts this program with -DWORKS, but this should be ambiguous between ::foo and N::foo. It correctly rejects without -DWORKS. clang rejects in both cases. The parameter pack is significant somehow too, if the parameter list were just T&& instead of T&&..., gcc rejects as ambiguous with -DWORKS too.
[Bug c++/85883] New: class template argument deduction fails in new-expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85883 Bug ID: 85883 Summary: class template argument deduction fails in new-expression Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Slightly reduced from https://stackoverflow.com/q/50478019/2069064: template struct Bar { Bar(T1, T2) { } }; int main() { auto x = Bar(1, 2); auto y = new Bar(3, 4); } The declaration of x works, the declaration of y fails with: : In function 'int main()': :10:26: error: class template argument deduction failed: auto y = new Bar(3, 4); ^ :10:26: error: no matching function for call to 'Bar()' :4:5: note: candidate: 'template Bar(T1, T2)-> Bar' Bar(T1, T2) { } ^~~ :4:5: note: template argument deduction/substitution failed: :10:26: note: candidate expects 2 arguments, 0 provided auto y = new Bar(3, 4); ^
[Bug c++/86327] New: Spurious error on non-constant expression in constexpr function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86327 Bug ID: 86327 Summary: Spurious error on non-constant expression in constexpr function Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced example from https://stackoverflow.com/q/51053280/2069064: int global = 0; constexpr int f(bool arg) { if (arg) { return 1; } return global++; } Fails on gcc trunk with: : In function 'constexpr int f(bool)': :8:1: error: the value of 'global' is not usable in a constant expression } ^ :1:5: note: 'int global' is not const int global = 0; ^~ Compiler returned: 1 But the function is fine. The near-equivalent formulation of constexpr int g(bool arg) { if (arg) { return 1; } else { return global++; } } also compiles fine.
[Bug c++/91262] New: using template type parameter after typename
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91262 Bug ID: 91262 Summary: using template type parameter after typename Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/57206006/2069064), this short example: struct Wrapper { template using type = T; }; template void foobar(typename Wrapper::template type); fails to compile with: foo.cxx:7:40: error: using template type parameter ‘Wrapper::type’ after ‘typename’ 7 | void foobar(typename Wrapper::template type); | But this is fine - just because Wrapper::type isn't dependent doesn't disallow us from using these keywords. clang accepts the example.
[Bug c++/91304] New: maybe_unused attribute ignored on variable declared in if declaration
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91304 Bug ID: 91304 Summary: maybe_unused attribute ignored on variable declared in if declaration Product: gcc Version: 9.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/57281641/2069064): int f(); void g() { if ([[maybe_unused]] int i = f()) { } } Even though i is declared [[maybe_unused]], this still emits a warning: : In function 'void g()': :5:28: warning: unused variable 'i' [-Wunused-variable] 5 | if ([[maybe_unused]] int i = f()) { } |^
[Bug c++/91319] New: Designated initializer doesn't support direct-initialization
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91319 Bug ID: 91319 Summary: Designated initializer doesn't support direct-initialization Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This currently fails to compile on trunk: struct X { explicit X() { } }; struct Aggr { X x; }; Aggr f() { return Aggr{.x{}}; } source>: In function 'Aggr f()': :10:21: error: converting to 'X' from initializer list would use explicit constructor 'X::X()' 10 | return Aggr{.x{}}; | ^ Compiler returned: 1 But it's intended to work (this is CWG 2359).
[Bug c++/91380] New: Requesting a better diagnostic for dumb include mistake
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91380 Bug ID: 91380 Summary: Requesting a better diagnostic for dumb include mistake Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- We just had an example in our codebase which did the moral equivalent of: #include "" gcc's diagnostic for this is: :1:10: fatal error: : No such file or directory 1 | #include "" | ^~ It's very subtle to notice that we accidentally used both ""s and <>s (indeed we spent a significant amount of time trying to figure out why the file couldn't be found despite definitely being there... the real example used a non-system header). clang's diagnostic for this is: :1:10: error: '' file not found, did you mean 'vector'? #include "" ^~ "vector" It's not based on knowing what vector is, it gives equivalently good diagnostics based on actually search include paths. e.g. if I put a foo.h in include/ and run clang++ -c foo.cxx -Iinclude where I'm trying to #include "" I get: foo.cxx:1:10: error: '' file not found, did you mean 'foo.h'? #include "" ^ "foo.h" This is super low priority, but I figure somebody else may have run into this problem in the past and also spent a while ripping their hair out as to why some file couldn't be found, so I thought I'd at least get it on your radar. Thank you.
[Bug c++/91380] Requesting a better diagnostic for dumb include mistake
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91380 --- Comment #3 from Barry Revzin --- In case it's at all helpful, here's the clang review that Tim found for this diagnostic: https://reviews.llvm.org/D51333
[Bug c++/91428] New: Please warn on if constexpr (std::is_constant_evaluated())
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91428 Bug ID: 91428 Summary: Please warn on if constexpr (std::is_constant_evaluated()) Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- A very common user error with std::is_constant_evaluated is to write this: #include constexpr int foo(int i) { if constexpr (std::is_constant_evaluated()) { return 42; } else { return i; } } That is, check if we're in the middle of constant evaluation with "if constexpr" instead of plain "if". This is the intuitive check to do, but unfortunately, since the condition here is manifestly constant evaluated, the result of check is unconditionally true. gcc implements this correctly - the above function is exactly equivalent to "return 42;" - but that's unlikely to be what the user intended the program to do. They likely intended to write: constexpr int foo(int i) { if (std::is_constant_evaluated()) { return 42; } else { return i; } } Can you please provide a warning for this erroneous usage?
[Bug c++/91429] New: Conditional explicit not respected with out-of-line definition
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91429 Bug ID: 91429 Summary: Conditional explicit not respected with out-of-line definition Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/57467490/2069064): using size_t = decltype(sizeof(0)); struct Str { template explicit(N > 7) Str(char const (&str)[N]); }; #ifdef OUT_OF_LINE template Str::Str(char const(&str)[N]) { } #endif Str a = "short"; Str b = "not so short"; As-is, gcc correctly rejects the construction of b (since that constructor is explicit). But with -DOUT_OF_LINE, gcc accepts.
[Bug c++/91483] New: Poor diagnostic on trying to take constexpr reference to non-static object
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91483 Bug ID: 91483 Summary: Poor diagnostic on trying to take constexpr reference to non-static object Product: gcc Version: 9.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Consider: struct X { int const& var; }; void foo() { constexpr int i = 42; constexpr X x{i}; } This is ill-formed because i doesn't have static storage duration. But the error gcc provides is: : In function 'void foo()': :7:20: error: 'const X{i}' is not a constant expression 7 | constexpr X x{i}; |^ It would be a lot nicer if the diagnostic here explained the reason that this isn't a constant expression.
[Bug c++/91548] New: Regression in constexpr evaluation of std::array
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91548 Bug ID: 91548 Summary: Regression in constexpr evaluation of std::array Product: gcc Version: 9.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- The following compiles on gcc 9.2 -std=c+=2a but fails on gcc trunk. This example is based on the implementation of std::array: using size_t = decltype(sizeof(0)); template constexpr T& impl(T const (&array)[N], size_t index) { return const_cast(array[index]); } template struct my_array { constexpr T& operator[](size_t i) { return impl(elems, i); } constexpr T const& operator[](size_t i) const { return elems[i]; } T elems[N]; }; bool f(int i) { static constexpr auto table = []() { my_array arr = {}; arr[2] = true; return arr; }(); return table[i]; } The error (https://godbolt.org/z/WKpVJa) is: : In function 'bool f(int)': :20:7: in 'constexpr' expansion of 'f(int)::{}.f(int)::()' :18:16: error: modifying a const object 'arr.my_array::operator[](2)' is not allowed in a constant expression 18 | arr[2] = true; :20:7: note: originally declared 'const' here 20 | }(); | ^ Compiler returned: 1
[Bug c++/91618] New: template-id required to friend a function template, even for a qualified-id
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91618 Bug ID: 91618 Summary: template-id required to friend a function template, even for a qualified-id Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/57730286/2069064): template void f(T); struct A { friend void ::f(A); }; gcc rejects this with: source>:4:22: error: 'void f(A)' should have been declared inside '::' 4 | friend void ::f(A); | ^ gcc accepts: template void f(T); struct A { friend void ::f<>(A); }; But [temp.friend]/1.3 says that qualified-ids can find matching function templates... I shouldn't need to provide a template-id.
[Bug c++/91847] New: init-capture pack of references requires ... on wrong side
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91847 Bug ID: 91847 Summary: init-capture pack of references requires ... on wrong side Product: gcc Version: 9.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- gcc implements the letter of the standard and allows this: template void foo(T&... ts) { [...&us=ts]{}; } While that is valid per the latest working draft, and is the wording specified in P0780R2, the direction we really want to go in is to put the ... on the other side of the &. That is, the declaration of 'us' should look the same as the declaration of 'ts'. This is CWG 2378. In other words, the correct syntax should be: template void foo(T&... ts) { [&...us=ts]{}; } clang implements the CWG 2378 rule, this issue should hopefully be resolved by the time C++20 ships.
[Bug c++/91974] New: function not sequenced before function argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91974 Bug ID: 91974 Summary: function not sequenced before function argument Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- >From StackOverflow (https://stackoverflow.com/q/58204296/2069064), reduced: extern void call(int); void a(int) { call(0); } void b(int) { call(1); } int main() { using T = void(*)(int); T f = a; f((f=b,0)); } This is a well-defined (if weird) program that should a - that is call(0). With gcc, it invokes call(1) (that is, the assignment that happens in the initialization of the function parameter happens before the load of the function itself). On -O2, the codegen is: main: sub rsp, 8 mov edi, 1 callcall(int) xor eax, eax add rsp, 8 ret
[Bug c++/91974] function not sequenced before function argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91974 --- Comment #2 from Barry Revzin --- C++17 does change this rule. expr.call/8: The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.
[Bug c++/91974] function not sequenced before function argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91974 --- Comment #4 from Barry Revzin --- Yes, sorry if that wasn't clear, this is with -std=c++17.
[Bug c++/83447] New: parameter after function parameter pack gets improperly deduced
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83447 Bug ID: 83447 Summary: parameter after function parameter pack gets improperly deduced Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This example compiles: template void foo(Args..., T ) { } int main() { foo(0); } with Args deducing as empty and T as int. But Args is a non-deduced context (http://eel.is/c++draft/temp#deduct.type-5.7). And I don't think "trailing" can be said to apply to Args here (http://eel.is/c++draft/temp#arg.explicit-3.sentence-2). The call should fail.
[Bug c++/83542] New: template deduction failure when using pack in both deduced and non-deduced contexts
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83542 Bug ID: 83542 Summary: template deduction failure when using pack in both deduced and non-deduced contexts Product: gcc Version: 7.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This example fails to compile: template struct list { }; template void foo(list, list, void(*)(T..., U...)) { } void f(int, int ) { } int main() { foo(list{}, list{}, &f); } on gcc 7.2. with: foo.cxx: In function ‘int main()’: foo.cxx:13:37: error: no matching function for call to ‘foo(list, list, void (*)(int, int))’ foo(list{}, list{}, &f); ^ foo.cxx:5:6: note: candidate: template void foo(list, list, void (*)(T ..., U ...)) void foo(list, list, void(*)(T..., U...)) ^~~ foo.cxx:5:6: note: template argument deduction/substitution failed: foo.cxx:13:37: note: inconsistent parameter pack deduction with ‘’ and ‘’ foo(list{}, list{}, &f); ^ But deduction should succeed - we can deduce T... and U... from the list<> arguments. Additionally, the error message isn't very helpful. What do the ‘’s refer to?
[Bug c++/83542] template deduction failure when using pack in both deduced and non-deduced contexts
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83542 --- Comment #1 from Barry Revzin --- This slightly different example: template struct list { }; template void foo(list, list, void(*)(T..., U)) { } void f(int, int) { } int main() { foo(list{}, list{}, &f); } fails with a different error: foo.cxx: In function ‘int main()’: foo.cxx:13:37: error: no matching function for call to ‘foo(list, list, void (*)(int, int))’ foo(list{}, list{}, &f); ^ foo.cxx:5:6: note: candidate: template void foo(list, list, void (*)(T ..., U)) void foo(list, list, void(*)(T..., U)) ^~~ foo.cxx:5:6: note: template argument deduction/substitution failed: foo.cxx:13:37: note: candidate expects 1 argument, 2 provided foo(list{}, list{}, &f); ^
[Bug c++/83614] New: deduction failure for template-template argument with trailing template parameter pack
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83614 Bug ID: 83614 Summary: deduction failure for template-template argument with trailing template parameter pack Product: gcc Version: 7.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Here's a short example: template struct X { }; template class A, typename T> struct Y { }; template class A, typename... Ts> void foo(Y ) { } template class A, typename T> void bar(Y ) { } int main() { Y y; foo(y); // error: X does not match A bar(y); // ok } The call to 'foo' should be able to deduce Ts... as {int}, but instead deduction fails and the error message complains about X not matching A (which it does). The call to 'bar' succeeds. clang compiles this.
[Bug c++/83806] New: Spurious unused-but-set-parameter with nullptr
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83806 Bug ID: 83806 Summary: Spurious unused-but-set-parameter with nullptr Product: gcc Version: 7.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This program: template bool equals(X x, Y y) { return (x == y); } int main() { const char* p = nullptr; equals(p, nullptr); } When compiled as: $ g++ -std=c++1z -Wunused-but-set-parameter bad.cxx bad.cxx: In instantiation of ‘bool equals(X, Y) [with X = const char*; Y = std::nullptr_t]’: bad.cxx:8:22: required from here bad.cxx:2:20: warning: parameter ‘y’ set but not used [-Wunused-but-set-parameter] bool equals(X x, Y y) { ^ But y is used, in a meaningful sense.
[Bug c++/89568] New: constexpr functions are implicitly noexcept
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89568 Bug ID: 89568 Summary: constexpr functions are implicitly noexcept Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Short repro: struct Y { }; bool operator<(Y a, Y b) { return false; } constexpr bool operator>(Y a, Y b) { return false; } static_assert(!noexcept(Y{} > Y{})); static_assert(!noexcept(Y{} < Y{})); Neither case should be noexcept, since neither function is marked noexcept, but the first static assertion triggers.
[Bug c++/89686] New: Lambda pack capture with pack on both sides
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89686 Bug ID: 89686 Summary: Lambda pack capture with pack on both sides Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Vittorio, the wizard of lambda+pack bugs, is at it again: https://stackoverflow.com/questions/55127906/lambda-pack-capture-with-ellipsis-on-both-sides-what-is-the-meaning template void foo(Ts... xs) { [...xs...]{}(); } int main() { foo(0, 1, 2); } gcc trunk accepts this, but it should be ill-formed - you can't have ellipses on both sides. Gotta be either simple-capture [...xs] or init-capture [...xs=xs]
[Bug c++/89989] New: missed devirtualization opportunity on final function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89989 Bug ID: 89989 Summary: missed devirtualization opportunity on final function Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Example: struct Base { virtual int foo() { return 0; } int bar() { return foo(); } }; struct Derived : Base { int foo() override final { return 1; } }; int call_foo(Derived& d) { return d.foo(); } int call_bar(Derived& d) { return d.bar(); } For call_foo, the devirtualization happens: call_foo(Derived&): mov eax, 1 ret For call_bar, gcc emits a branch to check whether 'd' is in fact a Derived: call_bar(Derived&): mov rax, QWORD PTR [rdi] mov rax, QWORD PTR [rax] cmp rax, OFFSET FLAT:Derived::foo() jne .L6 mov eax, 1 ret .L6: jmp rax But Derived::foo() is final, so there can't be any other valid behavior besides simply returning 1. Notably, if you add "int bar() { return foo(); }" to Derived as well, then call_bar also just emits "mov eax, 1".
[Bug c++/61414] enum class bitfield size-checking needs a separate warning flag controlling it
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #17 from Barry Revzin --- Hi, it's me, another programmer who would love to use enum classes in bitfields instead of having to static_cast back and forth :-) Can anybody fixup Sam's patch?
[Bug c++/78010] --Wsuggest-override reports a redundant warning on a 'final' method
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78010 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #8 from Barry Revzin --- Still happens on 9.1. This is actually worse than just a spurious warning. I want to use -Wsuggest-override, but we weren't carefully marking overrides in our code base for a long time... so I used clang-tidy's modernize-use-override check (https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-override.html) to do all the marking so that I can enable this warning. Yay tooling. clang-tidy, though, in addition to adding missing "override"s also removes redundant "virtual"s and replaces a redundant "override final" with just "final" (as Jonathan mentions in comment #2, the Core Guidelines also agree this is redundant). Which means that manual intervention is still necessary to get gcc to not warn. This is a really good warning (would've fixed at least two bugs that I've ran into in production), and we even have existing tooling to remove what would have been all the false positives via clang-tidy... just need gcc to not flag the remaining false positive cases.
[Bug c++/90413] New: Bad diagnostic when trying to copy an uncopyable type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90413 Bug ID: 90413 Summary: Bad diagnostic when trying to copy an uncopyable type Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Here's a short repro: template struct Bar { Bar() {} Bar(const Bar&) { static_assert(sizeof(T) == 1, ""); } }; template struct Foo { Foo() {} Foo(const Foo&) = default; Bar b; }; template struct Baz { Baz() {} Baz(const Baz& o) : b(o.b) {} Bar b; }; int main() { #ifdef DEFAULT Foo f; Foo g = f; #else Baz f; Baz g = f; #endif } Without -DDEFAULT, the diagnostic points to the offending line (:26 does appear in the trace): : In instantiation of 'Bar::Bar(const Bar&) [with T = int]': :17:30: required from 'Baz::Baz(const Baz&) [with T = int]' :26:18: required from here :5:33: error: static assertion failed 5 | static_assert(sizeof(T) == 1, ""); | ~~^~~~ Compiler returned: 1 With -DDEFAULT, the offending line disappears (no mention of :23 here at all)! : In instantiation of 'Bar::Bar(const Bar&) [with T = int]': :11:5: required from here :5:33: error: static assertion failed 5 | static_assert(sizeof(T) == 1, ""); | ~~^~~~ Compiler returned: 1 In larger examples, this makes it very difficult to actually find the source of error. A larger reproduction, closer to the real example we ran into: #include struct X { X(X const&) = delete; }; using Map = std::unordered_map; void copy_func(Map) {} void map_error(Map& m) { copy_func(m); } The 9.1 error is as follows (note that the line copy_func(m) appears nowhere in this trace, despite being the proximal cause of offense): In file included from /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/x86_64-linux-gnu/bits/c++allocator.h:33, from /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/bits/allocator.h:46, from /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/unordered_map:40, from :1: /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair; _Args = {const std::pair&}; _Tp = std::__detail::_Hash_node, false>]': /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/bits/alloc_traits.h:482:2: required from 'static void std::allocator_traits >::construct(std::allocator_traits >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair; _Args = {const std::pair&}; _Tp = std::__detail::_Hash_node, false>; std::allocator_traits >::allocator_type = std::allocator, false> >]' /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/bits/hashtable_policy.h:2087:36: required from 'std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type* std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...) [with _Args = {const std::pair&}; _NodeAlloc = std::allocator, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node, false>]' /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/bits/hashtable.h:1243:46: required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_Hashtable(const std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>&) [with _Key = int; _Value = std::pair; _Alloc = std::allocator >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to; _H1 = std::hash; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits]' /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/bits/unordered_map.h:181:7: required from here /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/ext/new_allocator.h:145:20: error: use of deleted function 'constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = X]' 145 | noexcept(noexcept(::new((void *)__p) |^~ 146 |_Up(std::forward<_Args>(__args)...))) |~~~ In file included from /opt/compiler-explorer/gcc-trunk-20190509/include/c++/10.0.0/unordered_map:43, from :1: /opt/comp
[Bug c++/90413] Bad diagnostic when trying to copy an uncopyable type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90413 --- Comment #1 from Barry Revzin --- clang also doesn't do this well: https://bugs.llvm.org/show_bug.cgi?id=41819
[Bug c++/78010] --Wsuggest-override reports a redundant warning on a 'final' method
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78010 --- Comment #13 from Barry Revzin --- Thanks Marek!
[Bug c++/90475] New: Diagnostic for designated initializer could be a lot better
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90475 Bug ID: 90475 Summary: Diagnostic for designated initializer could be a lot better Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- gcc 8 and 9 have made dramatic improvements in diagnostics, but here's a case where it could be a lot better: the "oops, I typoed my designated initializer" case: struct X { int i, j; }; X f() { return {.i=42, .k=17}; } emits: : In function 'X f()': :3:29: error: could not convert '{42, 17}' from '' to 'X' 3 | X f() { return {.i=42, .k=17}; } | ^ | | | Compiler returned: 1 Similarly: struct X { int i, j; }; void g(X ); void h() { g({.i=42, .k=17}); } emits: : In function 'void h()': :5:21: error: could not convert '{42, 17}' from '' to 'X' 5 | g({.i=42, .k=17}); | ^ | | | Compiler returned: 1 Would be very cool if the diagnostic could somehow point to the "k" initializer, rather than basically "I dunno what is this thing??" (obviously not the most high priority thing, just a nice to have)
[Bug c++/90769] New: Template instantiation recursion when trying to do a conversion template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90769 Bug ID: 90769 Summary: Template instantiation recursion when trying to do a conversion template Product: gcc Version: 9.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced slightly from https://stackoverflow.com/q/56470126/2069064: #include enum E {A, B}; template struct X { template = 0> constexpr X(float v); template = 0> operator OUT() const; }; #ifdef WORKS bool operator!=(X const& lhs, int) { return static_cast(lhs) == 0; } #else bool operator==(X const& lhs, int) { return static_cast(lhs) == 0; } #endif Compiling with g++ 9.1 -std=c++17, with -DWORKS this compiles fine. Without it, it fails due to reaching the max template instantiation limit. The only difference between the two cases is that one is declaring an operator== and the other is declaring an operator!=.
[Bug c++/90769] Template instantiation recursion when trying to do a conversion template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90769 --- Comment #1 from Barry Revzin --- Sorry, more reduced: #include enum E {A, B}; struct X { template = 0> constexpr X(int v); template = 0> operator OUT() const; }; #ifdef WORKS bool operator!=(X const& lhs, int) { return static_cast(lhs) == 0; } #else bool operator==(X const& lhs, int) { return static_cast(lhs) == 0; } #endif
[Bug c++/90943] New: Visiting inherited variants no longer works in 9.1
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90943 Bug ID: 90943 Summary: Visiting inherited variants no longer works in 9.1 Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Here's a short repro: #include struct V : std::variant { using std::variant::variant; }; namespace std { template <> struct variant_size : integral_constant { }; template <> struct variant_alternative<0, V> { using type = int; }; } V v = 42; int i = std::visit([](int){ return 17;}, v); This worked fine in gcc 8, but breaks in gcc 9 with: In file included from :1: /opt/compiler-explorer/gcc-9.1.0/include/c++/9.1.0/variant: In instantiation of 'constexpr const bool std::__detail::__variant::_Extra_visit_slot_needed::value': /opt/compiler-explorer/gcc-9.1.0/include/c++/9.1.0/variant:809:50: required from 'constexpr const int std::__detail::__variant::_Multi_array&&, V&), 1>::__do_cookie' /opt/compiler-explorer/gcc-9.1.0/include/c++/9.1.0/variant:821:53: required from 'struct std::__detail::__variant::_Multi_array&&, V&), 1>' /opt/compiler-explorer/gcc-9.1.0/include/c++/9.1.0/variant:1016:36: required from 'struct std::__detail::__variant::__gen_vtable&&, V&>' /opt/compiler-explorer/gcc-9.1.0/include/c++/9.1.0/variant:1637:23: required from 'constexpr decltype(auto) std::__do_visit(_Visitor&&, _Variants&& ...) [with bool __use_index = false; bool __same_return_types = true; _Visitor = ; _Variants = {V&}]' /opt/compiler-explorer/gcc-9.1.0/include/c++/9.1.0/variant:1653:24: required from 'constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = ; _Variants = {V&}]' :21:43: required from here /opt/compiler-explorer/gcc-9.1.0/include/c++/9.1.0/variant:778:5: error: incomplete type 'std::__detail::__variant::_Extra_visit_slot_needed::_Variant_never_valueless' used in nested name specifier 778 | && !_Variant_never_valueless<__remove_cvref_t<_Variant>>::value; | ^~~~ I realize that this kind of stuff isn't technically or officially sanctioned -- but doing this makes it very convenient to write an easy-to-use recursive variant without having to implement our own variant. Tim says you should call this NAD, but I'm being pretty optimistic :-)
[Bug libstdc++/90943] Visiting inherited variants no longer works in 9.1
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90943 --- Comment #2 from Barry Revzin --- What if we did something like (using pretty names for a sec): template struct _Extra_visit_slot_needed { template static bool_constant<__never_valueless<_Types...>()> __impl(const variant<_Types...>&); static false_type __impl(...); using _Variant_never_valueless = decltype(__impl(declval<_Variant>())); static constexpr bool value = (is_same_v<_Maybe_variant_cookie, __variant_cookie> || is_same_v<_Maybe_variant_cookie, __variant_idx_cookie>) && !_Variant_never_valueless::value; }; This should (modulo typos) work for real variant instantiations and also anything that inherits from some variant instantiation?
[Bug libstdc++/91007] New: stable_sort segfaults on -O3
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91007 Bug ID: 91007 Summary: stable_sort segfaults on -O3 Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/56779605/2069064): #include #include int main() { using V = std::vector; std::vector conns{ V{0,2}, V{0,2}, V{0,2}, }; std::stable_sort(conns.begin(), conns.end(), [](const V& a, const V& b){ return a[0] < b[0]; } ); } On gcc 9.1, compiled with -O3, this segfaults. With -O2 and under, it's fine. On gcc 8.3, it's fine.
[Bug c++/86439] New: CTAD with deleted copy constructor fails due to deduction-guide taking by value
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86439 Bug ID: 86439 Summary: CTAD with deleted copy constructor fails due to deduction-guide taking by value Product: gcc Version: 8.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from: https://stackoverflow.com/q/51244047/2069064 struct NC { NC() = default; NC(NC const&) = delete; NC& operator=(NC const&) = delete; }; template struct C { C(NC const&); }; C(NC) -> C<0>; int main() { NC nc; C c(nc); } clang accepts. gcc rejects this program with: : In function 'int main()': :16:11: error: class template argument deduction failed: C c(nc); ^ :16:11: error: use of deleted function 'NC::NC(const NC&)' :3:5: note: declared here NC(NC const&) = delete; ^~ :12:1: note: initializing argument 1 of 'C(NC)-> C<0>' C(NC) -> C<0>; ^ But nowhere do we need to copy NC here. CTAD doesn't require invoking the function, just picking the best viable candidate. And once we pick C<0>, actually constructing a C<0> is fine since it doesn't require a copy.
[Bug c++/86703] New: template auto fails deduction, where template int succeeds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86703 Bug ID: 86703 Summary: template auto fails deduction, where template int succeeds Product: gcc Version: 7.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced example from https://stackoverflow.com/q/51561232/2069064: struct false_type { static constexpr bool value = false; }; template // (*) -DAUTO=auto or -DAUTO=int struct true_type { static constexpr bool value = true; }; template true_type<(T::value(), void(), 0)> match_auto(int); template false_type match_auto(...); struct pass { static constexpr int value() { return 1; } }; struct fail { }; static_assert(decltype(match_auto(0))::value); static_assert(!decltype(match_auto(0))::value); With -DAUTO=int, this compiles. With -DAUTO=auto, the first static_assert (on pass) triggers (on gcc 7.3, 8.1, and trunk). There shouldn't be a difference here between int and auto. Both forms compile on clang.
[Bug c++/86818] New: injected-class-name interpreted as type instead of constructor
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86818 Bug ID: 86818 Summary: injected-class-name interpreted as type instead of constructor Product: gcc Version: 7.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- From https://stackoverflow.com/q/51621560/2069064: template using void_t = void; template struct X { static constexpr bool value = false; }; template struct X > { static constexpr bool value = true; }; struct T { }; static_assert(!X::value); According to [class.qual], I think "typename C::T" should be considered to name the constructor of C when C is T, so the assert should NOT trigger (because typename C::T is not a type, so we fallback to the primary template). This program compiles on clang, fails on gcc.
[Bug c++/86826] New: deduction fails on auto-returning function template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86826 Bug ID: 86826 Summary: deduction fails on auto-returning function template Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from: https://stackoverflow.com/q/51643222/2069064 template auto zero(T) { return 0; } template void deduce(F); void ex() { #ifdef VAR auto x = &zero; #endif #ifdef FUNC deduce(&zero); #endif } Compiling with -DVAR succeds. With -DVAR -DFUNC also succeeds. But with just -DFUNC fails: : In function 'void ex()': :9:20: error: no matching function for call to 'deduce()' deduce(&zero); ^ :2:28: note: candidate: 'template void deduce(F)' template void deduce(F); ^~ :2:28: note: template argument deduction/substitution failed: :9:20: note: couldn't deduce template parameter 'F' deduce(&zero); ^ Compiler returned: 1 If zero() didn't return auto (whether trailing return type or leading return type), code compiles fine. clang accepts.
[Bug c++/87399] New: Inconsistent determination of what is usable in a constant expression with __PRETTY_FUNCTION__
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87399 Bug ID: 87399 Summary: Inconsistent determination of what is usable in a constant expression with __PRETTY_FUNCTION__ Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from StackOverflow (https://stackoverflow.com/q/52472000/2069064): template struct X { }; constexpr int f(char const *s) { return *s; } void test() { constexpr int i = f(__PRETTY_FUNCTION__); X x; X y; } gcc accepts the declaration of x and rejects the declaration of y. clang accepts both. I am not sure, but based on my reading of [expr.const], since __PRETTY_FUNCTION__ is not defined with constexpr, we run afoul of 2.7, and both declarations of x and y should be rejected? Either way, it seems like either both should be accepted or both should be rejected.
[Bug c++/84689] New: is_invocable is true even for call operator via ambiguous base
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84689 Bug ID: 84689 Summary: is_invocable is true even for call operator via ambiguous base Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This static assert fires on gcc, it does not on clang: #include struct base { void operator()(int ) { } }; struct a : base { }; struct b : base { }; struct f: a, b { using a::operator(); using b::operator(); }; int main() { static_assert(!std::is_invocable_v); } Even though gcc reports f as being invocable with int, attempts to actually invoke it fail: int main() { f{}(4); // error: 'base' is an ambiguous base of 'f' }
[Bug c++/85149] New: False branch of if constexpr instantiated in generic lambda
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85149 Bug ID: 85149 Summary: False branch of if constexpr instantiated in generic lambda Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- On latest trunk (8.0.1), the following compiles. But with -DBUG it doesn't: template struct is_void { static constexpr bool value = false; }; template <> struct is_void { static constexpr bool value = true; }; template constexpr decltype(auto) pipeline(S source, T target) { return [=](auto... args) { if constexpr(false #ifdef BUG && is_void::value #endif ) { source(args...); return target(); } else { return target(source(args...)); } }; } int main() { pipeline([]{ return 10; }, [](int val){ return val * 10; }); } With -DBUG, the error is: prog.cc: In instantiation of 'constexpr decltype(auto) pipeline(S, T) [with S = main()::; T = main()::]': prog.cc:25:45: required from here prog.cc:16:26: error: no match for call to '(const main()::) ()' return target(); ~~^~ prog.cc:16:26: note: candidate: 'int (*)(int)' prog.cc:16:26: note: candidate expects 2 arguments, 1 provided prog.cc:25:24: note: candidate: 'main()::' [](int val){ return val * 10; }); ^ prog.cc:25:24: note: candidate expects 1 argument, 0 provided - Wrapping source and target into an aggregate instead gets you an ICE on gcc 7.3 (https://godbolt.org/g/WvzuCs): template struct is_void { static constexpr bool value = false; }; template <> struct is_void { static constexpr bool value = true; }; template struct pair { S first; T second; }; template pair(S, T) -> pair; template constexpr decltype(auto) pipeline(S&& source, T&& target) { return [callables = pair{source, target}](auto... args) { auto& [source, target] = callables; using source_return = decltype(source(args...)); if constexpr(false && is_void::value) { source(args...); return target(); } }; } void foo() { auto s = []{ return 42; }; auto t = [](int){}; auto p = pipeline(s, t); p(); }
[Bug c++/87530] New: copy elision in return statement doesn't check for rvalue reference to object type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87530 Bug ID: 87530 Summary: copy elision in return statement doesn't check for rvalue reference to object type Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Example from StackOverflow (https://stackoverflow.com/q/52662407/2069064): struct Base { }; template struct A : Base { A(); A(Base&&); }; A foo() { A v; return v; } gcc accepts this code, invoking the A(Base&&) constructor in the return statement. But the requirement in [class.copy.elision]/3 requires the first type in the selected constructor to be an rvalue reference to the object's type, which it is not.
[Bug libstdc++/87538] New: Incorrect noexcept specifier for not_fn
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87538 Bug ID: 87538 Summary: Incorrect noexcept specifier for not_fn Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Found by Edgar Rokjān (https://stackoverflow.com/q/52673235/2069064). The noexcept specifier for _Not_fn currently only checks the noexcept-ness of applying the ! operator on the return type, not of the actual call: noexcept(noexcept(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>())) As a result, this fails: #include struct X { int operator()(int); }; static_assert(!noexcept( std::not_fn(X{})(2))); While not_fn isn't actually specified to have any kind of noexcept-specifier, this one seems actively wrong - either it should propagate through the type's actual call function (so the above assert shouldn't trigger) or it should never be noexcept (likewise).
[Bug c++/87712] New: class template argument deduction fails with wrapped parentheses
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87712 Bug ID: 87712 Summary: class template argument deduction fails with wrapped parentheses Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Reduced from https://stackoverflow.com/q/52950967/2069064: template struct lit { lit(T ); }; template void operator+(lit, int); int main() { auto a = lit('b');// ok auto b = (lit('b')); // ok lit('b') + 1; // ok (lit('b')) + 1; // error: missing template arguments after 'lit' (lit('b') + 1); // ok }
[Bug c++/87712] class template argument deduction fails with wrapped parentheses
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87712 --- Comment #3 from Barry Revzin --- Didn't realize the OP had filed a bug report already.
[Bug c++/70099] New: Function found by ADL, but shouldn't be visible at point of definition
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70099 Bug ID: 70099 Summary: Function found by ADL, but shouldn't be visible at point of definition Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- The following fragment compiles on g++ 5.3.0: struct X { }; namespace foo { template void bar() { T{} < T{}; } void operator<(const X&, const X&) {} } int main() { foo::bar(); } But foo::operator<(const X&, const X&) isn't visible at the point of the definition of bar, and isn't in one of the associated namespaces of X, per [temp.dep.res].
[Bug c++/70142] New: Class members not in scope in exception-specification
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70142 Bug ID: 70142 Summary: Class members not in scope in exception-specification Product: gcc Version: 5.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- The following code fails to compile, with an error about y not being in scope: struct X { X() noexcept(noexcept(y+1)) { } int y; }; int main() { } However, [basic.scope.class]/1 says that the scope of class members includes exception-specifications.
[Bug c++/70141] [6.0 regression] template parameter not deducible in partial specialization of template inside template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70141 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #13 from Barry Revzin --- Markus - note that clang warns about the specialization, but compiles the example anyway which actually requires the selection of the supposedly unselectable specialization. This example: template struct X {}; template struct X {}; isn't related, since here T is a non-deduced context (nested-name-specifier), but OP's example is: template struct predicate::template inner> U is not in the nested-name-specifier, T is... but T isn't being deduced.
[Bug c++/41437] No access control for classes in template functions
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41437 Barry Revzin changed: What|Removed |Added CC||barry.revzin at gmail dot com --- Comment #7 from Barry Revzin --- This bug still exists in 5.3.0. For instance: class X { int mem; }; template auto foo(T) { return &X::mem; } int main() { foo(0); }
[Bug c++/70375] New: catch by value still allows explicit constructor
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70375 Bug ID: 70375 Summary: catch by value still allows explicit constructor Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- gcc 5.3.0 compiles this code: struct B { B() = default; explicit B(B const& ) { } }; struct D : B { }; int main() { try { throw D{}; } catch(B ) { } } but [except.handle]/15 says that the handler variable should be copy-initialized from the base class subobject of the exception object, which should be disallowed since the copy constructor is marked explicit.
[Bug c++/70971] New: ICE in parameter pack expansion
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70971 Bug ID: 70971 Summary: ICE in parameter pack expansion Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- This may not be totally minimal, but the following code: #include struct A {}; template struct B : A { }; template struct typelist {}; template struct tag { using type = T; }; template std::unique_ptr chooseB(typelist ) { return std::unique_ptr(new B); } template std::unique_ptr chooseB(typelist choices, Idx i, Rest... rest) { auto f = [=](auto tag){ return [=]{ return chooseB(choices, rest...); }; }; std::function()> fs[] = { f(tag{})... }; return fs[i](); } int main() { auto p = chooseB(typelist{}, 0, 1, 2); } on gcc 5.3 with g++ -std=c++1z -O2 -Wall -Wextra -Wconversion -pedantic -pthread produced (http://coliru.stacked-crooked.com/a/8dfc904ff5476477) main.cpp: In function 'std::unique_ptr chooseB(typelist, Idx, Rest ...) [with Ts = {}; Cs = {int, double, char}; Idx = int; Rest = {int, int}]': main.cpp:29:1: error: unrecognizable insn: } ^ (insn 28 19 29 2 (set (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars) (const_int -92 [0xffa4])) [65 MEM[(struct __lambda1 *)&fs + 4B]+0 S4 A32]) (reg/v 101 [ rest#0 ])) -1 (nil)) main.cpp:29:1: internal compiler error: in extract_insn, at recog.c:2287 libbacktrace could not find executable to open With -g instead of -O2 it compiles but segfaults. On clang it compiles fine.
[Bug c++/81486] New: Class template argument deduction fails with (), succeeds with {}
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81486 Bug ID: 81486 Summary: Class template argument deduction fails with (), succeeds with {} Product: gcc Version: 7.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Consider this example, simplified from https://stackoverflow.com/q/45195890/2069064: template struct C { C(T ); }; template <> struct C { }; C() -> C; int main() { auto a = C{}; // ok auto b = C(); // error } The two forms are equivalent in this context - a and b should both deduce to C. Yet, gcc accepts a and errors on b with: cannot deduce template arguments for 'C' from ()
[Bug c++/81789] New: CWG1687 performed too soon
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81789 Bug ID: 81789 Summary: CWG1687 performed too soon Product: gcc Version: 7.0.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Consider this reduced example taken from StackOverflow (https://stackoverflow.com/questions/45602368/correct-behavior-of-built-in-operator-candidates-of-the-overload-resolution-in-t): struct X { X(int*); }; struct Y { operator double(); }; int operator+(X, int); int main() { int{(int*)0 + Y()}; } gcc compiles it fine. But the built-in operator, operator+(int*, std::ptrdiff_t ) should be a better match and selected by overload resolution and THEN, as a result of CWG 1687, the expression should be considered ill-formed. However, it appears that gcc pre-rejects that overload first and instead picks the provided operator+(). clang does the opposite, preferring the builtin operator and then not rejecting it, so this program fails to compile, but for the wrong reason (due to not being able to convert int* to int).