[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.

[Bug c++/96876] New: missing check for destructibility of base classes in aggregate initialization

2020-08-31 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96876

Bug ID: 96876
   Summary: missing check for destructibility of base classes in
aggregate initialization
   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 accepts this invalid code (which is ill-formed because [dcl.init.aggr]/8
says it potentially-invokes the destructor for B, which [class.dtor]/15 says
requires the destructor to be accessible):

struct B {
protected:
~B() {}
};

struct C : B { int n; };

int f();

void g() {
C c{{}, f()};
}

... and generates wrong code for this similar example:

#include 

struct B {
public:
~B() { puts("destroyed"); }
};

struct C : B { int n; };

int f() { throw "hello"; }

int main() {
try {
C c{{}, f()};
} catch (const char*) {
}
}

... which is required to print "destroyed" (when the B base class subobject is
destroyed during stack unwinding), but with GCC does not.

[Bug c/96788] "integer constant is so large that it is unsigned" warning is incorrect

2020-08-26 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96788

--- Comment #4 from Richard Smith  ---
(In reply to Richard Smith from comment #3)
> such a literal "has no type" in C, which presumably results in undefined
> behavior

Ah, no, C11 6.4.4/2 makes this a constraint violation. But either way I think
there's room for a vendor extension here.

[Bug c/96788] "integer constant is so large that it is unsigned" warning is incorrect

2020-08-26 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96788

--- Comment #3 from Richard Smith  ---
In the mean time, what is GCC's intent here? Clang is following the behavior
described by GCC's diagnostic text, treating decimal integer literals that
don't fit in 'long long' but do fit in 'unsigned long long' as the latter type
(I've not checked back far enough to tell if this is what GCC ever actually
did, or if we got this by looking at the diagnostics and didn't check the
behavior). If that's not what GCC intends to do any more, that'd be useful for
us to know, and we can switch to following GCC's actual behavior. (It'd also
make sense to update the diagnostic text in that case!)

It looks like both the Clang behavior (treat the literal as 'unsigned long
long') and the GCC behavior (treat the literal as '__int128' where available
and 'long long' otherwise) are conforming extensions in both C and C++, even
though __int128 isn't (yet) an extended integer type: such a literal "has no
type" in C, which presumably results in undefined behavior, and makes the
program ill-formed in C++, so it seems there is room for a vendor extension in
both languages.

[Bug c/96788] New: "integer constant is so large that it is unsigned" warning is incorrect

2020-08-25 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96788

Bug ID: 96788
   Summary: "integer constant is so large that it is unsigned"
warning is incorrect
   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:

  typedef __typeof(9223372036854775808LL) T;

produces the warning:

  :1:18: warning: integer constant is so large that it is unsigned

for both C and C++ compilations, whether or not __int128 is available for the
target.

What actually appears to happen is that T is __int128 if __int128 is available,
and T is otherwise 'long long'.

[Bug c++/96719] New: non-standard handling of alias templates used as template template arguments

2020-08-19 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96719

Bug ID: 96719
   Summary: non-standard handling of alias templates used as
template template arguments
   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: ---

template struct A { using type = U; };
template using B = A;
template class Z> struct Q {
  using type = typename Z::type;
};

Here, Q::type should be float, but GCC believes it's int.

I think this is due to GCC implementing the (non-standard at this time) rule in
CWG1286. This is also reflected in incorrect manglings:

void f(Q) {}

... is mangled as if it were written as `f(Q)`, and other rejects-valids,
such as for:

void f(Q) {}
void f(Q) {}

[Bug c++/96604] New: rejects-valid on befriending specialization of conversion function template

2020-08-13 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96604

Bug ID: 96604
   Summary: rejects-valid on befriending specialization of
conversion function template
   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:

struct A { template operator T(); };
struct X {};
struct B { friend A::operator X(); };

Per [temp.mem]/5 and /6, I think this is supposed to perform template argument
deduction against the conversion function template and befriend operator T with
T = B.

Clang, EDG, and MSVC accept.

[Bug c++/96223] DR 1787 and indeterminate values in constexpr context

2020-08-06 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96223

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #2 from Richard Smith  ---
P1331R2 explicitly disallows in a constant evaluation:

"- an lvalue-to-rvalue conversion that is applied to an object with
indeterminate value ([basic.indet]);"

so GCC is correct to reject such cases.

[Bug c++/59978] C++11 Non-Type-Template-Parameter Pack Expansion not working according to standard

2020-07-13 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59978

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #1 from Richard Smith  ---
This appears to have been fixed in GCC 5.2 onwards.

[Bug c++/95349] Using std::launder(p) produces unexpected behavior where (p) produces expected behavior

2020-06-15 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349

--- Comment #37 from Richard Smith  
---
(In reply to Richard Biener from comment #36)
> The main issue I see is that this differing expectations of C and C++ are
> impossible to get correct at the same time.

That is a rather bold claim. I think you can satisfy both rule sets by using
the C++ rule even in C. It is conservatively correct to discard the effective /
dynamic type when you see a memcpy, and the C++ semantics require you to do so.

The C semantics also appear to require the same thing, if you cannot track the
destination back to either an object with a declared type or to a heap
allocation; as described in comment#35, GCC gets this wrong and presumably
miscompiles C code in some cases as a result.

It seems to me that all you're allowed to do within the bounds of conformance
is:

#1 if you can track the destination back to an object with declared type in C
code, then use its type as the effective type of the result

#2 if you can track the destination back to a heap allocation in C code, then
copy the effective type from source to destination

#3 otherwise (in either C or C++) erase the effective type of the destination

(#1 and #3 will presumably result in memcpy being replaced by some operation
that updates the effective type, rather than being eliminated entirely.)

[Bug c/95630] New: rejects-valid on comparison of pointers to complete vs incomplete types in C11 mode

2020-06-10 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95630

Bug ID: 95630
   Summary: rejects-valid on comparison of pointers to complete vs
incomplete types in C11 mode
   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:

int f(int (*p)[], int (*q)[3]) { return p < q; }

This is a constraint violation in C99, but the relevant rule was removed in
C11. GCC still rejects in -std=c11 mode under -pedantic-errors.

[Bug c++/95536] New: tag name injection doesn't happen for return type of a friend

2020-06-04 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95536

Bug ID: 95536
   Summary: tag name injection doesn't happen for return type of a
friend
   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 A {
friend struct B *f();
};
B *p;

GCC rejects this saying that 'B' is not declared, which is incorrect -- the
'struct B' introduces the name 'B' into the enclosing non-class scope. GCC gets
this right for

struct A {
friend void f(struct B *);
};
B *p;

so I'd guess that GCC is incorrectly applying the rules for friend class
declarations (eg, 'friend struct B;' does not make 'B' visible outside the
class).

[Bug c++/95349] Using std::launder(p) produces unexpected behavior where (p) produces expected behavior

2020-05-29 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349

--- Comment #20 from Richard Smith  
---
(In reply to Andrew Downing from comment #19)
> Not that it would make a difference in this particular situation, but is the
> intent of P0593R6 to only allow implicitly creating an object in the
> relevant storage location where one hasn't already been implicitly or
> explicitly created?

No, the new objects are allowed to replace existing objects. For example, this
implementation would also be correct:

std::uint64_t* s3(double* p) {
std::memmove(p, p, sizeof(double));
return std::launder(reinterpret_cast(p));
}

... on the basis that it has defined behavior if the memmove implicitly creates
an 'uint64_t' object in the underlying storage after it (notionally) copies the
contents elsewhere and before it (notionally) copies the contents back again.
(The 'launder' is necessary in order to form a pointer to the
implicitly-created uint64_t object, because p doesn't point to that object.)

[Bug c++/95349] Using std::launder(p) produces unexpected behavior where (p) produces expected behavior

2020-05-29 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349

--- Comment #18 from Richard Smith  
---
(In reply to Andrew Downing from comment #17)
> Also none of the behavior described in p0593 is required for this C++
> program to be well defined. All objects that are required to exists here are
> created explicitly. It's not relying on the implicit creation of any
> objects. This is valid C++17 code.

I agree, for what it's worth. I think the only thing that might suggest
otherwise is the wording in the C standard that says that memcpy copies the
effective type, but that doesn't mean anything in C++ (and it's also specified
in the language section of C, not the library section, so isn't part of the
wording that C++ incorporates by reference).

C++ doesn't have any wording that says what value an object has after you
memcpy the representation of a value of a different type over it, but there
isn't any provision for memcpy to change the dynamic type of the object prior
to P0593 (and after P0593, memcpy is only allowed to change the dynamic type if
doing so makes the program's behavior more defined).

[Bug c++/95349] Using std::launder(p) produces unexpected behavior where (p) produces expected behavior

2020-05-29 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349

--- Comment #16 from Richard Smith  
---
Per p0593, memcpy implicitly creates objects (of any implicit lifetime type) in
the destination. It does not propagate the objects in the source memory to the
destination memory, and can therefore be used to perform a bit cast. (This is
different from C, where memcpy either preserves or copies the effective type
depending on whether the destination has a declared type.)

The s3 function in comment#1 looks correct to me (with or without the launder).
Optimizing it to { return (uint64t *)p; } is incorrect, because it loses the
erasure of dynamic type information that p0593 requires from memcpy in C++.

[Bug c++/94676] New: constexpr destructors run too late for temporaries created inside __builtin_constant_p

2020-04-20 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94676

Bug ID: 94676
   Summary: constexpr destructors run too late for temporaries
created inside __builtin_constant_p
   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 A {
  int *p;
  constexpr ~A() { *p = 0; }
};
static_assert(!__builtin_constant_p((A{}, 123)));


I think this testcase should be accepted. The way I see it, there are two ways
one could approach this:

1) Run the destructor for the A temporary after evaluating
__builtin_constant_p's operand, notice the operand is non-constant, and
evaluate the __bcp call to 0.

2) Notice that the __bcp call's operand has a side-effect on the enclosing
evaluation (registering a non-trivial destructor for a temporary) and evaluate
the call to 0 due to that side-effect. [This is what Clang currently does.]

I was considering changing Clang's behavior from option 2 to option 1, but I
noticed that GCC actually appears to do a third thing:

3) Run the destructor at the end of the entire static-assert condition and
reject the program because the destructor (run outside of the protection of
__builtin_constant_p) has a side-effect.

I don't think there's an obvious correct answer here, but (3) doesn't seem
right to me.

[Bug c++/94569] alignas(object) with a weaker (smaller) alignment than the alignas(type) of it's type compiles, inconsistent with the C++ standard

2020-04-14 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94569

--- Comment #4 from Richard Smith  ---
(In reply to Richard Biener from comment #3)
> But isn't the alignas(32) also "appertaining to that entity"?

No. The alignas(32) appertains to the struct. This is specified in [class]/2:
"The optional attribute-specifier-seq appertains to the class".

[Bug c++/94569] alignas(object) with a weaker (smaller) alignment than the alignas(type) of it's type compiles, inconsistent with the C++ standard

2020-04-12 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94569

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #1 from Richard Smith  ---
I believe the particular rule that is violated by this example is
[dcl.align]p5:

"The combined effect of all alignment-specifiers in a declaration shall not
specify an alignment that is less strict than the alignment that would be
required for the entity being declared if all alignment-specifiers appertaining
to that entity were omitted."

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

2020-03-24 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295

--- Comment #6 from Richard Smith  ---
(In reply to Marc Glisse from comment #5)
> Ah, since you are here, and you appeared as an author of N3664 but not N3537
> (precisely when this subtlety happened), could you explain why? It isn't
> discussed in the paper, complicates the design, and I cannot think of any
> use for this distinction

It isn't discussed in the paper because it wasn't part of the original plan /
design, but was added due to committee push-back. People want some guarantees:

 * If they write a test for their global 'operator new' (particularly, testing
failure cases, mallinfo, the effect of configuration parameters on its
behavior, ...), that test should still work in the presence of the language
change.

 * A direct function call to a user-defined function should behave as a direct
function call to that user-defined function. Even if it has a non-identifier
name.

In the end, the language and user model we found to be most satisfying, given
the above, is: new-expressions, like std::allocator, may obtain storage by
calling 'operator new', but it's unspecified how often it's called and with
what arguments. And the language rules are an approximation of that idea.


(In reply to Marc Glisse from comment #5)
> This of course doesn't at all prevent from adding a __builtin_operator_new
> option in std::allocator, it only affects how motivated we should be to fix
> the non-conformance.

Well, in case it helps your analysis, LLVM once did what GCC does now (before
there were standard rules in place), and in practice we saw it break some stuff
(largely, tests for allocators, but also weird things like using 'operator
new((size_t)-1)' as a way to throw bad_alloc from code that can't '#include
').

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

2020-03-24 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295

--- Comment #4 from Richard Smith  ---
(In reply to Andrew Pinski from comment #3)
> PR 23383 is where part of the discussion was done.
> 
> In fact GCC implements the optimization without the builtin:
> https://gcc.gnu.org/legacy-ml/gcc-patches/2019-07/msg00136.html

Yep, looks like GCC miscompiles direct calls to operator new / operator delete
since that patch landed: https://godbolt.org/z/dK99Rz

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

2020-03-24 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295

--- Comment #2 from Richard Smith  ---
(In reply to Marc Glisse from comment #1)
> (In reply to Richard Smith from comment #0)
> > The C++ language rules do not permit optimization (eg, deletion) of direct
> > calls to 'operator new' and 'operator delete'.
> 
> I thought that was considered a bug?

No, it's intentional: if the user directly calls '::operator new(42)' and
they've replaced that function, the replacement function is guaranteed to be
called. In this regard, 'operator new' is just a regular function with a funny
name.

To be clear, the implicit call to 'operator new' produced by, say, 'new int'
*is* optimizable, but a direct explicit call to 'operator new(sizeof(int))' is
not.

> Gcc does optimize those, like it does malloc/free...

That sounds like non-conforming behavior.

> > This bug requests that libstdc++ uses these builtins when available.
> 
> So just in std::allocator, or are there other places?

std::allocator's specification has an explicit provision to permit these
optimizations, see [allocator.members]/4:

"The storage for the array is obtained by calling ::operator new (17.6.2), but
it is unspecified when or how often this function is called."

In Clang + libc++ at least, we interpret that as meaning we can call
'::operator new' zero times if we don't need the storage, just like for a
new-expression, and the LWG members I've talked to about this have agreed that
that's in line with the intent.

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

2020-03-23 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94295

Bug ID: 94295
   Summary: use __builtin_operator_new and
__builtin_operator_delete when available
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

See https://bugs.llvm.org/show_bug.cgi?id=45287 for some background.

The C++ language rules do not permit optimization (eg, deletion) of direct
calls to 'operator new' and 'operator delete'. libstdc++ uses such calls to
implement std::allocator:

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/ext/new_allocator.h#L112

As a consequence, allocations performed by libstdc++'s containers are not
optimizable.

Clang provides a pair of builtin functions to work around this issue:
https://clang.llvm.org/docs/LanguageExtensions.html#builtin-operator-new-and-builtin-operator-delete

__builtin_operator_new(args) is equivalent to ::operator new(args) except that
it permits optimizations.
__builtin_operator_delete(args) is equivalent to ::operator delete(args) except
that it permits optimizations.

You can detect support for these builtins with

#ifdef __has_builtin
#if __has_builtin(__builtin_operator_new) >= 201802L
// ...
#endif
#endif

(Note that __has_builtin(...) returned 1 for an older version of the builtins
that didn't support placement forms, and so couldn't be used for aligned
allocation and sized delete. It's probably not worth your time dealing with
those.)

This bug requests that libstdc++ uses these builtins when available.
(Separately, it'd be great if GCC considered supporting them too.)

[Bug c++/94227] New: ambiguous lookup for nested-name-specifier in using-declaration is not diagnosed

2020-03-19 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94227

Bug ID: 94227
   Summary: ambiguous lookup for nested-name-specifier in
using-declaration is not diagnosed
   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: ---

GCC accepts this invalid code:

namespace N1 {
  int ();
}

namespace N2 {
  struct N1 {
float ();
  };
}

using namespace N2;
int  = N1::f();


This should be rejected due to ambiguity: the name N1 on the final line is
looked up by unqualified lookup, and that lookup is ambiguous between ::N1 and
::N2::N1. But GCC accepts and selects ::N1.

(Originally filed as a Clang rejects-valid here: https://llvm.org/PR45216)

[Bug c++/92169] crash on referring to a local class member by unqualified name from outside the enclosing function

2020-01-30 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92169

--- Comment #4 from Richard Smith  ---
Aha! godbolt.org implicitly adds -g to its command line. Try that; that causes
a crash for this testcase for me with GCC 9.2.1.

[Bug c++/92169] crash on referring to a local class member by unqualified name from outside the enclosing function

2020-01-28 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92169

--- Comment #2 from Richard Smith  ---
Still crashes GCC trunk from today:

https://godbolt.org/z/zWvT4w

[Bug c++/92271] New: for consistency, __is_same_as should be named __is_same

2019-10-29 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92271

Bug ID: 92271
   Summary: for consistency, __is_same_as should be named
__is_same
   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: ---

The convention for type trait builtins adopted by essentially every C++
compiler vendor is to expose std::SOME_TRAIT::value as __SOME_TRAIT(A,
B, C).

GCC violates this convention in one case: std::is_same::value is exposed
as __is_same_as(A, B) rather than as __is_same(A, B).

For consistency and code portability, I suggest that GCC accepts __is_same as a
synonym for __is_same_as. (FWIW, Clang uses the name __is_same here, but will
soon accept __is_same_as for GCC compatibility.)

[Bug c++/92169] New: crash on referring to a local class member by unqualified name from outside the enclosing function

2019-10-21 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92169

Bug ID: 92169
   Summary: crash on referring to a local class member by
unqualified name from outside the enclosing function
   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: ---

[Probably no-one will ever write code like this outside a compiler test case,
but filing just in case this affects non-contrived situations.]

This code crashes every version of g++ that supports deduced return types:


auto f() {
static int n;
struct Y {
static int () { return n; }
struct X {
int ();
};
};
return Y::X();
};
using X = decltype(f());
int ::get() { return g(); }

[Bug c++/87150] [8 Regression] move ctor wrongly chosen in return stmt (derived vs. base)

2019-08-12 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87150

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #22 from Richard Smith  
---
(In reply to Marek Polacek from comment #20)
> (In reply to Jason Merrill from comment #19)
> > And now P1155/P1825 removes that text, so in C++20 mode the original
> > testcase needs to call the move constructor again.  Marek, I don't see
> > P1825R0 in cxx-status.html, was there a reason not to add it?
> 
> No, I followed clang's table but they're missing that one.  I'll fix that &
> open a PR for P1825R0.

FYI, it is in Clang's table, but I put it in the C++11 features list since it's
a DR and we're considering it to retroactively apply to C++11's addition of
move semantics.

[Bug c++/67898] rejects-valid on overloaded function as non-type template argument of dependent type

2019-06-20 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67898

--- Comment #2 from Richard Smith  ---
(Clang trunk now accepts both testcases.)

[Bug c++/86501] shadow template parameter

2019-06-14 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86501

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #2 from Richard Smith  ---
I think EDG and Clang are wrong here and GCC is right. The template friend
declaration introduces V into the global namespace, so it is not "redeclared
within its scope" (per [temp.local]p6).

[Bug c++/90792] incorrect mangling for beginning with an

2019-06-09 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90792

--- Comment #3 from Richard Smith  ---
(In reply to Andrew Pinski from comment #2)
> Related to the upstream ABI issue:
> https://github.com/itanium-cxx-abi/cxx-abi/issues/38

I don't think so, except that they're both about the 'sr' mangling in general.
These two issues seem to have been muddled up repeatedly on the issues you
cited.

ABI issue 38 is about whether we mangle the original syntax or some resolved
form of it. This issue (and PR88413) is about whether an 'E' is required to
terminate the nested-name-specifier in certain 'sr' productions. I think the
two questions are independent, and the ABI is currently clear that the 'E' is
required in the example in comment#0.

[Bug c++/90792] New: incorrect mangling for beginning with an

2019-06-08 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90792

Bug ID: 90792
   Summary: incorrect mangling for  beginning
with an 
   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: ---

Imported from https://llvm.org/PR14117

template struct IsConvertible {
  static const bool value =true;
};
template struct EnableIf {
  typedef int Type;
};
template   void   Handle(S x,  typename
EnableIf::value>::Type dummy) {
}
template void Handle( int x,  typename
EnableIf::value>::Type dummy );

gcc produces _Z6HandleIiEvT_N8EnableIfIXsr13IsConvertibleIS0_E5valueEE4TypeE
and clang produces
_Z6HandleIiEvT_N8EnableIfIXsr13IsConvertibleIS0_EE5valueEE4TypeE.

Per the Itanium ABI,
http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.unresolved-name there
are two rules that can produce an 'sr' mangling:

  ::= sr  
   ::= [gs] sr + E


  ::=  [  ]
   ::= 
   ::= 

  ::= 

  ::=  [  ]

Here, 13IsConvertible is an , not an
, so an E must be inserted after the qualifiers even if
there's only one of them.

The demangler has a matching bug; it can demangle the incorrect mangling but
not the correct one.

[Bug libstdc++/90266] missing or broken check for vector::size() exceeding max_size()

2019-04-26 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90266

Richard Smith  changed:

   What|Removed |Added

Version|unknown |8.3.0

--- Comment #3 from Richard Smith  ---
(In reply to Jonathan Wakely from comment #1)
> Which version are you using? (You didn't say)

Sorry for leaving that out! I was using "clang (trunk)" on godbolt, which is
apparently 8.3.0. Sounds like this was fixed in the interim?

[Bug libstdc++/90266] New: missing or broken check for vector::size() exceeding max_size()

2019-04-26 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90266

Bug ID: 90266
   Summary: missing or broken check for vector::size() exceeding
max_size()
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Testcase:

#include 

using T = int;

size_t e() {
std::vector vb;
return vb.max_size();
}

size_t f() {
std::vector vb(e());
vb.push_back({});
return vb.size();
}

size_t g() {
std::vector vb(e());
vb.push_back({});
vb.push_back({});
return vb.size();
}

Compiled using -m32, I find:

 * e() returns 0x3fff (good)
 * f() invokes operator new(-4) and returns 0 (wrong; should throw
length_error)
 * g() invokes operator new(-4) twice (?!) and returns 1

It looks like the check for size() exceeding max_size() is missing. [For a
compiler that deletes unused new/delete pairs, f() otherwise could incorrectly
compile to just "return 0;" with no exception thrown. Presumably the same would
happen under -m64 with an allocator that has a 32-bit max_size().]

[Bug c++/90107] New: rejects-valid on global-namespace-qualified variable declared after class definition

2019-04-15 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90107

Bug ID: 90107
   Summary: rejects-valid on global-namespace-qualified variable
declared after class definition
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Keywords: rejects-valid
  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 these valid examples, producing a bogus "expected ';' after struct
definition" diagnostic:

struct A;
namespace N { extern A a; }
struct A {} ::N::a;

struct A;
struct B { static A a; };
struct A {} ::B::a;

(I just fixed a rejects-valid on the same cases in Clang.)

[Bug c++/58074] [C++11][DR 1333] __is_trivial intrinsic fails for deleted members and for non-trivial copy-c'tors

2019-03-18 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58074

--- Comment #11 from Richard Smith  
---
The point of trivial (as distinguished from trivially-copyable) is that an
instance of type T can be created and "properly" initialized (albeit left with
an indeterminate value) without executing any code.

(The notion of a trivial type is not used by the core language, and is used in
the library only to constrain things like the template parameters of
basic_string and aligned_storage, where it is intentional that objects of type
T can be created by allocating suitable storage and performing no further
initialization.)

So I think the language rule after the application of the relevant DRs is
approximately right: a type with a deleted default constructor should not be
considered trivial.

(It's arguable that a type with multiple default constructors should perhaps
also not be considered trivial. Or maybe we should decide that the language
notion of "trivial" is a useless relic of "POD" and should be removed from the
core language, and that the library should be looking for types that are
trivially default-constructible and trivially-copyable in the places where it
currently looks for "trivial" types.)

[Bug c++/89600] New: rejects-valid on dependent block-scope using declaration

2019-03-05 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89600

Bug ID: 89600
   Summary: rejects-valid on dependent block-scope using
declaration
   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: ---

GCC rejects this valid code:

template T f() { using T::Bar; return Bar; }

As follows:

: In function 'T f()':
:2:39: error: 'T' is not a namespace or unscoped enum
2 | template T f() { using T::Bar; return Bar; }
  |   ^~~

... which is wrong; T could be an unscoped enumeration:

enum E { Bar };
E e = f();

[Bug c++/89001] New: g++ uses wrong mangling for lifetime-extended temporaries

2019-01-22 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89001

Bug ID: 89001
   Summary: g++ uses wrong mangling for lifetime-extended
temporaries
   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: ---

Consider:

inline int & = 0;
int *p = 

GCC mangles the lifetime-extended temporary as _ZGR1r0, which doesn't match the
ABI mangling rule
(http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-special-temporaries).
The mangling required by the ABI (and produced by Clang) is _ZGR1r_

[Bug c++/86049] Array bindings are not const when initializer is

2018-12-11 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86049

--- Comment #5 from Richard Smith  ---
This was just reported as http://lists.isocpp.org/core/2018/12/5320.php; I
don't believe it's on the core issues list yet.


[@Tomalak, I think the standard is clear here:

"If the assignment-expression in the initializer has array type A and no
ref-qualifier is present, e has type cv A"

Here, A is the array type 'const int[1]' and cv is empty, so e has type 'const
int[1]'. But, as noted in comment#2, that seems like the wrong outcome. It also
contradicts the non-normative note in [dcl.struct.bind]p3, which further
suggests that this outcome was probably not the intent of the wording.]

[Bug c/88382] New: undocumented GNU C extension: C++ raw string literals permitted in GNU C

2018-12-05 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88382

Bug ID: 88382
   Summary: undocumented GNU C extension: C++ raw string literals
permitted in GNU C
   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: ---

GCC's documentation of GNU C extensions appears not to mention allowing raw
string literals in C, which GCC has permitted in -std=gnu* since GCC 5.

[Bug middle-end/87237] __atomic_load on 4-byte-sized, 1-byte-aligned struct is not atomic

2018-09-11 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87237

--- Comment #4 from Richard Smith  ---
(In reply to Alexander Monakov from comment #3)
> With GCC size/align are 3/1 while with Clang it's 4/4 as you said

Oh sorry, you're right, I'd forgotten about this ABI discrepancy. We really
need to get the psABI fixed to say one way or the other! :)

[Bug middle-end/87237] __atomic_load on 4-byte-sized, 1-byte-aligned struct is not atomic

2018-09-11 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87237

--- Comment #2 from Richard Smith  ---
(In reply to Alexander Monakov from comment #1)
> GCC assumes the access is sufficiently aligned for an atomic object of
> corresponding type

I think that's only true for objects whose size corresponds to that of a
fundamental type. Consider:

struct B { char c[3]; };

Here, an atomic object of type B (eg, _Atomic(B) or std::atomic) would have
size=4, align=4, and yet GCC treats B as having an alignment of 1 for the
purpose of atomic accesses.

Rather, GCC appears (from its external behavior) to consider only the object
size and not the alignment for atomic accesses, and assumes power-of-2-sized
objects to be aligned to their size (or to the maximum alignment of a
fundamental type, whichever is lower).

There exists code that assumes that GCC behaves as documented in this regard.
For example, libc++'s std::atomic makes this assumption, and as a result,
std::atomic is not atomic when using gcc with libc++. For that reason,
changing GCC to avoid the unwarranted alignment assumption seems superior to me
to updating the documentation to match the behavior. (For what it's worth, I
recently fixed Clang to behave per the GCC documentation in this regard; Clang
used to fall back to a libcall for the underaligned case, but would mistakenly
call the "optimized" library routines that assume the object is sufficiently
aligned.)

[Bug c++/59372] accepts-invalid with constexpr function pointer variable as non-type template argument

2018-09-05 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59372

Richard Smith  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |FIXED

--- Comment #3 from Richard Smith  ---
Confirmed fixed.

[Bug c/87237] New: __atomic_load on 8-byte-sized, 1-byte-aligned struct is not atomic

2018-09-05 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87237

Bug ID: 87237
   Summary: __atomic_load on 8-byte-sized, 1-byte-aligned struct
is not atomic
   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: ---

It's my understanding that __atomic_load is supposed to work for an essentially
arbitrary TYPE, including the case where alignof(TYPE) < sizeof(TYPE). (From
the documentation, "The four non-arithmetic functions (load, store, exchange,
and compare_exchange) all have a generic version as well. This generic version
works on any data type.") However:

  struct A { char c[4]; } *p, *q;
  void f() { __atomic_load(p, q, 5); }

On x86_64, GCC emits f as a 'movl' from *p. That is not atomic if *p straddles
two cache lines.

libatomic's __atomic_load implementation gets this right, and falls back on a
mutex in the case where the source straddles two cache lines, but GCC doesn't
seem to realize it needs to call it.

[Bug c++/87097] New: value-initialization of an array of more than 1 element not treated as a constant initializer

2018-08-24 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87097

Bug ID: 87097
   Summary: value-initialization of an array of more than 1
element not treated as a constant initializer
   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: ---

Live testcase: https://godbolt.org/z/1JYWJS

For posterity:


struct A {
  constexpr A() : data() {}
  struct X { int n; };
  X data[2];
};

static_assert((A(), true));
static_assert(A().data[0].n == 0);
static_assert(A().data[1].n == 0);
constexpr A x;


GCC rejects this valid code with:

:9:29: error: non-constant condition for static assertion
9 | static_assert(A().data[1].n == 0);
  |   ~~^~~~
:9:29: error: accessing uninitialized member 'A::X::n'

:10:13: error: 'A{A::X [2]{A::X{0}, A::X()}}' is not a constant
expression
10 | constexpr A x;
   |

Looks like GCC fails to evaluate the initializer of the second and subsequent
elements of a value-initialized array during constant evaluation.

[Bug c/86983] New: documentation inconsistent with always_inline diagnostics for computed goto

2018-08-16 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86983

Bug ID: 86983
   Summary: documentation inconsistent with always_inline
diagnostics for computed goto
   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: ---

Per https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html a function
containing a computed goto can be inlined (so long as no label within it is
used to initialize a static variable):

> The & expressions for the same label might have different values if the 
> containing function is inlined or cloned. If a program relies on them being 
> always the same, __attribute__((__noinline__,__noclone__)) should be used to 
> prevent inlining and cloning. If & is used in a static variable 
> initializer, inlining and cloning is forbidden.

However, applying __attribute__((__always_inline__)) to a function containing a
computed goto produces this diagnostic:

> error: function 'void* f(void*)' can never be inlined because it contains a 
> computed goto

... which claims that a computed goto prevents inlining. (See
https://godbolt.org/g/XFhwQq)

Also, GCC warns on returning the address of a label from a function, which
makes sense if different invocations of the same function can have different
addresses for their labels (through inlining / cloning), but is a false
positive on an example such as the one at that godbolt.org link otherwise.


So, which is it?

Is GCC reserving the right to inline functions containing computed gotos in
some future version? (In which case, the always_inline diagnostic is somewhere
between misleading and wrong, and should probably be weakened from "can never
be inlined" to something like "was not inlined".)

Or has the computed goto rule been changed to "functions containing computed
goto will never be inlined or cloned"? (In which case the documentation is
wrong, and the warning on returning the address of a label seems questionable,
at least for an enabled-by-default warning, since it warns on reasonable code
and there doesn't seem to be a simple syntactic way to suppress the warning.)

[Bug c++/86849] g++ applies guaranteed copy elision to delegating construction, resulting in miscompiles

2018-08-06 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86849

--- Comment #1 from Richard Smith  ---
Interestingly, GCC does appear to suppress guaranteed copy elision if the class
has virtual base classes.


Perhaps GCC's approach to this problem is to assume that a function returning a
T by value cannot touch the tail padding of the T object if T is POD for the
purpose of layout, and so the tail padding cannot be modified in the case where
it's reusable by the enclosing object? (So we only have a problem in the case
where a complete-object constructor and a base-subobject constructor would do
different things, namely when the class has virtual base classes.)

The trouble with that approach is that other compilers do store to the tail
padding of T in a function returning T by value:

https://godbolt.org/g/MM7Wvb

... and indeed the standard requires this behavior:

http://eel.is/c++draft/dcl.init#6.2

"To zero-initialize an object or reference of type T means [...] if T is a
(possibly cv-qualified) non-union class type, its padding bits (6.7) are
initialized to zero bits [...]"

(so arguably that's another bug in GCC's behavior: it should zero-initialize
A's tail padding in the new example, but does not).

[Bug c++/86849] New: g++ applies guaranteed copy elision to delegating construction, resulting in miscompiles

2018-08-03 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86849

Bug ID: 86849
   Summary: g++ applies guaranteed copy elision to delegating
construction, resulting in miscompiles
   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: ---

Live testcase: https://godbolt.org/g/AKn7j7

For posterity:

#include 

struct A {
A() {}
A(int);
~A() {}

int n;
char k;
};

A f();
A::A(int) : A(f()) {}

A f() {
A result;
std::memset(, 0, sizeof(A));
return result; // (nrvo)
}

struct B {
char x, y, z;
};

struct X : A, virtual B { // B is in A's tail padding
X() : B{1, 2, 3}, A(4) {}
};

char test() {
X x;
return x.x; // should return 1
}

Here, GCC uses f() to directly construct the A base class of the X object, and
that tramples over A's tail padding (which contains the B virtual base class of
X, which has already been initialized).

It's not correct to apply guaranteed copy elision to a delegating construction,
just like it's not correct to apply it to a base class construction -- not even
in the C1 constructor variant, due to [[no_unique_address]].

[Bug c++/86769] g++ destroys condition variable in for statement too early

2018-07-31 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86769

--- Comment #1 from Richard Smith  ---
For easy reproduction: https://godbolt.org/g/dfZFxz

This does not appear to be a regression: this example appears to be miscompiled
by every version of GCC back to at least 4.1.

[Bug c++/86769] New: g++ destroys condition variable in for statement too early

2018-07-31 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86769

Bug ID: 86769
   Summary: g++ destroys condition variable in for statement too
early
   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 X { ~X(); operator bool(); };
void f(X &);
void g() { for (; X x = X(); f(x)); }

GCC miscompiles this by destroying the 'x' variable before the call to 'f(x)'.
Per C++ [stmt.for]p1, the above is equivalent to

while (X x = X()) {
  f(x);
}

So the 'x' variable should be destroyed *after* the third operand of the
for-statement is evaluated, not before.

[Bug c++/86049] Array bindings are not const when initializer is

2018-06-05 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86049

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #2 from Richard Smith  ---
I think this is a bug in the standard. The cv-qualifiers of the array type
should be discarded, as they would be for any normal auto deduction.

[Bug c++/76995] type-id/expression in cstyle-cast are disambiguated incorrectly

2018-04-15 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=76995

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #2 from Richard Smith  ---
This code is valid, and GCC is incorrect to reject it (as is Clang and EDG, of
course). The expression context

  (T())

is ambiguous: it could either be a C-style cast to the function type 'T()' or a
parenthesized functional cast expression constructing an object of type 'T'. A
correct parser is required to look at what follows the construct to figure out
which of these two cases we're in: if the following tokens form a valid
cast-expression, then it's an (ill-formed) cast to a function type. Otherwise,
it's a parenthesized functional cast.

The following tokens are (args...), which do not form a valid cast-expression,
so the overall expression unambiguously parses the same as 'mytype()(args...)',
rather than as a type cast.


And for the record: I think this language rule is ridiculous. As far as I can
determine, the only cases that result in this ambiguity involve a choice
between a cast to a function type and something else; since a cast to a
function type is not meaningful, we could -- and arguably should -- change the
grammar to treat such cases as the non-cast interpretation. But I think that
argues even more strongly that GCC is wrong to reject this.

[Bug c++/84414] miscompile due to assuming that object returned by value cannot alias its own member pointer values

2018-02-15 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84414

--- Comment #2 from Richard Smith  ---
> Where does the scope of object A inside Foo begin and end?

There is formally only one object. The object constructed in the return
statement of Foo is simply the same object that is named 'a' within Bar.


> Maybe it is time to file a DR to the C++ language folks about this case
> if there is not one already.

Hmm, the [class.temporary]/3 rule already gets very close to allowing this:

"When an object of class type X is passed to or returned from a function, if
each copy constructor, move constructor, and destructor of X is either trivial
or deleted, and X has at least one non-deleted copy or move constructor,
implementations are permitted to create a temporary object to hold the function
parameter or result object. The temporary object is constructed from the
function argument or return value, respectively, and the function’s parameter
or return object is initialized as if by using the non-deleted trivial
constructor to copy the temporary (even if that constructor is inaccessible or
would not be selected by overload resolution to perform a copy or move of the
object). [ Note: This latitude is granted to allow objects of class type to be
passed to or returned from functions in registers. — end note ]"

In fact, I think the *only* problem here is that the above rule does not allow
the caller and the callee to observe the objects having the same address.

I'll take this to the committee and see whether we can get that rule relaxed
slightly.

Would you be OK with this optimization only being permitted for the above class
types (those that can be passed/returned in registers)?

[Bug c++/84414] New: miscompile due to assuming that object returned by value cannot alias its own member pointer values

2018-02-15 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84414

Bug ID: 84414
   Summary: miscompile due to assuming that object returned by
value cannot alias its own member pointer values
   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
CC: timshen at gcc dot gnu.org
  Target Milestone: ---

GCC (all versions) miscompiles this code:


struct A {
  A *children;
  long long arr[100];

  A() : children() {}
  A(int) : children(this) {}
};

__attribute__((noinline))
A Foo() {
  return A(0);
}

A x[3] = {};

void Bar(int n) {
  A a = Foo();
  for (int i = 0; i < n; i++) {
a.children[i].children = x;
  }
}

int main() {
Bar(3);
return x[0].children || !x[1].children || !x[2].children;
}


A correct compilation must return 0 from main, but GCC at -O2 returns 1. The
reason is that it fails to reload 'a.children' on each iteration of the loop in
'Bar', reasoning (incorrectly) that the store to 'a.children[i].children'
cannot alias 'a.children' because 'a' has not escaped.

The above code has defined behavior in C++17, where the 'guaranteed copy
elision' rules mean that the 'this' pointer inside the A::A(int) constructor
points to the 'a' object inside 'Bar'. But since GCC chooses to perform copy
elision on this code in all language modes (and always has done so), and the
fact that it performed copy-elision is observable, this is not a C++17-specific
bug. (The same miscompile can also be observed via NRVO.)

[Bug c++/60352] [C++11] Bogus "error: conflicting declaration 'auto i'"

2017-12-08 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60352

--- Comment #3 from Richard Smith  ---
This bug still exists in GCC trunk.

[Bug c++/59930] template friend declarations, namespaces, and explicit instantiations don't mix

2017-11-21 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59930

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #1 from Richard Smith  ---
Another example, without the explicit instantiation:

namespace N {
  template class A {
template friend struct B;
  private:
int n;
  };
}

template struct B {
  int f(N::A ai) { return ai.n; }
};

int k = B().f({}); // incorrectly accepted


It looks like when GCC instantiates a friend class template declaration, it
incorrectly injects it into the global namespace (rather than the innermost
enclosing namespace) if redeclaration lookup doesn't find some prior
declaration of the class template to befriend.

That would make at least bug#64816, bug#78724, and bug#81347 duplicates of
this.

[Bug c++/81347] g++ confused by namespaces and friend classes

2017-11-21 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81347

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #4 from Richard Smith  ---
Duplicate of bug#59930 (friend class templates in class templates get injected
into the global namespace instead of the innermost enclosing namespace)?

[Bug c++/64816] gcc claims that constructor is private when it should be accessible

2017-11-21 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64816

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #5 from Richard Smith  ---
Possibly a duplicate of bug#59930? (It looks like class-scope friend class
template declarations sometimes inject the class template into the wrong
namespace, specifically if the template containing the friend is instantiated
before the befriended template is declared.)

[Bug c++/78724] Incorrect ambiguous reference error when template class was forward declarated as a friend

2017-11-21 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78724

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #1 from Richard Smith  ---
Probable duplicate of bug#59930 (friend class templates injected into wrong
namespace).

[Bug c++/65157] Unable to define a static template member function of a nested class as a friend of a sibling class.

2017-11-21 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65157

Richard Smith  changed:

   What|Removed |Added

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

--- Comment #2 from Richard Smith  ---
Clang is wrong; lookup for B::Create should fail because B is a dependent type,
which is what happens in GCC and EDG. Adding this before 'main' crashes Clang:

template<> class A::B {};
A::C c;

(Internally, Clang is marking the friend declaration as invalid, but failing to
actually produce a corresponding diagnostic.)

Filed as bugs.llvm.org/PR35377.

[Bug c++/52130] missing check for matching underlying type during instantiation of enum member of class template

2017-08-18 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52130

--- Comment #3 from Richard Smith  ---
The diagnostic in #1 is not only wrong for this case, it's also a rejects-valid
in the case where the underlying types match. I've filed
https://gcc.gnu.org/PR81895 for that.

[Bug c++/81895] New: gcc rejects out-of-line definition of enum member of class template under -pedantic-errors

2017-08-18 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81895

Bug ID: 81895
   Summary: gcc rejects out-of-line definition of enum member of
class template under -pedantic-errors
   Product: gcc
   Version: 7.2.1
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: ---

g++ -std=c++11 -pedantic-errors has a rejects-valid on this:

template struct S { enum class E : int; };
template enum class S::E : int { e };
S::E x = S::E::e;

The bogus error is:

error: 'enum S::E' is an enumeration template [-Wpedantic]

[Bug c++/81145] bogus "dereferencing type-punned pointer will break strict-aliasing rules" diagnostic with incomplete class type

2017-06-20 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81145

--- Comment #5 from Richard Smith  ---
Yes, according to godbolt this occurs in GCC 4.4 - 7.1, but not in trunk.
Unlike PR80593, it does not appear to be a GCC 7 regression, but it sure seems
plausible that that change fixed it =)

[Bug c++/81145] bogus "dereferencing type-punned pointer will break strict-aliasing rules" diagnostic with incomplete class type

2017-06-20 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81145

--- Comment #2 from Richard Smith  ---
I've tried a few things and not found any way to get wrong code. I think you're
right that this is just a diagnostic issue.

[Bug c++/81145] New: bogus "dereferencing type-punned pointer will break strict-aliasing rules" diagnostic with incomplete class type

2017-06-20 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81145

Bug ID: 81145
   Summary: bogus "dereferencing type-punned pointer will break
strict-aliasing rules" diagnostic with incomplete
class type
   Product: gcc
   Version: 7.0.1
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 B { int n; };
struct A
#ifndef BUG
 { B b; }
#endif
;

extern A a;
int n = reinterpret_cast<B*>()->n;

This produces a bogus "dereferencing type-punned pointer will break
strict-aliasing rules" diagnostic with -DBUG, but correctly suppresses the
warning when the definition of A is visible.

Note that under C++ P0137R1 / DR1776, the A object is pointer-interconvertible
with its b member, so the reinterpret_cast produces a usable pointer to a.b,
regardless of whether the definition of A is visible.

Perhaps GCC's TBAA should be less aggressive when comparing an incomplete type
against (at least) a standard-layout type?

[Bug demangler/80513] demangler walks past trailing nul in mangled name in a bunch of cases

2017-04-25 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80513

--- Comment #1 from Richard Smith  ---
While we're here, this check for overflow in consume_count is nonsense, and any
decent optimising compiler is going to optimise away the overflow check:

https://github.com/gcc-mirror/gcc/blob/master/libiberty/cplus-dem.c#L525

Testcase:

$ echo '_Z4294967297x' | c++filt
x

Oops.


It looks like item 2 in comment#0 was fixed recently
(https://github.com/gcc-mirror/gcc/commit/b2dcfe3da47412480529c8591ba0433cd495fbe3)
but item 1 is still live.

[Bug demangler/80513] New: demangler walks past trailing nul in mangled name in a bunch of cases

2017-04-24 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80513

Bug ID: 80513
   Summary: demangler walks past trailing nul in mangled name in a
bunch of cases
   Product: gcc
   Version: 7.0.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: demangler
  Assignee: unassigned at gcc dot gnu.org
  Reporter: richard-gccbugzilla at metafoo dot co.uk
  Target Milestone: ---

Example mangled name where demangler walks past two nuls:

$ echo '__thunk_16\0_\0_3foo' | c++filt 
virtual function thunk (delta:-16) for foo::~foo(void)

These are two separate bugs:

1) The gnu_special __thunk_ handling blindly assumes (without checking) that
the byte after __thunk_ is an underscore, and skips it:

  else if (strncmp (*mangled, "__thunk_", 8) == 0)
{
  int delta;

  (*mangled) += 8;
  delta = consume_count (mangled);
  if (delta == -1)
success = 0;
  else
{
  char *method = internal_cplus_demangle (work, ++*mangled);

2) The calls to "strchr (some_chars, mangled[i]) != NULL" throughout
cplus-dem.c are all wrong, as they do not properly handle the case where
mangled[i] is 0. (In that case, strchr returns a *non-null* pointer to the nul
terminator of some_chars.)

[Bug c++/79668] New: [c++1z] inconsistent handling of parameter matching in template template arguments

2017-02-21 Thread richard-gccbugzilla at metafoo dot co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79668

Bug ID: 79668
   Summary: [c++1z] inconsistent handling of parameter matching in
template template arguments
   Product: gcc
   Version: 7.0.1
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: ---

Consider the following:

template<template typename> struct A;
template typename> struct B;
template struct C;
A *ac;
B<short, C> *bc;

It should hopefully be clear that the type 'A' is valid if and only if the
type 'B<short, C>' is valid. However, under -std=c++1z, GCC accepts 'A' but
rejects 'B<short, C>':


:5:11: error: type/value mismatch at argument 2 in template parameter
list for 'template class >
struct B'
B<short, C> *bc;
^
:5:11: note:   expected a template of type 'template
class', got 'template struct C'
Compiler exited with result code 1


Note that the above error is also the one produced outside C++1z mode, so
perhaps whatever special handling is engaged for P0522R0 is missed in the case
where the template template parameter is dependent?

FWIW, Clang's implementation of P0522R0 accepts both cases.

  1   2   >