I have such code:
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();
}
Compiling it on OSX:
$ clang++ 1.cpp -shared
And running nm:
$ nm | c++filt
I am getting 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 symbols (local_value
and global_value
) have different linkage! One visible difference is that global_value
is defined in static member function and local_value
is defined in free function.
Can somebody explain why it happens?
UPD:
After comments reading it looks like I should clarify things.
Maybe using of c++filt
was a bad idea. Without it 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 data section.
man nm
says that:
If the symbol is local (non-external), the symbol's type is instead represented by the corresponding lowercase letter.
And that what I see. __ZZ9free_funcvE11local_value
is marked with lowercase b
and __ZZN7Storage7GetDataEvE5value
is marked with capital D
.
And this is the main part of the question. Why it happens like that?
UPD2 One more 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
Also there were some concerns about different sections symbols belong to. Putting __ZZ9free_funcvE11local_value
to the 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();
}
Compiling:
$ clang++ 1.cpp -shared
Checking:
$ nm
Gives:
0000000000000f50 T __Z17storage_test_funcv
0000000000000f30 T __Z9free_funcv
0000000000000f60 t __ZN7Storage7GetDataEv
0000000000001020 d __ZZ9free_funcvE11local_value
0000000000001024 D __ZZN7Storage7GetDataEvE5value
Now both symbols are in data section but still one of those is local and another is global. And the question is why it happens? Can somebody the logic on such compiler's decision?