[Bug c++/94252] New: Can't use a lambda in a requires expression

2020-03-21 Thread barry.revzin at gmail dot com
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

2020-03-26 Thread barry.revzin at gmail dot com
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

2020-05-12 Thread barry.revzin at gmail dot com
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

2020-05-21 Thread barry.revzin at gmail dot com
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

2020-05-28 Thread barry.revzin at gmail dot com
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

2020-05-28 Thread barry.revzin at gmail dot com
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

2020-05-28 Thread barry.revzin at gmail dot com
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

2020-06-07 Thread barry.revzin at gmail dot com
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

2020-06-09 Thread barry.revzin at gmail dot com
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

2020-06-27 Thread barry.revzin at gmail dot com
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

2020-07-07 Thread barry.revzin at gmail dot com
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

2020-07-09 Thread barry.revzin at gmail dot com
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

2020-07-09 Thread barry.revzin at gmail dot com
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?

2020-07-11 Thread barry.revzin at gmail dot com
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

2020-07-27 Thread barry.revzin at gmail dot com
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

2020-08-01 Thread barry.revzin at gmail dot com
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

2020-08-06 Thread barry.revzin at gmail dot com
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?

2020-08-10 Thread barry.revzin at gmail dot com
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

2020-08-13 Thread barry.revzin at gmail dot com
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

2019-10-24 Thread barry.revzin at gmail dot com
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

2019-12-03 Thread barry.revzin at gmail dot com
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

2019-12-17 Thread barry.revzin at gmail dot com
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

2019-12-18 Thread barry.revzin at gmail dot com
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

2019-12-19 Thread barry.revzin at gmail dot com
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

2019-12-27 Thread barry.revzin at gmail dot com
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

2019-12-30 Thread barry.revzin at gmail dot com
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

2019-12-30 Thread barry.revzin at gmail dot com
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

2020-01-28 Thread barry.revzin at gmail dot com
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

2020-01-28 Thread barry.revzin at gmail dot com
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

2020-02-15 Thread barry.revzin at gmail dot com
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

2020-02-25 Thread barry.revzin at gmail dot com
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

2020-02-25 Thread barry.revzin at gmail dot com
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

2020-02-25 Thread barry.revzin at gmail dot com
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

2020-02-25 Thread barry.revzin at gmail dot com
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

2020-02-29 Thread barry.revzin at gmail dot com
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

2020-02-29 Thread barry.revzin at gmail dot com
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

2019-01-07 Thread barry.revzin at gmail dot com
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

2019-01-15 Thread barry.revzin at gmail dot com
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

2019-01-22 Thread barry.revzin at gmail dot com
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

2019-01-24 Thread barry.revzin at gmail dot com
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

2019-01-24 Thread barry.revzin at gmail dot com
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

2019-01-25 Thread barry.revzin at gmail dot com
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

2019-01-25 Thread barry.revzin at gmail dot com
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

2019-02-02 Thread barry.revzin at gmail dot com
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

2019-02-06 Thread barry.revzin at gmail dot com
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

2018-05-02 Thread barry.revzin at gmail dot com
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

2018-05-22 Thread barry.revzin at gmail dot com
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

2018-06-26 Thread barry.revzin at gmail dot com
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

2019-07-25 Thread barry.revzin at gmail dot com
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

2019-07-30 Thread barry.revzin at gmail dot com
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

2019-08-01 Thread barry.revzin at gmail dot com
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

2019-08-06 Thread barry.revzin at gmail dot com
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

2019-08-07 Thread barry.revzin at gmail dot com
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())

2019-08-12 Thread barry.revzin at gmail dot com
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

2019-08-12 Thread barry.revzin at gmail dot com
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

2019-08-18 Thread barry.revzin at gmail dot com
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

2019-08-26 Thread barry.revzin at gmail dot com
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

2019-08-30 Thread barry.revzin at gmail dot com
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

2019-09-20 Thread barry.revzin at gmail dot com
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

2019-10-02 Thread barry.revzin at gmail dot com
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

2019-10-02 Thread barry.revzin at gmail dot com
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

2019-10-02 Thread barry.revzin at gmail dot com
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

2017-12-17 Thread barry.revzin at gmail dot com
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

2017-12-21 Thread barry.revzin at gmail dot com
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

2017-12-21 Thread barry.revzin at gmail dot com
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

2017-12-28 Thread barry.revzin at gmail dot com
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

2018-01-11 Thread barry.revzin at gmail dot com
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

2019-03-03 Thread barry.revzin at gmail dot com
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

2019-03-12 Thread barry.revzin at gmail dot com
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

2019-04-05 Thread barry.revzin at gmail dot com
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

2019-04-25 Thread barry.revzin at gmail dot com
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

2019-05-06 Thread barry.revzin at gmail dot com
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

2019-05-09 Thread barry.revzin at gmail dot com
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

2019-05-09 Thread barry.revzin at gmail dot com
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

2019-05-10 Thread barry.revzin at gmail dot com
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

2019-05-14 Thread barry.revzin at gmail dot com
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

2019-06-05 Thread barry.revzin at gmail dot com
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

2019-06-05 Thread barry.revzin at gmail dot com
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

2019-06-19 Thread barry.revzin at gmail dot com
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

2019-06-19 Thread barry.revzin at gmail dot com
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

2019-06-26 Thread barry.revzin at gmail dot com
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

2018-07-09 Thread barry.revzin at gmail dot com
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

2018-07-27 Thread barry.revzin at gmail dot com
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

2018-08-01 Thread barry.revzin at gmail dot com
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

2018-08-01 Thread barry.revzin at gmail dot com
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__

2018-09-23 Thread barry.revzin at gmail dot com
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

2018-03-03 Thread barry.revzin at gmail dot com
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

2018-03-31 Thread barry.revzin at gmail dot com
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

2018-10-05 Thread barry.revzin at gmail dot com
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

2018-10-05 Thread barry.revzin at gmail dot com
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

2018-10-23 Thread barry.revzin at gmail dot com
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

2018-10-23 Thread barry.revzin at gmail dot com
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

2016-03-05 Thread barry.revzin at gmail dot com
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

2016-03-08 Thread barry.revzin at gmail dot com
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

2016-03-08 Thread barry.revzin at gmail dot com
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

2016-03-13 Thread barry.revzin at gmail dot com
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

2016-03-23 Thread barry.revzin at gmail dot com
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

2016-05-05 Thread barry.revzin at gmail dot com
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 {}

2017-07-19 Thread barry.revzin at gmail dot com
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

2017-08-09 Thread barry.revzin at gmail dot com
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).

  1   2   3   >