union UN_1{
int j;
};
// it work if it is a struct
union UN_ {
// the order of members does not matter
int d1;
// it works if this (UN_1) is struct
union UN_1 d2;
// this fixes the problem
//int j;
};
// making it local variable does not help
union UN_ un_data;
int main(void){
un_data.d2.j = 20;
return 0;
}
when executed, results in the error:
Type of lvalue (int) not compatible with the effective type of the object being accessed (union UN_):
> in main at union.c:17:2
Undefined behavior (UB-EIO10):
see C11 section 6.5:7 http://rvdoc.org/C11/6.5
see C11 section J.2:1 item 37 http://rvdoc.org/C11/J.2
see CERT-C section EXP39-C http://rvdoc.org/CERT-C/EXP39-C
see MISRA-C section 8.1:3 http://rvdoc.org/MISRA-C/8.1
. However, if the outer union contains j (with the same name as in the inner union), the problem disappears. The difference is that in the second case, the lvalue that is used to access the object, has in its loc3 component an information that j is the active variant of d2.
i.e. with the outer union as the type and j as the member identifier. Rules for setVariantAtOffset contain a side condition that checks whether j is a member of UN_ - which is suspicious, and probably causes the 'normal' behavior when UN_ contains j as a member.
The following code
when executed, results in the error:
. However, if the outer union contains
j
(with the same name as in the inner union), the problem disappears. The difference is that in the second case, the lvalue that is used to access the object, has in itsloc3
component an information thatj
is the active variant ofd2
.I suspect the bug is somewhere near https://github.com/kframework/c-semantics/blob/master/semantics/c/language/common/typing/effective.k#L196-L212. This code is called in the translation semantics when processing the assignment to the (nested) member, from
createLv
throughupdateLastAccessVariant
tosetVariantToOffset
, which is called somewhat likei.e. with the outer union as the type and
j
as the member identifier. Rules forsetVariantAtOffset
contain a side condition that checks whetherj
is a member ofUN_
- which is suspicious, and probably causes the 'normal' behavior whenUN_
containsj
as a member.