StrictAliasingChecker implements checks on violation of the next paragraph (C++20 7.2.1 p11 [basic.lval]) of the C++20 Standard which is known as Strict Aliasing Rule. It operates on variable loads and stores. The checker compares the original type of the value with the type of the pointer with which the value is aliased.
Example:
int x = 42; auto c = *((char*)&x); // The original type is `int`. The aliased type is `char`. OK. auto f = *((float*)&x); // The original type is `int`. The aliased type is `float`. UB.
At the moment the checker supports only C++20.
Evolution of C++ Standard
C++98 | C++11 | C++14 | C++17 | C++20 (Fixed Issue 2051) |
---|---|---|---|---|
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: | - | - | - | If a program attempts to access (3.1) the stored value of an object through a glvalue |
- the dynamic type of the object | - | - | - | - |
- a cv-qualified version of the dynamic type of the object | - | - | - | Removed as duplicated of similar type. |
blank | - a type similar to the dynamic type of the object | - | - | Moved to the paragraph's main text (first row). |
- 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 | - | - | - | Removed as duplicated of similar type. |
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union) | - | - | - | Removed as a core defect (Issue 2051). This cannot arise in C++. |
- a type that is a (possibly cv-qualified) base class type of the dynamic type of the object | - | - | - | Removed as a core defect (Issue 2051). This cannot arise in C++. |
- a char, unsigned char | - | - | - a char, unsigned char, or std::byte type | - |
Paragraph from C Standard is true for all versions
C |
---|
An object shall have its stored value accessed only by an lvalue expression that has one of the following types: |
- a type compatible with the effective type of the object |
- a qualified version of a type compatible with the effective type of the object |
- a type that is the signed or unsigned type corresponding to the effective type of the object |
- a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object |
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union) |
- a character type |
Differences are in the type concepts between C and C++
has concept? | C | C++ |
---|---|---|
effective type | yes | no |
compatible type | yes | no |
dynamic type | no | yes |
similar type | no | yes |
Thus, the interpretation of the paragraph is different, depending on type concept meaning. E.g. the first statement "... similar to ... the dynamic type of the object" vs "a type compatible with the effective type of the object".
assert() it? Or maybe canonicalize defensively so that not to duplicate code in the caller, given that there's really only one correct way to do that?