Re: Using pure and const attributes for Meyers' singleton

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 4 April 2018 at 17:21,  <Antons.Jelkins@xxxxxx> wrote:
> From: Martin Sebor [mailto:msebor@xxxxxxxxx]
> Sent: Mittwoch, 4. April 2018 17:28
>
>> On 04/04/2018 07:25 AM, Antons.Jelkins@xxxxxx wrote:
>> > Hello,
>> >
>> > GCC has const and pure function attributes as described here:
>> > https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
>> >
>> > The attributes' specification is not as technical as the C++ standard, but their purpose seems to be to allow a
>> > compiler to call functions annotated with const or pure less than a program code says. The specs also say that
>> > such functions must not have any effects except their return value and the return value must depend only on
>> > function arguments and/or (in case of "pure") global variables.
>> >
>> > Assume, there is such Meyers' singleton:
>> >
>> > class MyClass
>> > {
>> > public:
>> >     MyClass();
>> > };
>> >
>> > [[ gnu::const ]]
>> > static const MyClass &myClass()
>> > {
>> >     static MyClass s_myClass;
>> >     return s_myClass;
>> > }
>> >
>> > Can const and pure attributes be used here? On the one hand, the singleton function does not have any observable
>> > effects other than its return value and it always returns the same value. So it is completely safe to optimise away multiple
>> > calls to this function. On the other hand, this function needs to construct the MyClass object on the first invocation.
>> > This includes calling a MyClass constructor and setting an implicit is-initialised flag to true. It also must be thread-safe.
>> > This could count as an effect besides the return value (although it is not visible from the outside).
>>
>> As you noted, the myClass() function has side-effects so declaring it const or pure violates the requirements in the manual.
>> Issuing a warning for such a function is an improvement worth considering.
>
> From the description it is not really clear what "no effects" actually means. Here is a quote from another e-mail from the GCC
> mailing list which implies "no observable effects":
>
> | But if we are allowed to DCE a lazy_i call with unused result then it really is "pure". Basically with this property
> | we consider the static variable it writes to as local, as it cannot be inspected in any other way than by calling
> | the function or inspecting its return value.
> https://gcc.gnu.org/ml/gcc/2012-10/msg00029.html
>
> Would it be somehow possible to confirm or refute that GCC does not treat constructing a static local variable as an effect in
> case of pure and/or const functions?

A static local variable is a global. The guard variable for the static
variable is also a local. So initialization of a static local variable
touches global memory, and so cannot be marked with attribute const.

>
>>
>> > void doThis(const MyClass&);
>> > void doThat(const MyClass&);
>> >
>> > void foo()
>> > {
>> >     doThis(myClass());
>> >     doThat(myClass());
>> > }
>> >
>> > GCC *does* optimise away the second call to myClass(). My question would be if this is an expected and desired
>> > behaviour which I can rely on, or this is a coincidence?
>>
>> It's certainly no coincidence but I would hesitate to claim it's something to rely on for code correctness.  Going purely by what the manual says:
>>
>>    ...the presence of the attribute on a function declaration
>>    allows GCC to emit more efficient code for some calls to
>>    the function.
>>
>> it's clear that attribute is just a hint for the optimizer, not a requirement on the compiler to avoid emitting redundant calls to such functions.
>>
>
> Probably I have poorly expressed myself. I was asking if I can expect that this code will invoke myClass() once (in case the second call is
> optimised away) or twice (if not), and during the first invocation it will properly construct the local static MyClass object? Or does this
> code from compiler's point of view has an undefined behaviour and it can e.g. skip constructing MyClass and call doThis() with an unitialised
> object?
>
>> Martin
>>
>> >
>> > Clang clearly treats this code as invalid, but they might change their behaviour if there is evidence that GCC implements a different rule:
>> > https://bugs.llvm.org/show_bug.cgi?id=36750
>> >
>> > Regards,
>> > Anton
>>



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux