public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* std::vector<__m128i> with non-standard allocators
@ 2012-06-11 17:45 Jack Lloyd
  2012-06-11 17:57 ` Jonathan Wakely
  0 siblings, 1 reply; 4+ messages in thread
From: Jack Lloyd @ 2012-06-11 17:45 UTC (permalink / raw)
  To: gcc-help


I'm having a problem using a custom allocator with a std::vector of
__m128i values, where _Destroy in stl_construct.h will invoke destroy
even on objects with trivial destructors with any allocator other than
std::alloctor. For instance you can see this with

   std::vector<__m128i, __gnu_cxx::new_allocator<__m128i>> v;

which for G++ 4.7.0 (in C++11 mode) produces

In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.0/include/g++-v4/x86_64-pc-linux-gnu/bits/c++allocator.h:34:0,
                 from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.0/include/g++-v4/bits/allocator.h:48,
                 from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.0/include/g++-v4/vector:62,
                 from vector.cpp:2:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.0/include/g++-v4/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::destroy(_Up*) [with _Up = __vector(2) long long int; _Tp = __vector(2) long long int]':
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.0/include/g++-v4/bits/alloc_traits.h:276:4:   required from 'static typename std::enable_if<std::allocator_traits<_Alloc>::__destroy_helper<_Tp>::value, void>::type std::allocator_traits<_Alloc>::_S_destroy(_Alloc&, _Tp*) [with _Tp = __vector(2) long long int; _Alloc = __gnu_cxx::new_allocator<__vector(2) long long int>; typename std::enable_if<std::allocator_traits<_Alloc>::__destroy_helper<_Tp>::value, void>::type = void]'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.0/include/g++-v4/bits/alloc_traits.h:399:4:   required from 'static void std::allocator_traits<_Alloc>::destroy(_Alloc&, _Tp*) [with _Tp = __vector(2) long long int; _Alloc = __gnu_cxx::new_allocator<__vector(2) long long int>]'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.0/include/g++-v4/bits/stl_construct.h:147:2:   required from 'void std::_Destroy(_ForwardIterator, _ForwardIterator, _Allocator&) [with _ForwardIterator = __vector(2) long long int*; _Allocator = __gnu_cxx::new_allocator<__vector(2) long long int>]'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.0/include/g++-v4/bits/stl_vector.h:403:9:   required from 'std::vector<_Tp, _Alloc>::~vector() [with _Tp = __vector(2) long long int; _Alloc = __gnu_cxx::new_allocator<__vector(2) long long int>]'
vector.cpp:8:60:   required from here
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.0/include/g++-v4/ext/new_allocator.h:114:29: error: request for member '~__vector(2) long long int' in '* __p', which is of non-class type '__vector(2) long long int'

Interestingly this appears to be due to the fact that for a freestanding

template<typename U> void destroy(U* p) { p->~U(); }

GCC has no issues with

long l;
destroy(&l);

but rejects

__m128i m;
destroy(&m);

with an error like the one above.

Is this behavior intentional/expected?

Please CC me on any replies as I am not on the list.

-Jack

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: std::vector<__m128i> with non-standard allocators
  2012-06-11 17:45 std::vector<__m128i> with non-standard allocators Jack Lloyd
@ 2012-06-11 17:57 ` Jonathan Wakely
  2012-06-11 18:50   ` Jack Lloyd
  0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Wakely @ 2012-06-11 17:57 UTC (permalink / raw)
  To: Jack Lloyd; +Cc: gcc-help

On 11 June 2012 18:44, Jack Lloyd wrote:
>
> I'm having a problem using a custom allocator with a std::vector of
> __m128i values, where _Destroy in stl_construct.h will invoke destroy
> even on objects with trivial destructors with any allocator other than
> std::alloctor.

That's intentional, it's not known whether a user-defined allocator
wants to do anything interesting in the destroy function.  We probably
could specialize it to know about __gnu_cxx::new_allocator though.

>
> Interestingly this appears to be due to the fact that for a freestanding
>
> template<typename U> void destroy(U* p) { p->~U(); }
>
> GCC has no issues with
>
> long l;
> destroy(&l);
>
> but rejects
>
> __m128i m;
> destroy(&m);
>
> with an error like the one above.
>
> Is this behavior intentional/expected?

The C++ standard says that in a psuedo-destructor call (i.e. an
expression like p->~U() for a non-class type) the operand shall be a
scalar type, which would seem to rule out vector types (but then the
standard says nothing about them anyway.)

You could either specialize the allocator's destroy function for the
case of __m128i so it does nothing, or file a bug asking for
pseudo-destructor calls to be allowed on types like __m128i.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: std::vector<__m128i> with non-standard allocators
  2012-06-11 17:57 ` Jonathan Wakely
