[Bug c++/114764] noexcept on a friend complains about incomplete type

2024-04-20 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114764

--- Comment #7 from Giuseppe D'Angelo  ---
I get it :)

If you wanted an actual use-case (rather than a synthetic testcase), we
stumbled upon this bug from implementing a friend operator==:


```
class S {

  bool comparesEqual(S, S) noexcept; // pass by value, object is
small/trivially copyable
  friend inline bool operator==(S a, S b) noexcept(noexcept(comparesEqual(S,
S))) {
 returns comparesEqual(a, b);
  }
};
```

which is the result of some macro expansions through which we support C++20's
comparisons in C++17 in Qt. The problem is the pass by value -- changing it to
pass by const-ref fixes it, but generates different linting about not passing a
small TC object by value...

[Bug c++/114764] noexcept on a friend complains about incomplete type

2024-04-19 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114764

--- Comment #5 from Giuseppe D'Angelo  ---
Just to understand, are we talking about an implementation challenge (because
within a class you may refer to stuff not yet declared when parsing the
noexcept spec, or similar), or that using noexcept on a friend "doesn't make
sense"?

[Bug c++/114764] noexcept on a friend complains about incomplete type

2024-04-18 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114764

--- Comment #3 from Giuseppe D'Angelo  ---
I guess you're referring to https://lists.isocpp.org/core/2019/07/6785.php ?

I'm really not sure why a friend function declaration is different from a free
function, where multiple equivalent declarations are allowed?

Btw, the "real" case was a definition of a friend (hidden friend). Could at
least that be supported?

[Bug c++/114764] New: noexcept on a friend complains about incomplete type

2024-04-18 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114764

Bug ID: 114764
   Summary: noexcept on a friend complains about incomplete type
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Testcase:

struct S
{
S(int) noexcept;

   void f() noexcept(noexcept(S(42)));
friend void g() noexcept(noexcept(S(42)));
};


https://godbolt.org/z/qn5Gs4M63



GCC 14 trunk rejects with:

:6:43: error: invalid use of incomplete type 'struct S'
6 | friend void g() noexcept(noexcept(S(42)));
  |   ^
:1:8: note: definition of 'struct S' is not complete until the closing
brace
1 | struct S
  |^
Compiler returned: 1



But that does not seem to be accurate:
https://eel.is/c++draft/class.mem.general#7 says "A complete-class context of a
class (template) is a [...] noexcept-specifier ([except.spec]) [...]  within
the member-specification of the class or class template." and a friend
declaration/definition is a member-specification.

This is possibly related to bug 70077.

For comparison Clang rejects, but MSVC accepts.

[Bug middle-end/114029] New: -Warray-bounds does not warn for global arrays

2024-02-21 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114029

Bug ID: 114029
   Summary: -Warray-bounds does not warn for global arrays
   Product: gcc
   Version: 13.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: middle-end
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Testcase https://gcc.godbolt.org/z/n3zPPE7bq


const int test[]={1, 2, 3};

int main()
{
return test[3];
}



GCC doesn't warn under -O2 -Wall. It does emit a -Warray-bounds warning if the
`test` array is moved inside `main`; but why not warning for a global variable?

For comparison, Clang always warns (even without any optimization/warning
flag).

[Bug libstdc++/113060] std::variant converting constructor/assignment is non-conforming after P2280?

2024-02-20 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113060

--- Comment #9 from Giuseppe D'Angelo  ---
Thank you, I'll amend P3146 with this new information, and try and make sure
that LEWG/LWG see the updated draft (if they discuss this before the next
mailing).

[Bug libstdc++/113060] std::variant converting constructor/assignment is non-conforming after P2280?

2024-02-19 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113060

--- Comment #7 from Giuseppe D'Angelo  ---
Hi,

> Note that this example adds a mediate function template 
> (test_array_element_initializable) to "reduce" the non-constexpr-ness of 
> std::declval.

That's very clever, thank you! 

Is it _supposed_ to work, though? I had imagined (possibly erroneusly) that
once one places the call to `test_array_element_initializable` using `declval`
as an argument, it would disqualify the whole thing from being usable in
constant expressions.

(It would help to have another compiler that implements P2280, so to do more
tests...)

[Bug libstdc++/112477] [13/14 Regression] Assignment of value-initialized iterators differs from value-initialization

2024-01-09 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112477

--- Comment #7 from Giuseppe D'Angelo  ---
Hi,

To be honest I didn't even notice it was a regression, but you're absolutely
right, I can't reproduce my problem with GCC 12, only with GCC 13 (both in
C++17 mode).

[Bug libstdc++/113060] std::variant converting constructor/assignment is non-conforming after P2280?

2023-12-18 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113060

