I have a code like this:
struct Storage { static int GetData() { static int global_value; return global_value++; } }; int free_func() { static int local_value; return local_value++; } int storage_test_func() { return Storage::GetData(); }
Compilation on OSX:
$ clang++ 1.cpp -shared
And nm works:
$ nm | c++filt
I get strange results:
0000000000000f50 T storage_test_func() 0000000000000f30 T free_func() 0000000000000f60 unsigned short Storage::GetData() 0000000000001024 bool free_func()::local_value 0000000000001020 D Storage::GetData()::global_value U dyld_stub_binder
Two characters ( local_value and global_value ) have a different relationship! One visible difference is that global_value is defined in a static member function, and local_value is defined in a free function.
Can someone explain why this is happening?
UPD:
After reading the comments, it seems like I should clarify the situation. Maybe using c++filt was a bad idea. Without this, it shows:
$ nm 0000000000000f50 T __Z17storage_test_funcv 0000000000000f30 T __Z9free_funcv 0000000000000f60 t __ZN7Storage7GetDataEv 0000000000001024 b __ZZ9free_funcvE11local_value 0000000000001020 D __ZZN7Storage7GetDataEvE5value U dyld_stub_binder
So yes. __ZZ9free_funcvE11local_value goes to BSS, and __ZZN7Storage7GetDataEvE5value goes to the data section.
man nm says that:
If the character is local (not external), the character type is instead represented by the corresponding lowercase letter.
And this is what I see. __ZZ9free_funcvE11local_value marked with lowercase b , and __ZZN7Storage7GetDataEvE5value capital D
And this is the main part of the question. Why it happens?
UPD2 Another way:
$ clang++ -c -emit-llvm 1.cpp $ llvm-dis 1.bc
shows how these variables are represented internally:
@_ZZ9free_funcvE11local_value = internal global i32 0, align 4 @_ZZN7Storage7GetDataEvE5value = global i32 0, align 4
UPD3
There were also some issues related to section symbols. Putting __ZZ9free_funcvE11local_value into a text section does not change its visibility:
struct Storage { static int GetData() { static int value; return value++; } }; int free_func() { static int local_value = 123; return local_value++; } int storage_test_func() { return Storage::GetData(); }
Compilation:
$ clang++ 1.cpp -shared
Verification:
$ nm
gives:
0000000000000f50 T __Z17storage_test_funcv 0000000000000f30 T __Z9free_funcv 0000000000000f60 t __ZN7Storage7GetDataEv 0000000000001020 d __ZZ9free_funcvE11local_value 0000000000001024 D __ZZN7Storage7GetDataEvE5value
Now both characters are in the data section, but another one is local and the other global . And the question is why is this happening? Can anyone have logic to solve such a compiler?