C++ Logo

std-discussion

Advanced search

std::variant and pointer aliasing problems

From: Myria <myriachan_at_[hidden]>
Date: Fri, 2 Oct 2020 15:50:03 -0700
Currently, there is a bug in Clang where the following program prints
4321 instead of the expected 1234 in optimized builds. As far as I
know, it has defined behavior; the pointer aliasing here is of
matching types.

// Must use libcxx
// clang++ -std=gnu++17 -O3 -fstrict-aliasing variant.cpp -o variant
#include <variant>
#include <cstdio>

struct s1 {unsigned short x;};
struct s2 {unsigned short x;};
using s1s2 = std::variant<s1, s2>;

static int read_s1x(s1 *p) { return p->x; }
static void write_s2x(s2 *p, int v) { p->x=v; }

int test(s1s2 *p1, s1s2 *p2, s1s2 *p3)
{
  if (read_s1x(std::get_if<s1>(p1)))
  {
    unsigned short temp;
    temp = std::get_if<s1>(p3)->x;
    p3->emplace<s2>(s2{temp});
    write_s2x(std::get_if<s2>(p2),1234);
    temp = std::get_if<s2>(p3)->x;
    p3->emplace<s1>(s1{temp});
  }
  return read_s1x(std::get_if<s1>(p1));
}
int test2(int x)
{
  s1s2 q[2];
  q[x].emplace<s1>(s1{4321});
  return test(q,q+x,q+x);
}
int main(void)
{
  std::printf("%d\n",test2(0));
}


This bug is caused by alias confusion within the union chain
comprising std::variant. It's a conversion to std::variant of some
Standard-compliant union code that was found to break Clang's (and
GCC's) type-based aliasing analysis. (Note that GCC only blows up
with the original version; somehow libstdc++'s std::variant is
immune.)

https://bugs.llvm.org/show_bug.cgi?id=34632

In that long thread, LLVM maintainers seem to think that the original
non-variant version can't be solved without pessimizing a large
variety of code. They suggest that writing to a union should always
require a union member access expression to have defined meaning.

But... that breaks std::variant. std::get_if returns a pointer to one
of the members, so accessing members of a substructure won't have a
union member access expression. This is what breaks Clang's TBAA,
just like the original non-variant code.

I've known about this for a while, but don't know what to do with it.

Melissa

Received on 2020-10-02 17:50:19