Bug 57403 - A vector of volatile int doesn't work, but one of volatile void * does
Summary: A vector of volatile int doesn't work, but one of volatile void * does
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-05-24 18:41 UTC by Nick Maclaren
Modified: 2014-10-13 14:40 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nick Maclaren 2013-05-24 18:41:29 UTC
In gcc 4.8.0, the following program fails horribly:

#include <vector>

int main () {
    std::vector<volatile int> memory(123);
}

Change the 'int' to void *' and it works.  It fails under OpenSUSE 11.4
and OpenSUSE 12.1, both on AMD 64-bit, and with gcc 4.6.2 as well.  The
messages are:

Test.cpp: In constructor 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = volatile int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<volatile int>]':
Test.cpp:4:41: error: could not convert '0' from 'int' to 'const volatile value_type& {aka const volatile int&}'
     std::vector<volatile int> memory(123);
                                         ^
Test.cpp: In function 'int main()':
Test.cpp:4:41: error: invalid initialization of reference of type 'const volatile value_type& {aka const volatile int&}' from expression of type 'int'
In file included from /home/nmm/GCC/include/c++/4.8.0/vector:65:0,
                 from Test.cpp:1:
/home/nmm/GCC/include/c++/4.8.0/bits/stl_vector.h:296:7: error: in passing argument 2 of 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = volatile int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<volatile int>]'
       vector(size_type __n, const value_type& __value = value_type(),
       ^
In file included from /home/nmm/GCC/include/c++/4.8.0/x86_64-unknown-linux-gnu/bits/c++allocator.h:33:0,
                 from /home/nmm/GCC/include/c++/4.8.0/bits/allocator.h:47,
                 from /home/nmm/GCC/include/c++/4.8.0/vector:62,
                 from Test.cpp:1:
/home/nmm/GCC/include/c++/4.8.0/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::deallocate(__gnu_cxx::new_allocator<_Tp>::pointer, __gnu_cxx::new_allocator<_Tp>::size_type) [with _Tp = volatile int; __gnu_cxx::new_allocator<_Tp>::pointer = volatile int*; __gnu_cxx::new_allocator<_Tp>::size_type = long unsigned int]':
/home/nmm/GCC/include/c++/4.8.0/bits/stl_vector.h:175:4:   required from 'void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(std::_Vector_base<_Tp, _Alloc>::pointer, std::size_t) [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::_Vector_base<_Tp, _Alloc>::pointer = volatile int*; std::size_t = long unsigned int]'
/home/nmm/GCC/include/c++/4.8.0/bits/stl_vector.h:162:33:   required from 'std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = volatile int; _Alloc = std::allocator<volatile int>]'
/home/nmm/GCC/include/c++/4.8.0/bits/stl_vector.h:298:23:   required from 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = volatile int; _Alloc = std::allocator<volatile int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = volatile int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<volatile int>]'
Test.cpp:4:41:   required from here
/home/nmm/GCC/include/c++/4.8.0/ext/new_allocator.h:110:30: error: invalid conversion from 'volatile void*' to 'void*' [-fpermissive]
       { ::operator delete(__p); }
                              ^
In file included from /home/nmm/GCC/include/c++/4.8.0/ext/new_allocator.h:33:0,
                 from /home/nmm/GCC/include/c++/4.8.0/x86_64-unknown-linux-gnu/bits/c++allocator.h:33,
                 from /home/nmm/GCC/include/c++/4.8.0/bits/allocator.h:47,
                 from /home/nmm/GCC/include/c++/4.8.0/vector:62,
                 from Test.cpp:1:
/home/nmm/GCC/include/c++/4.8.0/new:97:6: error:   initializing argument 1 of 'void operator delete(void*)' [-fpermissive]
 void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
      ^
Comment 1 Andrew Pinski 2013-05-24 18:43:56 UTC
Well volatile void * is a pointer to volatile void and the pointer itself does not have the volatile on it.

I think the only real issue here is the error message.  IIRC allocators do not (and cannot) support volatile qualified types.
Comment 2 Nick Maclaren 2013-05-24 19:01:55 UTC
On May 24 2013, pinskia at gcc dot gnu.org wrote:

>http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57403
>
> --- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> --- Well 
> volatile void * is a pointer to volatile void and the pointer itself does 
> not have the volatile on it.

Aargh!  Even after all this time, I still fall into that one :-(  Yes,
you are quite right, and I was making a stupid error.

> I think the only real issue here is the error message. IIRC allocators do 
> not (and cannot) support volatile qualified types.

That may well be true, but I can't find any such restriction in the C++
standard.  It would be a great help if the library specification weren't
so ambiguous - in this case, it hinges around the meaning of the word
'type', and the unqualified word is used with at least three meanings
in the standard.
Comment 3 Marc Glisse 2013-05-24 19:47:09 UTC
(In reply to Nick Maclaren from comment #2)
> That may well be true, but I can't find any such restriction in the C++
> standard.  It would be a great help if the library specification weren't
> so ambiguous - in this case, it hinges around the meaning of the word
> 'type', and the unqualified word is used with at least three meanings
> in the standard.

C++03 gives the prototype of the constructor:

explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator());

which shows that it can't work:

typedef volatile int T;
void f () { T const& a = T(); }

For C++11, the prototype changed, it gets harder to follow...
Comment 4 Daniel Krügler 2013-05-24 21:05:14 UTC
(In reply to Nick Maclaren from comment #2)
> That may well be true, but I can't find any such restriction in the C++
> standard.  It would be a great help if the library specification weren't
> so ambiguous - in this case, it hinges around the meaning of the word
> 'type', and the unqualified word is used with at least three meanings
> in the standard.

Actually there is a miss in Table 27, where the variables T, U, and C are described as

"any non-const object type (3.9)"

This should be corrected to

"any non-const non-volatile object type (3.9)"

I'm submitting an LWG issue for this.
Comment 5 Nick Maclaren 2013-06-18 10:39:07 UTC
Because of the last comment, I am not going to close this as resolved,
invalid, but please do so if appropriate.
Comment 6 Jonathan Wakely 2014-10-13 14:40:05 UTC
The standard containers don't support volatile types.