1

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.

1 Answers1

5

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

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • `specification of the function that follows it` - But `void func __attribute__((..)))` works as well. I think it rather works like `const`. `const` always applies to the nearest type identifier to the left, unless there is none, in which case it applies to the one on the right. You just cannot place attributes after `}`, since that would be like placing `const` after a semicolon or equal sign. – Mecki Apr 14 '21 at 12:05