3

Compiler generates code assuming that an int can be aliased by an unsigned int. The folowing code:

int f(int& a, unsigned int& b){
    a=10;
    b=12;
    return a;
}
int f(int& a, double& b){
    a=10;
    b=12;
    return a;
}

generates the folowing assembly, using Clang5 (similar code is produced by GCC or ICC):

f(int&, unsigned int&): # @f(int&, unsigned int&)
  mov dword ptr [rdi], 10
  mov dword ptr [rsi], 12
  mov eax, dword ptr [rdi]    #return value must be loaded since rdi might equal rsi
  ret
f(int&, double&): # @f(int&, double&)
  mov dword ptr [rdi], 10
  movabs rax, 4622945017495814144
  mov qword ptr [rsi], rax
  mov eax, 10        #return value is a direct value.
  ret

In the example above, in the first overload f the return value (in eax register) is either 10 or 12 if b and a refer to the same object. In the second overload, a and b cannot refer to the same object so the return value is always 10.

The strict aliasing rule is expressed by this paragraph of the C++ standard, [intro.object]/8:

[...] Two objects a and b with overlapping lifetimes that are not bit-fields may have the same address if one is nested within the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they have distinct addresses.

So according to this rule, an int cannot be aliased by an unsigned int.

Questions:

  1. Is there an exception to this rule in the C++ standard that would allow aliasing of int by unsigned int?

  2. If not, why all compilers assume this possibility?

Oliv
  • 17,610
  • 1
  • 29
  • 72
  • 1
    The strict aliasing rule is expressed by N4659 [basic.lval]/8 (point number differs among standard revisions) , not intro.object . The text you quote has nothing to do with strict aliasing – M.M Jan 02 '18 at 11:40
  • @M.M. I thought the strict aliasing rule was derived from this. So the paragraph cited in the anwer lead to exceptions to the rule we could derive from this paragraph. I had overlooked this paragraph. – Oliv Jan 02 '18 at 11:47
  • intro.object/8 is talking about the case of two objects, not two references that refer to the same object. The actual standard uses italics for *a* and *b* , not the typeface for code samples `a`, `b`; those are abstract symbols to indicate that we are talking about *two different objects*, and not two expressions or whatever – M.M Jan 02 '18 at 11:51

1 Answers1

4

Is there an exception to this rule in the C++ standard that would allow aliasing of int by unsigned int?

Yes, it's [basic.lval]/8:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • a type that is the signed or unsigned type corresponding to the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458