cgccfunction-attributes

Why is no warning given for the wrong use of __attribute__((pure)) in GCC?


I am trying to understand pure functions, and have been reading through the Wikipedia article on that topic. I wrote the minimal sample program as follows:

#include <stdio.h>

static int a = 1;

static __attribute__((pure)) int pure_function(int x, int y)
{
        return x + y;
}

static __attribute__((pure)) int impure_function(int x, int y)
{
        a++;
        return x + y;
}

int main(void)
{
        printf("pure_function(0, 0) = %d\n", pure_function(0, 0));
        printf("impure_function(0, 0) = %d\n", impure_function(0, 0));

        return 0;
}

I compiled this program with gcc -O2 -Wall -Wextra, expecting that an error, or at least a warning, should have been issued for decorating impure_function() with __attribute__((pure)). However, I received no warnings or errors, and the program also ran without issues.

Isn't marking impure_function() with __attribute__((pure)) incorrect? If so, why does it compile without any errors or warnings, even with the -Wextra and -Wall flags?

Thanks in advance!


Solution

  • A pure function is a hint for the optimizing compiler. Probably, gcc don't care about pure functions when you pass just -O0 to it (the default optimizations). So if f is pure (and defined outside of your translation unit, e.g. in some outside library), the GCC compiler might optimize y = f(x) + f(x); into something like

    { 
      int tmp = f(x); /// tmp is a fresh variable, not appearing elsewhere
      y = tmp + tmp;
    }
    

    but if f is not pure (which is the usual case: think of f calling printf or malloc), such an optimization is forbidden.

    Standard math functions like sin or sqrt are pure (except for IEEE rounding mode craziness, see http://floating-point-gui.de/ and Fluctuat for more), and they are complex enough to compute to make such optimizations worthwhile.

    You might compile your code with gcc -O2 -Wall -fdump-tree-all to guess what is happening inside the compiler. You could add the -fverbose-asm -S flags to get a generated *.s assembler file.

    You could also read the Bismon draft report (notably its section §1.4). It might give some intuitions related to your question.

    In your particular case, I am guessing that gcc is inlining your calls; and then purity matters less.

    If you have time to spend, you might consider writing your own GCC plugin to make such a warning. You'll spend months in writing it! These old slides might still be useful to you, even if the details are obsolete.

    At the theoretical level, be aware of Rice's theorem. A consequence of it is that perfect optimization of pure functions is probably impossible.

    Be aware of the GCC Resource Center, located in Bombay.