@ 2012-06-11 18:50   ` Jack Lloyd
  2012-06-11 19:21     ` Jonathan Wakely
  0 siblings, 1 reply; 4+ messages in thread
From: Jack Lloyd @ 2012-06-11 18:50 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: gcc-help

On Mon, Jun 11, 2012 at 06:57:05PM +0100, Jonathan Wakely wrote:

> The C++ standard says that in a psuedo-destructor call (i.e. an
> expression like p->~U() for a non-class type) the operand shall be a
> scalar type, which would seem to rule out vector types (but then the
> standard says nothing about them anyway.)

Thanks, I had no realized that the standard allows that for scalar
types.

> You could either specialize the allocator's destroy function for the
> case of __m128i so it does nothing, or file a bug asking for
> pseudo-destructor calls to be allowed on types like __m128i.

I considered specialization but that requires me to guess what vector
types someone might want to use (the various AVX, NEON, and AltiVec
types all seem reasonable in the context of the allocator I'm writing)
and additionally pollute the namespace by pulling in headers to find
the definitions, so I was hoping for another approach.

It's definitely pretty unfortunate that this is rejected in that it
seems (?) like the intent of the pseudo-destructor syntax is to ensure
that p->~U() is always well formed precisely to allow uniform syntax
for cases like this. I suppose I'll file a bug and hope that people
working on the C++ FE agree this is a reasonable thing to support. It
looks like Clang 3.1 also rejects, Intel C++ 12.1 and Visual C++ 2010
accepts. Not sure about Comeau as the online compiler doesn't seem to
know about emmintrin.h

-Jack

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: std::vector<__m128i> with non-standard allocators
  2012-06-11 18:50   ` Jack Lloyd
@ 2012-06-11 19:21     ` Jonathan Wakely
  0 siblings, 0 replies; 4+ messages in thread
From: Jonathan Wakely @ 2012-06-11 19:21 UTC (permalink / raw)
  To: Jack Lloyd; +Cc: gcc-help

On 11 June 2012 19:50, Jack Lloyd wrote:
> On Mon, Jun 11, 2012 at 06:57:05PM +0100, Jonathan Wakely wrote:
>
>> The C++ standard says that in a psuedo-destructor call (i.e. an
>> expression like p->~U() for a non-class type) the operand shall be a
>> scalar type, which would seem to rule out vector types (but then the
>> standard says nothing about them anyway.)
>
> Thanks, I had no realized that the standard allows that for scalar
> types.

You're not allowed to specialize templates from namespace std for
scalar types, but for your_custom_allocator or my_custom_allocator you
can specialize anything, or they could just be written to have special
handling for scalars without any specialization (e.g.
my_custom_allocator<int>::destroy(int*, size_t) could write to
std::cout every time it's called.)


>> You could either specialize the allocator's destroy function for the
>> case of __m128i so it does nothing, or file a bug asking for
>> pseudo-destructor calls to be allowed on types like __m128i.
>
> I considered specialization but that requires me to guess what vector
> types someone might want to use (the various AVX, NEON, and AltiVec
> types all seem reasonable in the context of the allocator I'm writing)
> and additionally pollute the namespace by pulling in headers to find
> the definitions, so I was hoping for another approach.
>
> It's definitely pretty unfortunate that this is rejected in that it
> seems (?) like the intent of the pseudo-destructor syntax is to ensure
> that p->~U() is always well formed precisely to allow uniform syntax
> for cases like this.

For scalar types, yes.  It's not valid to use a pseudo-destructor call
for non-scalar, non-class types e.g. this isn't valid:

typedef int array[2];
array a;
a.~array();

Vector types like __m128i aren't really part of the C++ type system,
so it's not entirely surprising they fall through the gaps between
well-defined features and extensions.

> I suppose I'll file a bug and hope that people
> working on the C++ FE agree this is a reasonable thing to support. It
> looks like Clang 3.1 also rejects, Intel C++ 12.1 and Visual C++ 2010
> accepts. Not sure about Comeau as the online compiler doesn't seem to
> know about emmintrin.h

I think the Comeau online compiler ensures no non-standard headers are usable.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-06-11 19:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-11 17:45 std::vector<__m128i> with non-standard allocators Jack Lloyd
2012-06-11 17:57 ` Jonathan Wakely
2012-06-11 18:50   ` Jack Lloyd
2012-06-11 19:21     ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).