Using pure and const attributes for Meyers' singleton
Jonathan Wakely
jwakely.gcc@gmail.com
Wed Apr 4 17:04:00 GMT 2018
On 4 April 2018 at 17:21, <Antons.Jelkins@bmw.de> wrote:
> From: Martin Sebor [mailto:msebor@gmail.com]
> Sent: Mittwoch, 4. April 2018 17:28
>
>> On 04/04/2018 07:25 AM, Antons.Jelkins@bmw.de 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
>>
More information about the Gcc-help
mailing list