[Bug c++/112455] New: befriending a lambda closure type doesn't grant access to the lambda body

2023-11-09 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112455

Bug ID: 112455
   Summary: befriending a lambda closure type doesn't grant access
to the lambda body
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase:


class C;

auto x = [](MyC *p) {
return p->n;
};

class C {
int n;
friend decltype(x);
} c;

int k = x();


This appears to be valid, and Clang, MSVC, and EDG accept, but GCC reports an
access error. The templated operator() of the lambda is a member function of a
friend of C, so should have access to C::n.

[Bug c++/111923] default argument is not treated as a complete-class context of a class

2023-10-24 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111923

--- Comment #9 from Richard Smith  ---
I don't think we intended for default arguments of class-scope lambdas to get
the same complete-class context treatment as default argument of member
functions, but the standard wording does currently seem to suggest that they do
get that treatment.

Filed https://github.com/cplusplus/CWG/issues/449 to suggest the standard
wording be fixed to match the implementations.

[Bug c++/111633] New: __restrict on a member function is permitted in an inconsistent location relative to ref-qualifiers

2023-09-28 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111633

Bug ID: 111633
   Summary: __restrict on a member function is permitted in an
inconsistent location relative to ref-qualifiers
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

GCC permits __restrict-qualified member functions. When combined with
ref-qualifiers, the __restrict is written with the cv-qualifiers instead of
after the ref-qualifier:

struct A {
  // accepted
  void f() const __restrict &;
  // rejected
  void f() const & __restrict;
};

This seems backwards to me. The `*this` parameter is of type `const &__restrict
self`, so the latter syntax seems more appropriate.

Perhaps it would make sense to accept the latter syntax, and possibly deprecate
the former? (In the case of no ref-qualifier, it might make sense to also
deprecate the case where the restrict qualifier is before or interleaved with
cv-qualifiers.)

[Bug c++/110938] [11/12/13/14 Regression] miscompile if implicit special member is deleted and mutable

2023-08-08 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110938

--- Comment #4 from Richard Smith  ---
Looks like the trait difference only happens if the templated constructor is
not deleted, but the ABI mismatch happens regardless. Possibly there are two
separate issues here?

[Bug c++/110938] New: miscompile if implicit special member is deleted in a subtle way

2023-08-07 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110938

Bug ID: 110938
   Summary: miscompile if implicit special member is deleted in a
subtle way
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase: https://godbolt.org/z/rKG8c166f

```
template struct Error {
  //static_assert(false);
  using type = T;
};

template using ArbitraryComputation = typename Error::type;

struct X {
  template X(ArbitraryComputation &) = delete;
  X(const X&) = default;
  X(X&&) = delete;
};

struct Y {
#if 0
  Y(const Y&) = default;
  Y(Y&&) = default;
#endif
  mutable X x;
  int n;
};

void print(int);

Y f();

void g() {
  print(f().n);
}
```

Uncommenting the `static_assert`, we can see that GCC never instantiates
`Error` in this example. But it must! If `ArbitraryComputation` evaluates
to `T`, then the non-trivial, templated constructor in `X` is used to copy the
member `Y::x`, so `Y` is not trivially-copyable.

This issue affects both type traits (GCC incorrectly evaluates
`__is_trivially_copyable(Y)` to true) and code generation (GCC emits `f()` as
returning in registers, which is both non-compliant with the ABI and doesn't
follow the C++ language rules because `Y` has no trivial copy or move
constructor).

If the `#if 0` is changed to `#if 1`, the problem disappears.

[Bug c++/31584] [DR502] nested enum not considered dependent

2023-06-04 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=31584

Richard Smith  changed:

   What|Removed |Added

 CC||richard-gccbugzilla@metafoo
   ||.co.uk

