[Bug libstdc++/110138] Extra constructor called when using basic_string::operator+

2023-06-08 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110138

--- Comment #6 from Jonathan Wakely  ---
What matters is the "value" of the allocator, not how many times it gets
copied.

[Bug libstdc++/110138] Extra constructor called when using basic_string::operator+

2023-06-08 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110138

--- Comment #5 from Jonathan Wakely  ---
Just use a stateful allocator and check that the correct state is propagated.

See testsuite/21_strings/basic_string/allocator/char/operator_plus.cc which
does exactly that.

[Bug libstdc++/110138] Extra constructor called when using basic_string::operator+

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

Hongyu Wang  changed:

   What|Removed |Added

 Resolution|--- |INVALID
 Status|UNCONFIRMED |RESOLVED

--- Comment #4 from Hongyu Wang  ---
(In reply to Jonathan Wakely from comment #3)
> (In reply to Hongyu Wang from comment #0)
> > GCC 12.3/Clang 16 outputs:
> > Alloc: 3
> > Alloc: 6
> > Alloc: 9
> > Alloc: 12
> 
> "Clang 16" here actually means "Any version of Clang with libstdc++ headers
> from GCC 12".
> 
> The figures for Clang's own libc++ are different:
> 
> Alloc: 0
> Alloc: 4
> Alloc: 8
> Alloc: 12
> 
> But again, this is meaningless. Nobody cares how many times an allocator is
> copied.

The original test intends to verify P1165R1 implementation and it uses a global
counter on allocator constructor to see if it is correctly selected, and
current change makes it copied twice so the result is not expected.

But yes, I agree the allocator constructor for string should be cheap, and the
original test should not rely on how many times the constructor was called to
verify P1165R1 (I suppose checks if soccc was called instead).

Thanks for the explanation, I will close this as invalid.

[Bug libstdc++/110138] Extra constructor called when using basic_string::operator+

2023-06-06 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110138

--- Comment #3 from Jonathan Wakely  ---
(In reply to Hongyu Wang from comment #0)
> GCC 12.3/Clang 16 outputs:
> Alloc: 3
> Alloc: 6
> Alloc: 9
> Alloc: 12

"Clang 16" here actually means "Any version of Clang with libstdc++ headers
from GCC 12".

The figures for Clang's own libc++ are different:

Alloc: 0
Alloc: 4
Alloc: 8
Alloc: 12

But again, this is meaningless. Nobody cares how many times an allocator is
copied.

[Bug libstdc++/110138] Extra constructor called when using basic_string::operator+

2023-06-06 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110138

--- Comment #2 from Jonathan Wakely  ---
Why do you care how many times an allocator is copied? They should be cheap
(essentially free) to copy.

A far more interesting test would look at how many bytes are allocated for
string concatenation:

#include 
#include 

int n_ = 0;
int b_ = 0;

void alloc_cnt() {
std::cout<< "Allocators: " << n_ << ", bytes: " << b_ << '\n';
}

template 
struct myAlloc_ : std:: allocator {
  myAlloc_() { }
  myAlloc_(myAlloc_&& r) { ++n_; }
  myAlloc_(const myAlloc_& r) { ++n_; }
  myAlloc_& operator=(const myAlloc_& other) { return *this; }

  T* allocate(std::size_t n) {
T* ptr = std::allocator::allocate(n);
b_ += n * sizeof(T);
return ptr;
  }
 template 
 struct rebind { typedef myAlloc_ other; };
};
using mystring = std:: basic_string,
myAlloc_>;


int main()
{
  mystring f_ = "abc0", b_ = "def", c_ = "xyz";
  alloc_cnt ();

  auto a = f_ + "mno" + b_;
  alloc_cnt ();

  auto c = c_ + f_ + b_;
  alloc_cnt ();

  auto d = c_ + (f_ + b_);
  alloc_cnt ();

  return 0;
}

With GCC 12:

Allocators: 3, bytes: 21
Allocators: 6, bytes: 83
Allocators: 9, bytes: 114
Allocators: 12, bytes: 176

With GCC 13:

Allocators: 3, bytes: 21
Allocators: 7, bytes: 52
Allocators: 11, bytes: 83
Allocators: 15, bytes: 114


The program uses less memory to achieve the same result. This was changed by
r13-3814-gc93baa93df2d45 and is actually important.

The number of copies of allocators is a meaningless figure.

[Bug libstdc++/110138] Extra constructor called when using basic_string::operator+

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

--- Comment #1 from Hongyu Wang  ---
operator+ now calls std::__cxx11::basic_string,
myAlloc_ >::get_allocator, and it will call the constructor again after
gimplify

__attribute__((nodiscard))
struct allocator_type std::__cxx11::basic_string,
myAlloc_ >::get_allocator (
const struct basic_string * const this)
{
  try
{
  _1 = std::__cxx11::basic_string,
myAlloc_ >::_M_get_allocator (this);
  myAlloc_::myAlloc_ (, _1);
  return ;
}
  catch
{
  <<>>
}
  __builtin_unreachable trap ();
}

Possibly caused by r13-3814-gc93baa93df2d45