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 >>