On 17 December 2014 at 15:48, Reid Kleckner <[email protected]> wrote:
> Are we sure this is correct? In the motivating example, what if 'f' gets
> inlined? Then 'g' will have the code of 'f' embedded into it, but it will
> not be part of the comdat that statically initializes the guard variable.

I see. The issue is that we produce

$_Z1fv = comdat any
@_ZZ1fvE1y = linkonce_odr global i32 0, comdat $_Z1fv, align 4
@_ZGVZ1fvE1y = linkonce_odr global i64 0, comdat $_Z1fv
define linkonce_odr i32* @_Z1fv() #1 comdat $_Z1fv {

So if f is inlined, g will be using _ZZ1fvE1y and _ZGVZ1fvE1y. In the
TU with the definition of  S::x , the _Z1fv comdat has no guard
variable. If the linker selects that, we get "relocation refers to
discarded section"

Before the patch we would still produce crashing code for the attached
testcase (as does gcc). Just compile/run with

$CXX -c test2.cpp -fPIC
$CXX -c test.cpp -O2 -fPIC
$CXX test2.o test.o -o t
./t

In the end the difference of this case is that f is inlined. It the
case of the static member variable the static init function never is.

The only option I can think of that would wold work is to use comdas
like now, but to always produce a guard variable. So when the variable
is found to be a constant, we would have

@_ZGVZ1fvE1y = linkonce_odr constant i64 1, comadat $_Z1fv

Cheers,
Rafael
struct S {
  static const int x;
};
//const int S::x = 42;
inline const int* f() {
  static const int y = S::x;
  return &y;
}
const int *g() { return f(); }
struct S {
  static const int x;
};
const int S::x = 42;
inline const int* f() {
  static const int y = S::x;
  return &y;
}
extern const int *g();
int main() { f(); g();}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to