7

I'm getting a weird gcc behaviour when dealing with weak const variables on different optimize levels (i.e. -O0 or -O1).

Here is the code:

def.h: declarations

const int var;
int copy;
int do_copy(void);

weak.c: weak var definition, do_copy implementation doing copy = var

#include "def.h"
const int __attribute__((weak)) var = 1;
int do_copy(void)
{
    copy = var;
    return var;
}

main.c: strong var definition, and use of do_copy

#include <stdio.h>
#include "def.h"
int copy = 0;
int copy2 = 0;
const int var = 2;
int main(void)
{
    copy2 = do_copy();
    printf("copy=%d, copy2=%d\n", copy, copy2);
    return 0;
}

From this 'main.c' code, I am expecting both copy and copy2 to retain the strong var value, being 2.

Here is the output with a -O0 optimization:

$ gcc -O0 -c main.c -o main0.o
$ gcc -O0 -c weak.c -o weak0.o
$ gcc main0.o weak0.o -o main0
$ ./main0
copy=2, copy2=2

This is the expected result.

Here is the output with a -O1 optimization:

$ gcc -O1 -c main.c -o main1.o
$ gcc -O1 -c weak.c -o weak1.o
$ gcc main1.o weak1.o -o main1
$ ./main1
copy=1, copy2=2

This is unexpected: while copy2 does retain the strong value (2), copy is actually set to the weak value (1)!

Within the 'weak.c' file, it looks like var is always evaluated to 1.
My take is that as var is declared const, the compiler thinks that its value will always be 1 and does this optimization on the whole file (except for the return statement). Hence, it misses the weak/strong thing, and does not care about the strong redefinition in 'main.c'!

The issue can be solved by :

  • setting the weak definition (const int __attribute__((weak)) var = 1;) in a separate file, say 'weak2.c'.
  • not making var constant (which might not be acceptable!): const int var; ---> int var;.

Still, this looks like a gcc bug to me, but am I missing something?

Appendix:

This is the used version of gcc:

$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Lrnt Gr
  • 369
  • 2
  • 9

0 Answers0