14

Consider these two functions:

int f1()
{
  alignas(int) char buf[sizeof(int)] = {};
  return *reinterpret_cast<int*>(buf);
}

int f2()
{
  alignas(int) char buf[sizeof(int)] = {};
  char* ptr = buf;
  return *reinterpret_cast<int*>(ptr);
}

GCC warns that the first violates strict-aliasing rules. But the second is OK.

Clang accepts both without complaint.

Is the warning legitimate?

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Yes. The "object" here is either a `char` or the array of `char`s and the glvalue is of type `int`; nothing in https://timsong-cpp.github.io/cppwp/basic.lval#8 covers this case. – T.C. Dec 23 '16 at 09:31
  • @T.C. do you mean it's impossible by standard, to alias a region of char, as some other type T ? because that's how optional and variant works isn't it. I can't help but to find this idea, if true, a risk to a these practical needs. I thought the exceptions to aliasing were including char for that purpose. – v.oddou Aug 02 '19 at 02:08

1 Answers1

10

The warning is legitimate. f2 is not OK (it is undefined behaviour), it just doesn't provoke the warning.

I suspect the reason that f2 doesn't provoke the warning is that:

int f3()
{
    int i = 0;
    char *ptr = reinterpret_cast<char*>(&i);
    return *reinterpret_cast<int*>(ptr);
}

Is entirely legal. You can use a char* (or a void*) as a "universal pointer" - provided you cast back to the right type before access. GCC is clearly being careful to avoid warning about f3, at a cost of not warning about f2.

Clang is failing to warn about either f1 or f2 - but it is not required to.

Peter O.
  • 32,158
  • 14
  • 82
  • 96