--- Comment #2 from Giuseppe D'Angelo  ---
(In reply to Jonathan Wakely from comment #1)
> (In reply to Giuseppe D'Angelo from comment #0)
> > GCC 14 implements P2280 (see #106650). 
> 
> N.B. if you say "Bug 106650" or "PR 106650" or "bug #106650" or pretty much
> anything except just #106650 then bugzilla makes it a clickable link :)

D'oh! 


> > it seems that variant should indeed accept construction from IC.
> 
> I'm not convinced that this change to the semantics of std::variant was an
> intended side effect of https://wg21.link/P2280 -- I think I'd prefer if the
> committee confirmed it.

Ok, I'll raise the question to LEWG. Or maybe EWG?


> The standard doesn't say that it _should_ work in a constant expression, it
> seems like you're assuming that because it's now possible to implement it so
> that it works, that it's required to work.
> 
> My reading of [variant.ctor] p14 is that "some invented variable x" is not a
> constant expression, so using std::declval as a stand-in for "some invented
> variable" is fine.


But it does say how you get that x, you get it from the statement:

  Tj x[] = {std​::​forward(t)};

Nowhere in there's a call to declval. My reasoning is simply that if you spell
FUN out for Ti = float, something like this (although the standard doesn't
really specify the signature of FUN, which is not ideal):

  template 
  auto FUN_float(T &) {
  float x[] = {std​::​forward(t)};
  }

then FUN_float(IC{}) is well-formed after P2280.

Note that in general

  IC c;   // not const!!!
  float f{c}; // OK

is well-formed, and this is even before P2280. What seems to have changed with
P2280 is that references do not disqualify expressions from being constant, and
thus we can now detect this case a requires-expression that uses references.


> If we made this change, then some cases that compile today would become
> ill-formed, e.g. see PR 113007. Under your reading, conversion from the
> constant 42 would be valid for both int64_t and double, and so the
> initialization would be ill-formed. But it would be well-formed when using a
> non-constant int equal to 42.

Are you sure it would? FUN_double(42) should be still ill-formed (!), due to
narrowing. 

My reasoning, in the context of P0870 (is_convertible_without_narrowing), is
that int->double requires a lvalue-to-rvalue conversion, and then this kicks in
https://eel.is/c++draft/expr.const#5.9 , disqualifying `t` from being treated
as a constant expression. So then the list-initialization of `x` triggers
narrowing.

This is different from IC->double, where there's no lvalue-to-rvalue conversion
(!), it's described here
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0870r5.html#ch5.9

Testcase: https://gcc.godbolt.org/z/rfvnfvYzs


> Apart from the fact it would be a breaking change, the difference in
> behaviour between runtime and compile time would be surprising. It would
> also mean that std::is_constructible would be misleading: it would say you
> can construct variant from 42, but when you try to do that it
> would fail to compile.

Sure, I'm really struggling at squaring the P2280 rules with detecting
narrowing conversions, but I'm not sure if this would actually break. (And I'm
not sure if something _else_ would break instead.)

[Bug libstdc++/113060] New: std::variant converting constructor/assignment is non-conforming after P2280?

2023-12-18 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113060

Bug ID: 113060
   Summary: std::variant converting constructor/assignment is
non-conforming after P2280?
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

GCC 14 implements P2280 (see #106650). 

As a side effect of that, the "narrowing detector" used in std::variant's
converting constructor/assignment is now too restrictive. This code:


// IC is a type with a constexpr conversion operator
using IC = std::integral_constant;
std::variant v( IC{} );

should work after P2280 (libstdc++ says ill-formed).

---

https://eel.is/c++draft/variant.ctor#14 says:

> Let Tj be a type that is determined as follows: build an imaginary function 
> FUN(Ti) for each alternative type Ti for which Ti x[] = 
> {std​::​forward(t)}; is well-formed for some invented variable x.
> The overload FUN(Tj) selected by overload resolution for the expression 
> FUN(std​::​forward(​t)) defines the alternative Tj which is the type of 
> the contained value after construction.


Right now libstdc++ implements this by means of SFINAE:

> https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/variant#L787-L823


IC is convertible to float, and given the constexpr nature of its conversion
operator (to int), it wouldn't be a narrowing conversion:

  IC ic;
  float f{ic}; // not narrowing

However, using SFINAE means that std::declval() is used to build the
"candidate" argument of FUN. declval is not a constexpr function so its
returned value is not considered to be usable in constant expressions. 

The net effect is that `Ti x[] = {std​::​forward(t)};` is considered to be a
narrowing conversion ([dcl.init.list], int->float, source is not a constant
expression), and FUN(float) rejected.

But nowhere does [variant.ctor] talk about using std::declval; if one
reimplements the same check with a constraint, then GCC 14 accepts the
conversion:

template 
concept FUN_constraint = requires(T &) {
{ std::type_identity_t{ std::forward(t) } };
};

template 
requires FUN_constraint
void FUN(float);

FUN( IC{} ); // OK

https://gcc.godbolt.org/z/xP9z97v35

P2280 is necessary to make this work, because otherwise the usage of a
reference in the requires-expression would make `t` again not usable in
constant expressions. In conclusion, it seems that variant should indeed
accept construction from IC.

(I can't cross-check this report with other compilers as none of them
implements P2280 yet.)

[Bug tree-optimization/112637] New: Bogus -Wmaybe-uninitialized warning

2023-11-20 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112637

Bug ID: 112637
   Summary: Bogus -Wmaybe-uninitialized warning
   Product: gcc
   Version: 13.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: tree-optimization
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Testcase from Qt: https://gcc.godbolt.org/z/6brn9Knra


class QBenchmarkIterationController
{
public:
QBenchmarkIterationController() noexcept;
bool isDone() const noexcept;
void next() noexcept;
};

class QBenchmarkIterationControllerWrapper {
QBenchmarkIterationController controller;
bool first = true;

public:
QBenchmarkIterationControllerWrapper() = default;
bool isDone() const noexcept { return !first && controller.isDone(); }
void next() noexcept { first = false; controller.next(); }
};



int f() noexcept;
void check(bool);

void testcase()
{
int result;

for (QBenchmarkIterationControllerWrapper w; !w.isDone(); w.next())
result = f();

check(result == 42);
}


With warnings enabled and any level of optimization enabled, results in:


: In function 'void testcase()':
:31:10: warning: 'result' may be used uninitialized
[-Wmaybe-uninitialized]
   31 | check(result == 42);
  | ~^~
:26:9: note: 'result' was declared here
   26 | int result;
  | ^~



But this is bogus, as the loop is always entered at least once. 

Removing the declaration of QBenchmarkIterationController's constructor makes
the warning disappear.



Upstream Qt patch discussion:
https://codereview.qt-project.org/c/qt/qtbase/+/518574

[Bug libstdc++/112477] Assignment of value-initialized iterators differs from value-initialization

2023-11-10 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112477

Giuseppe D'Angelo  changed:

   What|Removed |Added

  Component|c++ |libstdc++

--- Comment #1 from Giuseppe D'Angelo  ---
Sorry, I've accidentally selected the wrong component.

[Bug c++/112477] New: Assignment of value-initialized iterators differs from value-initialization

2023-11-10 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112477

Bug ID: 112477
   Summary: Assignment of value-initialized iterators differs from
value-initialization
   Product: gcc
   Version: 13.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

In debug mode there seems to be a difference between a value-initialized
iterator, and an iterator that gets assigned from a value-initialized iterator.

Testcase: https://gcc.godbolt.org/z/hW7d7Pao3

#define _GLIBCXX_DEBUG
#include 

int main() {
using M = std::map;
using I = M::iterator;

M map{ {1, 1}, {2, 2} };

I it1 = map.begin();
it1 = I{};

I it2{};
(void)(it1 == it2); 
}

Results in 

  Error: attempt to compare a singular iterator to a 
  singular (value-initialized) iterator.


It's not entirely clear to me why this shouldn't "just work™", although this is
probably threading the needle; assignment *from* a singular iterator isn't
really discussed in https://eel.is/c++draft/iterator.requirements.general#7 nor
in https://eel.is/c++draft/forward.iterators#2 . 

(One may argue that this last sentence was added by N3644, when iterators still
required copiability, so copying a value-constructed iterator should have value
semantics and the result be indistinguishable from value-initializing...)

[Bug libstdc++/58338] Add noexcept to functions with a narrow contract

2023-07-09 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58338

Giuseppe D'Angelo  changed:

   What|Removed |Added

 CC||dangelog at gmail dot com

--- Comment #17 from Giuseppe D'Angelo  ---
Hi,

How does all of this intersect with the Lakos' Rule (cf. the very recent P2837
and P2861)? I get that implementations have the freedom of strenghtening the
noexcept contract; but is this patch following some specific libstdc++ policy
(documented somewhere) -- such as, if a precondition violation is detected,
libstdc++ just abort()s the process, so technically speaking, it never throws?

[Bug c++/110404] Feature request: add a new option which is like -ftrivial-auto-var-init=zero but zero-initialize instead of zero-fill

2023-06-26 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110404

--- Comment #2 from Giuseppe D'Angelo  ---
(In reply to Richard Biener from comment #1)
> But your testcase is invoking undefined behavior when inspecting 'ptr'? 
> That doesn't change with -ftrivial-auto-var-init=zero, so getting a trap is
> good
> here and you need to fix your code instead.

Hi,

Well, the point of -ftrivial-auto-var-init=zero is to turn that UB in a
specific  behavior, that is, to read 0. From a formal point of view, this is a
perfectly valid expression of UB.

The problem I'm raising above is that I'd like reads of uninitialized pointers
to yield nullptr, which is currently not the case of pointers to data members
on Itanium.

--

Then there's the question regarding whether GCC can "see the UB" and e.g.
optimize the whole thing away, based on reasonings like "this code exhibits UB,
therefore it can never be called, therefore it's dead, therefore I can remove
it".

I don't know if this is actually the case at the moment, but if it is, I'd
consider it a *different* bug report. The whole point of
-ftrivial-auto-var-init=zero is to prevent that sort of UB from manifesting
itself (by zero-filling the storage); to prevent leaking "secrets" (leaks that
imply an uninitialized read anyhow, so UB);  etc.

I am not able at the moment to prove or disprove this using GCC. Clang however
disables such UB-optimizations when using -ftrivial-auto-var-init=zero :

https://gcc.godbolt.org/z/qhMxM11jE

[Bug middle-end/110375] -ftrivial-auto-var-init=zero issues with pointers to data members

2023-06-25 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110375

--- Comment #5 from Giuseppe D'Angelo  ---
Done in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110404 .

[Bug c++/110404] New: Feature request: make -ftrivial-auto-var-init=zero zero-initialize, not zero-fill

2023-06-25 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110404

Bug ID: 110404
   Summary: Feature request: make -ftrivial-auto-var-init=zero
zero-initialize, not zero-fill
   Product: gcc
   Version: 13.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hello,

This is the same report as bug 110375, however turned into a wishlist/feature
request for the C++ front-end.


Right now -ftrivial-auto-var-init=zero is a middle-end feature that zero-fills
storage for automatic variables. 0x00 is a bit pattern that works _almost_
universally to set a "safe" default. However, pointers to data members are a
problem: on Itanium, a null pointer to data member is represented by -1u, and
not 0.


https://itanium-cxx-abi.github.io/cxx-abi/abi.html#data-member-pointers


This means that this snippet hits the assert under
-ftrivial-auto-var-init=zero:


#include 
struct S {};

int main() {
int S::*ptr;
assert(ptr == nullptr);
}

https://gcc.godbolt.org/z/7sb6GcbPE



IMHO it would be more useful to have -ftrivial-auto-var-init=zero to mean "to
_value-initialize_ automatic variables" (and zero-fill padding bits), including
non-static data members of classes, recursively, before a constructor is
eventually run. 

Such value-initialization for scalar types resolves into zero-initialization
(and *not* zero-filling), as per https://eel.is/c++draft/dcl.init#general-9.3 ,
so the name "=zero" is still somehow appropriate. The difference is that
zero-initialization will correctly sets *all* pointers types to null.

--

Regarding whether one should change -ftrivial-auto-var-init=zero semantics or
introduce a new command line option, I'd rather change the semantics. The fact
that it's currently a middle-end feature is not interesting at all for the
end-user. In their mind, what they want is zero-initialization, not
zero-filling (aka any sort of pointer is nullptr, any arithmetic is 0, etc;
irregardless of ABI).

For the C front-end, this shouldn't mean any change (unless GCC runs on some C
ABI where pointers or floating pointes aren't all 0-bits?). For the C++
front-end, this means fixing pointers to data members Itanium.

--

References:
* https://github.com/llvm/llvm-project/issues/63471 twin bug report
* https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2723r1.html that
aims to zero-initialize variables with automatic storage, but erronousely say
that GCC and Clang already implement this feature.

[Bug middle-end/110375] -ftrivial-auto-var-init=zero issues with pointers to data members

2023-06-24 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110375

--- Comment #4 from Giuseppe D'Angelo  ---
(In reply to Andrew Pinski from comment #3)
> (In reply to Giuseppe D'Angelo from comment #2)
> > (In reply to Andrew Pinski from comment #1)
> > > The code is undefined,
> > 
> > Sure, although there are C++ proposals to make it well-defined /
> > implementatiopn-defined (see
> > https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2723r1.html and
> > https://isocpp.org/files/papers/P2795R1.html).
> > 
> > But that's beside the point, I'm not claiming that the code does not have UB
> > -- although I'm not sure whether, if -ftrivial-auto-var-init is in use, an
> > optimizer stops considering such reads as UB. At least Clang stops:
> > https://gcc.godbolt.org/z/bKW5Mccsa
> 
> But those proposals will be done in the front-end

That's not P2723R1's claim. Quoting:

"We propose to zero-initialize all objects of automatic storage duration,
making C++ safer by default.

This was implemented as an opt-in compiler flag in 2018 for LLVM [LLVMReview]
and MSVC [WinKernel], and 2021 in for GCC [GCCReview]."


This report (and Clang's) shows that that's misleading.


> while
> -ftrivial-auto-var-init=zero is a generic non-front-end option. The
> middle-end will see the right thing and that option will not have an effect
> really.


Fair enough; then, please, could this report be turned into a feature request
for the C/C++ frontends?

[Bug middle-end/110375] -ftrivial-auto-var-init=zero issues with pointers to data members

2023-06-24 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110375

--- Comment #2 from Giuseppe D'Angelo  ---
(In reply to Andrew Pinski from comment #1)
> The code is undefined,

Sure, although there are C++ proposals to make it well-defined /
implementatiopn-defined (see
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2723r1.html and
https://isocpp.org/files/papers/P2795R1.html).

But that's beside the point, I'm not claiming that the code does not have UB --
although I'm not sure whether, if -ftrivial-auto-var-init is in use, an
optimizer stops considering such reads as UB. At least Clang stops:
https://gcc.godbolt.org/z/bKW5Mccsa



> the point to initialize it something which might be
> safe enough for most cases. Yes in the case of pointer to data members, it
> is not the same as null but that is ok, it is still intialized to something.

What I'm asking is to make it safe for *more* cases, so I don't see what's
wrong with such a feature request. -ftrivial-auto-var-init has several options
precisely because one may want different bit patterns of initialization for
various purposes (safety/ease of debugging/...); right now it's just 

* all 0 (=zero)
* all 0xFE (=pattern)


Something that zero-initializes is missing, and I'm asking to make =zero do so.

--

Anyhow, this is useful information, because P2795R1 claims its proposed
behavior is already implemented by GCC, while it actually isn't. It also isn't
by Clang (twin bug report https://github.com/llvm/llvm-project/issues/63471 ).

[Bug middle-end/110375] New: -ftrivial-auto-var-init=zero issues with pointers to data members

2023-06-23 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110375

Bug ID: 110375
   Summary: -ftrivial-auto-var-init=zero issues with pointers to
data members
   Product: gcc
   Version: 13.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: middle-end
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

-ftrivial-auto-var-init=zero is documented to "Initialize automatic variables
with zeroes". 

I assume that means to memset(0) their storage. 0 is a bit pattern that works
_almost_ universally to set a "safe" default. However, pointers to data members
are a problem: on Itanium, a null pointer to data member is represented by -1u,
and not 0.

https://itanium-cxx-abi.github.io/cxx-abi/abi.html#data-member-pointers


This means that this snippet hits the assert under
-ftrivial-auto-var-init=zero:


#include 
struct S {};

int main() {
int S::*ptr;
assert(ptr == nullptr);
}

https://gcc.godbolt.org/z/7sb6GcbPE


IMHO it would be more useful to have -ftrivial-auto-var-init=zero to mean "to
_value-initialize_ automatic variables", including non-static data members of
classes, recursively, before a constructor is eventually run. 

Such value-initialization for scalar taypes resolves into zero-initialization
(and *not* zero-filling), as per https://eel.is/c++draft/dcl.init#general-9.3 ,
so the name "=zero" is still somehow appropriate. The difference is that
zero-initialization will correctly sets *all* pointers types to null.

[Bug libstdc++/108846] std::copy, std::copy_n and std::copy_backward on potentially overlapping subobjects

2023-03-02 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108846

--- Comment #20 from Giuseppe D'Angelo  ---
Thanks for the patch!

Should ranges_algobase.h also be similarly changed? There's a memmove in its
copy/move code as well:

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/include/bits/ranges_algobase.h;hb=HEAD#l263

[Bug libstdc++/108846] std::copy, std::copy_n and std::copy_backward on potentially overlapping subobjects

2023-02-25 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108846

--- Comment #15 from Giuseppe D'Angelo  ---
That's not what I meant; a type can be trivial(ly copyable) and move-only.

Here's a modification of Arthur's example:

// move-only
struct B {
B(int i, short j) : i(i), j(j) {}
B(B &&) = default;
B =(B &&) = default;
int i;
short j; 
};
struct D : B {
D(int i, short j, short x) : B(i, j), x(x) {}
D(D &&) = default;
D =(D &&) = default;
short x;
};
int main() {
D ddst(1, 2, 3);
D dsrc(4, 5, 6);
B *dst = 
B *src = 
static_assert(std::is_trivially_copyable_v);

std::move(src, src+1, dst);
assert(ddst.x == 3); 
}


The call to std::move ends up in the same memmove codepath as std::copy_n (B is
trivially copyable), but with the proposed patch it will fail to compile
because it's not actually copy assignable.

[Bug libstdc++/108846] std::copy, std::copy_n and std::copy_backward on potentially overlapping subobjects

2023-02-24 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108846

--- Comment #12 from Giuseppe D'Angelo  ---
(In reply to Jonathan Wakely from comment #9)
> (In reply to Giuseppe D'Angelo from comment #5)
> > https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/
> > stl_algobase.h#L417-L437
> > 
> > Is the extent of the fix just to add another branch to the if (_Num) check
> > here?
> 
> Yes, I think that's the simplest place to fix it.
> 
> And we can even get rid of the static assertion, because the Num==1 branch
> will require assignability now.
> 
> --- a/libstdc++-v3/include/bits/stl_algobase.h
> +++ b/libstdc++-v3/include/bits/stl_algobase.h
> @@ -737,16 +737,11 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
> static _Tp*
> __copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result)
> {
> -#if __cplusplus >= 201103L
> - using __assignable = __conditional_t<_IsMove,
> -  is_move_assignable<_Tp>,
> -  is_copy_assignable<_Tp>>;
> - // trivial types can have deleted assignment
> - static_assert( __assignable::value, "type must be assignable" );
> -#endif
>   const ptrdiff_t _Num = __last - __first;
> - if (_Num)
> + if (__builtin_expect(_Num > 1, true))
> __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num);
> + else if (_Num == 1)
> +   *__result = *__first;
>   return __result - _Num;
> }
>  };


If this code path also takes care of std::move(b,e,o), then this doesn't sound
correct -- for _Num==1 and _IsMove==true, then it should use a move assignment
(std::move(*__first)). But then that std::move doesn't actually work as __first
is a pointer to const...

[Bug libstdc++/108846] std::copy, std::copy_n on potentially overlapping subobjects

2023-02-20 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108846

--- Comment #5 from Giuseppe D'Angelo  ---
> In the case of copy family algorithms, I believe it's OK to specially handle 
> cases where last - first == 1.

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_algobase.h#L417-L437

Is the extent of the fix just to add another branch to the if (_Num) check
here? I've just tried locally, and it seems to work. It also doesn't seem that
libstdc++ uses memcpy/memmove elsewhere (e.g. in std::fill).

[Bug c++/99625] GCC does not detect narrowing in aggregate initialization

2022-11-15 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99625

--- Comment #5 from Giuseppe D'Angelo  ---
No problem, thanks for working on GCC :)

[Bug c++/99625] GCC does not detect narrowing in aggregate initialization

2022-11-15 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99625

--- Comment #3 from Giuseppe D'Angelo  ---
Hi,

Sorry to ping, but some time has gone by -- I guess this fell through the
cracks?

[Bug c++/107697] New: -Wredundant-move misses std::move applied to const objects (instead of const references)

2022-11-15 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107697

Bug ID: 107697
   Summary: -Wredundant-move misses std::move applied to const
objects (instead of const references)
   Product: gcc
   Version: 13.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hi,

Consider this testcase:



#include 

using T = std::vector;

void f(T); 

void use1(const T t)  { f(std::move(t)); }
void use2(const T ) { f(std::move(t)); }
void use3() {
const T t;
f(std::move(t));
}




Currently -Wredundant-move warns only for case 2. But in all three cases
std::move is actually not doing anything good (copy constructor is always
selected). It would be nice if they all were diagnosed.

If I change `f` to `void f(const T &)` then there's no warning at all. I'm
thinking that probably this case should be diagnosed as well.

Clang-tidy's performance-move-const-arg diagnoses them all.

[Bug libstdc++/107525] propagate_const should not be using SFINAE on its conversion operators

2022-11-04 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107525

--- Comment #9 from Giuseppe D'Angelo  ---
(In reply to Jonathan Wakely from comment #5) 
> Please don't! At least not in the next 9 days. We intend to vote out LFTSv3
> at next week's meeting, there will be no more proposals for LFTS considered.
> And I don't want to derail the vote next week by having open proposals
> arriving at the last minute.

No problem, I wouldn't have done this before a few weeks anyhow.


> Feel free to file a library issue though. If propagate_const ever gets
> proposed for inclusion in the standard then this should be taken into
> account.

OK.

Thank you very much for the prompt fix.

(Ville: guess what, this bug stem from trying to make uic and friends use
propagate_const. Small world!)

[Bug libstdc++/107525] propagate_const should not be using SFINAE on its conversion operators

2022-11-04 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107525

--- Comment #4 from Giuseppe D'Angelo  ---
(In reply to Jonathan Wakely from comment #1)
> (In reply to Giuseppe D'Angelo from comment #0)
> > So. ideally, the conversion operators should be using C++20 constraints, but
> > of course that's not possible.
> 
> It's totally possible for C++20 mode.
> 
> I don't know how much motivation anybody has to do anything about this
> though.

Sorry, what I meant is, of course there is interest at keeping this code to
compile in pre-C++20 mode, and possibly have the same semantics no matter
what's the language version used? Or is it acceptable to have such an "API
break"? (E.g. stuff like `is_convertible_v, Base *>`
changes value.)


> And the spec seems wrong as well. The const overload should be constrained 
> for const T being convertible to const element_type*.

Yes, that sounds like a defect to me.

--

More in general, I think these operators are strangely defined. I'm not sure
why they're not simply defined to be 

  template  operator U *() requires (std::is_convertible_v);

mut.mut. for the `const` version. 

The current definition also allows for pointer arithmetic (only if one uses a
C++20 constraint, otherwise it doesn't work), which is something the original
paper says it does NOT want to support. And the current definition allows for
`delete`ing a propagate_const, which maybe is wanted, but in contradiction with
the lack of support for pointer arithmetic.

I guess I'll need to submit a paper.

[Bug libstdc++/107525] New: propagate_const should not be using SFINAE on its conversion operators

2022-11-04 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107525

Bug ID: 107525
   Summary: propagate_const should not be using SFINAE on its
conversion operators
   Product: gcc
   Version: 12.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

propagate_const in the LFTSv3 has implicit conversion operators which have
constraints on them:

https://cplusplus.github.io/fundamentals-ts/v3.html#propagate_const.const_observers

> constexpr operator const element_type*() const;
> 
> Constraints:
>T is an object pointer type or has an implicit conversion to const 
> element_type*. 
> Returns:
>get().

libstdc++ implements these constraints by means of SFINAE on the operators.
This is user-hostile: using SFINAE means that the conversion operator is now a
function template, and that means that https://eel.is/c++draft/over.ics.user#3
kicks in:

> If the user-defined conversion is specified by a specialization of a 
> conversion function template, the second standard conversion sequence shall 
> have exact match rank.


Concretely, this means that for instance we lose implicit conversions towards
base classes of the pointed-to type:

std::experimental::propagate_const ptr;

Derived *d1 = ptr;  // Convert precisely to Derived *: OK
Base *b1= ptr;  // Convert to a pointer to a base: ERROR

Base *b2= static_cast(ptr); // OK
Base *b3= static_cast(ptr);// ERROR

Base *b4= ptr.get();  // OK


But these should all work. The design of propagate_const is for it to be
"drop-in replacement", maximizing compatibility with existing code.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4388.html says
explictly

"When T is an object pointer type operator value* exists and allows implicit
conversion to a pointer. This avoids using get to access the pointer in
contexts where it was unnecesary before addition of the propagate_const
wrapper."

--

So. ideally, the conversion operators should be using C++20 constraints, but of
course that's not possible. I guess that a reasonable alternative would be to
isolate them in a base class, and apply SFINAE on that base class instead?

[Bug c++/107507] New: Conversion function templates are not sometimes not considered if the return type is type dependent

2022-11-02 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107507

Bug ID: 107507
   Summary: Conversion function templates are not sometimes not
considered if the return type is type dependent
   Product: gcc
   Version: 12.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Testcase:

template 
struct Test {
template 
operator T();
};

int main() {
Test t;

int *x = t; // OK
int *y = t + 42; // ERROR
}



: In function 'int main()':
:20:16: error: no match for 'operator+' (operand types are 'Test'
and 'int')
  228 | int *y = t + 42;
  |  ~ ^ ~~
  |  |   |
  |  |   int
  |  Test




This seems to depend on whether the conversion operators themselves are
function templates that return a type dependend on T. For instance, this works:


template 
struct Test {
template 
operator int *(); // don't return a type that depends on T
};

int main() {
Test t;

int *x = t; 
int *y = t + 42; // OK
}



And also this works:



template 
struct Test {
operator T(); // not a template
};

int main() {
Test t;

int *x = t;
int *y = t + 42;
}



I see that conversion function templates are treated in a special way in a
couple of places in the Standard but I'm not sure -- e.g. does
https://eel.is/c++draft/over.ics.user#3 apply here?. For comparison, Clang also
rejects this, while MSVC (in C++latest mode) accepts it.

[Bug c++/107495] GCC does not consider the right contextual implicit conversions

2022-11-01 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107495

--- Comment #1 from Giuseppe D'Angelo  ---
Variation of the above:

  struct Test {
  template 
  operator int *() const;
  };

  Test t;
  delete t;

also fails:

: In function 'int main()':
:32:12: error: default type conversion cannot deduce template argument
for 'template Test::operator int*() const'
   32 | delete t;
  |^
:32:12: error: type 'struct Test' argument given to 'delete', expected
pointer


But here I'm not 100% sure; is there is supposed to be any template argument
deduction? Clang rejects this as well, while MSVC accepts it.

[Bug c++/107495] New: GCC does not consider the right contextual implicit conversions

2022-11-01 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107495

Bug ID: 107495
   Summary: GCC does not consider the right contextual implicit
conversions
   Product: gcc
   Version: 12.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Testcase:

struct Test {
operator int *() const;
operator void *() const;
};

int main() {
Test t;
delete t;
}


GCC rejects this:

: In function 'int main()':
:32:12: error: ambiguous default type conversion from 'Test'
   32 | delete t;
  |^
:32:12: note:   candidate conversions include 'Test::operator void*()
const' and 'Test::operator int*() const'
:32:12: error: type 'struct Test' argument given to 'delete', expected
pointer



But this is wrong. https://eel.is/c++draft/expr.delete#1.sentence-5 says "If of
class type, the operand is contextually implicitly converted to a pointer to
object type" and the attached note explicitly says "This implies that an object
cannot be deleted using a pointer of type void* because void is not an object
type".

The definition of contextual conversion says
https://eel.is/c++draft/conv#general-5 :

"C is searched for non-explicit conversion functions whose return type is cv T
or reference to cv T such that T is allowed by the context. There shall be
exactly one such T."


There is exactly one such T (conversion to pointer of object type), so GCC is
rejecting valid code.

[Bug c++/102396] [11/12 Regression] ICE when using concepts, in get, at cp/constraint.cc:2637 since r11-6245-g79f57d5cb070bb02

2021-12-13 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102396

--- Comment #6 from Giuseppe D'Angelo  ---
That's brilliant! I really hadn't thought that pushing the hidden friend into a
private base would work nonetheless. Thanks!

[Bug c++/102396] [11/12 Regression] ICE when using concepts, in get, at cp/constraint.cc:2637 since r11-6245-g79f57d5cb070bb02

2021-12-09 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102396

--- Comment #4 from Giuseppe D'Angelo  ---
To elaborate on the last comment, this testcase does complain about the
redefinition. 


#include 
#include 


template  class S;

template 
static inline std::true_type is_S_impl(const S&);
static inline std::false_type is_S_impl(...);

template 
concept is_S = decltype(is_S_impl(std::declval()))::value;



template 
struct S {
using type = T;
T data;

S();
explicit S(const T &);

template 
requires is_S && (!is_S) &&
std::equality_comparable_with
friend bool operator==(const V , const U ) { return v.data == u; }
};

void f() {
S s1; s1 == 123;
S s2; s2 == 123.4;
}

[Bug c++/102396] [11/12 Regression] ICE when using concepts, in get, at cp/constraint.cc:2637 since r11-6245-g79f57d5cb070bb02

2021-12-09 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102396

--- Comment #3 from Giuseppe D'Angelo  ---
Hello Patrick,

Thank you for the insights. I'm left wondering however if the CWG resolution
would possibly ever allow the operator== to be defined as a hidden friend; the
workaround you mentioned may lead to redefinition errors (as now it doesn't
depend on S any more)?

[Bug libstdc++/102221] Missed optimizations for algorithms over std::unique_ptr

2021-12-09 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102221

--- Comment #6 from Giuseppe D'Angelo  ---
Hi,

(Sorry for chiming in after all this time); given this might not entirely be
libstdc++ related (cf. the latest testcase), would it be possible for someone
on the optimizer to gave their opinion?

[Bug c++/102283] Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter

2021-10-01 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

--- Comment #5 from Giuseppe D'Angelo  ---
(Sorry for the delay)

Thank you for the analysis. I'm now not really sure if GCC is doing something
wrong (vs Clang/MSVC). Feel free to close/suspend this task if you strongly
believe GCC is right here.

[Bug c++/102399] New: Cannot mix GCC and C++11 / C23 attribute syntax

2021-09-18 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102399

Bug ID: 102399
   Summary: Cannot mix GCC and C++11 / C23 attribute syntax
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hello,

If one tries to mix GCC's attribute syntax (__attribute__) and with C++11 / C23
([[attribute]]), GCC rejects the code (no matter what the order of the
attributes is):


  #define EXPORT __attribute__((visibility("default")))

  struct [[nodiscard]] EXPORT Foo { Foo(); };


https://gcc.godbolt.org/z/W868xjeMq


While a workaround exists (by sticking to the same "kind" of attribute syntax),
it's not always possible or easy to achieve in big codebases, where for
compatibility/legacy reasons the attributes are expanded via macros and can
expand to a random combination of GCC or C++ attributes.

For comparison, Clang and MSVC allow mixed syntaxes.

[Bug c++/102397] New: Documentation of attribute syntax does not discuss C++11 / C23 attribute syntax

2021-09-18 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102397

Bug ID: 102397
   Summary: Documentation of attribute syntax does not discuss
C++11 / C23 attribute syntax
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hi,

The available documentation for attributes syntax 

https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax

does not mention at all the possibility that in C++11 (and, I imagine, in C23)
one can specify any GCC-specific attribute using a [[gnu::attribute]] attribute
specifier, and not only the GCC-specific __attribute__((attribute)) syntax.

I think it would be worth mentioning in there that this is actually OK and
fully supported.

[Bug c++/102396] New: ICE when using concepts, in get, at cp/constraint.cc:2637

2021-09-18 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102396

Bug ID: 102396
   Summary: ICE when using concepts, in get, at
cp/constraint.cc:2637
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hello,

This testcase (which gets accepted by Clang and MSVC) causes an ICE under
GCC-12-trunk, and an erroneous compilation error on GCC 11.2.


#include 
#include 
#include 
#include 

template  struct S;

template  constexpr bool is_S = false;
template  constexpr bool is_S> = true;

template 
struct S {
T data;

S();
explicit S(const T &);

template , bool> = false>
requires std::equality_comparable_with
friend bool operator==(const S , const U ) { return s.data == u; }
};

template 
bool operator==(const S , const S ) { return a.data == b.data; }


int main() {
using SD = S;

char data[sizeof(SD) * 10];
std::span span((SD*)std::begin(data), (SD*)std::end(data));

//static_assert(std::equality_comparable::iterator>);

std::ranges::uninitialized_default_construct(span);
}



The error:



/opt/compiler-explorer/gcc-trunk-20210918/include/c++/12.0.0/concepts:280:17:
internal compiler error: in get, at cp/constraint.cc:2637
  280 |   { __t == __u } -> __boolean_testable;
  | ^~
0x1fc77b9 internal_error(char const*, ...)
???:0
0x713d19 fancy_abort(char const*, int, char const*)
???:0
0x7970af satisfaction_cache::get()
???:0
0x79cd8a constraints_satisfied_p(tree_node*, tree_node*)
???:0
0x9ba323 fn_type_unification(tree_node*, tree_node*, tree_node*, tree_node*
const*, unsigned int, tree_node*, unification_kind_t, int, conversion**, bool,
bool)
???:0
0x73f150 build_new_op(op_location_t const&, tree_code, int, tree_node*,
tree_node*, tree_node*, tree_node**, int)
???:0
0xa2fc50 build_x_binary_op(op_location_t const&, tree_code, tree_node*,
tree_code, tree_node*, tree_code, tree_node**, int)
???:0
0x79cd42 tsubst_requires_expr(tree_node*, tree_node*, int, tree_node*)
???:0
0x79cd8a constraints_satisfied_p(tree_node*, tree_node*)
???:0
0x9ba323 fn_type_unification(tree_node*, tree_node*, tree_node*, tree_node*
const*, unsigned int, tree_node*, unification_kind_t, int, conversion**, bool,
bool)
???:0
0x73f150 build_new_op(op_location_t const&, tree_code, int, tree_node*,
tree_node*, tree_node*, tree_node**, int)
???:0
0xa2fc50 build_x_binary_op(op_location_t const&, tree_code, tree_node*,
tree_code, tree_node*, tree_code, tree_node**, int)
???:0
0x9816d7 instantiate_decl(tree_node*, bool, bool)
???:0
0x9c3e1b instantiate_pending_templates(int)
???:0
0x82a899 c_parse_final_cleanups()
???:0

[Bug c++/102283] Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter

2021-09-15 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

--- Comment #2 from Giuseppe D'Angelo  ---
Hi,

Do you think that in my original testcase the call should be rejected as
ambiguous as well? (It seems "reasonable" to me, but maybe I'm missing some
niche detail about overload resolution when combined with template deduction.)


This small variation over the testcase:


struct A { };
struct B { };

template 
void f(T &&); // #1
void f(const B&) = delete; // #2

int main() {
  f({});
}

This now makes GCC select #2, and fail to compile because it's deleted; Clang
and MSVC still select #1. But a further, minor change:


struct A { };
struct B { };

template  // <-- changed this
void f(T &&); // #1
void f(const B&) = delete; // #2

int main() {
  f({});
}

makes GCC select #1...

[Bug c++/102283] New: Inconsistent/wrong overload resolution when using an initializer list and a defaulted template parameter

2021-09-10 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102283

Bug ID: 102283
   Summary: Inconsistent/wrong overload resolution when using an
initializer list and a defaulted template parameter
   Product: gcc
   Version: 11.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hello,

The following testcase has an "inconsistent" overload resolution:


template 
struct helper {};

struct data {};

template 
struct S 
{
template 
void f(T2 &&); // #1

template 
void f(const helper &); // #2
};

int main() {
S s1;
S s2;
s1.f({});
s2.f({});
}


https://gcc.godbolt.org/z/nsj48M7af


On GCC 11, the the first call to f() resolves to #1, but the second call
resolves to #2. I cannot find any reason for this inconsistency in the ranking
of the overloads; no warnings are emitted under -Wall -Wextra. 

Clang and MSVC both always call #1.

[Bug libstdc++/102221] Missed optimizations for algorithms over std::unique_ptr

2021-09-09 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102221

--- Comment #5 from Giuseppe D'Angelo  ---
Here's a further testcase that doesn't even use unique_ptr:


#include 
#include 

using ptr = int *;
using rawptr = int *;

#ifndef RESTRICT
#define RESTRICT
#endif

void swap(ptr & RESTRICT a, ptr & RESTRICT b) 
{
if (std::addressof(a) == std::addressof(b)) 
__builtin_unreachable();

ptr tmp = a; a = nullptr; // ptr tmp = std::move(a)

// a = std::move(b)
#if ONE
{
// a.reset(b.release())
rawptr tmp = b;   // b.release()
b = nullptr;
rawptr old = a;   // a.reset(tmp)
a = tmp; 
delete old;
}
#elif TWO
{
// move+swap
rawptr tmp = b; b = nullptr; // ptr tmp = std::move(b)
{ // a.swap(tmp)
rawptr tmp2 = a;
a = tmp;
tmp = tmp2;
}
// ~tmp
delete tmp;
}
#elif THREE
{
delete a; a = b; b = nullptr;
}
#else
#error 
#endif
delete b; b = tmp; tmp = nullptr; // b = std::move(tmp)
delete tmp;
}

https://gcc.godbolt.org/z/bv1T64ndo




ONE and TWO don't elide the delete, unless the arguments are marked
__restrict__. THREE does elide it. Sounds like some escape analysis going
wrong, combined with unique_ptr's self-move-assignment safety (that "bans"
THREE's implementation).

[Bug libstdc++/102221] Missed optimizations for algorithms over std::unique_ptr

2021-09-08 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102221

--- Comment #2 from Giuseppe D'Angelo  ---
Hi,

Thanks for the analysis!

That basically allows me to reduce the testcase to something as simple as a
swap:


#include 
#include 

#if defined(SMART)
using ptr = std::unique_ptr;
#else
using ptr = int *;
#endif

auto swap1(ptr , ptr ) {
if ( == )
__builtin_unreachable(); // 

ptr tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}

auto swap2(ptr , ptr )
{
// deliberate
std::swap(a, b);
}

https://gcc.godbolt.org/z/Tqzz5eqrW


In both cases there's basically a call to "delete nullptr" that doesn't get
removed. I don't think this falls on libstdc++, rather than on the optimizer?

[Bug c++/102221] New: Missed optimizations for algorithms over std::unique_ptr

2021-09-06 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102221

Bug ID: 102221
   Summary: Missed optimizations for algorithms over
std::unique_ptr
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Sorting/heaping/etc. an array/vector of unique_ptr generates worse codegen than
the equivalent code on an array of raw pointers. This is a missed optimization,
as the operations involved should just be mere swaps.

For instance:


#include 
#include 

#if defined(SMART)
using ptr = std::unique_ptr;
#else
using ptr = int*;
#endif

void f()
{
extern ptr *data;
const auto cmp = [](const auto , const auto ) { return *a < *b; };
std::sort(data, data+1000, cmp);
}


https://gcc.godbolt.org/z/7zPYxr9q7


This generates quite some extra code (including calls to operator delete); the
result is that such a sort is slower than the countepart with a raw pointer.

[Bug middle-end/101134] Bogus -Wstringop-overflow warning about non-existent overflow

2021-06-24 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101134

--- Comment #13 from Giuseppe D'Angelo  ---
Hi,

(In reply to Martin Sebor from comment #12)
> So in general, the distinction between the two cases can only be made when
> it can be discerned from the IL, and the IL doesn't always preserve the
> conditional nature of the problem statement.  So every warning must always
> be viewed as a "maybe" kind of a warning.  It will never be a sure a thing,
> either at the scope of individual functions, and certainly not with inlining
> or function cloning.

I think there's been a misunderstanding. Apologies if I created confusion, let
me try and reset the conversation:

I perfectly understand if, in the context of this particular warning (or any
other similar middle-end warning), it is very hard, or currently impossible, or
even always impossible to distinguish between the "maybe" case and the
"certain" case. 

Without such a distinction available or possible, I'm also OK with raising 
false positives. Therefore, in relation to this aspect of the original
submission (the code raising a false positive warning), I'm perfectly fine at
marking the request of not triggering the warning altogether as out of scope /
won't fix / etc.


On other hand, I was not OK with the idea that the *warning message* should
keep saying that "there *is* an overflow", in a positive indicative mood. All
I'd really ask there would be to reword the message in order to say something
like "there *may be* an overflow" instead. It might seem like a trivial/useless
change for someone who knows how the middle-end works and where such warnings
come from, but it would bring a lot of clarity to end-users (to me, at least)
if any warning message would clearly indicate whether it may be a false
positive. And that could be achieved by simply adding "may" to the warning
messages in question.

Does this make sense?

Thanks,

[Bug middle-end/101134] Bogus -Wstringop-overflow warning about non-existent overflow

2021-06-24 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101134

--- Comment #8 from Giuseppe D'Angelo  ---
In a -Wall build, it's a bit unfair to pretend the users to know if a warning
is being generated by the frontend, the middleend, the backend and so on. All
they get is a list of warnings saying "this is like this, this is like that".
You're saying that all such warnings should be treated as "maybe", as false
positives are a possibility. But I don't agree with this. 

First, as I said, the mood of the warning is "indicative", which denotes
certainty and reality, not possibility. (But I'll grant, not being a native
English speaker, this may just be a personal impression of the warning being
"stern".)

Second, the presence of things like -Wmaybe-uninitialized vs -Wuninitialized
hints at the fact that GCC *wants* to distinguish these "maybe" vs. "certain"
cases, at least in certain contexts (like, where it CAN do that!), and give
different warnings if it can.

Third, frontend warnings simply don't have false positives: if the compiler
tells you "this function may be marked override", "this class has virtual
functions but no virtual destructor", "this case label falls through into the
next one", that's absolutely true in 100% of the cases. A false positive here
would clearly be treated as a bug in GCC, and not dismissed as "but it's a
warning, and a warning is just a 'maybe', and yes, GCC is telling you to add
`override`, and then you added it, and now the program doesn't even build any
more because the warning was wrong and `override` was not even needed, but see,
it's your fault for not understanding the 'maybe' part".

So, in a nutshell, yes, I'd be much more comfortable if warnings that denote a
possibility (for any reason, really, I'm not asking to NEVER generate false
positives) would simply have "may" or "might" added to their text. If that's
the majority of middle-end warnings because they all generate false positives,
why would that be a problem, in principle?

But fair enough, let's agree to disagree. :)

[Bug middle-end/101134] Bogus -Wstringop-overflow warning about non-existent overflow

2021-06-22 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101134

--- Comment #6 from Giuseppe D'Angelo  ---
(In reply to Martin Sebor from comment #5)
> It wouldn't be right to change the wording of just one warning because the
> problem applies to all flow based diagnostics.  They all depend on various
> optimizations that propagate constants, add or remove tests, and change the
> control flow graph.  A statement that in the source code is conditional on
> the values of various parameters might in the intermediate representation
> appear unconditional with constants as a result, even be unconditionally
> invalid but unreachable.  This is true at function scope as well as across
> function call boundaries thanks to inlining.  Changing the wording for all
> of them to try to somehow reflect this wouldn't help because then all
> instances of them all would have to use the new form.

Sorry, why wouldn't help? That is, given the fact that these warnings do have
false positives, why would it bad for such warnings to say "something bad MIGHT
be happening here" vs "something bad IS happening here"? 

For an end user, it makes a lot of difference to know if the compiler has
definitely found something wrong vs. the compiler may or may not have found it.
Just a tiny language change in the printed mesage would reassure the user that
the warning could, in fact, be a false positive. (Compare this to "there IS
something bad here". You read the code in question, and you don't see what's
bad, and you start digging around trying to understand "why is the compiler
telling me that there IS something bad? Am I not seeing something?".)


> -Wuninitialized and -Wmaybe-uninitialized aren't substantially different in
> this.  The latter is unique only in that it diagnoses arguments of PHI
> nodes, which are the results of conditional expressions.  This property is
> described by the following sentence in the manual:
> 
> "...if there exists a path from the function entry to a use of the object
> that is initialized, but there exist some other paths for which the object
> is not initialized, the compiler emits a warning if it cannot prove the
> uninitialized paths are not executed at run time."
> 
> This is only roughly what happens but there are many instances of
> -Wuninitialized that could be described using the same sentence, even though
> it doesn't consider PHI nodes.  If we do introduce a similar distinction in
> other warnings like -Wstringop-overflow it will be on top of the instances
> already issued by them, not a subset of them.
> 
> This is a general property of all flow based warnings in GCC except those
> emitted by the static analyzer which doesn't depend on the same
> optimizations (only a very small subset of them).  All warnings (flow based
> or otherwise, including those issued by the analyzer) should always be
> viewed as documented, i.e., as "messages that report constructions that are
> not inherently erroneous but that are risky or suggest there may have been
> an error."

"not inherently erroneous" is as per language rules (i.e. the program isn't
ill-formed). But "there may have been" an error is the key I'm trying to point
out. The compiler can prove that something is a mistake, or can only estimate
that, and so raise a false positive. I'd rather have a message telling me
whether a given warning is because of a proof or an estimate.

[Bug middle-end/101134] Bogus -Wstringop-overflow warning about non-existent overflow

2021-06-22 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101134

--- Comment #4 from Giuseppe D'Angelo  ---
Could the warning messages then be changed to point out that the issue is only
a mere possibility? Using an "assertive" wording makes users believe that GCC
has positively and conclusively proved that there's something wrong, whilst
it's exactly the opposite (it didn't prove anything, and it's a false
positive).

Uninitialized warnings have this distinction and warn in two different ("may be
used uninitialized" vs "is used initialized"). If here the distinction cannot
be made, AND false positives are allowed to warn, I'd really prefer the "may be
overflowing" wording than the "is overflowing" existing one.

[Bug c++/100796] [11 Regression] GCC does not honor #pragma diagnostic ignored when using the integrated preprocessor

2021-06-21 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100796

--- Comment #10 from Giuseppe D'Angelo  ---
Thank you very much.

[Bug middle-end/101134] Bogus -Wstringop-overflow warning about non-existent overflow

2021-06-21 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101134

--- Comment #2 from Giuseppe D'Angelo  ---
As I said,

> Adding enough __builtin_unreachable() for that condition removes the 
> warnings, but it should not be necessary.

I disagree with the resolution, though. While I understand that GCC cannot
reason globally, the warning message itself is miselading, as it's worded in a
way that makes the user think that GCC has *conclusevely* proven the existence
of a problem, while in fact GCC is wrong. Specifically, this statement:

> :75:31: warning: writing 1 byte into a region of size 0 
> [-Wstringop-overflow=]

At least, I'd like a less strong wording if GCC cannot *prove* this but only
estimate it (e.g. "warning: possible string overflow (writing 1 byte...)").
Ideally, even, having two separate warnings or two separate warning levels
(overflow proved / overflow just estimated) so one can enable only one of the
two if needed.

[Bug middle-end/101134] New: Bogus -Wstringop-overflow warning about non-existent overflow

2021-06-19 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101134

Bug ID: 101134
   Summary: Bogus -Wstringop-overflow warning about non-existent
overflow
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: middle-end
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hello,

This reduced testcase from Qt raises a -Wstring-overflow warning on GCC 11.1
when compiling under -O2 -g -Wall -Wextra:

#include 
#include 

struct QTestCharBuffer
{
enum { InitialSize = 512 };

inline QTestCharBuffer() : buf(staticBuf)
{
staticBuf[0] = '\0';
}

QTestCharBuffer(const QTestCharBuffer &) = delete;
QTestCharBuffer =(const QTestCharBuffer &) = delete;

inline ~QTestCharBuffer()
{
if (buf != staticBuf)
free(buf);
}

inline char *data()
{
return buf;
}

inline int size() const
{
return _size;
}

inline bool reset(int newSize)
{
char *newBuf = nullptr;
if (buf == staticBuf) {
// if we point to our internal buffer, we need to malloc first
newBuf = reinterpret_cast(malloc(newSize));
} else {
// if we already malloc'ed, just realloc
newBuf = reinterpret_cast(realloc(buf, newSize));
}

// if the allocation went wrong (newBuf == 0), we leave the object
as is
if (!newBuf)
return false;

_size = newSize;
buf = newBuf;
return true;
}

private:
int _size = InitialSize;
char* buf;
char staticBuf[InitialSize];
};


typedef int (*StringFormatFunction)(QTestCharBuffer*,char const*,size_t);

/*
A wrapper for string functions written to work with a fixed size buffer
so they can be called
with a dynamically allocated buffer.
*/
int allocateStringFn(QTestCharBuffer* str, char const* src,
StringFormatFunction func)
{
static const int MAXSIZE = 1024*1024*2;

int size = str->size();

int res = 0;

for (;;) {
res = func(str, src, size);
str->data()[size - 1] = '\0';
if (res < size) {
// We succeeded or fatally failed
break;
}
// buffer wasn't big enough, try again
size *= 2;
if (size > MAXSIZE) {
break;
}
if (!str->reset(size))
break; // ran out of memory - bye
}

return res;
}

int xmlQuote(QTestCharBuffer* destBuf, char const* src, size_t n)
{
if (n == 0) return 0;

char *dest = destBuf->data();
*dest = 0;
if (!src) return 0;

char* begin = dest;
char* end = dest + n;

while (dest < end) {
switch (*src) {

#define MAP_ENTITY(chr, ent) \
case chr:   \
if (dest + sizeof(ent) < end) { \
strcpy(dest, ent);  \
dest += sizeof(ent) - 1;\
}   \
else {  \
*dest = 0;  \
return (dest+sizeof(ent)-begin);\
}   \
++src;  \
break;

MAP_ENTITY('>', "");
MAP_ENTITY('<', "");
MAP_ENTITY('\'', "");
MAP_ENTITY('"', "");
MAP_ENTITY('&', "");

// not strictly necessary, but allows handling of comments
without
// having to explicitly look for `--'
MAP_ENTITY('-', "");

#undef MAP_ENTITY

case 0:
*dest = 0;
return (dest-begin);

default:
*dest = *src;
++dest;
++src;
break;
}
}

// If we get here, dest was completely filled (dest == end)
*(dest-1) = 0;
return (dest-begin);
}

int xmlQuote(QTestCharBuffer* str, char const* src)
{
return allocateStringFn(str, src, xmlQuote);
}

void enterTestFunction(const char *function)
{
QTestCharBuffer quotedFunction;
xmlQuote(, function);
}


Godbolt link: https://gcc.godbolt.org/z/aPMdYjqEa

The warning is

In function 'int 

[Bug c++/100796] [11 Regression] GCC does not honor #pragma diagnostic ignored when using the integrated preprocessor

2021-06-15 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100796

--- Comment #6 from Giuseppe D'Angelo  ---
Hi,

Wow, that was quick!

I can't really judge the merit of the patch, but I've picked it on top of the
GCC 11.1.0 tarball and can confirm that it seems to fix all the warnings for
us. Thank you very much!

[Bug c++/100796] [11 Regression] GCC does not honor #pragma diagnostic ignored when using the integrated preprocessor

2021-06-14 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100796

--- Comment #4 from Giuseppe D'Angelo  ---
Created attachment 51011
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=51011=edit
testcase

Hi,

I've tried to "carve" a subset of files that show the problem. Apologies for
not really being minimal.

How to reproduce: 
1) uncompress
2) cd $dir/home/peppe/projects/src/qt5/qtbase/build
3) (with c++ = GCC 11) run

c++ -DQT_CONCURRENT_LIB -DQT_CORE_LIB
-DQT_TESTCASE_BUILDDIR=\"/home/peppe/projects/src/qt5/qtbase/build/tests/auto/corelib/io/qurl\"
-DQT_TESTCASE_SOURCEDIR=\"/home/peppe/projects/src/qt5/qtbase/tests/auto/corelib/io/qurl\"
-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE
-Itests/auto/corelib/io/qurl/tst_qurl_autogen/include
-I../tests/auto/corelib/io/qurl -Itests/auto/corelib/io/qurl -Iinclude
-Iinclude/QtCore -I../mkspecs/linux-g++ -Iinclude/QtTest -Iinclude/QtConcurrent
-Isrc/testlib -Iinclude/QtTest/6.2.0 -Iinclude/QtTest/6.2.0/QtTest
-Isrc/corelib -Iinclude/QtCore/6.2.0 -Iinclude/QtCore/6.2.0/QtCore -g -fPIE
-fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wextra -fPIC -pthread
-Wsuggest-override -std=gnu++2a -o /dev/null  -c
../tests/auto/corelib/io/qurl/tst_qurl.cpp


That for me generates a bunch of false warnings such as

> include/QtCore/../../../src/corelib/kernel/qtmetamacros.h:159:32: warning: 
> ‘virtual const QMetaObject* QSocketNotifier::metaObject() const’ can be 
> marked override [-Wsuggest-override]
>   159 | virtual const QMetaObject *metaObject() const; \
>   |^~
> include/QtCore/../../../src/corelib/kernel/qsocketnotifier.h:51:5: note: in 
> expansion of macro ‘Q_OBJECT’
>51 | Q_OBJECT
>   | ^~~~


and many more.

As mentioned before: adding -no-integrated-cpp to the command line, and/or
splitting the compilation in explicit preprocessing+compilation, makes the
warnings disappear.

Please let me know if the testcase works or if I forgot to add something
(hoping that system headers don't make a difference, anyways, I'm testing under
Ubuntu 20.04).

[Bug c++/100796] [11 Regression] GCC does not honor #pragma diagnostic ignored when using the integrated preprocessor

2021-05-27 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100796

--- Comment #2 from Giuseppe D'Angelo  ---
Well, GCC 8-9-10 don't have this problem at all for us. This appeared only when
upgrading to 11.

Anyways, I'm not sure if it's the same issue. PR 53431 seems to be about the
preprocessor itself ignoring the pragmas -- like raising -Wundef even under a
pragma. 

Here is not quite about the preprocessor (in fact, the not-honored pragma can
only be honored by the compiler, it's about -Wsuggest-override). The compiler
seems to ignore that pragma in _random_ places (it's very inconsistent; the
majority of code is not flagged, except for a few occurrences).

If I run the preprocessor manually, the pragma is still correctly present in
the preprocessed output. However: running the compiler over that preprocessed
output does NOT raise the warning. That leads to the fact that adding
-no-integrated-cpp is a successful workaround; this makes me think something
broke in there...?

[Bug c++/100796] New: [11 Regression] GCC does not honor #pragma diagnostic ignored when using the integrated preprocessor

2021-05-27 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100796

Bug ID: 100796
   Summary: [11 Regression] GCC does not honor #pragma diagnostic
ignored when using the integrated preprocessor
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hi,

When building the qtbase `dev` branch with GCC 11, a bunch of warnings are
generated even in the presence of a ignoring pragma. 

For a bit of context, in Qt there's a macro called Q_OBJECT that users can add
to their classes; this macro expands to a series of declarations, including a
couple of virtuals. These may raise -Wsuggest-override warnings, in user code,
so such warnings are suppressed via pragmas (as part of the Q_OBJECT macro
itself).

GCC 10 honors the pragmas and doesn't raise warnings, but GCC 11 doesn't honor
them, resulting in warnings like

include/QtCore/../../../src/corelib/kernel/qtmetamacros.h:159:32: error:
‘virtual const QMetaObject* QTextObject::metaObject() const’ can be marked
override [-Werror=suggest-override]
  159 | virtual const QMetaObject *metaObject() const; \
  |^~
include/QtGui/../../../src/gui/text/qtextobject.h:62:5: note: in expansion
of macro ‘Q_OBJECT’
   62 | Q_OBJECT
  | ^~~~
include/QtCore/../../../src/corelib/kernel/qtmetamacros.h:160:19: error:
‘virtual void* QTextObject::qt_metacast(const char*)’ can be marked override
[-Werror=suggest-override]
  160 | virtual void *qt_metacast(const char *); \
  |   ^~~
include/QtGui/../../../src/gui/text/qtextobject.h:62:5: note: in expansion
of macro ‘Q_OBJECT’
   62 | Q_OBJECT
  | ^~~~

And so on and so forth.

Now, the peculiarity of this bug is that if you disable the integrated
preprocessor via -no-integrated-cpp then everything works fine. Similarly, if
you take a preprocessed output and compile *that*, then no warnings are raised.
I therefore suspect a regression in the integrated preprocessor.

For this reason I'm actually unable to attach a testcase: a preprocessed output
 compiles just fine. Please advise as of what kind of test I could do / provide
to help you track this one down. 



If you wish to try and compile Qt yourself, then it's relatively easy: 

1) clone git://code.qt.io/qt/qtbase.git , checkout dev
2) get a very recent CMake 
3) mkdir build
4) (with GCC 11 in PATH, or force it via CC/CXX env) cmake -GNinja
-DCMAKE_BUILD_TYPE=Debug -DQT_BUILD_EXAMPLES_BY_DEFAULT=OFF
-DQT_BUILD_TESTS_BY_DEFAULT=OFF -DFEATURE_developer_build=ON ../path/to/qtbase
5) ninja


Upstream bug: https://bugreports.qt.io/browse/QTBUG-93360

[Bug middle-end/54202] Overeager warning about freeing non-heap objects

2021-05-17 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54202

Giuseppe D'Angelo  changed:

   What|Removed |Added

 CC||dangelog at gmail dot com

--- Comment #8 from Giuseppe D'Angelo  ---
The original testcase by Thiago still fails with GCC 11.

Unfortunately, GCC 11 decided to turn -Wfree-nonheap-object on by default (!),
resulting in false positives for Qt users (containers in Qt use this pattern).
For instance 

https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/tools/qlinkedlist.h?h=5.15

struct QT_DEPRECATED_VERSION_5_15 QLinkedListData
{
QLinkedListData *n, *p;
QtPrivate::RefCount ref; // set to -1 for shared_null
int size;
uint sharable : 1;

Q_CORE_EXPORT static const QLinkedListData shared_null;
};

template 
inline QLinkedList::~QLinkedList()
{
if (!d->ref.deref())
freeData(d); // never called on shared_null because of the check
}


template 
void QLinkedList::freeData(QLinkedListData *x)
{
// ...
delete x; // -Wfree-nonheap-object here
}

[Bug libstdc++/96416] to_address() is broken by static_assert in pointer_traits

2021-04-21 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96416

--- Comment #18 from Giuseppe D'Angelo  ---
Hello,

(In reply to Jonathan Wakely from comment #17)
> (In reply to Giuseppe D'Angelo from comment #14)
> > To summarize:
> > 
> > * should a wording defect be raised against std::to_address(Ptr), to state
> > that pointer_traits being well-formed is actually a prerequisite?
> 
> I'd prefer if pointer_traits was just SFINAE friendly.

I guess that's a reasonable thing to wish for, given I'm not the first falling
for it; I hope I'll be the last :)

> > * should LWG3446's resolution be amended?
> 
> See https://cplusplus.github.io/LWG/issue3541
> 
> > * if there's going to be a GCC 10.3, is the commit above solving LWG3446
> > going to be cherry-picked into it? Otherwise, either one blacklists GCC 10,
> > or has to specialize pointer_traits there as a workaround (?).
> 
> It missed the 10.3 release, but it's on the gcc-10 branch as r10-9698, which
> will be in GCC 10.4:
> https://gcc.gnu.org/g:32a859531e854382c18abf0b14a306d83f793eb5
> That also includes the fix for LWG 3541.

Thank you very much for the new issue and the cherry-pick of the fix.

[Bug libstdc++/96416] to_address() is broken by static_assert in pointer_traits

2021-03-27 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96416

--- Comment #14 from Giuseppe D'Angelo  ---
Hello,

(In reply to Glen Joseph Fernandes from comment #11)
> > if it can never be used.
> 
> You're misunderstanding.   to_address(p) requires that pointer_traits is
> valid. It just doesn't need to have a to_address member function.

Thank you for clarifying this. I think the wording in the standard is very
unfortunate, but combined with the realization that pointer_traits isn't
SFINAE-friendly, then it's the only intended meaning.



> If (for contiguous iterators, which came later) you want pointer_traits
> to be valid even when X does not have element_type, that is a design change
> to pointer_traits.

One might claim that pointer_traits should become SFINAE-friendly (like C++17's
iterator_traits), but sure, that's a different design question and not
necessarily needed here.


(In reply to Jonathan Wakely from comment #12)
> (In reply to Giuseppe D'Angelo from comment #10)
> > (By the way, finding this bug is quite hard. Could "address_of" be changed
> > to "to_address" , in the bug description?
> 
> Done.

Thank you!



(In reply to Arthur O'Dwyer from comment #13)
> > And are you recommending that everyone who defines their custom contiguous
> > iterators specializes pointer_traits for them? Call it _quite_ annoying...
> 
> Definitely not! When you define a contiguous iterator type, you should just
> give it a sixth nested typedef alongside the other five (or three in C++20):
> `using element_type = value_type;`. This enables contiguous-iterator
> machinery.
> See
> https://stackoverflow.com/questions/65712091/in-c20-how-do-i-write-a-
> contiguous-iterator/66050521#66050521


This gets evil really quick: the presence of both value_type and element_type
in an contiguous iterator will make you smash face-first against LWG3446, which
isn't implemented in GCC 10 AFAICS.

https://cplusplus.github.io/LWG/issue3446


What's more, the accepted resolution wording for it appears to be wrong:


  template
requires has-member-element-type &&
 same_as,
remove_cv_t>
  struct indirectly_readable_traits
: cond-value-type { };


For const iterators, value_type is actually different from element_type (!).
Thankfully libstdc++ seems to have considered this as a non-standard extension,
https://github.com/gcc-mirror/gcc/commit/186aa6304570e15065f31482e9c27326a3a6679f
 


To summarize:

* should a wording defect be raised against std::to_address(Ptr), to state that
pointer_traits being well-formed is actually a prerequisite?

* should LWG3446's resolution be amended?

* if there's going to be a GCC 10.3, is the commit above solving LWG3446 going
to be cherry-picked into it? Otherwise, either one blacklists GCC 10, or has to
specialize pointer_traits there as a workaround (?).


Thank you all for the insightful comments.

[Bug libstdc++/96416] address_of() is broken by static_assert in pointer_traits

2021-03-26 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96416

--- Comment #10 from Giuseppe D'Angelo  ---
(By the way, finding this bug is quite hard. Could "address_of" be changed to
"to_address" , in the bug description? I think that's the intended meaning.
And, "to_pointer", mentioned a few times, doesn't exist.)

[Bug libstdc++/96416] address_of() is broken by static_assert in pointer_traits

2021-03-26 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96416

Giuseppe D'Angelo  changed:

   What|Removed |Added

 CC||dangelog at gmail dot com

--- Comment #9 from Giuseppe D'Angelo  ---
Hi,

Stumbled across this indeed when trying to use contiguous iterators.

Sure enough, pointer_traits for them is ill-formed. But then I don't understand
why the "otherwise to_­address(p.operator->())" part is in the Standard at all,
if it can never be used.

Has this been raised as a library defect?

And are you recommending that everyone who defines their custom contiguous
iterators specializes pointer_traits for them? Call it _quite_ annoying...

[Bug c++/99625] New: GCC does not detect narrowing in aggregate initialization

2021-03-17 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99625

Bug ID: 99625
   Summary: GCC does not detect narrowing in aggregate
initialization
   Product: gcc
   Version: 10.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Testcase:

extern long double l;

struct S {
S(int) {}
};

S s[] = { l };


This is supposed to be ill-formed because of narrowing. GCC does not reject the
code, nor it warns (as it usually does for narrowing).

The relevant rule is in [dcl.init.aggr]:

https://eel.is/c++draft/dcl.init.aggr#4.2.sentence-2

> Otherwise, the element is copy-initialized from the corresponding 
> initializer-clause or is initialized with the brace-or-equal-initializer of 
> the corresponding designated-initializer-clause.
> If that initializer is of the form assignment-expression or = 
> assignment-expression and a narrowing conversion ([dcl.init.list]) is 
> required to convert the expression, the program is ill-formed.


That rule has been changed in C++20 with designated initializers, but the same
one was also there for C++17 and before, e.g.
https://timsong-cpp.github.io/cppwp/n4659/dcl.init.aggr#3


For comparison, Clang accepts with no warnings, but MSVC warns about narrowing.

[Bug c++/99032] New: GCC accepts attributes on friend declarations (not definitions)

2021-02-09 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99032

Bug ID: 99032
   Summary: GCC accepts attributes on friend declarations (not
definitions)
   Product: gcc
   Version: 10.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dangelog at gmail dot com
  Target Milestone: ---

Hi,

The following code is accepted by GCC 10.2:

  struct S { [[deprecated]] friend void f(); };

No errors and no warnings are generated under -Wall -Wextra -pedantic.

The code is however ill-formed: an attribute cannot appear on a friend 
declaration which isn't also a definition:

https://eel.is/c++draft/dcl.attr#grammar-5.sentence-3

If an attribute-specifier-seq appertains to a friend declaration
([class.friend]), that declaration shall be a definition.


For comparison, Clang rejects this, and MSVC accepts it (without warnings).

[Bug tree-optimization/87952] Missed optimization for std::get_if on std::variant

2020-10-27 Thread dangelog at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87952

Giuseppe D'Angelo  changed:

   What|Removed |Added

 CC||dangelog at gmail dot com

--- Comment #2 from Giuseppe D'Angelo  ---
Still valid as 10.2.

There's just been some discussion related to this missed optimization on the
std-proposals mailing list. It's also worth noticing that neither GCC nor Clang
remove the branch from some slightly different code:

int& test(std::variant )
{
return *std::get_if();
}

GCC 10.2 generates:

test(std::variant&):
  xorl %eax, %eax
  cmpb $0, 8(%rdi)
  cmove %rdi, %rax
  ret

Clang 11 generates:

test(std::__1::variant&): # @test(std::__1::variant&)
  xorl %eax, %eax
  cmpl $0, 8(%rdi)
  cmoveq %rdi, %rax
  retq


If one pushes things a little bit, both compilers remove the branch:

int& test(std::variant& v)
{
auto result = std::get_if();
if (!result) __builtin_unreachable();
return *result;
}

GCC:
test(std::variant&):
  movq %rdi, %rax
  ret

Clang:
test(std::__1::variant&): # @test(std::__1::variant&)
  movq %rdi, %rax
  retq


Could you please elaborate on what you mean by "might end up as a security
issue"?