On Fri, Feb 26, 2016 at 7:12 AM, Robert Haberlach <rh633@cam.ac.uk> wrote:
I apologize in advance if this was discussed before; I didn't check the entire archive. Consider

  static_assert(alignof(float) >= alignof(int) && sizeof(float) >= sizeof(int));
  int foo(float f) {
    return *std::launder(reinterpret_cast<int*>(&f)); }

As it stands, invocation of foo is undefined, as the argument to launder is not pointing to an object of type int (or similar) within its lifetime,
violating launder's requirement.

launder is designed to inhibit address propagation analysis, which is the only concerning optimization. Moreover, as long as all usual conditions are
met (alignment, size & trap values), this should be fine on any implementation. If so, can we make the above formally well-defined?
This is not fine. Type-based aliasing analysis (TBAA) is allowed to determine that the write to "f" and the read from the dereference is not related.
Consider the effects of inlining:
int main(void) { return !foo(0.5f); }

becomes (loosely):

int main(void) {
  int __ret;
  {
    float __f = 0.5f;
    __ret = *std::launder(reinterpret_cast<int *>(&__f)); 
  }
  return !__ret;
}

The implementation is allowed to observe that there are no TBAA-compatible reads of the value of __f within its lifetime. The likely result is that the initialization of __f would be optimized away.

-- HT

Being able to use launder in such scenarios would render circumlocutions via memcpy superfluous.

Robert
_______________________________________________
ub mailing list
ub@isocpp.open-std.org
http://www.open-std.org/mailman/listinfo/ub