Closed llvmbot closed 10 years ago
Optimizers are scary …
Sorry for the noise!
The optimizer is still able to prove that it doesn't need to reference the actual static.
The following is an example that will have a linker error under all levels of optimizations:
template
int main() {
return foo
Note that this program, and all of the programs you have posted, have undefined behavior because they don't provide a definition of the static variable.
New code, works with -O1 and -O2, shouldn't work, because the uninitialised static member is used.
--- foo.hpp ---
template
T * const payload;
public:
foo(T const val) : payload(foo<T>::alloc.allocate(1)) {
this->payload[0] = val;
}
virtual ~foo() {
foo<T>::alloc.deallocate(payload, 1);
}
T const & getPayload() const {
return this->payload[0];
}
};
--- main.cpp ---
int main() {
foo
c++ -O2 main.cpp && ./a.out
0x801c06058: 1337 c++ -O1 main.cpp && ./a.out
0x801c06058: 1337 c++ -O0 main.cpp && ./a.out
/tmp/main-e745e6.o: In functionfoo<int>::foo(int)': main.cpp:(.text._ZN3fooIiEC2Ei[_ZN3fooIiEC2Ei]+0xc): undefined reference to
foo: :alloc' /tmp/main-e745e6.o: In function foo<int>::~foo()': main.cpp:(.text._ZN3fooIiED2Ev[_ZN3fooIiED2Ev]+0xc): undefined reference to
foo: :alloc' c++: error: linker command failed with exit code 1 (use -v to see invocation)
I have code where the static member is an std::allocator and I definitely use it.
You never provide a definition of your static member.
Adding a definition would make your program successfully link:
template
As to why it works when optimizations are applied: the optimizer realizes you aren't using the 'static_member' variable and optimizes away the references to it.
Extended Description
First of all I do not know whether static template members are permitted. I figure there are some initialisation issues for the linker to sort out if a template is used in multiple object files.
In any way I think the behaviour should be the same for all optimisation levels.
EXAMPLE CODE
--- foo.hpp ---
ifndef _FOOHPP
define _FOOHPP
template
class foo {
private:
static T static_member;
};
endif / _FOOHPP /
--- main.cpp ---
include "foo.hpp"
int main() { foo bar;
bar.dynamic_method();
foo::static_method();
return 0;
}
CLANG VERSION
OS
DIRECT COMPILE
COMPILE FIRST LINK LATER