Search code examples
cgccgcc-extensions

Difference between gcc __attribute__ placement


While playing around with gcc __attribute__ for functions, I noticed that there is a difference in code generation depending on where I place the attribute. In below examples, I want the compiler not to optimize away my call to use().

Compiler: x86-64 gcc(trunk)

Options: -O3 -Wall

void  __attribute__((noinline, optimize("O0"))) use() {} 
int main () 
{
    use();
}
use:
        push    rbp
        mov     rbp, rsp
        nop
        pop     rbp
        ret
main:
        xor     eax, eax
        call    use
        xor     eax, eax
        ret

However, if I change the placement of the attribute, different code is generated.

void   use() {} __attribute__((noinline, optimize("O0")))
int main () 
{
    use();
}
main:
        push    rbp
        mov     rbp, rsp
        mov     eax, 0
        pop     rbp
        ret
use:
        ret

If I don't put any attributes, I get this:

void   use() {} 
int main () 
{
    use();
}
use:
        ret
main:
        xor     eax, eax
        ret

Now, the attributes I see attributes used at gcc_Common-Function-Attributes are all present in function declarations not definitions. I am not sure if I should only be using them only in declarations.(since using them in definition seems to work in one instance above) My question is what are the rules for placement of __attribute__ and why does the above behave way it does? I checked out gcc_Attribute-Syntax , but I am afraid I did not understand it quite well.


Solution

  • __attribute__ is part of the specification of the function that follows it. Your second version is actually:

    __attribute__((noinline, optimize("O0"))) int main() {
        ...
    }
    

    You're setting the attributes of the main() function, not the use() function.

    Remember that newlies don't have any special meaning in parsing C code, so putting the attribute on the same line as the use() declaration doesn't actually make it part of that.