--- Comment #13 from Richard Smith  
---
(In reply to Andrew Pinski from comment #12)
> GCC, ICC, clang and MSVC all accept the testcase in comment #11.

I believe the testcase is valid. The instantiation of `C` looks like
this:

struct C
{
  enum Inner { c };

  template struct Dispatcher;

  template struct Dispatcher 
  { };

};

... and the template argument `c` here refers to the non-dependent enumeration
constant `C::c`.

The rule governing whether the original template `C` is valid is
[temp.res.general]/6 (https://eel.is/c++draft/temp.res.general#6), and in
particular:

> no diagnostic shall be issued for a template for which a valid specialization 
> can be generated

Because `C` has valid specializations, it's valid.

[Bug c++/110101] New: inconsistent behavior for array-to-pointer decay in constant evaluation in template argument

2023-06-02 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110101

Bug ID: 110101
   Summary: inconsistent behavior for array-to-pointer decay in
constant evaluation in template argument
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase:

template struct X {};
int arr[32];
constexpr void *id(void *p) { return p; }
void f(X) {} // #1
void f(X) {} // #2
void f(X) {} // #3

Here, the three template arguments all represent the same address, but #1 and
#3 point to the first array element whereas #2 points to the array itself.

But GCC instead says that #1 and #2 are redefinitions, and that #1/#2 and #3 do
not conflict -- and mangles #1 and #2 the same, but gives a different mangling
to #3.

It looks like the array-to-pointer conversion is not being properly handled
here.

[Bug c++/109654] unnecessary "cannot bind packed field to reference" error when referenced type has aligned(1) attribute

2023-04-28 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109654

--- Comment #2 from Richard Smith  ---
Hm, that doesn't explain why the second example I gave is accepted. But I
suppose what's happening there is probably just that the `packed` attribute is
ignored entirely for fields with alignment 1, so this behaves the same as

```
packed_int i;
int  = i;
```

... which indeed doesn't produce an error or even a warning, presumably for the
same reason (the alignment isn't part of the canonical type of i).

[Bug c++/109654] New: unnecessary "cannot bind packed field to reference" error when referenced type has aligned(1) attribute

2023-04-27 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109654

Bug ID: 109654
   Summary: unnecessary "cannot bind packed field to reference"
error when referenced type has aligned(1) attribute
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

As a workaround for people hitting #36566, I think GCC should accept cases like
this:


typedef __attribute__((aligned(1))) int packed_int;

struct __attribute__((packed)) Foo {
int i;
packed_int& get() { return i; }
};


Unfortunately GCC rejects:


:5:32: error: cannot bind packed field '((Foo*)this)->Foo::i' to
'packed_int&' {aka 'int&'}
5 | packed_int& get() { return i; }
  |


And conversely, GCC accepts this code, which has a genuine misalignment issue:


typedef __attribute__((aligned(1))) int packed_int;

struct __attribute__((packed)) Foo {
packed_int i;
int& get() { return i; }
};


I wonder if the check is mistakenly looking at the alignment of the source type
instead of the alignment of the referent of the reference type?

[Bug libstdc++/109442] Dead local copy of std::vector not removed from function

2023-04-17 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109442

--- Comment #16 from Richard Smith  
---
(In reply to Richard Biener from comment #15)
> I was specifically looking at C++20 7.6.2.7/10 to /14 (but maybe also
> others and of course the relevant parts of the delete expression).  In
> particular the extra leeway the standard provides to new/delete _expressions_
> vs. calls of the global replaceable operators directly - do the
> __builtin_operator_{new,delete} in this regard behave like new/delete
> _expressions_ or like direct calls to the operators?

They permit the same optimizations as new/delete expressions. The sections of
the C++ standard that you referred to are what the documentation for the
builtins means when it says:

"[__builtin_operator_new] allows certain optimizations that the C++ standard
does not permit for a direct function call to ::operator new (in particular,
removing new / delete pairs and merging allocations)"

> Do the builtins call one of the replaceable global new/delete operators
> and thus users can reliably override them?

If the implementation doesn't provide storage in some other way, optimize away
the allocation, or merge it with another allocation, then yes, the storage is
obtained by calling the corresponding replaceable global new/delete operators.
Per the documentation:

"A call to __builtin_operator_new(args) is exactly the same as a call to
::operator new(args), except that [text quoted above]"

> How do the builtins behave during constexpr evaluation?  new/delete
> expressions have their behavior documented in the standard.

They behave exactly like a direct call to the replaceable global allocation
function.

In Clang's implementation, direct calls to ::operator new and ::operator delete
are permitted within calls to std::allocator::allocate and
std::allocator::deallocate during constant evaluation, and are treated as
allocating or deallocating arrays of T; consequently, calls to
__builtin_operator_new and __builtin_operator_delete are permitted in the same
contexts. In all other contexts, Clang rejects such calls, because the callee
is not declared `constexpr`.

[Bug libstdc++/109442] Dead local copy of std::vector not removed from function

2023-04-16 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109442

--- Comment #14 from Richard Smith  
---
If I understand correctly, you're looking for documentation that

  __builtin_operator_new(size)

has the exact same semantics and permits the same optimizations as `::new T`
for a trivially-constructible non-array type `T` whose size is `size` and that

  __builtin_operator_delete(p)

has the exact same semantics and permits the same optimizations as `::delete p`
for a trivially-destructible non-array type `T` whose size is `size`, with `p`
of type `T*` -- and similarly for the other (aligned, nothrow) variants?

That is the intent; I can look into getting Clang's documentation updated to
say that more explicitly if that's useful to you.

[Bug c++/100825] function signature constraints are not a part of mangled name

2023-04-07 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100825

Richard Smith  changed:

   What|Removed |Added

 CC||richard-gccbugzilla@metafoo
   ||.co.uk

--- Comment #14 from Richard Smith  
---
I've proposed mangling rules on the ABI list:
https://github.com/itanium-cxx-abi/cxx-abi/issues/24#issuecomment-1491130332

We're ready to land an implementation in Clang; I would appreciate feedback
from GCC folks first, though.

[Bug c++/109422] wrong depth used for template parameter mangling for lambdas in function signatures

2023-04-05 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109422

--- Comment #1 from Richard Smith  ---
> This should instead be mangled as T_TL__

Sorry, that's wrong; the rule we ended up with would mangle this as T_TL0__.

[Bug c++/109422] New: wrong depth used for template parameter mangling for lambdas in function signatures

2023-04-05 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109422

Bug ID: 109422
   Summary: wrong depth used for template parameter mangling for
lambdas in function signatures
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase:

struct C {
  template
  void f(decltype([](T, auto) { return 0; })) {}  
};
void g() { C().f({}); }

GCC mangles f as _ZN1C1fIiEEvDTtlNS_UlT_T_E_EEE -- note that this is
mangling / numbering the lambda directly within C, which is not permitted by
http://itanium-cxx-abi.github.io/cxx-abi/abi.html#closure-types but seems like
the best choice (see https://github.com/itanium-cxx-abi/cxx-abi/issues/165).

But the mangling of the  as T_T_ is definitely wrong -- two
different template parameters should not be mangled the same. This should
instead be mangled as T_TL__ under
https://github.com/itanium-cxx-abi/cxx-abi/issues/31#issuecomment-528122117

[Bug c++/109337] c++2a test concepts4.C passes when it should fail

2023-03-29 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109337

Richard Smith  changed:

   What|Removed |Added

 CC||richard-gccbugzilla@metafoo
   ||.co.uk

--- Comment #6 from Richard Smith  ---
(In reply to Andrew Pinski from comment #5)
> (In reply to Christopher Di Bella from comment #3)
> > This is apparently a Clang bug: the RHS of `R42c` isn't evaluated because of
> > short-circuiting. Apologies for the noise and thanks for helping me work
> > through it.
> 
> No, clang and GCC disagree even on:
> ```
> template  concept A42b = true;
> template  concept R42c = A42b;
> 
> static_assert (R42c);
> ```
> 
> There is no short-circuting here.

No substitution is performed into 'Tc&' here, because normalization of R42c
produces the atomic constraint 'true' with an empty parameter mapping. So the
type 'void&' is never formed.

[Bug c++/108090] New: pack expansion of using declarations doesn't properly handle dependent conversion function names

2022-12-13 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108090

Bug ID: 108090
   Summary: pack expansion of using declarations doesn't properly
handle dependent conversion function names
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase, which I believe is valid, and other compilers accept:

template struct As { operator T(); };
template struct AsAll : As... {
  using As::operator T...;
};
AsAll x;

But GCC rejects:

:3:26: error: parameter packs not expanded with '...':
3 |   using As::operator T...;
  |  ^~~
:3:26: note: 'T'

[Bug c++/91292] Mangler incorrectly handles negative numbers in expressions

2021-09-24 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91292

--- Comment #7 from Richard Smith  ---
(In reply to Patrick Palka from comment #3)
> Hmm, but according to
> http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling.literal the
> mangling of a negative integer literal is prefixed with "n",

There is no such thing as a negative integer literal.

The ABI document says "negative integer *values* are preceded with "n""; this
case is reached when mangling fully-resolved template arguments via the

 ::= 

production, not when mangling an instantiation-dependent expression. For
example, given

template struct X {};
template void f(X, X<-1>) {}
template void f<1>(X<-1>, X<-1>);

the proper mangling is

_Z1fILi1EEv1XIXmlT_ngLi1EEES0_ILin1EE

using ngLi1E for the instantiation-dependent expression -1 and Lin1E for the
non-instantiation-dependent value -1.


(In reply to Patrick Palka from comment #4)
> And if -(1) is to be mangled the same as -1, then shouldn't
> 
>   template
>   typename std::enable_if<(int)sizeof(T) >= -(1), int>::type size1(T *t);
> 
>   template
>   typename std::enable_if<(int)sizeof(T) >= -1, int>::type size1(T *t);
> 
> be considered two declarations of the same function?  But IIUC that would
> contradict [temp.over.link]p5, which says
> 
>   Two expressions involving template parameters are considered equivalent if
> two function definitions containing the expressions would satisfy the
> one-definition rule
> 
> but IIUC the one-definition rule fails here because -1 is not the same
> (token-wise) as -(1).

These declarations are functionally-equivalent but not equivalent, so a program
is not permitted to contain both. That language rule exists in order to allow
implementations to do things like ignore parentheses in mangling, as the
Itanium C++ ABI does.

Note that parentheses are never mangled (except for a weird corner case
involving pointers to members), so if your argument were correct it would apply
very broadly. For example, that argument would imply that -1 and (-1) would
need different manglings.

[Bug c++/102071] New: crash when combining -faligned-new=N with array cookie

2021-08-25 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102071

Bug ID: 102071
   Summary: crash when combining -faligned-new=N with array cookie
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase:

struct X { ~X(); int c; };
extern int n;
X *p = new X[n];


Compiling with -faligned-new=2 gives:

:3:15: internal compiler error: tree check: expected class 'vl_exp',
have 'unary' (nop_expr) in stabilize_call, at cp/tree.c:5739
3 | X *p = new X[n];
  |   ^
0x1f2c1d9 internal_error(char const*, ...)
???:0
0x6baa59 tree_class_check_failed(tree_node const*, tree_code_class, char
const*, int, char const*)
???:0
0xab0d8d stabilize_call(tree_node*, tree_node**)
???:0
0x8e0551 build_new(unsigned int, vec**,
tree_node*, tree_node*, vec**, int, int)
???:0
0x9cffc5 c_parse_file()
???:0
0xb55092 c_common_parse_file()
???:0


FWIW, for this example, Clang passes align_val_t{max(alignof(size_t),
alignof(X))} as the alignment argument to ensure the cookie is suitably
aligned.

[Bug libstdc++/94295] use __builtin_operator_new and __builtin_operator_delete when available

2021-07-20 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295

--- Comment #8 from Richard Smith  ---
(In reply to Jonathan Wakely from comment #7)
> Richard S., is there any reason to use the built-ins for the constant
> evaluation case?

No, Clang's constant evaluator treats the built-ins and calls to replaceable
global [de]allocation functions identically. (The built-ins might be
*marginally* more efficient, but it's not worth an #ifdef.)

[Bug c++/101370] New: miscompile of self-referential constexpr or constinit array initializer

2021-07-07 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101370

Bug ID: 101370
   Summary: miscompile of self-referential constexpr or constinit
array initializer
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase (reduced from tcmalloc):


struct Elem {
Elem* next_ = this;
Elem* prev_ = this;
};

constinit Elem qs[3];


GCC generates a zero initializer for qs:


qs:
.zero   48


If the `constinit` is removed, GCC instead incorrectly generates a dynamic
initializer, so presumably GCC knows that this variable *should* have a
constant initializer but can't actually form one.

The same problem can be observed without constinit:


constexpr Elem rs[3];
const void *p = rs;


... again results in a zero-initialized global and no dynamic initializer.

[Bug c++/100640] New: GCC permits explicit instantiation of a constructor template with an explicit template argument list

2021-05-17 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100640

Bug ID: 100640
   Summary: GCC permits explicit instantiation of a constructor
template with an explicit template argument list
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Example:

struct A {
  template A() {}
};
template A::A();

GCC accepts this without even a warning under -std=c++20 -pedantic-errors, but
this is not valid C++.

If this is an intentional extension, it doesn't appear to be documented (and
presumably should be rejected under -pedantic-errors).

[Bug c++/99534] New: bogus UDL diagnostic for header-name followed by macro

2021-03-10 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99534

Bug ID: 99534
   Summary: bogus UDL diagnostic for header-name followed by macro
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase:

#define M
#include "foo.h"M
#include M

This produces two warnings

warning: invalid suffix on literal; C++11 requires a space between literal and
string macro [-Wliteral-suffix]

At least the second diagnostic appears to be incorrect:  is not a string
literal and lexically can't have a UDL suffix applied.

The first diagnostic might also be incorrect (the header-name production for
double-quoted strings also can't have a UDL suffix), but the max munch rule
appears to require that we lex a string-literal rather than a header-name here!
I think that's probably a wording bug, and the lexer should prefer to produce a
header-name token whenever possible. (I'm taking that part to WG21 CWG; Clang
also diagnoses this, but EDG does not.)

[Bug c++/99209] lambdas in function template signatures instantiated with wrong semantic context

2021-02-22 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99209

--- Comment #1 from Richard Smith  ---
Here's a more interesting example: https://godbolt.org/z/83c36q


#include 

constexpr char f(...) { return 'g'; }
constexpr decltype(auto) f_adl(auto a) { return f(a); }

namespace A {
constexpr char f(auto) { return 'A'; }
template void g(char FunctionParam =
f_adl([]{})) {
char Local = f_adl([]{});
std::cout << TemplateParam << FunctionParam << Local;
}
}

namespace B {
constexpr char f(auto) { return 'B'; }
void call() { A::g(); }
}

int main() { B::call(); }


This prints 'BgA', but should print 'AAA'. So the three lambdas actually
exhibit three different behaviors, not two.

[Bug c++/99209] New: lambdas in function template signatures instantiated with wrong semantic context

2021-02-22 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99209

Bug ID: 99209
   Summary: lambdas in function template signatures instantiated
with wrong semantic context
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase:

constexpr decltype(auto) f_adl(auto a) { return f(a); }

namespace A {
constexpr int f(auto) { return 0; }
template void g(int = f_adl([]{})) {
f_adl([]{});
}
}

int main() {
A::g();
}

Here, the f_adl calls for the default template argument and default function
argument incorrectly result in errors, because f can't be found by ADL.

I suspect this is because the lambdas are being created in the wrong semantic
context. (That is also visible in the output of __PRETTY_FUNCTION__ /
std::source_location::current().function_name() in the lambda and in the
mangling of the lambda closure type, but I think both of those are valid
implementation choices -- the function name is implementation-defined and such
instantiated lambdas appear to be numbered after those lambdas for which the
ABI requires a numbering).

[Bug c++/99176] New: GCC rejects const_cast of null pointer in constant expressions

2021-02-19 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99176

Bug ID: 99176
   Summary: GCC rejects const_cast of null pointer in constant
expressions
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

GCC rejects:

constexpr const int *p = nullptr;
constexpr int *q = const_cast(p);

saying:

:2:20: error: conversion of 'const int*' null pointer to 'int*' is not
a constant expression
2 | constexpr int *q = const_cast(p);
  |^~~

I don't think any such rule exists, and other compilers accept. This only
appears to affect const_casts of null pointers; non-null pointer const casts
seem to work OK. Perhaps GCC thinks that this is a reinterpret_cast / cast from
void* or something like that?

It looks like this regressed between GCC 6 and GCC 7.

[Bug c++/55120] Inaccessible virtual base constructor does not prevent generation of default constructor

2021-01-29 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55120

--- Comment #11 from Richard Smith  
---
(In reply to Jonathan Wakely from comment #10)
> It looks like Clang has a bug with the inaccessible constructor too, and
> strangely inconsistent handling of the inaccessible destructor.

Access checks are performed on names and on derived-to-base conversions.

On the constructor side, I think comment#4 is still relevant: it's not clear
that a defaulted constructor does anything that would require an access check.
I don't think it's clear that we perform a derived-to-base conversion, because
constructing a base class doesn't perform a normal member function call. (We're
not even *allowed* to perform a derived-to-virtual-base conversion until after
the base is constructed per the 'period of construction' rules.) And I don't
think it's reasonable to imagine that a defaulted constructor names its base
classes via injected-class-names or something like that -- that name could be
shadowed in the derived class with no effect on the validity of the defaulted
constructor. Likewise, I don't think we can imagine that the default
constructor for D names the default constructor of V as a member of D (which
would be inaccessible), because the default constructor of V is not inherited
into B and D by default, so we need to imagine it's named as a member of V, and
it's accessible as a member of V.

On the destructor side, I think [class.dtor]/7 is clear that only access to the
destructor is considered, not access to the base subobject, and [class.dtor]/14
says the call is performed as if with a qualified name, so the fact that the
destructor of the base is inaccessible as a member of the derived class is
irrelevant -- it's accessible as a member of the base class, so the access
check succeeds and the function is not deleted. However, I think the implicit
definition of the destructor is ill-formed under [class.dtor]/14, because a
derived-to-base conversion is presumably implied there.

I think Clang follows the above interpretation (it accepts the construction
side, does not treat the destructor as deleted, but rejects the implicit
definition of the destructor), except that it never triggers the implicit
definition of a trivial destructor, so it fails to diagnose the problem in the
definition of D::~D() for the example in comment#0. (But does diagnose if ~V is
non-trivial.)

I think we should ask to have the core issue reopened, because I don't think
the wording says anything sensible here. If we really want this case to be
ill-formed, we need clarification on whether that applies only to the
destruction side or also to construction, and presumably we should make the
destructor be deleted in this case, not merely be ill-formed when implicitly
defined.

[Bug c++/98859] New: pedantic error on use of __VA_OPT__ before C++20 is unnecessary and counterproductive

2021-01-27 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98859

Bug ID: 98859
   Summary: pedantic error on use of __VA_OPT__ before C++20 is
unnecessary and counterproductive
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

There's no good way in ISO C or C++ to express what the GNU ,##__VA_ARGS__
extension does prior to the addition of __VA_OPT__. However, code targeting new
compilers (that doesn't want to use GNU C / GNU C++) cannot reliably use
__VA_OPT__ instead of the comma paste extension, because GCC's -pedantic-errors
mode rejects it outside C++20.

Such rejection is unnecessary: __VA_OPT__ is a reserved identifier in other
language modes, so there is no conformance reason to issue a diagnostic on its
use. I think it'd be useful for GCC to unconditionally allow using __VA_OPT__
in all language modes. (I'm changing Clang to do the same.)

[Bug c++/98804] GCC misparses template in pack expansion as comparison

2021-01-24 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98804

--- Comment #1 from Richard Smith  ---
Somewhat more reduced:

struct X { constexpr X(int&) {} };
template struct Y {};

int a;
auto h(int b) -> Y; // #1
auto h(int b) -> Y; // #2

GCC accepts #1, but for #2 it produces seven (!) error messages:

:6:21: error: template argument 1 is invalid
6 | auto h(int b) -> Y;
  | ^
:6:21: error: template argument 1 is invalid
:6:21: error: template argument 1 is invalid
:6:21: error: template argument 1 is invalid
:6:18: error: invalid template-id
6 | auto h(int b) -> Y;
  |  ^
:6:21: error: use of parameter outside function body before '>' token
6 | auto h(int b) -> Y;
  | ^
:6:6: error: deduced class type 'Y' in function return type
6 | auto h(int b) -> Y;
  |  ^
:2:20: note: 'template > struct Y' declared here
2 | template struct Y {};
  |^

As far as I'm aware, both #1 and #2 are valid. (I think the "use of parameter
outside function body" restriction is referring to [dcl.fct.default]/9, but
that refers only to uses of parameters within default arguments, not uses in
other contexts in the function declaration.)

[Bug c/98217] Prefer a warning for when VLAs declared on stack

2020-12-09 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98217

Richard Smith  changed:

   What|Removed |Added

 CC||richard-gccbugzilla@metafoo
   ||.co.uk

--- Comment #6 from Richard Smith  ---
Hi GCC folks! My preferred approach to take on the Clang side would be to
change -Wvla to not warn on function parameter types, if GCC is prepared to
make the same change. I don't think the current meaning of -Wvla is useful, and
warning only in cases where there is a variably-modified type on the stack
seems like the better meaning for -Wvla.

[Bug c++/97358] [8/9/10 Regression] ICE while building firefox since r8-2720

2020-10-15 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97358

Richard Smith  changed:

   What|Removed |Added

 CC||richard-gccbugzilla@metafoo
   ||.co.uk

--- Comment #19 from Richard Smith  
---
(In reply to Jason Merrill from comment #10)
> This doesn't look valid to me.  In
> 
>   [x...] { x; }...
> 
> we capture the entire pack, but then try to use only a single element.  This
> should be rejected because the use of x in the lambda body is not expanded

The reference to 'x' is expanded within the scope of the parameter pack, though
(which is the entire function template, because 'x' here refers to the
parameter of the enclosing function template). So I think that case 2 is valid,
and expands to

foo(
  [x...] { return x.[0]; },
  [x...] { return x.[1]; },
  ...
  [x...] { return x.[N]; },
);

(That is, each lambda captures the entire pack and then uses only part of it.)
More generally, I think cases such as

foo([x...] { return f(x..., x); } ...);

... are valid, resulting in expansions such as

foo(
  [x...] { return f(x.[0], x.[1], ..., x.[N], x.[0]; },
  [x...] { return f(x.[0], x.[1], ..., x.[N], x.[1]; },
  ...
  [x...] { return f(x.[0], x.[1], ..., x.[N], x.[N]; },
);

I think Case 3 is not valid because the reference to the pack y is not expanded
*within the scope of that pack*, though it's not clear that the standard
actually clearly says that anywhere.

[Bug c++/97256] auto function return different result

2020-10-01 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97256

--- Comment #6 from Richard Smith  ---
My apologies, I misread the testcase. Yes, this is UB.

[Bug c++/97256] auto function return different result

2020-10-01 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97256

Richard Smith  changed:

   What|Removed |Added

 CC||richard-gccbugzilla@metafoo
   ||.co.uk

--- Comment #4 from Richard Smith  ---
The reference to 'b' from within the lambda is not an odr-use, so is not
transformed into a use of the lambda's capture. This program has defined
behavior and is being miscompiled.

[Bug c++/97222] GCC discards attributes aligned and may_alias for typedefs passed as template arguments

2020-09-28 Thread richard-gccbugzilla at metafoo dot co.uk via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97222

Richard Smith  changed:

   What|Removed |Added

 CC||richard-gccbugzilla@metafoo
   ||.co.uk

--- Comment #3 from Richard Smith  ---
> would be interesting to see how ICC mangles the aligned case

It doesn't, it just takes the properties from whichever instantiation happens
to be performed first. On ICC,

 std::cout << alignof(typename identity::type) << std::endl;
 std::cout << alignof(typename identity::type) << std::endl;

prints 4 4, and 

 std::cout << alignof(typename identity::type) << std::endl;
 std::cout << alignof(typename identity::type) << std::endl;

prints 16 16. The ICC behavior seems unsound, compared to the GCC / Clang
behavior of (effectively) stripping the attribute from template arguments.

> There is NO way defined at this point to mange for some attributes
> including but not limited to may_alias and alignment.

These can be mangled as s:
http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.qualified-type

Presumably the more problematic part from an ABI perspective is that this will
change a bunch of existing manglings. Similarly from a source compatibility
standpoint, making the alignment override part of the type would be a breaking
change. It'd probably be better to add a new syntax for the new functionality
(please, not based on an attributed typedef this time!) and deprecate the old
way.