[function] Placement new warnings from gcc 6

::functor_type {aka boost::spirit::qi::detail::parser_binder<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard,
Hi, In my tests on gcc 6 I'm seeing these warnings which stem from Boost.Function: ../boost/function/function_template.hpp:572:11: warning: placement new constructing an object of type 'boost::spirit::qi::detail::parser_binder<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::nil_> > > > > > > >, mpl_::bool_<false> >' and size '8' in a region of type 'char' and size '1' [-Wplacement-new=] ../boost/function/function_base.hpp:308:13: warning: placement new constructing an object of type 'boost::detail::function::functor_manager_common<boost::spirit::qi::detail::parser_binder<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::nil_> > > > > > > >, mpl_::bool_<false> > true, false>, boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::any_uint_parser<unsigned int, 10u, 1u, -1>, boost::fusion::nil_> > > > > > > >, mpl_::bool_<false> >}' and size '8' in a region of type 'char' and size '1' [-Wplacement-new=] I'm not familiar with boost::function internals, but the warning looks serious enough to do something about it. I.e. if it's actually benign, it would be nice to silence it to avoid causing panic.

AMDG On 04/01/2016 02:11 AM, Andrey Semashev wrote:
In my tests on gcc 6 I'm seeing these warnings which stem from Boost.Function:
../boost/function/function_template.hpp:572:11: warning: placement new constructing an object of type '<snip>' and size '8' in a region of type 'char' and size '1' [-Wplacement-new=]
I'm not familiar with boost::function internals, but the warning looks serious enough to do something about it. I.e. if it's actually benign, it would be nice to silence it to avoid causing panic.
The 'char' in question is the first element of an array of sufficient size. In Christ, Steven Watanabe

Steven Watanabe wrote:
On 04/01/2016 02:11 AM, Andrey Semashev wrote:
In my tests on gcc 6 I'm seeing these warnings which stem from Boost.Function:
../boost/function/function_template.hpp:572:11: warning: placement new constructing an object of type '<snip>' and size '8' in a region of type 'char' and size '1' [-Wplacement-new=]
The 'char' in question is the first element of an array of sufficient size.
The buffer does have sufficient size but the char is not an array element. It's a char member of a union. We could make this clearer by making function_buffer::data be an array with a sufficient size by, for instance, duplicating the definition of "union function_buffer" and taking its sizeof... or just by using &functor instead of &functor.data at line 572, although this might trigger aliasing warnings with other g++ versions.

On 2016-04-01 19:37, Peter Dimov wrote:
Steven Watanabe wrote:
On 04/01/2016 02:11 AM, Andrey Semashev wrote:
In my tests on gcc 6 I'm seeing these warnings which stem from >
Boost.Function:
../boost/function/function_template.hpp:572:11: warning: placement
new > constructing an object of type '<snip>'
and size '8' in a region of type 'char' and size '1' [-Wplacement-new=]
The 'char' in question is the first element of an array of sufficient size.
The buffer does have sufficient size but the char is not an array element. It's a char member of a union.
We could make this clearer by making function_buffer::data be an array with a sufficient size by, for instance, duplicating the definition of "union function_buffer" and taking its sizeof...
Thanks. I've made a patch with a similar idea: https://github.com/boostorg/function/pull/9 It passes tests on gcc 5.2 and MSVC-14, but unfortunately I don't have gcc 6 locally to verify that the warnings are actually gone.

