[Mesa-dev] [PATCH] nir: Make C++ more happy with NIR_SRC_INIT and NIR_DEST_INIT

Francisco Jerez currojerez at riseup.net
Fri Jun 26 18:23:25 PDT 2015


Jason Ekstrand <jason at jlekstrand.net> writes:

> On Fri, Jun 26, 2015 at 3:34 PM, Francisco Jerez <currojerez at riseup.net> wrote:
>> Jason Ekstrand <jason at jlekstrand.net> writes:
>>
>>> On Fri, Jun 26, 2015 at 3:03 PM, Francisco Jerez <currojerez at riseup.net> wrote:
>>>> Jason Ekstrand <jason at jlekstrand.net> writes:
>>>>
>>>>> On Fri, Jun 26, 2015 at 12:08 PM, Francisco Jerez <currojerez at riseup.net> wrote:
>>>>>> Jason Ekstrand <jason at jlekstrand.net> writes:
>>>>>>
>>>>>>> In C, if you partially initialize a structure, the rest of the struct gets
>>>>>>> set to 0.  C++, however, does not have this rule so GCC throws warnings
>>>>>>> whenver NIR_SRC_INIT or NIR_DEST_INIT is used in C++.
>>>>>>
>>>>>> I don't think that's right, in C++ initializers missing from an
>>>>>> aggregate initializer list are also defined to be initialized
>>>>>> (value-initialized to be more precise, what would set them to zero in
>>>>>> this case just like in C).
>>>>>
>>>>> Yes, that is correct.  I just did a second attempt that, instead,
>>>>> defines a static const variable named NIR_SRC_INIT with a partial
>>>>> initializer.  C++ still gets grumpy and gives me a pile of "missing
>>>>> initializer" warnings.
>>>>>
>>>> That's likely related to the warning flags you have enabled in CXXFLAGS,
>>>> not to C++ itself.  Maybe you have -Wmissing-field-initializers enabled
>>>> for C++ only?
>>>>
>>>>>>> Since nir.h contains a static inline that uses NIR_SRC_INIT, every C++
>>>>>>> file that includes nir.h complains about this.
>>>>>>>
>>>>>> I suspect the reason why this causes a warning may be that you're using
>>>>>> compound literals? (which are a C99-specific feature and not part of C++)
>>>>>>
>>>>>>> This patch adds a small static inline function that makes a struct,
>>>>>>> memsets it to 0, and returns it.  NIR_SRC_INIT and NIR_DEST_INIT are then
>>>>>>> wrappers around this function.
>>>>>>
>>>>>> In C++ you could just call the implicitly defined default constructor
>>>>>> for nir_src or nir_dest, like 'nir_src()'.
>>>>>
>>>>> The implicitly defined default constructor does nothing to POD types,
>>>>> so doing so would explicitly *not* perform the desired action of
>>>>> zeroing out the data.
>>>>>
>>>>
>>>> Indeed, but 'nir_src()' doesn't only call the implicitly-defined trivial
>>>> default constructor, it value-initializes the object (See section 8.5/8
>>>> of the C++14 spec) what for POD types causes all members to be
>>>> zero-initialized.
>>>
>>> It looks like this greatly depends on your C++ version.  If it's C++11
>>> or above, I believe it does get zero-initialized.  If it's earlier
>>> than C++11, it doesn't.  At least that's the way I read this:
>>>
>>> http://en.cppreference.com/w/cpp/language/value_initialization
>>
>> Not really, it will get zero-initialized back to C++98.  AFAICT what the
>> article is trying to say is that in C++98 what is now referred to as
>> value-initialization used to be called default-initialization in the
>> spec, but still it had the effect of zero-initializing the structure.
>
> Ok, I did some more reading and I think I'm convinced now.  Figuring
> out what "nir_src src = nir_src()" actually does should *not* take
> this much research.  I'll send an updated patch on Monday.
> --Jason

Then again this is likely to only be required because you somehow end up
with different warning options in C and C++.  Omitting members in an
aggregate initializer is valid C++, and has the same effect as
value-initializing the missing members, see section 8.5.1 "Aggregates"
of the C++14 spec:

| 7 If there are fewer initializer-clauses in the list than there are
|   members in the aggregate, then each member not explicitly
|   initialized shall be initialized from its brace-or-equal-initializer
|   or, if there is no brace-or-equal-initializer, from an empty
|   initializer list (8.5.4).

And 8.5.4 "List-initialization":

| 3 List-initialization of an object or reference of type T is defined
|   as follows:
|[..]
|    — Otherwise, if the initializer list has no elements, the object is
|      value-initialized.

That said, doing 'nir_src()' does have the advantage that you avoid
using non-standard compound literals in C++, but you could definitely
avoid them in some other way (e.g. just omit the '(nir_src)' type?) that
doesn't involve using separate preprocessor paths for C and C++.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 212 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150627/0e09b141/attachment.sig>


More information about the mesa-dev mailing list