Andrey Semashev wrote:
Thanks. I've made a patch with a similar idea:
This works, although the following alternative: template<class T> union function_buffer_ { // as before mutable T data; }; size_t const function_buffer_size = sizeof(function_buffer_<char>); typedef function_buffer_<char[function_buffer_size]> function_buffer; seems slightly more maintainable as it doesn't perform the size computation separately.

On 2016-04-02 15:45, Peter Dimov wrote:
Andrey Semashev wrote:
Thanks. I've made a patch with a similar idea:
This works, although the following alternative:
template<class T> union function_buffer_ { // as before mutable T data; };
size_t const function_buffer_size = sizeof(function_buffer_<char>);
typedef function_buffer_<char[function_buffer_size]> function_buffer;
seems slightly more maintainable as it doesn't perform the size computation separately.
That instantiates the template twice, maybe it'll affect compile times. Also, I'm a bit cautious about using an array type in template parameters - maybe it'll cause trouble on ancient compilers? I guess, I could extract all members other than 'data' to a separate union and then: union function_buffer { mutable function_buffer_members m; mutable char data[sizeof(function_buffer_members)]; }; This would require more modifications to the code though. (Sigh... if only we could inherit unions...)

On 2016-04-02 16:08, Andrey Semashev wrote:
On 2016-04-02 15:45, Peter Dimov wrote:
Andrey Semashev wrote:
Thanks. I've made a patch with a similar idea:
This works, although the following alternative:
template<class T> union function_buffer_ { // as before mutable T data; };
size_t const function_buffer_size = sizeof(function_buffer_<char>);
typedef function_buffer_<char[function_buffer_size]> function_buffer;
seems slightly more maintainable as it doesn't perform the size computation separately.
That instantiates the template twice, maybe it'll affect compile times. Also, I'm a bit cautious about using an array type in template parameters - maybe it'll cause trouble on ancient compilers?
I guess, I could extract all members other than 'data' to a separate union and then:
union function_buffer { mutable function_buffer_members m; mutable char data[sizeof(function_buffer_members)]; };
This would require more modifications to the code though.
Ok, I updated my pull request to implement the above version.

On 2016-04-02 17:34, Andrey Semashev wrote:
Ok, I updated my pull request to implement the above version.
Could someone please have a look at the PR? The final release of gcc 6 seems to still have the warning. https://github.com/boostorg/function/pull/9

On 04/02/2016 08:08 AM, Andrey Semashev wrote: [snip]
union function_buffer { mutable function_buffer_members m; mutable char data[sizeof(function_buffer_members)]; };
This would require more modifications to the code though.
(Sigh... if only we could inherit unions...)
Could you provide an example of how you'd like to inherit unions? I'm guessing: union function_buffer : supertype_1 , supertype_2 ... , supertype_N { }; where all of the supertype_I's would occupy the same storage?

On 2016-04-03 14:39, Larry Evans wrote:
On 04/02/2016 08:08 AM, Andrey Semashev wrote: [snip]
union function_buffer { mutable function_buffer_members m; mutable char data[sizeof(function_buffer_members)]; };
This would require more modifications to the code though.
(Sigh... if only we could inherit unions...)
Could you provide an example of how you'd like to inherit unions? I'm guessing:
union function_buffer : supertype_1 , supertype_2 ... , supertype_N { };
where all of the supertype_I's would occupy the same storage?
Yes. More precisely, all supertype_I's and function_buffer's members would map to the same storage, and supertype_I's members would be syntactically addressed as if those were members of function_buffer (i.e. similarly how it is with structs and classes). The above function_buffer definition could be written as: union function_buffer : public function_buffer_base { mutable char data[sizeof(function_buffer_base)]; }; and members of function_buffer and function_buffer_base could be addressed similarly: function_buffer fb; fb.obj_ptr = ...; fb.data = ...;

On 3/04/2016 02:08, Andrey Semashev wrote:
I guess, I could extract all members other than 'data' to a separate union and then:
union function_buffer { mutable function_buffer_members m; mutable char data[sizeof(function_buffer_members)]; };
This would require more modifications to the code though.
(Sigh... if only we could inherit unions...)
Could you do this with an anonymous union? eg: union function_buffer { mutable union function_buffer_members { ... }; mutable char data[sizeof(function_buffer_members)]; }; Haven't tested this; not sure if it's legal to get the sizeof a subtype nested in the same scope like this, but it at least seems plausible.

On 2016-04-04 04:35, Gavin Lambert wrote:
On 3/04/2016 02:08, Andrey Semashev wrote:
I guess, I could extract all members other than 'data' to a separate union and then:
union function_buffer { mutable function_buffer_members m; mutable char data[sizeof(function_buffer_members)]; };
This would require more modifications to the code though.
(Sigh... if only we could inherit unions...)
Could you do this with an anonymous union? eg:
union function_buffer { mutable union function_buffer_members { ... }; mutable char data[sizeof(function_buffer_members)]; };
Haven't tested this; not sure if it's legal to get the sizeof a subtype nested in the same scope like this, but it at least seems plausible.
That is a named union in your example. And if it's anonymous then you have no name to apply sizeof to.

On 4/04/2016 19:52, Andrey Semashev wrote:
On 2016-04-04 04:35, Gavin Lambert wrote:
Could you do this with an anonymous union? eg:
union function_buffer { mutable union function_buffer_members { ... }; mutable char data[sizeof(function_buffer_members)]; };
Haven't tested this; not sure if it's legal to get the sizeof a subtype nested in the same scope like this, but it at least seems plausible.
That is a named union in your example. And if it's anonymous then you have no name to apply sizeof to.
Type name != member name. It is still an anonymous union.

Mere moments ago, quoth I:
On 4/04/2016 19:52, Andrey Semashev wrote:
On 2016-04-04 04:35, Gavin Lambert wrote:
Could you do this with an anonymous union? eg:
union function_buffer { mutable union function_buffer_members { ... }; mutable char data[sizeof(function_buffer_members)]; };
Haven't tested this; not sure if it's legal to get the sizeof a subtype nested in the same scope like this, but it at least seems plausible.
That is a named union in your example. And if it's anonymous then you have no name to apply sizeof to.
Type name != member name. It is still an anonymous union.
Although on further reflection, allowing a tag name on an anonymous union might be a Microsoft-specific extension (though GCC can enable support for it via command-line parameter). It's probably something that *ought* to be in the standard, but that probably doesn't help you much at this time.

On 2016-04-05 06:45, Gavin Lambert wrote:
Mere moments ago, quoth I:
On 4/04/2016 19:52, Andrey Semashev wrote:
On 2016-04-04 04:35, Gavin Lambert wrote:
Could you do this with an anonymous union? eg:
union function_buffer { mutable union function_buffer_members { ... }; mutable char data[sizeof(function_buffer_members)]; };
Haven't tested this; not sure if it's legal to get the sizeof a subtype nested in the same scope like this, but it at least seems plausible.
That is a named union in your example. And if it's anonymous then you have no name to apply sizeof to.
Type name != member name. It is still an anonymous union.
Although on further reflection, allowing a tag name on an anonymous union might be a Microsoft-specific extension (though GCC can enable support for it via command-line parameter).
Oh, if that's a non-standard extension then I'm not aware of it.
It's probably something that *ought* to be in the standard, but that probably doesn't help you much at this time.
I'd say it *should not* be in the standard as it is very confusing.

On 2016-04-05 06:39, Gavin Lambert wrote:
On 4/04/2016 19:52, Andrey Semashev wrote:
On 2016-04-04 04:35, Gavin Lambert wrote:
Could you do this with an anonymous union? eg:
union function_buffer { mutable union function_buffer_members { ... }; mutable char data[sizeof(function_buffer_members)]; };
Haven't tested this; not sure if it's legal to get the sizeof a subtype nested in the same scope like this, but it at least seems plausible.
That is a named union in your example. And if it's anonymous then you have no name to apply sizeof to.
Type name != member name. It is still an anonymous union.
It is not. My reading of the above code snippet is that there is a nested function_buffer_members union type definition. There is no member of that type in function_buffer, and since it is not an anonymous union, its members are not "inlined" into the containing scope (i.e. the function_buffer union). The mutable keyword is illegal in that context.

On 5/04/2016 16:12, Andrey Semashev wrote:
On 2016-04-05 06:39, Gavin Lambert wrote:
Type name != member name. It is still an anonymous union.
It is not. My reading of the above code snippet is that there is a nested function_buffer_members union type definition. There is no member of that type in function_buffer, and since it is not an anonymous union, its members are not "inlined" into the containing scope (i.e. the function_buffer union). The mutable keyword is illegal in that context.
See https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html (specifically the discussion near "-fms-extensions"). Although interestingly, current MS compilers at least do appear to treat this as a nested type declaration rather than an anonymous member declaration. In any case, we've established that this isn't going to work, so I won't say any more on it.
participants (5)
-
Andrey Semashev
-
Gavin Lambert
-
Larry Evans
-
Peter Dimov
-
Steven Watanabe